xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision acee19a797ddf2cfc7f6c84b447ad4001457556a)
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;
411*acee19a7SJed 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) {
1779*acee19a7SJed 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);
2283*acee19a7SJed 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);
2287*acee19a7SJed 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 */
25903b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
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;
26173b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
26183b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
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 */
26323b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
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 */
2715de534f79Sstefano_zampini         Bs = PetscBLASIntCast(size_of_constraint);
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) {
2728de534f79Sstefano_zampini 
27293b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
27303b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
2731de534f79Sstefano_zampini 
27323b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
27333b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
27343b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
27353b03a366Sstefano_zampini       for (j=0;j<temp_constraints;j++) {
27363b03a366Sstefano_zampini         for (k=0;k<j+1;k++) {
27373b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
27383425bc38SStefano Zampini           /* hand made complex dot product -> replace */
27393b03a366Sstefano_zampini           dot_result = 0.0;
27403b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
27413b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
27423b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
27433b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
27443b03a366Sstefano_zampini           }
27453b03a366Sstefano_zampini #else
27463b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
27473b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
27483b03a366Sstefano_zampini #endif
27493b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
27503b03a366Sstefano_zampini         }
27513b03a366Sstefano_zampini       }
27523425bc38SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27533b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
27543425bc38SStefano Zampini /*      LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr); */
27553425bc38SStefano Zampini       LAPACKsyevx_("V","A","U",&Bt,correlation_mat,&Bt,&dummy_real,&dummy_real,&dummy_int,&dummy_int,
27563425bc38SStefano Zampini                  &abs_tol,&eigs_found,singular_vals,singular_vectors,&Bt,work,&lwork,iwork,ifail,&lierr);
27573b03a366Sstefano_zampini #else
27583425bc38SStefano Zampini /*  LAPACK call is missing here! TODO */
27593425bc38SStefano Zampini       SETERRQ(((PetscObject) pc)->comm, PETSC_ERR_SUP, "Not yet implemented for complexes when PETSC_MISSING_GESVD = 1");
27603b03a366Sstefano_zampini #endif
27613425bc38SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEVX Lapack routine %d",(int)lierr);
27623425bc38SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
27633b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
27643b03a366Sstefano_zampini       j=0;
27653b03a366Sstefano_zampini       while (j < Bt && singular_vals[j] < tol) j++;
27663b03a366Sstefano_zampini       total_counts=total_counts-j;
27673b03a366Sstefano_zampini       if (j<temp_constraints) {
27683b03a366Sstefano_zampini         for (k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
27693425bc38SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27703b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
27713425bc38SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
27723b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
27733b03a366Sstefano_zampini         for (k=0;k<Bt-j;k++) {
27743b03a366Sstefano_zampini           for (ii=0;ii<size_of_constraint;ii++) {
27753b03a366Sstefano_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];
27763b03a366Sstefano_zampini           }
27773b03a366Sstefano_zampini         }
27783b03a366Sstefano_zampini       }
2779de534f79Sstefano_zampini 
27803b03a366Sstefano_zampini #else  /* on missing GESVD */
27813b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
27823b03a366Sstefano_zampini       if (min_n > size_of_constraint) min_n = size_of_constraint;
27833b03a366Sstefano_zampini       dummy_int = Bs;
2784670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
27853b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
27863b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
27873b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
27883b03a366Sstefano_zampini #else
27893b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
27903b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
27913b03a366Sstefano_zampini #endif
27923b03a366Sstefano_zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
2793670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
27943b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
27953b03a366Sstefano_zampini       j=0;
27963b03a366Sstefano_zampini       while (j < min_n && singular_vals[min_n-j-1] < tol) j++;
27973b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
27983b03a366Sstefano_zampini #endif
27993b03a366Sstefano_zampini     }
28003b03a366Sstefano_zampini   }
2801534831adSStefano Zampini 
2802da1bb401SStefano Zampini   n_constraints=total_counts-n_vertices;
2803da1bb401SStefano Zampini   local_primal_size = total_counts;
28043b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
28053b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
28063b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
2807da1bb401SStefano Zampini   pcbddc->local_primal_size = local_primal_size;
2808534831adSStefano Zampini 
2809534831adSStefano Zampini   /* Create constraint matrix */
2810534831adSStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
2811534831adSStefano Zampini   /* so we need to set it up properly either with or without change of basis */
2812534831adSStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
2813534831adSStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
2814534831adSStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
2815534831adSStefano Zampini   /* compute a local numbering of constraints : vertices first then constraints */
2816534831adSStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
2817534831adSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array_vector);CHKERRQ(ierr);
2818534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&aux_primal_numbering);CHKERRQ(ierr);
2819534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&aux_primal_permutation);CHKERRQ(ierr);
2820534831adSStefano Zampini   total_counts=0;
2821534831adSStefano Zampini   /* find vertices: subdomain corners plus dofs with basis changed */
2822534831adSStefano Zampini   for (i=0;i<local_primal_size;i++) {
2823534831adSStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
2824534831adSStefano Zampini     if (change_basis[i] || size_of_constraint == 1) {
2825534831adSStefano Zampini       k=0;
2826534831adSStefano Zampini       while (k < size_of_constraint && array_vector[temp_indices_to_constraint[temp_indices[i]+size_of_constraint-k-1]] != 0.0) {
2827534831adSStefano Zampini         k=k+1;
2828534831adSStefano Zampini       }
2829534831adSStefano Zampini       j=temp_indices_to_constraint[temp_indices[i]+size_of_constraint-k-1];
2830534831adSStefano Zampini       array_vector[j] = 1.0;
2831534831adSStefano Zampini       aux_primal_numbering[total_counts]=j;
2832534831adSStefano Zampini       aux_primal_permutation[total_counts]=total_counts;
2833534831adSStefano Zampini       total_counts++;
2834534831adSStefano Zampini     }
2835534831adSStefano Zampini   }
2836534831adSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array_vector);CHKERRQ(ierr);
2837534831adSStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2838534831adSStefano Zampini   ierr = PetscSortIntWithPermutation(total_counts,aux_primal_numbering,aux_primal_permutation);
2839534831adSStefano Zampini   /* nonzero structure */
2840534831adSStefano Zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
2841534831adSStefano Zampini   for (i=0;i<total_counts;i++) {
2842534831adSStefano Zampini     nnz[i]=1;
2843534831adSStefano Zampini   }
2844534831adSStefano Zampini   j=total_counts;
2845534831adSStefano Zampini   for (i=n_vertices;i<local_primal_size;i++) {
2846534831adSStefano Zampini     if (!change_basis[i]) {
2847534831adSStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2848534831adSStefano Zampini       j++;
2849534831adSStefano Zampini     }
2850534831adSStefano Zampini   }
2851534831adSStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2852534831adSStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2853534831adSStefano Zampini   /* set values in constraint matrix */
2854534831adSStefano Zampini   for (i=0;i<total_counts;i++) {
2855534831adSStefano Zampini     j = aux_primal_permutation[i];
2856534831adSStefano Zampini     k = aux_primal_numbering[j];
2857534831adSStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,k,1.0,INSERT_VALUES);CHKERRQ(ierr);
2858534831adSStefano Zampini   }
2859534831adSStefano Zampini   for (i=n_vertices;i<local_primal_size;i++) {
2860534831adSStefano Zampini     if (!change_basis[i]) {
2861534831adSStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2862534831adSStefano 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);
2863534831adSStefano Zampini       total_counts++;
2864534831adSStefano Zampini     }
2865534831adSStefano Zampini   }
2866534831adSStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2867534831adSStefano Zampini   ierr = PetscFree(aux_primal_permutation);CHKERRQ(ierr);
2868534831adSStefano Zampini   /* assembling */
2869534831adSStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2870534831adSStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2871534831adSStefano Zampini 
2872534831adSStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->usechangeofbasis is FALSE */
2873534831adSStefano Zampini   if (pcbddc->usechangeofbasis) {
2874534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2875534831adSStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2876534831adSStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2877534831adSStefano Zampini     /* work arrays */
2878534831adSStefano Zampini     /* we need to reuse these arrays, so we free them */
2879534831adSStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
2880534831adSStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
2881534831adSStefano Zampini     ierr = PetscMalloc(pcis->n_B*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
2882534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
2883534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*sizeof(PetscScalar),&work);CHKERRQ(ierr);
2884534831adSStefano Zampini     ierr = PetscMalloc((nnsp_addone+nnsp_size)*sizeof(PetscBLASInt),&ipiv);CHKERRQ(ierr);
2885534831adSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2886534831adSStefano Zampini       nnz[i]=1;
2887534831adSStefano Zampini     }
2888534831adSStefano Zampini     /* Overestimated nonzeros per row */
2889534831adSStefano Zampini     k=1;
2890534831adSStefano Zampini     for (i=pcbddc->n_vertices;i<local_primal_size;i++) {
2891534831adSStefano Zampini       if (change_basis[i]) {
2892534831adSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2893534831adSStefano Zampini         if (k < size_of_constraint) {
2894534831adSStefano Zampini           k = size_of_constraint;
2895534831adSStefano Zampini         }
2896534831adSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
2897534831adSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2898534831adSStefano Zampini         }
2899534831adSStefano Zampini       }
2900534831adSStefano Zampini     }
2901534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2902534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2903534831adSStefano Zampini     /* Temporary array to store indices */
2904534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&is_indices);CHKERRQ(ierr);
2905534831adSStefano Zampini     /* Set initial identity in the matrix */
2906534831adSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2907534831adSStefano Zampini       ierr = MatSetValue(pcbddc->ChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2908534831adSStefano Zampini     }
2909534831adSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2910534831adSStefano Zampini     /* Change of basis matrix is evaluated as the FIRST APPROACH in */
2911534831adSStefano Zampini     /* Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (6.2.1) */
2912534831adSStefano Zampini     temp_constraints = 0;
291393dc3b60SStefano Zampini     if (pcbddc->n_vertices < local_primal_size) {
2914534831adSStefano Zampini       temp_start_ptr = temp_indices_to_constraint_B[temp_indices[pcbddc->n_vertices]];
291593dc3b60SStefano Zampini     }
2916534831adSStefano Zampini     for (i=pcbddc->n_vertices;i<local_primal_size;i++) {
2917534831adSStefano Zampini       if (change_basis[i]) {
2918534831adSStefano Zampini         compute_submatrix = PETSC_FALSE;
2919534831adSStefano Zampini         useksp = PETSC_FALSE;
2920534831adSStefano Zampini         if (temp_start_ptr == temp_indices_to_constraint_B[temp_indices[i]]) {
2921534831adSStefano Zampini           temp_constraints++;
292204eaf177SStefano Zampini           if (i == local_primal_size -1 ||  temp_start_ptr != temp_indices_to_constraint_B[temp_indices[i+1]]) {
2923534831adSStefano Zampini             compute_submatrix = PETSC_TRUE;
2924534831adSStefano Zampini           }
2925534831adSStefano Zampini         }
2926534831adSStefano Zampini         if (compute_submatrix) {
2927534831adSStefano Zampini           if (temp_constraints > 1 || pcbddc->use_nnsp_true) {
2928534831adSStefano Zampini             useksp = PETSC_TRUE;
2929534831adSStefano Zampini           }
2930534831adSStefano Zampini           size_of_constraint = temp_indices[i+1]-temp_indices[i];
2931534831adSStefano Zampini           if (useksp) { /* experimental */
2932534831adSStefano Zampini             ierr = MatCreate(PETSC_COMM_SELF,&temp_mat);CHKERRQ(ierr);
2933534831adSStefano Zampini             ierr = MatSetType(temp_mat,impMatType);CHKERRQ(ierr);
2934534831adSStefano Zampini             ierr = MatSetSizes(temp_mat,size_of_constraint,size_of_constraint,size_of_constraint,size_of_constraint);CHKERRQ(ierr);
2935534831adSStefano Zampini             ierr = MatSeqAIJSetPreallocation(temp_mat,size_of_constraint,PETSC_NULL);CHKERRQ(ierr);
2936534831adSStefano Zampini           }
2937534831adSStefano Zampini           /* First _size_of_constraint-temp_constraints_ columns */
2938534831adSStefano Zampini           dual_dofs = size_of_constraint-temp_constraints;
2939534831adSStefano Zampini           start_constraint = i+1-temp_constraints;
2940534831adSStefano Zampini           for (s=0;s<dual_dofs;s++) {
2941534831adSStefano Zampini             is_indices[0] = s;
2942534831adSStefano Zampini             for (j=0;j<temp_constraints;j++) {
2943534831adSStefano Zampini               for (k=0;k<temp_constraints;k++) {
2944534831adSStefano Zampini                 temp_basis[j*temp_constraints+k]=temp_quadrature_constraint[temp_indices[start_constraint+k]+s+j+1];
2945534831adSStefano Zampini               }
2946534831adSStefano Zampini               work[j]=-temp_quadrature_constraint[temp_indices[start_constraint+j]+s];
2947534831adSStefano Zampini               is_indices[j+1]=s+j+1;
2948534831adSStefano Zampini             }
2949534831adSStefano Zampini             Bt = temp_constraints;
2950534831adSStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2951534831adSStefano Zampini             LAPACKgesv_(&Bt,&Bone,temp_basis,&Bt,ipiv,work,&Bt,&lierr);
2952534831adSStefano Zampini             if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESV Lapack routine %d",(int)lierr);
2953534831adSStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2954534831adSStefano Zampini             j = temp_indices_to_constraint_B[temp_indices[start_constraint]+s];
2955534831adSStefano 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);
2956534831adSStefano Zampini             if (useksp) {
2957534831adSStefano Zampini               /* temp mat with transposed rows and columns */
2958534831adSStefano Zampini               ierr = MatSetValues(temp_mat,1,&s,temp_constraints,&is_indices[1],work,INSERT_VALUES);CHKERRQ(ierr);
2959534831adSStefano Zampini               ierr = MatSetValue(temp_mat,is_indices[0],is_indices[0],1.0,INSERT_VALUES);CHKERRQ(ierr);
2960534831adSStefano Zampini             }
2961534831adSStefano Zampini           }
2962534831adSStefano Zampini           if (useksp) {
2963534831adSStefano Zampini             /* last rows of temp_mat */
2964534831adSStefano Zampini             for (j=0;j<size_of_constraint;j++) {
2965534831adSStefano Zampini               is_indices[j] = j;
2966534831adSStefano Zampini             }
2967534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2968534831adSStefano Zampini               k = s + dual_dofs;
2969534831adSStefano Zampini               ierr = MatSetValues(temp_mat,1,&k,size_of_constraint,is_indices,&temp_quadrature_constraint[temp_indices[start_constraint+s]],INSERT_VALUES);CHKERRQ(ierr);
2970534831adSStefano Zampini             }
2971534831adSStefano Zampini             ierr = MatAssemblyBegin(temp_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2972534831adSStefano Zampini             ierr = MatAssemblyEnd(temp_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2973534831adSStefano Zampini             ierr = MatGetVecs(temp_mat,&temp_vec,PETSC_NULL);CHKERRQ(ierr);
2974534831adSStefano Zampini             ierr = KSPCreate(PETSC_COMM_SELF,&temp_ksp);CHKERRQ(ierr);
2975534831adSStefano Zampini             ierr = KSPSetOperators(temp_ksp,temp_mat,temp_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
2976534831adSStefano Zampini             ierr = KSPSetType(temp_ksp,KSPPREONLY);CHKERRQ(ierr);
2977ffe5efe1SStefano Zampini             ierr = KSPGetPC(temp_ksp,&temp_pc);CHKERRQ(ierr);
2978ffe5efe1SStefano Zampini             ierr = PCSetType(temp_pc,PCLU);CHKERRQ(ierr);
2979534831adSStefano Zampini             ierr = KSPSetUp(temp_ksp);CHKERRQ(ierr);
2980534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2981534831adSStefano Zampini               ierr = VecSet(temp_vec,0.0);CHKERRQ(ierr);
2982534831adSStefano Zampini               ierr = VecSetValue(temp_vec,s+dual_dofs,1.0,INSERT_VALUES);CHKERRQ(ierr);
2983534831adSStefano Zampini               ierr = VecAssemblyBegin(temp_vec);CHKERRQ(ierr);
2984534831adSStefano Zampini               ierr = VecAssemblyEnd(temp_vec);CHKERRQ(ierr);
2985534831adSStefano Zampini               ierr = KSPSolve(temp_ksp,temp_vec,temp_vec);CHKERRQ(ierr);
2986534831adSStefano Zampini               ierr = VecGetArray(temp_vec,&array_vector);CHKERRQ(ierr);
2987534831adSStefano Zampini               j = temp_indices_to_constraint_B[temp_indices[start_constraint+s]+size_of_constraint-s-1];
2988534831adSStefano Zampini               /* last columns of change of basis matrix associated to new primal dofs */
2989534831adSStefano 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);
2990534831adSStefano Zampini               ierr = VecRestoreArray(temp_vec,&array_vector);CHKERRQ(ierr);
2991534831adSStefano Zampini             }
2992534831adSStefano Zampini             ierr = MatDestroy(&temp_mat);CHKERRQ(ierr);
2993534831adSStefano Zampini             ierr = KSPDestroy(&temp_ksp);CHKERRQ(ierr);
2994534831adSStefano Zampini             ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2995534831adSStefano Zampini           } else {
2996534831adSStefano Zampini             /* last columns of change of basis matrix associated to new primal dofs */
2997534831adSStefano Zampini             for (s=0;s<temp_constraints;s++) {
2998534831adSStefano Zampini               j = temp_indices_to_constraint_B[temp_indices[start_constraint+s]+size_of_constraint-s-1];
2999534831adSStefano 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);
3000534831adSStefano Zampini             }
3001534831adSStefano Zampini           }
3002534831adSStefano Zampini           /* prepare for the next cycle */
3003534831adSStefano Zampini           temp_constraints = 0;
300404eaf177SStefano Zampini           if (i != local_primal_size -1) {
3005534831adSStefano Zampini             temp_start_ptr = temp_indices_to_constraint_B[temp_indices[i+1]];
3006534831adSStefano Zampini           }
3007534831adSStefano Zampini         }
3008534831adSStefano Zampini       }
300904eaf177SStefano Zampini     }
3010534831adSStefano Zampini     /* assembling */
3011534831adSStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3012534831adSStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3013534831adSStefano Zampini     ierr = PetscFree(ipiv);CHKERRQ(ierr);
3014534831adSStefano Zampini     ierr = PetscFree(is_indices);CHKERRQ(ierr);
3015534831adSStefano Zampini   }
30163b03a366Sstefano_zampini   /* free workspace no longer needed */
30173b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
30183b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
30193b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
30203b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
30213b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
30223b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
3023534831adSStefano Zampini   ierr = PetscFree(change_basis);CHKERRQ(ierr);
30243b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
3025534831adSStefano Zampini   ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
3026534831adSStefano Zampini   ierr = PetscFree(local_to_B);CHKERRQ(ierr);
30273b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
30283425bc38SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
30293425bc38SStefano Zampini   ierr = PetscFree(iwork);CHKERRQ(ierr);
30303425bc38SStefano Zampini   ierr = PetscFree(ifail);CHKERRQ(ierr);
30313425bc38SStefano Zampini   ierr = PetscFree(singular_vectors);CHKERRQ(ierr);
30323425bc38SStefano Zampini #endif
3033da1bb401SStefano Zampini   for (k=0;k<nnsp_size;k++) {
3034da1bb401SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
3035da1bb401SStefano Zampini   }
30363b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
30373b03a366Sstefano_zampini   PetscFunctionReturn(0);
30383b03a366Sstefano_zampini }
30393b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
30400c7d97c5SJed Brown #undef __FUNCT__
30410c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
304253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
30430c7d97c5SJed Brown {
30440c7d97c5SJed Brown   PetscErrorCode    ierr;
30450c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
30460c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
30470c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
3048534831adSStefano Zampini   Mat               change_mat_all;
30490c7d97c5SJed Brown   IS                is_R_local;
30500c7d97c5SJed Brown   IS                is_V_local;
30510c7d97c5SJed Brown   IS                is_C_local;
30520c7d97c5SJed Brown   IS                is_aux1;
30530c7d97c5SJed Brown   IS                is_aux2;
305419fd82e9SBarry Smith   VecType           impVecType;
305519fd82e9SBarry Smith   MatType           impMatType;
30560c7d97c5SJed Brown   PetscInt          n_R=0;
30570c7d97c5SJed Brown   PetscInt          n_D=0;
30580c7d97c5SJed Brown   PetscInt          n_B=0;
30590c7d97c5SJed Brown   PetscScalar       zero=0.0;
30600c7d97c5SJed Brown   PetscScalar       one=1.0;
30610c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
30620c7d97c5SJed Brown   PetscScalar*      array;
30630c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
30640c7d97c5SJed Brown   PetscInt          *idx_R_local;
30650c7d97c5SJed Brown   PetscInt          *idx_V_B;
30660c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
30670c7d97c5SJed Brown   PetscScalar       *constraints_errors;
30680c7d97c5SJed Brown   /* auxiliary indices */
3069534831adSStefano Zampini   PetscInt          i,j,k;
3070e269702eSStefano Zampini   /* for verbose output of bddc */
3071e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
3072e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
3073a0ba757dSStefano Zampini   /* for counting coarse dofs */
3074534831adSStefano Zampini   PetscInt          n_vertices,n_constraints;
30753b03a366Sstefano_zampini   PetscInt          size_of_constraint;
30763b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
30773b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
3078534831adSStefano Zampini   PetscInt          *vertices,*nnz,*is_indices,*temp_indices;
30790c7d97c5SJed Brown 
30800c7d97c5SJed Brown   PetscFunctionBegin;
30810c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
30820c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
3083534831adSStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
3084534831adSStefano Zampini   impMatType = MATSEQDENSE;
3085534831adSStefano Zampini   impVecType = VECSEQ;
3086da1bb401SStefano Zampini   /* get vertex indices from constraint matrix */
3087534831adSStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
3088534831adSStefano Zampini   n_vertices=0;
3089da1bb401SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
3090da1bb401SStefano Zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3091da1bb401SStefano Zampini     if (size_of_constraint == 1) {
3092534831adSStefano Zampini       vertices[n_vertices]=row_cmat_indices[0];
3093534831adSStefano Zampini       n_vertices++;
3094a0ba757dSStefano Zampini     }
3095da1bb401SStefano Zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3096a0ba757dSStefano Zampini   }
3097534831adSStefano Zampini   /* Set number of constraints */
3098534831adSStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
3099534831adSStefano Zampini 
3100534831adSStefano Zampini   /* vertices in boundary numbering */
3101534831adSStefano Zampini   if (n_vertices) {
3102534831adSStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
3103534831adSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3104534831adSStefano Zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
3105534831adSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3106534831adSStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3107534831adSStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3108534831adSStefano Zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
3109534831adSStefano Zampini     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3110534831adSStefano Zampini     for (i=0; i<n_vertices; i++) {
3111534831adSStefano Zampini       j=0;
3112534831adSStefano Zampini       while (array[j] != i) {j++;}
3113534831adSStefano Zampini       idx_V_B[i]=j;
3114534831adSStefano Zampini     }
3115534831adSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3116534831adSStefano Zampini   }
3117534831adSStefano Zampini 
3118534831adSStefano Zampini   /* transform local matrices if needed */
3119534831adSStefano Zampini   if (pcbddc->usechangeofbasis) {
3120534831adSStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
3121534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3122534831adSStefano Zampini     for (i=0;i<n_D;i++) {
3123534831adSStefano Zampini       nnz[is_indices[i]]=1;
3124534831adSStefano Zampini     }
3125534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3126534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3127534831adSStefano Zampini     k=1;
3128534831adSStefano Zampini     for (i=0;i<n_B;i++) {
3129534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
3130534831adSStefano Zampini       nnz[is_indices[i]]=j;
3131534831adSStefano Zampini       if (k < j) {
3132534831adSStefano Zampini         k = j;
3133534831adSStefano Zampini       }
3134534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
3135534831adSStefano Zampini     }
3136534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3137534831adSStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
3138534831adSStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
3139534831adSStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
3140534831adSStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
3141534831adSStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
3142534831adSStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
3143534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3144534831adSStefano Zampini     for (i=0;i<n_D;i++) {
3145534831adSStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3146534831adSStefano Zampini     }
3147534831adSStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3148534831adSStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3149534831adSStefano Zampini     for (i=0;i<n_B;i++) {
3150534831adSStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
3151534831adSStefano Zampini       for (k=0;k<j;k++) {
3152534831adSStefano Zampini         temp_indices[k]=is_indices[row_cmat_indices[k]];
3153534831adSStefano Zampini       }
3154534831adSStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
3155534831adSStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
3156534831adSStefano Zampini     }
3157534831adSStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3158534831adSStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3159534831adSStefano Zampini     ierr = MatPtAP(matis->A,change_mat_all,MAT_INITIAL_MATRIX,1.0,&pcbddc->local_mat);CHKERRQ(ierr);
3160534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
3161534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
3162534831adSStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
3163534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
3164534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
3165534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
3166534831adSStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
3167534831adSStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3168534831adSStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
3169534831adSStefano Zampini   } else {
3170534831adSStefano Zampini     /* without change of basis, the local matrix is unchanged */
3171534831adSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
3172534831adSStefano Zampini     pcbddc->local_mat = matis->A;
3173534831adSStefano Zampini   }
31740bdf917eSStefano Zampini   /* Change global null space passed in by the user if change of basis has been performed */
31750bdf917eSStefano Zampini   if (pcbddc->NullSpace && pcbddc->usechangeofbasis) {
31760bdf917eSStefano Zampini     ierr = PCBDDCAdaptNullSpace(pc);CHKERRQ(ierr);
31770bdf917eSStefano Zampini   }
3178a0ba757dSStefano Zampini 
31790c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
31800c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
31810c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
31823b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
31833b03a366Sstefano_zampini   ierr = PetscMalloc((pcis->n - n_vertices)*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
31840c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
31850c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3186e269702eSStefano Zampini   if (dbg_flag) {
31870c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
31880c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31890c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
31900c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
31913b03a366Sstefano_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);
3192534831adSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
31930c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31940c7d97c5SJed Brown   }
3195534831adSStefano Zampini 
31960c7d97c5SJed Brown   /* Allocate needed vectors */
3197534831adSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
31983972b0daSStefano Zampini   ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
31990c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
32000c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
32010c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
32020c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
3203d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
32040c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
32050c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
32060c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
32070c7d97c5SJed Brown 
32080c7d97c5SJed Brown   /* Creating some index sets needed  */
32090c7d97c5SJed Brown   /* For submatrices */
3210da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
32113b03a366Sstefano_zampini   if (n_vertices)    {
3212da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_OWN_POINTER,&is_V_local);CHKERRQ(ierr);
32133b03a366Sstefano_zampini   }
3214da1bb401SStefano Zampini   if (n_constraints) {
3215da1bb401SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
3216da1bb401SStefano Zampini   }
3217da1bb401SStefano Zampini 
32180c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
32190c7d97c5SJed Brown   {
32200c7d97c5SJed Brown     PetscInt   *aux_array1;
32210c7d97c5SJed Brown     PetscInt   *aux_array2;
32222e8d2280SStefano Zampini     PetscInt   *idx_I_local;
32230c7d97c5SJed Brown 
32243b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
32253b03a366Sstefano_zampini     ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
32260c7d97c5SJed Brown 
32272e8d2280SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
32280c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
32292e8d2280SStefano Zampini     for (i=0; i<n_D; i++) { array[idx_I_local[i]] = 0; }
32302e8d2280SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idx_I_local);CHKERRQ(ierr);
32312e8d2280SStefano Zampini     for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[j] = i; j++; } }
32320c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3233da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
32342e8d2280SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32352e8d2280SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32360c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
32372e8d2280SStefano Zampini     for (i=0, j=0; i<n_B; i++) { if (array[i] == one) { aux_array2[j] = i; j++; } }
32383828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
3239da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
32400c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
32410c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
32420c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
32430c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
32440c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
32450c7d97c5SJed Brown 
324629622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
32470c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
32480c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
32492e8d2280SStefano Zampini       for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == zero) { aux_array1[j] = i; j++; } }
32500c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3251da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
32520c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
32530c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
32540c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
32550c7d97c5SJed Brown     }
32560c7d97c5SJed Brown   }
32570c7d97c5SJed Brown 
32580c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
32590c7d97c5SJed Brown   {
32600c7d97c5SJed Brown     Mat  A_RR;
326153cdbc3dSStefano Zampini     PC   pc_temp;
32620c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
326353cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
326453cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
326553cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
326653cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
3267da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
32680c7d97c5SJed Brown     /* default */
326953cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
327053cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32710c7d97c5SJed Brown     /* Allow user's customization */
327253cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
3273950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
3274950d796eSStefano Zampini     if (!n_D) {
32752e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3276950d796eSStefano Zampini     }
327753cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
327853cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
32793972b0daSStefano Zampini     /* set ksp_D into pcis data */
32803972b0daSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
32813972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
32823972b0daSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
32830c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
3284534831adSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
328553cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
328653cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
328753cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
328853cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
3289da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
32900c7d97c5SJed Brown     /* default */
329153cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
329253cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
32930c7d97c5SJed Brown     /* Allow user's customization */
329453cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
3295950d796eSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero */
3296950d796eSStefano Zampini     if (!pcis->n) {
32972e8d2280SStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
3298950d796eSStefano Zampini     }
329953cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
330053cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
330129622bf0SStefano Zampini     /* check Dirichlet and Neumann solvers and adapt them is a nullspace correction is needed */
3302b76ba322SStefano Zampini     {
33030c7d97c5SJed Brown       Vec         temp_vec;
3304b76ba322SStefano Zampini       PetscReal   value;
3305b76ba322SStefano Zampini       PetscMPIInt use_exact,use_exact_reduced;
33060c7d97c5SJed Brown 
3307a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
3308a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
3309a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3310a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
3311a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
3312a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
331329622bf0SStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
3314b76ba322SStefano Zampini       use_exact = 1;
3315b76ba322SStefano Zampini       if (PetscAbsReal(value) > 1.e-4) {
3316b76ba322SStefano Zampini         use_exact = 0;
3317b76ba322SStefano Zampini       }
3318b76ba322SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,((PetscObject)pc)->comm);CHKERRQ(ierr);
3319b76ba322SStefano Zampini       pcbddc->use_exact_dirichlet = (PetscBool) use_exact_reduced;
3320b76ba322SStefano Zampini       if (dbg_flag) {
3321a0ba757dSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3322a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3323a0ba757dSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
3324a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
332529622bf0SStefano Zampini       }
332629622bf0SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->inexact_prec_type) {
332729622bf0SStefano Zampini         ierr = PCBDDCAdaptLocalProblem(pc,pcis->is_I_local);
332829622bf0SStefano Zampini       }
3329d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
3330d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
3331d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
3332d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
3333d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
3334d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
3335e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
333629622bf0SStefano Zampini       use_exact = 1;
333729622bf0SStefano Zampini       if (PetscAbsReal(value) > 1.e-4) {
333829622bf0SStefano Zampini         use_exact = 0;
333929622bf0SStefano Zampini       }
334029622bf0SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,((PetscObject)pc)->comm);CHKERRQ(ierr);
334129622bf0SStefano Zampini       if (dbg_flag) {
33420c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
3343d49ef151SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
33440c7d97c5SJed Brown       }
334529622bf0SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) {
334629622bf0SStefano Zampini         ierr = PCBDDCAdaptLocalProblem(pc,is_R_local);
334729622bf0SStefano Zampini       }
3348b76ba322SStefano Zampini     }
33490c7d97c5SJed Brown     /* free Neumann problem's matrix */
33500c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
33510c7d97c5SJed Brown   }
33520c7d97c5SJed Brown 
33530c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
33540c7d97c5SJed Brown   {
33550c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
33560bdf917eSStefano Zampini     Mat          M1;
33570c7d97c5SJed Brown     Mat          C_CR;
33583b03a366Sstefano_zampini     Mat          AUXMAT;
33590c7d97c5SJed Brown     Vec          vec1_C;
33600c7d97c5SJed Brown     Vec          vec2_C;
33610c7d97c5SJed Brown     Vec          vec1_V;
33620c7d97c5SJed Brown     Vec          vec2_V;
33630c7d97c5SJed Brown     PetscInt     *nnz;
33640c7d97c5SJed Brown     PetscInt     *auxindices;
336553cdbc3dSStefano Zampini     PetscInt     index;
33660c7d97c5SJed Brown     PetscScalar* array2;
33670c7d97c5SJed Brown     MatFactorInfo matinfo;
33680c7d97c5SJed Brown 
33690c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
33700c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
33710c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
33720c7d97c5SJed Brown     for (i=0;i<pcis->n;i++) {auxindices[i]=i;}
33730c7d97c5SJed Brown 
33740c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
33753b03a366Sstefano_zampini     if (n_vertices) {
33760c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
33773b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
33780c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
33790c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
33800c7d97c5SJed Brown     }
3381534831adSStefano Zampini     if (n_constraints) {
33820c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
3383534831adSStefano Zampini       ierr = VecSetSizes(vec1_C,n_constraints,n_constraints);CHKERRQ(ierr);
33840c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
33850c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
33860c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
33870c7d97c5SJed Brown     }
33880c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
33893b03a366Sstefano_zampini     if (n_constraints) {
33900c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
33913b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
33920c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
33933b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
33940c7d97c5SJed Brown 
339557a90decSStefano Zampini       /* Create Constraint matrix on R nodes: C_{CR}  */
339657a90decSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
339757a90decSStefano Zampini       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
339857a90decSStefano Zampini 
33990c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
34003b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
34013b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
34023b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
340357a90decSStefano Zampini         ierr = VecGetArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
340457a90decSStefano Zampini         ierr = MatGetRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
34053b03a366Sstefano_zampini         for (j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
340657a90decSStefano Zampini         ierr = MatRestoreRow(C_CR,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
340757a90decSStefano Zampini         ierr = VecRestoreArray(pcbddc->vec1_R,&array);CHKERRQ(ierr);
34083b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
340953cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
34103b03a366Sstefano_zampini         /* Set values */
34110c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
34123b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
34130c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
34140c7d97c5SJed Brown       }
34150c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34160c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34170c7d97c5SJed Brown 
34180c7d97c5SJed Brown       /* Assemble AUXMAT = (LUFactor)(-C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} */
34190c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
3420d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
34213b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
34220c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
34230c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
34240c7d97c5SJed Brown 
34253b03a366Sstefano_zampini       /* Assemble explicitly M1 = (C_{CR} A_{RR}^{-1} C^T_{CR})^{-1} needed in preproc  */
3426d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
34273b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
34280c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
34293b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
34303b03a366Sstefano_zampini       for (i=0;i<n_constraints;i++) {
34310c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
34320c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
34330c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
34340c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
34350c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
34360c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
34370c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
34383b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
34390c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
34400c7d97c5SJed Brown       }
34410c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34420c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34430c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
34440c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
34450c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
34460c7d97c5SJed Brown 
34470c7d97c5SJed Brown     }
34480c7d97c5SJed Brown 
34490c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
34503b03a366Sstefano_zampini     if (n_vertices) {
3451534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3452534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3453534831adSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
34540c7d97c5SJed Brown     }
34550c7d97c5SJed Brown 
34560c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
3457d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
34580c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
34590c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
34603b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
346129622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
3462d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
34630c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
34640c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
34653b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
34660c7d97c5SJed Brown     }
34670c7d97c5SJed Brown 
3468e269702eSStefano Zampini     if (dbg_flag) {
34690c7d97c5SJed Brown       ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
34700c7d97c5SJed Brown       ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
34710c7d97c5SJed Brown     }
34723b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
34730c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
34740c7d97c5SJed Brown 
34750c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
34763b03a366Sstefano_zampini     for (i=0;i<n_vertices;i++) {
34770c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
34780c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
34790c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
34800c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
34810c7d97c5SJed Brown       /* solution of saddle point problem */
34820bdf917eSStefano Zampini       ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
34830bdf917eSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
34840c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
34853b03a366Sstefano_zampini       if (n_constraints) {
34860c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
34870c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
34880c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
34890c7d97c5SJed Brown       }
34900c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
34910c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
34920c7d97c5SJed Brown 
34930c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
34940c7d97c5SJed Brown       /* coarse basis functions */
34950c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
34960c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
34970c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
34980c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
34993b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
35000c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
35010c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
350229622bf0SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag) {
35030c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35040c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35050c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35063b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
35070c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35080c7d97c5SJed Brown       }
35090c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
35100c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
3511da1bb401SStefano Zampini       for (j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } /* WARNING -> column major ordering */
35120c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35133b03a366Sstefano_zampini       if (n_constraints) {
35140c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
3515da1bb401SStefano 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 */
35160c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35170c7d97c5SJed Brown       }
35180c7d97c5SJed Brown 
3519e269702eSStefano Zampini       if (dbg_flag) {
35200c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
3521d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
35220c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35230c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35240c7d97c5SJed Brown         for (j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
35253b03a366Sstefano_zampini         array[ vertices[i] ] = one;
35260c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35270c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35280c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
3529d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
35300c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
35310c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
35323b03a366Sstefano_zampini         for (j=0;j<n_vertices;j++) { array2[j]=array[j]; }
35330c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35343b03a366Sstefano_zampini         if (n_constraints) {
35350c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
35363b03a366Sstefano_zampini           for (j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
35370c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35380c7d97c5SJed Brown         }
35390c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
35400c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
35410c7d97c5SJed Brown         /* check saddle point solution */
3542534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
35433b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
35443b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
35453b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
35460c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35473b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
35480c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
35493b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
35500c7d97c5SJed Brown       }
35510c7d97c5SJed Brown     }
35520c7d97c5SJed Brown 
35533b03a366Sstefano_zampini     for (i=0;i<n_constraints;i++) {
3554d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
35550c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
35560c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
35570c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
35580c7d97c5SJed Brown       /* solution of saddle point problem */
35590c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
35600c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
35610c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
35623b03a366Sstefano_zampini       if (n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
35630c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
35640c7d97c5SJed Brown       /* coarse basis functions */
35653b03a366Sstefano_zampini       index=i+n_vertices;
35660c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
35670c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35680c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35690c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
357053cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
35710c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
357229622bf0SStefano Zampini       if (pcbddc->inexact_prec_type || dbg_flag) {
35730c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35740c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35750c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
357653cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
35770c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
35780c7d97c5SJed Brown       }
35790c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
35803b03a366Sstefano_zampini       if (n_vertices) {
35810c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
3582da1bb401SStefano Zampini         for (j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} /* WARNING -> column major ordering */
35830c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
35840c7d97c5SJed Brown       }
35850c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
3586da1bb401SStefano 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 */
35870c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
35880c7d97c5SJed Brown 
3589e269702eSStefano Zampini       if (dbg_flag) {
35900c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
359153cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
35920c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35930c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35940c7d97c5SJed Brown         for (j=0;j<n_R;j++) { array[ idx_R_local[j] ] = array2[j]; }
35950c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
35960c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
35970c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
359853cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
35990c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
36003b03a366Sstefano_zampini         if (n_vertices) {
36010c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
36023b03a366Sstefano_zampini           for (j=0;j<n_vertices;j++) {array2[j]=-array[j];}
36030c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
36040c7d97c5SJed Brown         }
36050c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
36063b03a366Sstefano_zampini         for (j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
36070c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
36080c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
36093972b0daSStefano Zampini         /* check saddle point solution */
3610534831adSStefano Zampini         ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
36113b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
361253cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
36133b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
36140c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
361553cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
36160c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
361753cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
36180c7d97c5SJed Brown       }
36190c7d97c5SJed Brown     }
36200c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36210c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
362229622bf0SStefano Zampini     if (pcbddc->inexact_prec_type || dbg_flag) {
36230c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36240c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36250c7d97c5SJed Brown     }
36260c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
36270c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
36289d2fce94SStefano Zampini     if (dbg_flag) {
36290c7d97c5SJed Brown       Mat         coarse_sub_mat;
36300c7d97c5SJed Brown       Mat         TM1,TM2,TM3,TM4;
36310c7d97c5SJed Brown       Mat         coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
363219fd82e9SBarry Smith       MatType     checkmattype=MATSEQAIJ;
36330c7d97c5SJed Brown       PetscScalar value;
36340c7d97c5SJed Brown 
3635c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
3636c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
3637c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
3638c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
3639c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
3640c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
3641c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
3642c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
36430c7d97c5SJed Brown 
36440c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
36450c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
36460c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
364753cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
364853cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
364953cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
3650c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
365153cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
365253cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
3653c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
365453cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
365553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365853cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
365953cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
36600c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
36610c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
36620c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
36630c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
366453cdbc3dSStefano 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); }
36650c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
366653cdbc3dSStefano 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); }
36670c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
366853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
366953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
367053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
367153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
367253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
367353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
367453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
367553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
367653cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
367753cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
367853cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
36790c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
36800c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
36810c7d97c5SJed Brown     }
36820c7d97c5SJed Brown     /* free memory */
36833b03a366Sstefano_zampini     if (n_vertices) {
36840c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
36850c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
36860c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
36870c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
36880c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
36890c7d97c5SJed Brown     }
3690534831adSStefano Zampini     if (n_constraints) {
36910c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
36920c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
36930c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
36940c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
36950c7d97c5SJed Brown     }
3696a929c220SStefano Zampini     ierr = PetscFree(auxindices);CHKERRQ(ierr);
3697a929c220SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
3698a929c220SStefano Zampini     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
3699a929c220SStefano Zampini     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
3700a929c220SStefano Zampini     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
37010c7d97c5SJed Brown   }
37020c7d97c5SJed Brown   /* free memory */
37033b03a366Sstefano_zampini   if (n_vertices) {
37040c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
37050c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
37060c7d97c5SJed Brown   }
37070c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
37080c7d97c5SJed Brown 
37090c7d97c5SJed Brown   PetscFunctionReturn(0);
37100c7d97c5SJed Brown }
37110c7d97c5SJed Brown 
37120c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
37130c7d97c5SJed Brown 
37140c7d97c5SJed Brown #undef __FUNCT__
37150c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
371653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
37170c7d97c5SJed Brown {
37180c7d97c5SJed Brown   Mat_IS                 *matis    = (Mat_IS*)pc->pmat->data;
37190c7d97c5SJed Brown   PC_BDDC                *pcbddc   = (PC_BDDC*)pc->data;
37200c7d97c5SJed Brown   PC_IS                  *pcis     = (PC_IS*)pc->data;
37210c7d97c5SJed Brown   MPI_Comm               prec_comm = ((PetscObject)pc)->comm;
37220c7d97c5SJed Brown   MPI_Comm               coarse_comm;
37230c7d97c5SJed Brown 
37240c7d97c5SJed Brown   /* common to all choiches */
37250c7d97c5SJed Brown   PetscScalar            *temp_coarse_mat_vals;
37260c7d97c5SJed Brown   PetscScalar            *ins_coarse_mat_vals;
37270c7d97c5SJed Brown   PetscInt               *ins_local_primal_indices;
37280c7d97c5SJed Brown   PetscMPIInt            *localsizes2,*localdispl2;
37290c7d97c5SJed Brown   PetscMPIInt            size_prec_comm;
37300c7d97c5SJed Brown   PetscMPIInt            rank_prec_comm;
37310c7d97c5SJed Brown   PetscMPIInt            active_rank=MPI_PROC_NULL;
37320c7d97c5SJed Brown   PetscMPIInt            master_proc=0;
37330c7d97c5SJed Brown   PetscInt               ins_local_primal_size;
37340c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
37350c7d97c5SJed Brown   PetscMPIInt            *ranks_recv;
37360c7d97c5SJed Brown   PetscMPIInt            count_recv=0;
37370c7d97c5SJed Brown   PetscMPIInt            rank_coarse_proc_send_to;
37380c7d97c5SJed Brown   PetscMPIInt            coarse_color = MPI_UNDEFINED;
37390c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
37400c7d97c5SJed Brown   /* some other variables */
37410c7d97c5SJed Brown   PetscErrorCode         ierr;
374219fd82e9SBarry Smith   MatType                coarse_mat_type;
374319fd82e9SBarry Smith   PCType                 coarse_pc_type;
374419fd82e9SBarry Smith   KSPType                coarse_ksp_type;
374553cdbc3dSStefano Zampini   PC                     pc_temp;
37464fad6a16SStefano Zampini   PetscInt               i,j,k;
37473b03a366Sstefano_zampini   PetscInt               max_it_coarse_ksp=1;  /* don't increase this value */
3748e269702eSStefano Zampini   /* verbose output viewer */
3749e269702eSStefano Zampini   PetscViewer            viewer=pcbddc->dbg_viewer;
3750e269702eSStefano Zampini   PetscBool              dbg_flag=pcbddc->dbg_flag;
3751142dfd88SStefano Zampini 
3752ea7e1babSStefano Zampini   PetscInt               offset,offset2;
3753a929c220SStefano Zampini   PetscMPIInt            im_active,active_procs;
3754523858cfSStefano Zampini   PetscInt               *dnz,*onz;
3755142dfd88SStefano Zampini 
3756142dfd88SStefano Zampini   PetscBool              setsym,issym=PETSC_FALSE;
37570c7d97c5SJed Brown 
37580c7d97c5SJed Brown   PetscFunctionBegin;
37590c7d97c5SJed Brown   ins_local_primal_indices = 0;
37600c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
37610c7d97c5SJed Brown   localsizes2              = 0;
37620c7d97c5SJed Brown   localdispl2              = 0;
37630c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
37640c7d97c5SJed Brown   coarse_ISLG              = 0;
37650c7d97c5SJed Brown 
376653cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
376753cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
3768142dfd88SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
3769142dfd88SStefano Zampini 
3770beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
3771beed3852SStefano Zampini   {
3772ef028eecSStefano Zampini     PetscInt     *auxlocal_primal;
3773da1bb401SStefano Zampini     PetscInt     *row_cmat_indices;
37742e8d2280SStefano Zampini     PetscInt     *aux_ordering;
37752e8d2280SStefano Zampini     PetscInt     *row_cmat_global_indices;
3776ef028eecSStefano Zampini     PetscInt     *dof_sizes,*dof_displs;
37773b03a366Sstefano_zampini     PetscInt     size_of_constraint;
37782e8d2280SStefano Zampini     PetscBool    *array_bool;
3779ef028eecSStefano Zampini     PetscBool    first_found;
3780ef028eecSStefano Zampini     PetscInt     first_index,old_index,s;
3781ef028eecSStefano Zampini     PetscMPIInt  mpi_local_primal_size;
3782ef028eecSStefano Zampini     PetscScalar  coarsesum,*array;
3783ef028eecSStefano Zampini 
3784ef028eecSStefano Zampini     mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
3785beed3852SStefano Zampini 
3786beed3852SStefano Zampini     /* Construct needed data structures for message passing */
3787ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
3788ffe5efe1SStefano Zampini     j = 0;
3789142dfd88SStefano Zampini     if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3790ffe5efe1SStefano Zampini       j = size_prec_comm;
3791ffe5efe1SStefano Zampini     }
3792ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
3793ffe5efe1SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
3794beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
3795142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == REPLICATED_BDDC || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
37965619798eSStefano Zampini       ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
3797ffe5efe1SStefano Zampini     } else {
3798ffe5efe1SStefano Zampini       ierr = MPI_Gather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3799ffe5efe1SStefano Zampini     }
3800beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
3801ffe5efe1SStefano Zampini     for (i=0; i<j; i++) {
3802beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
3803beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
3804beed3852SStefano Zampini     }
3805beed3852SStefano Zampini 
3806da1bb401SStefano Zampini     /* First let's count coarse dofs.
3807beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
3808beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
3809beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
3810ef028eecSStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
38112e8d2280SStefano Zampini     j = 0;
38122e8d2280SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
38132e8d2280SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
38142e8d2280SStefano Zampini       if (j < size_of_constraint) {
38152e8d2280SStefano Zampini         j = size_of_constraint;
38162e8d2280SStefano Zampini       }
38172e8d2280SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
38182e8d2280SStefano Zampini     }
38192e8d2280SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&aux_ordering);CHKERRQ(ierr);
38202e8d2280SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&row_cmat_global_indices);CHKERRQ(ierr);
38212e8d2280SStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscBool),&array_bool);CHKERRQ(ierr);
38222e8d2280SStefano Zampini     for (i=0;i<pcis->n;i++) {
38232e8d2280SStefano Zampini       array_bool[i] = PETSC_FALSE;
38242e8d2280SStefano Zampini     }
3825da1bb401SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3826da1bb401SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
38273b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
38282e8d2280SStefano Zampini         aux_ordering[j] = j;
38292e8d2280SStefano Zampini       }
38302e8d2280SStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
38312e8d2280SStefano Zampini       ierr = PetscSortIntWithPermutation(size_of_constraint,row_cmat_global_indices,aux_ordering);CHKERRQ(ierr);
38322e8d2280SStefano Zampini       for (j=0; j<size_of_constraint; j++) {
38332e8d2280SStefano Zampini         k = row_cmat_indices[aux_ordering[j]];
38342e8d2280SStefano Zampini         if (!array_bool[k]) {
38352e8d2280SStefano Zampini           array_bool[k] = PETSC_TRUE;
3836da1bb401SStefano Zampini           auxlocal_primal[i] = k;
3837beed3852SStefano Zampini           break;
3838beed3852SStefano Zampini         }
3839beed3852SStefano Zampini       }
3840da1bb401SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
3841beed3852SStefano Zampini     }
38422e8d2280SStefano Zampini     ierr = PetscFree(aux_ordering);CHKERRQ(ierr);
3843ef028eecSStefano Zampini     ierr = PetscFree(array_bool);CHKERRQ(ierr);
3844ef028eecSStefano Zampini     ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
38452e8d2280SStefano Zampini 
3846ef028eecSStefano Zampini     /* Compute number of coarse dofs */
3847ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
3848ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3849ef028eecSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3850ef028eecSStefano Zampini       array[auxlocal_primal[i]]=1.0;
3851ef028eecSStefano Zampini     }
3852ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3853ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3854ef028eecSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3855ef028eecSStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3856ef028eecSStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
3857ef028eecSStefano Zampini     pcbddc->coarse_size = (PetscInt)coarsesum;
3858ef028eecSStefano Zampini 
3859ef028eecSStefano Zampini     /* Fill pcis->vec1_global with cumulative function for global numbering */
3860ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_global,&array);CHKERRQ(ierr);
3861ef028eecSStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&s);CHKERRQ(ierr);
3862ef028eecSStefano Zampini     k = 0;
3863ef028eecSStefano Zampini     first_index = -1;
3864ef028eecSStefano Zampini     first_found = PETSC_FALSE;
3865ef028eecSStefano Zampini     for (i=0;i<s;i++) {
3866ef028eecSStefano Zampini       if (!first_found && array[i] > 0.0) {
3867ef028eecSStefano Zampini         first_found = PETSC_TRUE;
3868ef028eecSStefano Zampini         first_index = i;
3869ef028eecSStefano Zampini       }
3870ef028eecSStefano Zampini       k += (PetscInt)array[i];
3871ef028eecSStefano Zampini     }
3872ef028eecSStefano Zampini     j = (!rank_prec_comm ? size_prec_comm : 0);
3873ef028eecSStefano Zampini     ierr = PetscMalloc(j*sizeof(*dof_sizes),&dof_sizes);CHKERRQ(ierr);
3874ef028eecSStefano Zampini     ierr = PetscMalloc(j*sizeof(*dof_displs),&dof_displs);CHKERRQ(ierr);
3875ef028eecSStefano Zampini     ierr = MPI_Gather(&k,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3876ef028eecSStefano Zampini     if (!rank_prec_comm) {
3877ef028eecSStefano Zampini       dof_displs[0]=0;
3878ef028eecSStefano Zampini       for (i=1;i<size_prec_comm;i++) {
3879ef028eecSStefano Zampini         dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
3880ef028eecSStefano Zampini       }
3881ef028eecSStefano Zampini     }
3882ef028eecSStefano Zampini     ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&k,1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
3883ef028eecSStefano Zampini     if (first_found) {
3884ef028eecSStefano Zampini       array[first_index] += k;
3885ef028eecSStefano Zampini       old_index = first_index;
3886ef028eecSStefano Zampini       for (i=first_index+1;i<s;i++) {
3887ef028eecSStefano Zampini         if (array[i] > 0.0) {
3888ef028eecSStefano Zampini           array[i] += array[old_index];
3889ef028eecSStefano Zampini           old_index = i;
3890ef028eecSStefano Zampini         }
3891ef028eecSStefano Zampini       }
3892ef028eecSStefano Zampini     }
3893ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_global,&array);CHKERRQ(ierr);
3894ef028eecSStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
3895ef028eecSStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3896ef028eecSStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3897ef028eecSStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3898ef028eecSStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3899ef028eecSStefano Zampini       pcbddc->local_primal_indices[i] = (PetscInt)array[auxlocal_primal[i]]-1;
3900ef028eecSStefano Zampini     }
3901ef028eecSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3902ef028eecSStefano Zampini     ierr = PetscFree(dof_displs);CHKERRQ(ierr);
3903ef028eecSStefano Zampini     ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
3904ef028eecSStefano Zampini 
3905ef028eecSStefano Zampini     if (dbg_flag) {
39062e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39072e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
39082e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse indices\n");CHKERRQ(ierr);
39092e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
39102e8d2280SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3911ef028eecSStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
3912ef028eecSStefano Zampini         array[auxlocal_primal[i]]=1.0;
39132e8d2280SStefano Zampini       }
3914beed3852SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39152e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3916da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3917da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3918da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3919da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3920da1bb401SStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39212e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
39222e8d2280SStefano Zampini         if (array[i] == 1.0) {
39232e8d2280SStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,1,&i,&j);CHKERRQ(ierr);
39242e8d2280SStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d: WRONG COARSE INDEX %d (local %d)\n",PetscGlobalRank,j,i);CHKERRQ(ierr);
39252e8d2280SStefano Zampini         }
39262e8d2280SStefano Zampini       }
39272e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39282e8d2280SStefano Zampini       for (i=0;i<pcis->n;i++) {
39292e8d2280SStefano Zampini         if (array[i] > 0.0) {
39302e8d2280SStefano Zampini           array[i] = 1.0/array[i];
39312e8d2280SStefano Zampini         }
39322e8d2280SStefano Zampini       }
3933da1bb401SStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
39342e8d2280SStefano Zampini       ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3935da1bb401SStefano Zampini       ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3936da1bb401SStefano Zampini       ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3937da1bb401SStefano Zampini       ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
39382e8d2280SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem SHOULD be %lf\n",coarsesum);CHKERRQ(ierr);
39392e8d2280SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39402e8d2280SStefano Zampini     }
3941142dfd88SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
39420bdf917eSStefano Zampini   }
39430bdf917eSStefano Zampini 
39442e8d2280SStefano Zampini   if (dbg_flag) {
39457cf533a6SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem is %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
39462e8d2280SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39472e8d2280SStefano Zampini   }
39482e8d2280SStefano Zampini 
3949a929c220SStefano Zampini   im_active = 0;
39500bdf917eSStefano Zampini   if (pcis->n) { im_active = 1; }
3951a929c220SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
39520bdf917eSStefano Zampini 
39530bdf917eSStefano Zampini   /* adapt coarse problem type */
39544fad6a16SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
39554fad6a16SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
3956a929c220SStefano Zampini       if ((active_procs/pcbddc->coarsening_ratio) < 2) {
39570bdf917eSStefano Zampini         if (dbg_flag) {
3958a929c220SStefano 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);
39590bdf917eSStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39600bdf917eSStefano Zampini         }
39610bdf917eSStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
3962142dfd88SStefano Zampini       }
39634fad6a16SStefano Zampini     } else {
39644fad6a16SStefano Zampini       if (dbg_flag) {
3965a929c220SStefano 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);
39664fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
39674fad6a16SStefano Zampini       }
39684fad6a16SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
39694fad6a16SStefano Zampini     }
39704fad6a16SStefano Zampini   }
3971beed3852SStefano Zampini 
39720c7d97c5SJed Brown   switch (pcbddc->coarse_problem_type) {
39730c7d97c5SJed Brown 
3974da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
39750c7d97c5SJed Brown     {
39760c7d97c5SJed Brown       /* we need additional variables */
39770c7d97c5SJed Brown       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
39780c7d97c5SJed Brown       MetisInt    *metis_coarse_subdivision;
39790c7d97c5SJed Brown       MetisInt    options[METIS_NOPTIONS];
39800c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
39810c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
39820c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
39830c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
39840c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
39850c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
39860c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
39870c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
39880c7d97c5SJed Brown       MetisInt    *faces_adjncy;
39890c7d97c5SJed Brown       MetisInt    *faces_xadj;
39900c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
39910c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
39920c7d97c5SJed Brown       PetscInt    *array_int;
39930c7d97c5SJed Brown       PetscMPIInt my_faces=0;
39940c7d97c5SJed Brown       PetscMPIInt total_faces=0;
39953828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
39960c7d97c5SJed Brown 
39970c7d97c5SJed Brown       /* define some quantities */
39980c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
39990c7d97c5SJed Brown       coarse_mat_type = MATIS;
40000c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
4001142dfd88SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
40020c7d97c5SJed Brown 
40030c7d97c5SJed Brown       /* details of coarse decomposition */
4004a929c220SStefano Zampini       n_subdomains = active_procs;
40050c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
4006a929c220SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
40073828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
40083828260eSStefano Zampini 
4009a929c220SStefano Zampini #if 0
4010a929c220SStefano Zampini       PetscMPIInt     *old_ranks;
4011a929c220SStefano Zampini       PetscInt        *new_ranks,*jj,*ii;
4012a929c220SStefano Zampini       MatPartitioning mat_part;
4013a929c220SStefano Zampini       IS              coarse_new_decomposition,is_numbering;
4014a929c220SStefano Zampini       PetscViewer     viewer_test;
4015a929c220SStefano Zampini       MPI_Comm        test_coarse_comm;
4016a929c220SStefano Zampini       PetscMPIInt     test_coarse_color;
4017a929c220SStefano Zampini       Mat             mat_adj;
4018a929c220SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
4019a929c220SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
4020a929c220SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
4021a929c220SStefano Zampini       test_coarse_color = (im_active ? 0 : MPI_UNDEFINED);
4022a929c220SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
4023a929c220SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
4024a929c220SStefano Zampini       if (im_active) {
4025a929c220SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
4026a929c220SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
4027a929c220SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
4028a929c220SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
4029a929c220SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
4030a929c220SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
4031a929c220SStefano Zampini           new_ranks[i] = -1;
4032a929c220SStefano Zampini         }
4033a929c220SStefano Zampini         for (i=0;i<n_subdomains;i++) {
4034a929c220SStefano Zampini           new_ranks[old_ranks[i]] = i;
4035a929c220SStefano Zampini         }
4036a929c220SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
4037a929c220SStefano Zampini         k = pcis->n_neigh-1;
4038a929c220SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
4039a929c220SStefano Zampini         ii[0]=0;
4040a929c220SStefano Zampini         ii[1]=k;
4041a929c220SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
4042a929c220SStefano Zampini         for (i=0;i<k;i++) {
4043a929c220SStefano Zampini           jj[i]=new_ranks[pcis->neigh[i+1]];
4044a929c220SStefano Zampini         }
4045a929c220SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
4046a929c220SStefano Zampini         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,PETSC_NULL,&mat_adj);CHKERRQ(ierr);
4047a929c220SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
4048a929c220SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
4049a929c220SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
4050a929c220SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
4051a929c220SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
4052a929c220SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
4053a929c220SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
4054a929c220SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
4055a929c220SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
4056a929c220SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
4057a929c220SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
4058a929c220SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
4059a929c220SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
4060a929c220SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
4061a929c220SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
4062a929c220SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
4063a929c220SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
4064a929c220SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
4065a929c220SStefano Zampini       }
4066a929c220SStefano Zampini #endif
4067a929c220SStefano Zampini 
40684fad6a16SStefano Zampini       /* build CSR graph of subdomains' connectivity */
40690c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
40703828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
40710c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {/* i=1 so I don't count myself -> faces nodes counts to 1 */
40720c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40730c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
40740c7d97c5SJed Brown         }
40750c7d97c5SJed Brown       }
40760c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {
40770c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40787cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0) {
40790c7d97c5SJed Brown             my_faces++;
40800c7d97c5SJed Brown             break;
40810c7d97c5SJed Brown           }
40820c7d97c5SJed Brown         }
40830c7d97c5SJed Brown       }
40840c7d97c5SJed Brown 
408553cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
40860c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
40870c7d97c5SJed Brown       my_faces=0;
40880c7d97c5SJed Brown       for (i=1;i<pcis->n_neigh;i++) {
40890c7d97c5SJed Brown         for (j=0;j<pcis->n_shared[i];j++) {
40907cf533a6SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0) {
40910c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
40920c7d97c5SJed Brown             my_faces++;
40930c7d97c5SJed Brown             break;
40940c7d97c5SJed Brown           }
40950c7d97c5SJed Brown         }
40960c7d97c5SJed Brown       }
40970c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
40980c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
40990c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
41000c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
41010c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
41020c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
41030c7d97c5SJed Brown       }
410453cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
41050c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41060c7d97c5SJed Brown         faces_xadj[0]=0;
41070c7d97c5SJed Brown         faces_displacements[0]=0;
41080c7d97c5SJed Brown         j=0;
41090c7d97c5SJed Brown         for (i=1;i<size_prec_comm+1;i++) {
41100c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
41110c7d97c5SJed Brown           if (number_of_faces[i-1]) {
41120c7d97c5SJed Brown             j++;
41130c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
41140c7d97c5SJed Brown           }
41150c7d97c5SJed Brown         }
41160c7d97c5SJed Brown       }
411753cdbc3dSStefano 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);
41180c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
41190c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
41200c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41213828260eSStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
41220c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
41230c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
41240c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
41250c7d97c5SJed Brown       }
41260c7d97c5SJed Brown 
41270c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
41283828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
41290c7d97c5SJed Brown         ncon=1;
41300c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
41310c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
41320c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
41330c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
41340c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
41350c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
41360c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
41374fad6a16SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
41383828260eSStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
41393828260eSStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
41403828260eSStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
41410c7d97c5SJed Brown             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
4142142dfd88SStefano 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);
41433828260eSStefano Zampini           } else {
41443828260eSStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
4145142dfd88SStefano 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);
41463828260eSStefano Zampini           }
41474fad6a16SStefano Zampini         } else {
41484fad6a16SStefano Zampini           for (i=0;i<n_subdomains;i++) {
41494fad6a16SStefano Zampini             metis_coarse_subdivision[i]=i;
41504fad6a16SStefano Zampini           }
41514fad6a16SStefano Zampini         }
41520c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
41530c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
41540bdf917eSStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
41550c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
41560bdf917eSStefano Zampini         for (i=0;i<size_prec_comm;i++) { coarse_subdivision[i]=MPI_PROC_NULL; }
41570bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++)   { coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]); }
41580c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
41590c7d97c5SJed Brown       }
41600c7d97c5SJed Brown 
41610c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
41620c7d97c5SJed Brown       if (!(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts) {
4163da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
4164da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
41650c7d97c5SJed Brown       }
4166da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
4167da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
416853cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
41690c7d97c5SJed Brown 
41700c7d97c5SJed Brown       if (coarse_color == 0) {
417153cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
417253cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
41730c7d97c5SJed Brown       } else {
41740c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
41750c7d97c5SJed Brown       }
41760c7d97c5SJed Brown 
41777cf533a6SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
41780c7d97c5SJed Brown       if (rank_coarse_comm == master_proc) {
41790c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
41800bdf917eSStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
41810bdf917eSStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
41820c7d97c5SJed Brown         /* some initializations */
41830c7d97c5SJed Brown         displacements_recv[0]=0;
41840bdf917eSStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
41850c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
41860bdf917eSStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
41870bdf917eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
41880bdf917eSStefano Zampini             if (coarse_subdivision[i]==j) {
41890c7d97c5SJed Brown               total_count_recv[j]++;
41900bdf917eSStefano Zampini             }
41910bdf917eSStefano Zampini           }
41920bdf917eSStefano Zampini         }
41930c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
41940bdf917eSStefano Zampini         for (i=1;i<size_coarse_comm;i++) { displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1]; }
41950c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
41960c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
41970c7d97c5SJed Brown         for (j=0;j<size_coarse_comm;j++) {
41983828260eSStefano Zampini           for (i=0;i<size_prec_comm;i++) {
41990c7d97c5SJed Brown             if (coarse_subdivision[i]==j) {
42000c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
42013828260eSStefano Zampini               total_count_recv[j]+=1;
42020c7d97c5SJed Brown             }
42030c7d97c5SJed Brown           }
42040c7d97c5SJed Brown         }
4205da1bb401SStefano Zampini         /* for (j=0;j<size_coarse_comm;j++) {
42063828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
42073828260eSStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
42083828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
42093828260eSStefano Zampini           }
42103828260eSStefano Zampini           printf("\n");
4211da1bb401SStefano Zampini         } */
42120c7d97c5SJed Brown 
42130c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
42140bdf917eSStefano Zampini         for (i=0;i<n_subdomains;i++) {
42150bdf917eSStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
42160bdf917eSStefano Zampini         }
4217da1bb401SStefano Zampini         /* printf("coarse_subdivision in old end new ranks\n");
42180c7d97c5SJed Brown         for (i=0;i<size_prec_comm;i++)
42193828260eSStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
42203828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
42213828260eSStefano Zampini           } else {
42223828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
42233828260eSStefano Zampini           }
4224da1bb401SStefano Zampini         printf("\n"); */
42250c7d97c5SJed Brown       }
42260c7d97c5SJed Brown 
42270c7d97c5SJed Brown       /* Scatter new decomposition for send details */
422853cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
42290c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
42300c7d97c5SJed Brown       if (coarse_color == 0) {
423153cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
42320c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
423353cdbc3dSStefano 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);
42340c7d97c5SJed Brown       }
42350c7d97c5SJed Brown 
4236da1bb401SStefano Zampini       /* printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
4237da1bb401SStefano Zampini       if (coarse_color == 0) {
4238da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
4239da1bb401SStefano Zampini         for (i=0;i<count_recv;i++)
4240da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
4241da1bb401SStefano Zampini         printf("\n");
4242da1bb401SStefano Zampini       } */
42430c7d97c5SJed Brown 
42440c7d97c5SJed Brown       if (rank_prec_comm == master_proc) {
42450bdf917eSStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
4246da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
42470bdf917eSStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
42480c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
42490c7d97c5SJed Brown       }
42500c7d97c5SJed Brown       break;
42510c7d97c5SJed Brown     }
42520c7d97c5SJed Brown 
42530c7d97c5SJed Brown     case(REPLICATED_BDDC):
42540c7d97c5SJed Brown 
42550c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
42560c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
42570c7d97c5SJed Brown       coarse_pc_type  = PCLU;
425853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42590c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
42600c7d97c5SJed Brown       active_rank = rank_prec_comm;
42610c7d97c5SJed Brown       break;
42620c7d97c5SJed Brown 
42630c7d97c5SJed Brown     case(PARALLEL_BDDC):
42640c7d97c5SJed Brown 
42650c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
42660c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
42670c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
426853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42690c7d97c5SJed Brown       coarse_comm = prec_comm;
42700c7d97c5SJed Brown       active_rank = rank_prec_comm;
42710c7d97c5SJed Brown       break;
42720c7d97c5SJed Brown 
42730c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
42740c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
42750c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
42760c7d97c5SJed Brown       coarse_pc_type = PCLU;
427753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
42780c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
42790c7d97c5SJed Brown       active_rank = master_proc;
42800c7d97c5SJed Brown       break;
42810c7d97c5SJed Brown   }
42820c7d97c5SJed Brown 
42830c7d97c5SJed Brown   switch (pcbddc->coarse_communications_type) {
42840c7d97c5SJed Brown 
42850c7d97c5SJed Brown     case(SCATTERS_BDDC):
42860c7d97c5SJed Brown       {
42870c7d97c5SJed Brown         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
42880c7d97c5SJed Brown 
42892e8d2280SStefano Zampini           IS coarse_IS;
42902e8d2280SStefano Zampini 
4291523858cfSStefano Zampini           if (pcbddc->coarsening_ratio == 1) {
4292523858cfSStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
4293523858cfSStefano Zampini             ins_local_primal_indices = pcbddc->local_primal_indices;
4294523858cfSStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
4295523858cfSStefano Zampini             /* nonzeros */
4296523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
4297523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
4298523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
4299523858cfSStefano Zampini               dnz[i] = ins_local_primal_size;
4300523858cfSStefano Zampini             }
4301523858cfSStefano Zampini           } else {
43020c7d97c5SJed Brown             PetscMPIInt send_size;
4303ef028eecSStefano Zampini             PetscMPIInt *send_buffer;
43040c7d97c5SJed Brown             PetscInt    *aux_ins_indices;
43050c7d97c5SJed Brown             PetscInt    ii,jj;
43060c7d97c5SJed Brown             MPI_Request *requests;
4307ef028eecSStefano Zampini 
4308523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
4309523858cfSStefano Zampini             /* reusing pcbddc->local_primal_displacements and pcbddc->replicated_primal_size */
4310523858cfSStefano Zampini             ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
4311523858cfSStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
4312523858cfSStefano Zampini             pcbddc->replicated_primal_size = count_recv;
4313523858cfSStefano Zampini             j = 0;
4314523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4315523858cfSStefano Zampini               pcbddc->local_primal_displacements[i] = j;
4316523858cfSStefano Zampini               j += pcbddc->local_primal_sizes[ranks_recv[i]];
4317523858cfSStefano Zampini             }
4318523858cfSStefano Zampini             pcbddc->local_primal_displacements[count_recv] = j;
4319523858cfSStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
43200c7d97c5SJed Brown             /* allocate auxiliary space */
4321523858cfSStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
43220c7d97c5SJed Brown             ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
43230c7d97c5SJed Brown             ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
43240c7d97c5SJed Brown             /* allocate stuffs for message massing */
43250c7d97c5SJed Brown             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
4326523858cfSStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
4327523858cfSStefano Zampini             /* send indices to be inserted */
4328523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4329523858cfSStefano Zampini               send_size = pcbddc->local_primal_sizes[ranks_recv[i]];
4330523858cfSStefano 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);
4331523858cfSStefano Zampini             }
4332523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4333523858cfSStefano Zampini               send_size = pcbddc->local_primal_size;
4334ef028eecSStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
4335ef028eecSStefano Zampini               for (i=0;i<send_size;i++) {
4336ef028eecSStefano Zampini                 send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
4337ef028eecSStefano Zampini               }
4338ef028eecSStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
4339523858cfSStefano Zampini             }
4340523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4341ef028eecSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4342ef028eecSStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
4343ef028eecSStefano Zampini             }
43440c7d97c5SJed Brown             j = 0;
43450c7d97c5SJed Brown             for (i=0;i<count_recv;i++) {
43462e8d2280SStefano Zampini               ii = pcbddc->local_primal_displacements[i+1]-pcbddc->local_primal_displacements[i];
43472e8d2280SStefano Zampini               localsizes2[i] = ii*ii;
43480c7d97c5SJed Brown               localdispl2[i] = j;
43490c7d97c5SJed Brown               j += localsizes2[i];
4350523858cfSStefano Zampini               jj = pcbddc->local_primal_displacements[i];
43514fad6a16SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
43522e8d2280SStefano Zampini               for (k=0;k<ii;k++) {
43534fad6a16SStefano Zampini                 aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]] += 1;
43540c7d97c5SJed Brown               }
43554fad6a16SStefano Zampini             }
4356523858cfSStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
43570c7d97c5SJed Brown             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
43580c7d97c5SJed Brown             /* evaluate how many values I will insert in coarse mat */
43590c7d97c5SJed Brown             ins_local_primal_size = 0;
4360ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
4361ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
43620c7d97c5SJed Brown                 ins_local_primal_size++;
4363ea7e1babSStefano Zampini               }
4364ea7e1babSStefano Zampini             }
43650c7d97c5SJed Brown             /* evaluate indices I will insert in coarse mat */
43660c7d97c5SJed Brown             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
43670c7d97c5SJed Brown             j = 0;
4368ea7e1babSStefano Zampini             for (i=0;i<pcbddc->coarse_size;i++) {
4369ea7e1babSStefano Zampini               if (aux_ins_indices[i]) {
43702e8d2280SStefano Zampini                 ins_local_primal_indices[j] = i;
43712e8d2280SStefano Zampini                 j++;
4372ea7e1babSStefano Zampini               }
4373ea7e1babSStefano Zampini             }
4374523858cfSStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
4375523858cfSStefano Zampini             for (i=0;i<count_recv;i++) {
4376523858cfSStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
4377523858cfSStefano Zampini             }
4378523858cfSStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL) {
4379523858cfSStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
4380523858cfSStefano 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);
4381523858cfSStefano Zampini             }
4382523858cfSStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
4383523858cfSStefano Zampini             /* nonzeros */
4384523858cfSStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
4385523858cfSStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
43860c7d97c5SJed Brown             /* use aux_ins_indices to realize a global to local mapping */
43870c7d97c5SJed Brown             j=0;
43880c7d97c5SJed Brown             for (i=0;i<pcbddc->coarse_size;i++) {
43890c7d97c5SJed Brown               if (aux_ins_indices[i]==0) {
43900c7d97c5SJed Brown                 aux_ins_indices[i]=-1;
43910c7d97c5SJed Brown               } else {
43920c7d97c5SJed Brown                 aux_ins_indices[i]=j;
43930c7d97c5SJed Brown                 j++;
43940c7d97c5SJed Brown               }
43950c7d97c5SJed Brown             }
43964fad6a16SStefano Zampini             for (i=0;i<count_recv;i++) {
4397523858cfSStefano Zampini               j = pcbddc->local_primal_sizes[ranks_recv[i]];
4398523858cfSStefano Zampini               for (k=0;k<j;k++) {
4399523858cfSStefano Zampini                 dnz[aux_ins_indices[pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[i]+k]]] += j;
44000c7d97c5SJed Brown               }
44010c7d97c5SJed Brown             }
4402523858cfSStefano Zampini             /* check */
4403523858cfSStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
4404523858cfSStefano Zampini               if (dnz[i] > ins_local_primal_size) {
4405523858cfSStefano Zampini                 dnz[i] = ins_local_primal_size;
44060c7d97c5SJed Brown               }
44070c7d97c5SJed Brown             }
44080c7d97c5SJed Brown             ierr = PetscFree(requests);CHKERRQ(ierr);
44090c7d97c5SJed Brown             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
44100c7d97c5SJed Brown             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
44114fad6a16SStefano Zampini           }
44120c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
4413142dfd88SStefano Zampini           if (coarse_comm != MPI_COMM_NULL) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
44140c7d97c5SJed Brown           coarse_comm = prec_comm;
44150c7d97c5SJed Brown           active_rank = rank_prec_comm;
44160c7d97c5SJed Brown           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
44170c7d97c5SJed Brown           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
44180c7d97c5SJed Brown           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
44192e8d2280SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
44200c7d97c5SJed Brown           /* arrays for values insertion */
44210c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
44222e8d2280SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
44230c7d97c5SJed Brown           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
44240c7d97c5SJed Brown           for (j=0;j<ins_local_primal_size;j++) {
44250c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
44264fad6a16SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
44274fad6a16SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
44284fad6a16SStefano Zampini             }
44290c7d97c5SJed Brown           }
44300c7d97c5SJed Brown         }
44310c7d97c5SJed Brown         break;
44320c7d97c5SJed Brown 
44330c7d97c5SJed Brown     }
44340c7d97c5SJed Brown 
44350c7d97c5SJed Brown     case(GATHERS_BDDC):
44360c7d97c5SJed Brown       {
44370c7d97c5SJed Brown 
44380c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
4439ef028eecSStefano Zampini         PetscMPIInt *send_buffer;
44400c7d97c5SJed Brown 
44410c7d97c5SJed Brown         if (rank_prec_comm==active_rank) {
44420c7d97c5SJed Brown           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
44430bdf917eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscScalar),&pcbddc->replicated_local_primal_values);CHKERRQ(ierr);
44440c7d97c5SJed Brown           ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
44450c7d97c5SJed Brown           ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
44460c7d97c5SJed Brown           /* arrays for values insertion */
44474fad6a16SStefano Zampini           for (i=0;i<size_prec_comm;i++) { localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i]; }
44480c7d97c5SJed Brown           localdispl2[0]=0;
44494fad6a16SStefano Zampini           for (i=1;i<size_prec_comm;i++) { localdispl2[i]=localsizes2[i-1]+localdispl2[i-1]; }
44500c7d97c5SJed Brown           j=0;
44514fad6a16SStefano Zampini           for (i=0;i<size_prec_comm;i++) { j+=localsizes2[i]; }
44520c7d97c5SJed Brown           ierr = PetscMalloc (j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
44530c7d97c5SJed Brown         }
44540c7d97c5SJed Brown 
44550c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
44560c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
4457ef028eecSStefano Zampini         ierr = PetscMalloc(mysize*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
4458ef028eecSStefano Zampini         for (i=0;i<mysize;i++) {
4459ef028eecSStefano Zampini           send_buffer[i]=(PetscMPIInt)pcbddc->local_primal_indices[i];
4460ef028eecSStefano Zampini         }
44610c7d97c5SJed Brown         if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC) {
4462ef028eecSStefano 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);
446353cdbc3dSStefano 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);
44640c7d97c5SJed Brown         } else {
4465ef028eecSStefano 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);
446653cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
44670c7d97c5SJed Brown         }
4468ef028eecSStefano Zampini         ierr = PetscFree(send_buffer);CHKERRQ(ierr);
44690c7d97c5SJed Brown         break;
4470da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
44710c7d97c5SJed Brown   }
44720c7d97c5SJed Brown 
44730c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
44740c7d97c5SJed Brown   if (rank_prec_comm == active_rank) {
4475142dfd88SStefano Zampini 
4476142dfd88SStefano Zampini     Mat matis_coarse_local_mat;
4477142dfd88SStefano Zampini 
44780c7d97c5SJed Brown     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
44790c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
44800c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
44810c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
44823b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
4483da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
44843b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
44850c7d97c5SJed Brown     } else {
44864fad6a16SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
44873b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
44880c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
44893b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
4490da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
4491a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
44920c7d97c5SJed Brown     }
4493142dfd88SStefano Zampini     /* preallocation */
4494142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
4495ef028eecSStefano Zampini 
4496142dfd88SStefano Zampini       PetscInt lrows,lcols;
4497ef028eecSStefano Zampini 
4498142dfd88SStefano Zampini       ierr = MatGetLocalSize(pcbddc->coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
4499142dfd88SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
4500ef028eecSStefano Zampini 
4501142dfd88SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
4502ef028eecSStefano Zampini 
4503ef028eecSStefano Zampini         Vec         vec_dnz,vec_onz;
4504ef028eecSStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
4505ef028eecSStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
4506ef028eecSStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
4507ef028eecSStefano Zampini 
4508ef028eecSStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
4509ef028eecSStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,pcbddc->coarse_size);CHKERRQ(ierr);
4510ef028eecSStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
4511ef028eecSStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
4512ef028eecSStefano Zampini 
4513ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
4514ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
4515ef028eecSStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
4516ef028eecSStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
4517ef028eecSStefano Zampini 
4518ef028eecSStefano Zampini         ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
4519ef028eecSStefano Zampini         ierr = MatGetOwnershipRanges(pcbddc->coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
4520142dfd88SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
4521ef028eecSStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
4522ef028eecSStefano Zampini             row_ownership[j]=i;
4523142dfd88SStefano Zampini           }
4524142dfd88SStefano Zampini         }
4525ef028eecSStefano Zampini 
4526ef028eecSStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
4527ef028eecSStefano Zampini           coarse_index_row = pcbddc->local_primal_indices[i];
4528ef028eecSStefano Zampini           owner = row_ownership[coarse_index_row];
4529ef028eecSStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
4530ef028eecSStefano Zampini             owner = row_ownership[coarse_index_row];
4531ef028eecSStefano Zampini             coarse_index_col = pcbddc->local_primal_indices[j];
4532ef028eecSStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1]) {
4533ef028eecSStefano Zampini               my_dnz[i] += 1.0;
4534142dfd88SStefano Zampini             } else {
4535ef028eecSStefano Zampini               my_onz[i] += 1.0;
4536142dfd88SStefano Zampini             }
4537ef028eecSStefano Zampini             if (i != j) {
4538ef028eecSStefano Zampini               owner = row_ownership[coarse_index_col];
4539ef028eecSStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1]) {
4540ef028eecSStefano Zampini                 my_dnz[j] += 1.0;
4541142dfd88SStefano Zampini               } else {
4542ef028eecSStefano Zampini                 my_onz[j] += 1.0;
4543142dfd88SStefano Zampini               }
4544142dfd88SStefano Zampini             }
4545142dfd88SStefano Zampini           }
4546142dfd88SStefano Zampini         }
4547ef028eecSStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
4548ef028eecSStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
4549a929c220SStefano Zampini         if (pcbddc->local_primal_size) {
4550ef028eecSStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
4551ef028eecSStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,pcbddc->local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
4552a929c220SStefano Zampini         }
4553ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
4554ef028eecSStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
4555ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
4556ef028eecSStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
4557ef028eecSStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
4558ef028eecSStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
4559ef028eecSStefano Zampini         for (i=0;i<j;i++) {
4560ef028eecSStefano Zampini           dnz[i] = (PetscInt)array[i];
4561142dfd88SStefano Zampini         }
4562ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
4563ef028eecSStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
4564ef028eecSStefano Zampini         for (i=0;i<j;i++) {
4565ef028eecSStefano Zampini           onz[i] = (PetscInt)array[i];
4566142dfd88SStefano Zampini         }
4567ef028eecSStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
4568ef028eecSStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
4569ef028eecSStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
4570ef028eecSStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
4571ef028eecSStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
4572ef028eecSStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
4573142dfd88SStefano Zampini       } else {
4574142dfd88SStefano Zampini         for (k=0;k<size_prec_comm;k++) {
4575142dfd88SStefano Zampini           offset=pcbddc->local_primal_displacements[k];
4576142dfd88SStefano Zampini           offset2=localdispl2[k];
4577142dfd88SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_sizes[k];
4578ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4579ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4580ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4581ef028eecSStefano Zampini           }
4582142dfd88SStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4583142dfd88SStefano Zampini             ierr = MatPreallocateSet(ins_local_primal_indices[j],ins_local_primal_size,ins_local_primal_indices,dnz,onz);CHKERRQ(ierr);
4584142dfd88SStefano Zampini           }
4585ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4586142dfd88SStefano Zampini         }
4587142dfd88SStefano Zampini       }
4588142dfd88SStefano Zampini       /* check */
4589142dfd88SStefano Zampini       for (i=0;i<lrows;i++) {
4590142dfd88SStefano Zampini         if (dnz[i]>lcols) {
4591142dfd88SStefano Zampini           dnz[i]=lcols;
4592142dfd88SStefano Zampini         }
4593142dfd88SStefano Zampini         if (onz[i]>pcbddc->coarse_size-lcols) {
4594142dfd88SStefano Zampini           onz[i]=pcbddc->coarse_size-lcols;
4595142dfd88SStefano Zampini         }
4596142dfd88SStefano Zampini       }
4597142dfd88SStefano Zampini       ierr = MatSeqAIJSetPreallocation(pcbddc->coarse_mat,PETSC_NULL,dnz);CHKERRQ(ierr);
4598142dfd88SStefano Zampini       ierr = MatMPIAIJSetPreallocation(pcbddc->coarse_mat,PETSC_NULL,dnz,PETSC_NULL,onz);CHKERRQ(ierr);
4599142dfd88SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
4600142dfd88SStefano Zampini     } else {
4601523858cfSStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
4602523858cfSStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
4603142dfd88SStefano Zampini     }
4604142dfd88SStefano Zampini     /* insert values */
4605523858cfSStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
46060c7d97c5SJed 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);
4607523858cfSStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4608523858cfSStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
4609523858cfSStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
4610523858cfSStefano 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);
4611523858cfSStefano Zampini       } else {
4612523858cfSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4613523858cfSStefano Zampini         for (k=0;k<pcbddc->replicated_primal_size;k++) {
4614523858cfSStefano Zampini           offset = pcbddc->local_primal_displacements[k];
4615523858cfSStefano Zampini           offset2 = localdispl2[k];
4616523858cfSStefano Zampini           ins_local_primal_size = pcbddc->local_primal_displacements[k+1]-pcbddc->local_primal_displacements[k];
4617ef028eecSStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4618ef028eecSStefano Zampini           for (j=0;j<ins_local_primal_size;j++) {
4619ef028eecSStefano Zampini             ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4620ef028eecSStefano Zampini           }
4621523858cfSStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
4622523858cfSStefano 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);
4623ef028eecSStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4624523858cfSStefano Zampini         }
4625523858cfSStefano Zampini       }
4626523858cfSStefano Zampini       ins_local_primal_indices = 0;
4627523858cfSStefano Zampini       ins_coarse_mat_vals = 0;
4628ea7e1babSStefano Zampini     } else {
4629ea7e1babSStefano Zampini       for (k=0;k<size_prec_comm;k++) {
4630ea7e1babSStefano Zampini         offset=pcbddc->local_primal_displacements[k];
4631ea7e1babSStefano Zampini         offset2=localdispl2[k];
4632ea7e1babSStefano Zampini         ins_local_primal_size = pcbddc->local_primal_sizes[k];
4633ef028eecSStefano Zampini         ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
4634ef028eecSStefano Zampini         for (j=0;j<ins_local_primal_size;j++) {
4635ef028eecSStefano Zampini           ins_local_primal_indices[j]=(PetscInt)pcbddc->replicated_local_primal_indices[offset+j];
4636ef028eecSStefano Zampini         }
4637ea7e1babSStefano Zampini         ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
4638ea7e1babSStefano 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);
4639ef028eecSStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
4640ea7e1babSStefano Zampini       }
4641ea7e1babSStefano Zampini       ins_local_primal_indices = 0;
4642ea7e1babSStefano Zampini       ins_coarse_mat_vals = 0;
4643ea7e1babSStefano Zampini     }
46440c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46450c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4646142dfd88SStefano Zampini     /* symmetry of coarse matrix */
4647142dfd88SStefano Zampini     if (issym) {
4648142dfd88SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
4649142dfd88SStefano Zampini     }
46500c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
46510bdf917eSStefano Zampini   }
46520bdf917eSStefano Zampini 
46530bdf917eSStefano Zampini   /* create loc to glob scatters if needed */
46540bdf917eSStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
46550bdf917eSStefano Zampini      IS local_IS,global_IS;
46560bdf917eSStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
46570bdf917eSStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
46580bdf917eSStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
46590bdf917eSStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
46600bdf917eSStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
46610bdf917eSStefano Zampini   }
46620bdf917eSStefano Zampini 
4663a929c220SStefano Zampini   /* free memory no longer needed */
4664a929c220SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
4665a929c220SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
4666a929c220SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
4667a929c220SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
4668a929c220SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
4669a929c220SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
4670a929c220SStefano Zampini 
46710bdf917eSStefano Zampini   /* Eval coarse null space */
46720bdf917eSStefano Zampini   if (pcbddc->NullSpace) {
46730bdf917eSStefano Zampini     const Vec      *nsp_vecs;
46740bdf917eSStefano Zampini     PetscInt       nsp_size,coarse_nsp_size;
46750bdf917eSStefano Zampini     PetscBool      nsp_has_cnst;
46760bdf917eSStefano Zampini     PetscReal      test_null;
46770bdf917eSStefano Zampini     Vec            *coarse_nsp_vecs;
46780bdf917eSStefano Zampini 
46790bdf917eSStefano Zampini     coarse_nsp_size = 0;
46800bdf917eSStefano Zampini     coarse_nsp_vecs = 0;
46810bdf917eSStefano Zampini     ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr);
46820bdf917eSStefano Zampini     if (rank_prec_comm == active_rank) {
46830bdf917eSStefano Zampini       ierr = PetscMalloc((nsp_size+1)*sizeof(Vec),&coarse_nsp_vecs);CHKERRQ(ierr);
46840bdf917eSStefano Zampini       for (i=0;i<nsp_size+1;i++) {
46850bdf917eSStefano Zampini         ierr = VecDuplicate(pcbddc->coarse_vec,&coarse_nsp_vecs[i]);CHKERRQ(ierr);
46860bdf917eSStefano Zampini       }
46870bdf917eSStefano Zampini     }
46880bdf917eSStefano Zampini     if (nsp_has_cnst) {
46890bdf917eSStefano Zampini       ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
46900bdf917eSStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
46910bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46920bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46930bdf917eSStefano Zampini       if (rank_prec_comm == active_rank) {
46940bdf917eSStefano Zampini         ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
46950bdf917eSStefano Zampini         ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&test_null);CHKERRQ(ierr);
46960bdf917eSStefano Zampini         if (test_null > 1.0e-12 && pcbddc->dbg_flag) {
46970bdf917eSStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Constant coarse null space error % 1.14e\n",test_null);CHKERRQ(ierr);
46980bdf917eSStefano Zampini         }
46990bdf917eSStefano Zampini         ierr = VecCopy(pcbddc->coarse_vec,coarse_nsp_vecs[coarse_nsp_size]);CHKERRQ(ierr);
47000bdf917eSStefano Zampini         coarse_nsp_size++;
47010bdf917eSStefano Zampini       }
47020bdf917eSStefano Zampini     }
47030bdf917eSStefano Zampini     for (i=0;i<nsp_size;i++)  {
47040bdf917eSStefano Zampini       ierr = VecScatterBegin(matis->ctx,nsp_vecs[i],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47050bdf917eSStefano Zampini       ierr = VecScatterEnd  (matis->ctx,nsp_vecs[i],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47060bdf917eSStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
47070bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47080bdf917eSStefano Zampini       ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47090bdf917eSStefano Zampini       if (rank_prec_comm == active_rank) {
47100bdf917eSStefano Zampini         ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
47110bdf917eSStefano Zampini         ierr = VecNorm(pcbddc->coarse_rhs,NORM_2,&test_null);CHKERRQ(ierr);
47120bdf917eSStefano Zampini         if (test_null > 1.0e-12 && pcbddc->dbg_flag) {
47130bdf917eSStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Vec %d coarse null space error % 1.14e\n",i,test_null);CHKERRQ(ierr);
47140bdf917eSStefano Zampini         }
47150bdf917eSStefano Zampini         ierr = VecCopy(pcbddc->coarse_vec,coarse_nsp_vecs[coarse_nsp_size]);CHKERRQ(ierr);
47160bdf917eSStefano Zampini         coarse_nsp_size++;
47170bdf917eSStefano Zampini       }
47180bdf917eSStefano Zampini     }
47190bdf917eSStefano Zampini     if (coarse_nsp_size > 0) {
47200bdf917eSStefano Zampini       /* TODO orthonormalize vecs */
47210bdf917eSStefano Zampini       ierr = VecNormalize(coarse_nsp_vecs[0],PETSC_NULL);CHKERRQ(ierr);
47220bdf917eSStefano Zampini       ierr = MatNullSpaceCreate(coarse_comm,PETSC_FALSE,coarse_nsp_size,coarse_nsp_vecs,&pcbddc->CoarseNullSpace);CHKERRQ(ierr);
47230bdf917eSStefano Zampini       for (i=0;i<nsp_size+1;i++) {
47240bdf917eSStefano Zampini         ierr = VecDestroy(&coarse_nsp_vecs[i]);CHKERRQ(ierr);
47250bdf917eSStefano Zampini       }
47260bdf917eSStefano Zampini     }
47270bdf917eSStefano Zampini     ierr = PetscFree(coarse_nsp_vecs);CHKERRQ(ierr);
47280bdf917eSStefano Zampini   }
47290bdf917eSStefano Zampini 
47300bdf917eSStefano Zampini   /* KSP for coarse problem */
47310bdf917eSStefano Zampini   if (rank_prec_comm == active_rank) {
47322e8d2280SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
47330bdf917eSStefano Zampini 
473453cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
473553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
473653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
47373b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
473853cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
473953cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
474053cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
47410c7d97c5SJed Brown     /* Allow user's customization */
4742da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
47430c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
474453cdbc3dSStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
47454fad6a16SStefano Zampini       i = pcbddc->current_level+1;
47464fad6a16SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
47474fad6a16SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
47484fad6a16SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
474953cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
47500bdf917eSStefano Zampini       if (pcbddc->CoarseNullSpace) { ierr = PCBDDCSetNullSpace(pc_temp,pcbddc->CoarseNullSpace);CHKERRQ(ierr); }
47514fad6a16SStefano Zampini       if (dbg_flag) {
47524fad6a16SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
47534fad6a16SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
475453cdbc3dSStefano Zampini       }
47554fad6a16SStefano Zampini     }
47564fad6a16SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
475753cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4758142dfd88SStefano Zampini 
47592e8d2280SStefano Zampini     ierr = KSPGetTolerances(pcbddc->coarse_ksp,PETSC_NULL,PETSC_NULL,PETSC_NULL,&j);CHKERRQ(ierr);
47602e8d2280SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
47612e8d2280SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
47622e8d2280SStefano Zampini     if (j == 1) {
47632e8d2280SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
47642e8d2280SStefano Zampini       if (isbddc) {
47652e8d2280SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
47665619798eSStefano Zampini       }
47675619798eSStefano Zampini     }
47680c7d97c5SJed Brown   }
4769a929c220SStefano Zampini   /* Check coarse problem if requested */
4770142dfd88SStefano Zampini   if (dbg_flag && rank_prec_comm == active_rank) {
4771142dfd88SStefano Zampini     KSP       check_ksp;
4772142dfd88SStefano Zampini     PC        check_pc;
4773142dfd88SStefano Zampini     Vec       check_vec;
4774142dfd88SStefano Zampini     PetscReal abs_infty_error,infty_error,lambda_min,lambda_max;
477519fd82e9SBarry Smith     KSPType   check_ksp_type;
47760c7d97c5SJed Brown 
4777142dfd88SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
4778142dfd88SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
4779142dfd88SStefano Zampini     ierr = KSPSetOperators(check_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
47800bdf917eSStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
4781142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4782142dfd88SStefano Zampini       if (issym) {
4783142dfd88SStefano Zampini         check_ksp_type = KSPCG;
4784142dfd88SStefano Zampini       } else {
4785142dfd88SStefano Zampini         check_ksp_type = KSPGMRES;
4786142dfd88SStefano Zampini       }
4787142dfd88SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
4788142dfd88SStefano Zampini     } else {
4789142dfd88SStefano Zampini       check_ksp_type = KSPPREONLY;
4790142dfd88SStefano Zampini     }
4791142dfd88SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
4792142dfd88SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4793142dfd88SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4794142dfd88SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4795142dfd88SStefano Zampini     /* create random vec */
4796142dfd88SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
4797142dfd88SStefano Zampini     ierr = VecSetRandom(check_vec,PETSC_NULL);CHKERRQ(ierr);
47980bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) { ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,check_vec,PETSC_NULL);CHKERRQ(ierr); }
4799142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
4800142dfd88SStefano Zampini     /* solve coarse problem */
4801142dfd88SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
48020bdf917eSStefano Zampini     if (pcbddc->CoarseNullSpace) { ierr = MatNullSpaceRemove(pcbddc->CoarseNullSpace,pcbddc->coarse_vec,PETSC_NULL);CHKERRQ(ierr); }
4803142dfd88SStefano Zampini     /* check coarse problem residual error */
4804142dfd88SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
4805142dfd88SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
4806142dfd88SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
4807142dfd88SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4808142dfd88SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
4809142dfd88SStefano Zampini     /* get eigenvalue estimation if inexact */
4810142dfd88SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
4811142dfd88SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
4812142dfd88SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
4813142dfd88SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
4814e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
48153b03a366Sstefano_zampini     }
4816142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
4817142dfd88SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
4818142dfd88SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
481953cdbc3dSStefano Zampini   }
4820142dfd88SStefano Zampini   if (dbg_flag) { ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); }
48210c7d97c5SJed Brown 
48220c7d97c5SJed Brown   PetscFunctionReturn(0);
48230c7d97c5SJed Brown }
48240c7d97c5SJed Brown 
48250c7d97c5SJed Brown #undef __FUNCT__
48260c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
482753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
48280c7d97c5SJed Brown {
48290c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
48300c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)pc->data;
48310c7d97c5SJed Brown   Mat_IS         *matis  = (Mat_IS*)pc->pmat->data;
4832da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
48337cf533a6SStefano Zampini   PetscInt       *is_indices,*auxis;
48343b03a366Sstefano_zampini   PetscInt       bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
4835da1bb401SStefano Zampini   PetscInt       total_counts,nodes_touched,where_values=1,vertex_size;
4836534831adSStefano Zampini   PetscMPIInt    adapt_interface=0,adapt_interface_reduced=0,NEUMANNCNT=0;
4837da1bb401SStefano Zampini   PetscBool      same_set;
4838a0ba757dSStefano Zampini   MPI_Comm       interface_comm=((PetscObject)pc)->comm;
48393b03a366Sstefano_zampini   PetscBool      use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
48403b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
48413b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
4842a81d60d8SStefano Zampini   IS             used_IS,*custom_ISForDofs;
4843da1bb401SStefano Zampini   PetscScalar    *array;
4844da1bb401SStefano Zampini   PetscScalar    *array2;
4845da1bb401SStefano Zampini   PetscViewer    viewer=pcbddc->dbg_viewer;
4846a929c220SStefano Zampini   PetscInt       *queue_in_global_numbering;
48470c7d97c5SJed Brown 
48480c7d97c5SJed Brown   PetscFunctionBegin;
4849da1bb401SStefano Zampini   /* Setup local adjacency graph */
4850da1bb401SStefano Zampini   mat_graph->nvtxs=pcis->n;
4851534831adSStefano Zampini   if (!mat_graph->xadj) { NEUMANNCNT = 1; }
4852da1bb401SStefano Zampini   ierr = PCBDDCSetupLocalAdjacencyGraph(pc);CHKERRQ(ierr);
4853a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
4854a0ba757dSStefano 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);
48553972b0daSStefano Zampini   ierr = PetscMalloc2(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched);CHKERRQ(ierr);
4856a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4857a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4858a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
4859a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
48603828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
4861a0ba757dSStefano Zampini 
4862a81d60d8SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof
4863a81d60d8SStefano Zampini      Get information about dofs' splitting if provided by the user
4864a81d60d8SStefano Zampini      Otherwise it assumes a constant block size */
4865a81d60d8SStefano Zampini   vertex_size=0;
4866a81d60d8SStefano Zampini   if (!pcbddc->n_ISForDofs) {
4867a81d60d8SStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
4868a81d60d8SStefano Zampini     ierr = PetscMalloc(bs*sizeof(IS),&custom_ISForDofs);CHKERRQ(ierr);
4869a81d60d8SStefano Zampini     for (i=0;i<bs;i++) {
4870a81d60d8SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n/bs,i,bs,&custom_ISForDofs[i]);CHKERRQ(ierr);
4871a81d60d8SStefano Zampini     }
4872a81d60d8SStefano Zampini     ierr = PCBDDCSetDofsSplitting(pc,bs,custom_ISForDofs);CHKERRQ(ierr);
4873a81d60d8SStefano Zampini     vertex_size=1;
4874a81d60d8SStefano Zampini     /* remove my references to IS objects */
4875a81d60d8SStefano Zampini     for (i=0;i<bs;i++) {
4876a81d60d8SStefano Zampini       ierr = ISDestroy(&custom_ISForDofs[i]);CHKERRQ(ierr);
4877a81d60d8SStefano Zampini     }
4878a81d60d8SStefano Zampini     ierr = PetscFree(custom_ISForDofs);CHKERRQ(ierr);
4879a81d60d8SStefano Zampini   }
48809c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
4881a81d60d8SStefano Zampini     ierr = ISGetSize(pcbddc->ISForDofs[i],&k);CHKERRQ(ierr);
48829c0446d6SStefano Zampini     ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
4883a81d60d8SStefano Zampini     for (j=0;j<k;j++) {
48849c0446d6SStefano Zampini       mat_graph->which_dof[is_indices[j]]=i;
48859c0446d6SStefano Zampini     }
48869c0446d6SStefano Zampini     ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
48879c0446d6SStefano Zampini   }
4888a81d60d8SStefano Zampini   /* use mat block size as vertex size if it has not yet set */
4889a81d60d8SStefano Zampini   if (!vertex_size) {
48903b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
48910c7d97c5SJed Brown   }
4892a81d60d8SStefano Zampini 
48933b03a366Sstefano_zampini   /* count number of neigh per node */
48940c7d97c5SJed Brown   total_counts=0;
48953b03a366Sstefano_zampini   for (i=1;i<pcis->n_neigh;i++) {
48960c7d97c5SJed Brown     s=pcis->n_shared[i];
48970c7d97c5SJed Brown     total_counts+=s;
489853cdbc3dSStefano Zampini     for (j=0;j<s;j++) {
48990c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
49000c7d97c5SJed Brown     }
49010c7d97c5SJed Brown   }
4902534831adSStefano Zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for nodes lying on the interface */
490336e030ebSStefano Zampini   ierr = PCBDDCGetNeumannBoundaries(pc,&used_IS);CHKERRQ(ierr);
4904da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4905da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
490636e030ebSStefano Zampini   if (used_IS) {
490736e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&neumann_bsize);CHKERRQ(ierr);
490836e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
490953cdbc3dSStefano Zampini     for (i=0;i<neumann_bsize;i++) {
491053cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
4911534831adSStefano Zampini       if (mat_graph->count[iindex] > NEUMANNCNT && array[iindex]==0.0) {
491253cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
49130c7d97c5SJed Brown         total_counts++;
4914da1bb401SStefano Zampini         array[iindex]=array[iindex]+1.0;
4915f23aa3ddSBarry 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);
49160c7d97c5SJed Brown     }
49170c7d97c5SJed Brown   }
4918da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4919da1bb401SStefano Zampini   /* allocate space for storing the set of neighbours for each node */
4920da1bb401SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&mat_graph->neighbours_set);CHKERRQ(ierr);
4921da1bb401SStefano Zampini   if (mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&mat_graph->neighbours_set[0]);CHKERRQ(ierr); }
4922da1bb401SStefano 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];
4923a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
49243b03a366Sstefano_zampini   for (i=1;i<pcis->n_neigh;i++) {
49250c7d97c5SJed Brown     s=pcis->n_shared[i];
49260c7d97c5SJed Brown     for (j=0;j<s;j++) {
49270c7d97c5SJed Brown       k=pcis->shared[i][j];
4928da1bb401SStefano Zampini       mat_graph->neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
49290c7d97c5SJed Brown       mat_graph->count[k]+=1;
49300c7d97c5SJed Brown     }
49310c7d97c5SJed Brown   }
4932da1bb401SStefano Zampini   /* Check consistency of Neumann nodes */
4933da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4934da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4935da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4936da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4937da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4938da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
49393b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
494036e030ebSStefano Zampini   if (used_IS) {
494153cdbc3dSStefano Zampini     for (i=0;i<neumann_bsize;i++) {
494253cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
4943534831adSStefano Zampini       if (mat_graph->count[iindex] > NEUMANNCNT) {
4944da1bb401SStefano Zampini         if (mat_graph->count[iindex]+1 != (PetscInt)array[iindex]) {
4945da1bb401SStefano 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]);
4946da1bb401SStefano Zampini         }
4947da1bb401SStefano Zampini         mat_graph->neighbours_set[iindex][mat_graph->count[iindex]] = -1;
494853cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
49490c7d97c5SJed Brown       }
49500c7d97c5SJed Brown     }
495136e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
49520c7d97c5SJed Brown   }
4953da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4954da1bb401SStefano Zampini   /* sort set of sharing subdomains */
4955da1bb401SStefano Zampini   for (i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],mat_graph->neighbours_set[i]);CHKERRQ(ierr); }
49563b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
4957da1bb401SStefano Zampini   for (i=0;i<mat_graph->nvtxs;i++) {mat_graph->touched[i]=PETSC_FALSE;}
4958da1bb401SStefano Zampini   nodes_touched=0;
495936e030ebSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&used_IS);CHKERRQ(ierr);
4960da1bb401SStefano Zampini   ierr = VecSet(pcis->vec2_N,0.0);CHKERRQ(ierr);
4961da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4962da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4963da1bb401SStefano Zampini   if (used_IS) {
4964da1bb401SStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
4965f23aa3ddSBarry 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");
4966da1bb401SStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
4967da1bb401SStefano Zampini     for (i=0;i<dirichlet_bsize;i++) {
4968da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
4969da1bb401SStefano Zampini       if (mat_graph->count[iindex] && !mat_graph->touched[iindex]) {
4970f23aa3ddSBarry 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);
4971da1bb401SStefano Zampini         mat_graph->touched[iindex]=PETSC_TRUE;
4972da1bb401SStefano Zampini         mat_graph->where[iindex]=0;
4973da1bb401SStefano Zampini         nodes_touched++;
4974da1bb401SStefano Zampini         array2[iindex]=array2[iindex]+1.0;
4975da1bb401SStefano Zampini       }
4976da1bb401SStefano Zampini     }
4977da1bb401SStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
4978da1bb401SStefano Zampini   }
4979da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4980da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
4981da1bb401SStefano Zampini   /* Check consistency of Dirichlet nodes */
4982da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
4983da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4984da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4985da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4986da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4987da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4988da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4989da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4990da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4991da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4992da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4993da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4994da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
499536e030ebSStefano Zampini   if (used_IS) {
499636e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
499736e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
49983b03a366Sstefano_zampini     for (i=0;i<dirichlet_bsize;i++) {
4999da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
5000da1bb401SStefano Zampini       if (array[iindex]>1.0 && array[iindex]!=array2[iindex]) {
5001da1bb401SStefano 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]);
5002da1bb401SStefano Zampini       }
50033b03a366Sstefano_zampini     }
500436e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
50053b03a366Sstefano_zampini   }
5006da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
5007da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
5008da1bb401SStefano Zampini 
50090c7d97c5SJed Brown   for (i=0;i<mat_graph->nvtxs;i++) {
50103b03a366Sstefano_zampini     if (!mat_graph->count[i]) {  /* interior nodes */
50110c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
50120c7d97c5SJed Brown       mat_graph->where[i]=0;
50130c7d97c5SJed Brown       nodes_touched++;
50140c7d97c5SJed Brown     }
50150c7d97c5SJed Brown   }
50160c7d97c5SJed Brown   mat_graph->ncmps = 0;
5017da1bb401SStefano Zampini   i=0;
50180c7d97c5SJed Brown   while (nodes_touched<mat_graph->nvtxs) {
5019a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
50200c7d97c5SJed Brown     while (mat_graph->touched[i]) i++;
50210c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
5022a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
50230c7d97c5SJed Brown     nodes_touched++;
5024a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
50250c7d97c5SJed Brown     for (j=i+1;j<mat_graph->nvtxs;j++) {
5026a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
5027da1bb401SStefano Zampini       if (!mat_graph->touched[j] && mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j]) {
5028a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
50290c7d97c5SJed Brown         same_set=PETSC_TRUE;
50300c7d97c5SJed Brown         for (k=0;k<mat_graph->count[j];k++) {
5031da1bb401SStefano Zampini           if (mat_graph->neighbours_set[i][k]!=mat_graph->neighbours_set[j][k]) {
50320c7d97c5SJed Brown             same_set=PETSC_FALSE;
50330c7d97c5SJed Brown           }
50340c7d97c5SJed Brown         }
5035a0ba757dSStefano Zampini         /* I found a friend of mine */
50360c7d97c5SJed Brown         if (same_set) {
5037a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
50380c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
50390c7d97c5SJed Brown           nodes_touched++;
50400c7d97c5SJed Brown         }
50410c7d97c5SJed Brown       }
50420c7d97c5SJed Brown     }
5043a0ba757dSStefano Zampini     where_values++;
50440c7d97c5SJed Brown   }
5045a0ba757dSStefano Zampini   where_values--; if (where_values<0) where_values=0;
5046a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
5047a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
5048a0ba757dSStefano Zampini   if (where_values) {
5049a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
5050a0ba757dSStefano Zampini   }
5051a929c220SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&queue_in_global_numbering);CHKERRQ(ierr);
5052a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
5053a0ba757dSStefano Zampini   for (i=0;i<where_values;i++) {
50547cf533a6SStefano Zampini     /* We are not sure that on a given subset of the local interface,
50557cf533a6SStefano Zampini        two connected components will be the same among sharing subdomains */
50563b03a366Sstefano_zampini     if (mat_graph->where_ncmps[i]>1) {
5057a0ba757dSStefano Zampini       adapt_interface=1;
5058a0ba757dSStefano Zampini       break;
5059a0ba757dSStefano Zampini     }
5060a0ba757dSStefano Zampini   }
5061a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
5062da1bb401SStefano Zampini   if (pcbddc->dbg_flag && adapt_interface_reduced) {
5063d8923723SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Adapting interface\n");CHKERRQ(ierr);
5064da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
5065da1bb401SStefano Zampini   }
5066a0ba757dSStefano Zampini   if (where_values && adapt_interface_reduced) {
5067a0ba757dSStefano Zampini     PetscInt    sum_requests=0,my_rank;
5068a0ba757dSStefano Zampini     PetscInt    buffer_size,start_of_recv,size_of_recv,start_of_send;
5069a0ba757dSStefano Zampini     PetscInt    temp_buffer_size,ins_val,global_where_counter;
5070a0ba757dSStefano Zampini     PetscInt    *cum_recv_counts;
5071a0ba757dSStefano Zampini     PetscInt    *where_to_nodes_indices;
5072a0ba757dSStefano Zampini     PetscInt    *petsc_buffer;
5073a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
5074a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
5075a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
5076a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
5077a0ba757dSStefano Zampini     PetscInt    *sizes_of_sends;
5078a0ba757dSStefano Zampini     MPI_Request *send_requests;
5079a0ba757dSStefano Zampini     MPI_Request *recv_requests;
5080a0ba757dSStefano Zampini     PetscInt    *where_cc_adapt;
5081a0ba757dSStefano Zampini     PetscInt    **temp_buffer;
5082a0ba757dSStefano Zampini     PetscInt    *nodes_to_temp_buffer_indices;
5083a0ba757dSStefano Zampini     PetscInt    *add_to_where;
50847cf533a6SStefano Zampini     PetscInt    *aux_new_xadj,*new_xadj,*new_adjncy;
5085a0ba757dSStefano Zampini 
50867cf533a6SStefano Zampini     /* Retrict adjacency graph using information from connected components */
50877cf533a6SStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&aux_new_xadj);CHKERRQ(ierr);
50887cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
50897cf533a6SStefano Zampini       aux_new_xadj[i]=1;
50907cf533a6SStefano Zampini     }
50917cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
50927cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
50937cf533a6SStefano Zampini       for (j=0;j<k;j++) {
50947cf533a6SStefano Zampini         aux_new_xadj[mat_graph->queue[mat_graph->cptr[i]+j]]=k;
50957cf533a6SStefano Zampini       }
50967cf533a6SStefano Zampini     }
50977cf533a6SStefano Zampini     j = 0;
50987cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
50997cf533a6SStefano Zampini       j += aux_new_xadj[i];
51007cf533a6SStefano Zampini     }
51017cf533a6SStefano Zampini     ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&new_xadj);CHKERRQ(ierr);
51027cf533a6SStefano Zampini     ierr = PetscMalloc(j*sizeof(PetscInt),&new_adjncy);CHKERRQ(ierr);
51037cf533a6SStefano Zampini     new_xadj[0]=0;
51047cf533a6SStefano Zampini     for (i=0;i<mat_graph->nvtxs;i++) {
51057cf533a6SStefano Zampini       new_xadj[i+1]=new_xadj[i]+aux_new_xadj[i];
51067cf533a6SStefano Zampini       if (aux_new_xadj[i]==1) {
51077cf533a6SStefano Zampini         new_adjncy[new_xadj[i]]=i;
51087cf533a6SStefano Zampini       }
51097cf533a6SStefano Zampini     }
5110354b9337SStefano Zampini     ierr = PetscFree(aux_new_xadj);CHKERRQ(ierr);
51117cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
51127cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
51137cf533a6SStefano Zampini       for (j=0;j<k;j++) {
51147cf533a6SStefano 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);
51157cf533a6SStefano Zampini       }
51167cf533a6SStefano Zampini     }
51177cf533a6SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,mat_graph->nvtxs,new_xadj,new_adjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
51187cf533a6SStefano Zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
51197cf533a6SStefano Zampini     for (i=0;i<mat_graph->ncmps;i++) {
51207cf533a6SStefano Zampini       k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
51217cf533a6SStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,k,&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
51227cf533a6SStefano Zampini       ierr = PetscSortIntWithArray(k,&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
51237cf533a6SStefano Zampini     }
51247cf533a6SStefano Zampini     /* allocate some space */
5125a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
5126a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
5127a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
5128a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
5129a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
5130a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
5131a0ba757dSStefano Zampini     for (i=1;i<where_values+1;i++) {
5132a0ba757dSStefano Zampini       j=0;
5133d8923723SStefano Zampini       while (mat_graph->where[j] != i) { j++; }
5134a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
5135da1bb401SStefano 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  */
51363b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
5137a0ba757dSStefano Zampini     }
5138a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
5139a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
5140a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
5141a0ba757dSStefano Zampini     for (i=0;i<cum_recv_counts[where_values];i++) {
5142a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
5143a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
5144a0ba757dSStefano Zampini     }
5145a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
5146a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5147a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
5148da1bb401SStefano Zampini       k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
5149a0ba757dSStefano Zampini       for (;k<mat_graph->count[j];k++) {
5150da1bb401SStefano 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);
5151da1bb401SStefano 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);
5152a0ba757dSStefano Zampini         sum_requests++;
5153a0ba757dSStefano Zampini       }
5154a0ba757dSStefano Zampini     }
5155a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5156a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5157a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
5158a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
5159a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
5160a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5161a0ba757dSStefano Zampini       for (j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++) {
51623b03a366Sstefano_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 */
51633b03a366Sstefano_zampini         if (mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1) {
5164a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
5165a0ba757dSStefano Zampini           break;
5166a0ba757dSStefano Zampini         }
5167a0ba757dSStefano Zampini       }
5168a0ba757dSStefano Zampini     }
5169d8923723SStefano Zampini     buffer_size = 0;
5170d8923723SStefano Zampini     for (i=0;i<where_values;i++) {
5171d8923723SStefano Zampini       if (where_cc_adapt[i]) {
5172d8923723SStefano Zampini         for (j=i;j<mat_graph->ncmps;j++) {
5173d8923723SStefano Zampini           if (mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
5174d8923723SStefano Zampini             buffer_size += 1 + mat_graph->cptr[j+1]-mat_graph->cptr[j];
5175d8923723SStefano Zampini           }
5176d8923723SStefano Zampini         }
5177d8923723SStefano Zampini       }
5178d8923723SStefano Zampini     }
5179d8923723SStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
5180a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
5181a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
5182a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
5183a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
5184a0ba757dSStefano Zampini     sum_requests=0;
5185a0ba757dSStefano Zampini     start_of_send=0;
5186a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
5187a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5188a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5189a0ba757dSStefano Zampini         size_of_send=0;
5190a0ba757dSStefano Zampini         for (j=i;j<mat_graph->ncmps;j++) {
5191a0ba757dSStefano Zampini           if (mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
5192a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
5193a0ba757dSStefano Zampini             size_of_send+=1;
5194a0ba757dSStefano Zampini             for (k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
5195a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
5196a0ba757dSStefano Zampini             }
5197a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
5198a0ba757dSStefano Zampini           }
5199a0ba757dSStefano Zampini         }
5200a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
5201da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
520211d8f4c2SStefano Zampini         sizes_of_sends[i]=size_of_send;
5203a0ba757dSStefano Zampini         for (;k<mat_graph->count[j];k++) {
520411d8f4c2SStefano 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);
5205da1bb401SStefano 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);
5206a0ba757dSStefano Zampini           sum_requests++;
5207a0ba757dSStefano Zampini         }
5208a0ba757dSStefano Zampini         start_of_send+=size_of_send;
5209a0ba757dSStefano Zampini       }
5210a0ba757dSStefano Zampini     }
5211a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5212a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5213a0ba757dSStefano Zampini     buffer_size=0;
5214a0ba757dSStefano Zampini     for (k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
5215a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
5216a0ba757dSStefano Zampini     /* now exchange the data */
5217a0ba757dSStefano Zampini     start_of_recv=0;
5218a0ba757dSStefano Zampini     start_of_send=0;
5219a0ba757dSStefano Zampini     sum_requests=0;
5220a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5221a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5222a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
5223a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
5224da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
5225a0ba757dSStefano Zampini         for (;k<mat_graph->count[j];k++) {
5226da1bb401SStefano 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);
5227a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
5228da1bb401SStefano 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);
5229a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
5230a0ba757dSStefano Zampini           sum_requests++;
5231a0ba757dSStefano Zampini         }
5232a0ba757dSStefano Zampini         start_of_send+=size_of_send;
5233a0ba757dSStefano Zampini       }
5234a0ba757dSStefano Zampini     }
5235a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5236a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
5237a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
5238a0ba757dSStefano Zampini     for (k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
5239a0ba757dSStefano Zampini     for (j=0;j<buffer_size;) {
5240a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
5241a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
5242a0ba757dSStefano Zampini        j+=k;
5243a0ba757dSStefano Zampini     }
5244a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
5245a0ba757dSStefano Zampini     start_of_recv=0;
5246a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
5247a0ba757dSStefano Zampini     global_where_counter=0;
5248a0ba757dSStefano Zampini     for (i=0;i<where_values;i++) {
5249a0ba757dSStefano Zampini       if (where_cc_adapt[i]) {
5250a0ba757dSStefano Zampini         temp_buffer_size=0;
5251a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
5252a0ba757dSStefano Zampini         for (j=0;j<mat_graph->nvtxs;j++) {
5253a0ba757dSStefano Zampini           if (mat_graph->where[j]==i+1) {
5254a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
5255a0ba757dSStefano Zampini             temp_buffer_size++;
5256a0ba757dSStefano Zampini           } else {
5257a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
5258a0ba757dSStefano Zampini           }
5259a0ba757dSStefano Zampini         }
5260a0ba757dSStefano Zampini         /* allocate some temporary space */
5261a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
5262a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
5263a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
5264a0ba757dSStefano Zampini         for (j=1;j<temp_buffer_size;j++) {
5265a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
5266a0ba757dSStefano Zampini         }
5267a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
5268a0ba757dSStefano Zampini            temp buffer structure:
5269a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
5270a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
5271a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
5272a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
5273a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
5274a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
5275a0ba757dSStefano Zampini              [ 0, 0, 0;
5276a0ba757dSStefano Zampini                0, 0, 1;
5277a0ba757dSStefano Zampini                1, 1, 2;
5278a0ba757dSStefano Zampini                1, 1, 2;
5279a0ba757dSStefano Zampini                0, 1, 0; ];
5280a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
5281a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
5282a0ba757dSStefano Zampini                                                                                                                                    */
5283a0ba757dSStefano Zampini         for (j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
5284a0ba757dSStefano Zampini           ins_val=0;
5285a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
5286a0ba757dSStefano Zampini           for (buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
5287a0ba757dSStefano Zampini             for (k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
5288a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
5289a0ba757dSStefano Zampini             }
5290a0ba757dSStefano Zampini             buffer_size+=k;
5291a0ba757dSStefano Zampini             ins_val++;
5292a0ba757dSStefano Zampini           }
5293a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
5294a0ba757dSStefano Zampini           sum_requests++;
5295a0ba757dSStefano Zampini         }
5296a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
5297a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
5298a0ba757dSStefano Zampini         for (j=0;j<temp_buffer_size;j++) {
5299a0ba757dSStefano Zampini           if (!add_to_where[j]) { /* found a new cc  */
5300a0ba757dSStefano Zampini             global_where_counter++;
5301a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
5302a0ba757dSStefano Zampini             for (k=j+1;k<temp_buffer_size;k++) { /* check for other nodes in new cc */
5303a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
5304a0ba757dSStefano Zampini               for (s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++) {
5305a0ba757dSStefano Zampini                 if (temp_buffer[j][s]!=temp_buffer[k][s]) {
5306a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
5307a0ba757dSStefano Zampini                   break;
5308a0ba757dSStefano Zampini                 }
5309a0ba757dSStefano Zampini               }
53102e8d2280SStefano Zampini               if (same_set) { add_to_where[k]=global_where_counter; }
5311a0ba757dSStefano Zampini             }
5312a0ba757dSStefano Zampini           }
5313a0ba757dSStefano Zampini         }
5314a0ba757dSStefano Zampini         /* insert new data in where array */
5315a0ba757dSStefano Zampini         temp_buffer_size=0;
5316a0ba757dSStefano Zampini         for (j=0;j<mat_graph->nvtxs;j++) {
5317a0ba757dSStefano Zampini           if (mat_graph->where[j]==i+1) {
5318a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
5319a0ba757dSStefano Zampini             temp_buffer_size++;
5320a0ba757dSStefano Zampini           }
5321a0ba757dSStefano Zampini         }
5322a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
5323a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
5324a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
5325a0ba757dSStefano Zampini       }
5326a0ba757dSStefano Zampini     }
5327a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
5328a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
5329a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
5330a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
5331a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
5332a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
5333a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
5334a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
5335a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
5336a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
533723d4d1a5SStefano Zampini     ierr = PetscFree(where_cc_adapt);CHKERRQ(ierr);
5338a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
5339a0ba757dSStefano Zampini     if (global_where_counter) {
5340a0ba757dSStefano Zampini       for (i=0;i<mat_graph->nvtxs;i++) { mat_graph->touched[i]=PETSC_FALSE; }
5341a0ba757dSStefano Zampini       global_where_counter=0;
5342a0ba757dSStefano Zampini       for (i=0;i<mat_graph->nvtxs;i++) {
5343a0ba757dSStefano Zampini         if (mat_graph->where[i] && !mat_graph->touched[i]) {
5344a0ba757dSStefano Zampini           global_where_counter++;
5345a0ba757dSStefano Zampini           for (j=i+1;j<mat_graph->nvtxs;j++) {
5346a0ba757dSStefano Zampini             if (!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
5347a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
5348a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
5349a0ba757dSStefano Zampini             }
5350a0ba757dSStefano Zampini           }
5351a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
5352a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
5353a0ba757dSStefano Zampini         }
5354a0ba757dSStefano Zampini       }
5355a0ba757dSStefano Zampini       where_values=global_where_counter;
5356a0ba757dSStefano Zampini     }
5357a0ba757dSStefano Zampini     if (global_where_counter) {
5358a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
5359a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
5360a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
5361a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
5362a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
5363a0ba757dSStefano Zampini     }
53643b03a366Sstefano_zampini   } /* Finished adapting interface */
5365a929c220SStefano Zampini   /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
5366a929c220SStefano Zampini   for (i=0;i<mat_graph->ncmps;i++) {
5367a929c220SStefano Zampini     k = mat_graph->cptr[i+1]-mat_graph->cptr[i];
5368a929c220SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,k,&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
5369a929c220SStefano Zampini     ierr = PetscSortIntWithArray(k,&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
5370a929c220SStefano Zampini   }
5371a929c220SStefano Zampini 
53720c7d97c5SJed Brown   PetscInt  nfc=0;
53730c7d97c5SJed Brown   PetscInt  nec=0;
53740c7d97c5SJed Brown   PetscInt  nvc=0;
53753b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
53760c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
53773b03a366Sstefano_zampini     if (mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size) {
5378534831adSStefano Zampini       if (mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1) { /* 1 neigh Neumann fake included */
53790c7d97c5SJed Brown         nfc++;
53803b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
53813b03a366Sstefano_zampini         nec++;
53823b03a366Sstefano_zampini       }
53830c7d97c5SJed Brown     } else {
53843b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
53853b03a366Sstefano_zampini     }
53863b03a366Sstefano_zampini   }
53873b03a366Sstefano_zampini   if (!nec) { /* we are in a 2d case -> no faces, only edges */
53883b03a366Sstefano_zampini     nec = nfc;
53893b03a366Sstefano_zampini     nfc = 0;
53903b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
53913b03a366Sstefano_zampini   }
53923972b0daSStefano Zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set. */
53933972b0daSStefano Zampini   k=0;
53943972b0daSStefano Zampini   for (i=0; i<mat_graph->ncmps; i++) {
53953972b0daSStefano Zampini     j=mat_graph->cptr[i+1]-mat_graph->cptr[i];
53963972b0daSStefano Zampini     if (j > k) {
53973972b0daSStefano Zampini       k=j;
53983972b0daSStefano Zampini     }
5399ba1573a8SStefano Zampini     if (j<=vertex_size) {
5400ba1573a8SStefano Zampini       k+=vertex_size;
5401ba1573a8SStefano Zampini     }
54023972b0daSStefano Zampini   }
54033972b0daSStefano Zampini   ierr = PetscMalloc(k*sizeof(PetscInt),&auxis);CHKERRQ(ierr);
54043b03a366Sstefano_zampini   if (!pcbddc->vertices_flag && !pcbddc->edges_flag) {
54053b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
54063b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
54073b03a366Sstefano_zampini   }
54083b03a366Sstefano_zampini   if (!pcbddc->vertices_flag && !pcbddc->faces_flag) {
54093b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
54103b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
54113b03a366Sstefano_zampini   }
54123b03a366Sstefano_zampini   nfc=0;
54133b03a366Sstefano_zampini   nec=0;
54143b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
54153b03a366Sstefano_zampini     if (mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size) {
54163b03a366Sstefano_zampini       for (j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
54173972b0daSStefano Zampini         auxis[j]=mat_graph->queue[mat_graph->cptr[i]+j];
54183b03a366Sstefano_zampini       }
54193b03a366Sstefano_zampini       if (mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1) {
54203b03a366Sstefano_zampini         if (twodim_flag) {
54213b03a366Sstefano_zampini           if (use_edges) {
54223972b0daSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
54233b03a366Sstefano_zampini             nec++;
54243b03a366Sstefano_zampini           }
54253b03a366Sstefano_zampini         } else {
54263b03a366Sstefano_zampini           if (use_faces) {
54273972b0daSStefano Zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
54283b03a366Sstefano_zampini             nfc++;
54293b03a366Sstefano_zampini           }
54303b03a366Sstefano_zampini         }
54313b03a366Sstefano_zampini       } else {
54323b03a366Sstefano_zampini         if (use_edges) {
54333972b0daSStefano Zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,auxis,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
54340c7d97c5SJed Brown           nec++;
54350c7d97c5SJed Brown         }
54360c7d97c5SJed Brown       }
54370c7d97c5SJed Brown     }
54383b03a366Sstefano_zampini   }
54393b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
54403b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
54413b03a366Sstefano_zampini   nvc=0;
54420c7d97c5SJed Brown   if (!pcbddc->constraints_flag) {
54433b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
54443b03a366Sstefano_zampini       if (mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size) {
54453b03a366Sstefano_zampini         for (j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
54463972b0daSStefano Zampini           auxis[nvc]=mat_graph->queue[j];
54470c7d97c5SJed Brown           nvc++;
54480c7d97c5SJed Brown         }
54490c7d97c5SJed Brown       }
54500c7d97c5SJed Brown     }
54510c7d97c5SJed Brown   }
5452a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
54533972b0daSStefano Zampini   ierr = PetscSortInt(nvc,auxis);CHKERRQ(ierr);
54543972b0daSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,auxis,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
5455e269702eSStefano Zampini   if (pcbddc->dbg_flag) {
5456d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
5457d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
5458d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
54590c7d97c5SJed Brown     for (i=0;i<mat_graph->ncmps;i++) {
54603b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
54613b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
5462da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"subdomains: ");
5463da1bb401SStefano Zampini       for (j=0;j<mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]; j++) {
5464da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->neighbours_set[mat_graph->queue[mat_graph->cptr[i]]][j]);
5465da1bb401SStefano Zampini       }
5466da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");
54670c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++) {
5468a929c220SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",mat_graph->queue[j],queue_in_global_numbering[j]);CHKERRQ(ierr);
54690c7d97c5SJed Brown       }
54700c7d97c5SJed Brown     }
5471da1bb401SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
54723b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
54733b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
54743b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
5475d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
54760c7d97c5SJed Brown   }
54773972b0daSStefano Zampini   ierr = PetscFree(auxis);CHKERRQ(ierr);
5478a929c220SStefano Zampini   ierr = PetscFree(queue_in_global_numbering);CHKERRQ(ierr);
54790c7d97c5SJed Brown   PetscFunctionReturn(0);
54800c7d97c5SJed Brown }
54810c7d97c5SJed Brown 
54820c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
54830c7d97c5SJed Brown 
54840c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
5485da1bb401SStefano Zampini    in source file contig.c of METIS library (version 5.0.1)
5486da1bb401SStefano Zampini    It finds connected components of each partition labeled from 1 to n_dist  */
54870c7d97c5SJed Brown 
54880c7d97c5SJed Brown #undef __FUNCT__
54890c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
54909c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist)
54910c7d97c5SJed Brown {
54920c7d97c5SJed Brown   PetscInt  i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
54930c7d97c5SJed Brown   PetscInt  *xadj, *adjncy, *where, *queue;
54940c7d97c5SJed Brown   PetscInt  *cptr;
54950c7d97c5SJed Brown   PetscBool *touched;
54960c7d97c5SJed Brown 
54970c7d97c5SJed Brown   PetscFunctionBegin;
54980c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
54990c7d97c5SJed Brown   xadj    = graph->xadj;
55000c7d97c5SJed Brown   adjncy  = graph->adjncy;
55010c7d97c5SJed Brown   where   = graph->where;
55020c7d97c5SJed Brown   touched = graph->touched;
55030c7d97c5SJed Brown   queue   = graph->queue;
55040c7d97c5SJed Brown   cptr    = graph->cptr;
55050c7d97c5SJed Brown 
55062e8d2280SStefano Zampini   for (i=0; i<nvtxs; i++) {
55070c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
55082e8d2280SStefano Zampini   }
55090c7d97c5SJed Brown 
55100c7d97c5SJed Brown   cum_queue=0;
55110c7d97c5SJed Brown   ncmps=0;
55120c7d97c5SJed Brown 
55130c7d97c5SJed Brown   for (n=0; n<n_dist; n++) {
5514da1bb401SStefano Zampini     pid = n+1;  /* partition labeled by 0 is discarded */
55150c7d97c5SJed Brown     nleft = 0;
55160c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
55170c7d97c5SJed Brown       if (where[i] == pid)
55180c7d97c5SJed Brown         nleft++;
55190c7d97c5SJed Brown     }
55200c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
55210c7d97c5SJed Brown       if (where[i] == pid)
55220c7d97c5SJed Brown         break;
55230c7d97c5SJed Brown     }
55240c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
55250c7d97c5SJed Brown     queue[cum_queue] = i;
55260c7d97c5SJed Brown     first = 0; last = 1;
55270c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
55280c7d97c5SJed Brown     ncmps_pid = 0;
55290c7d97c5SJed Brown     while (first != nleft) {
55300c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
55310c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
55320c7d97c5SJed Brown         ncmps_pid++;
55330c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
55340c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
55350c7d97c5SJed Brown             break;
55360c7d97c5SJed Brown         }
55370c7d97c5SJed Brown         queue[cum_queue+last] = i;
55380c7d97c5SJed Brown         last++;
55390c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
55400c7d97c5SJed Brown       }
55410c7d97c5SJed Brown       i = queue[cum_queue+first];
55420c7d97c5SJed Brown       first++;
55430c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
55440c7d97c5SJed Brown         k = adjncy[j];
55450c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
55460c7d97c5SJed Brown           queue[cum_queue+last] = k;
55470c7d97c5SJed Brown           last++;
55480c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
55490c7d97c5SJed Brown         }
55500c7d97c5SJed Brown       }
55510c7d97c5SJed Brown     }
55520c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
55530c7d97c5SJed Brown     ncmps_pid++;
55540c7d97c5SJed Brown     cum_queue=cptr[ncmps];
5555a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
55560c7d97c5SJed Brown   }
55570c7d97c5SJed Brown   graph->ncmps = ncmps;
55580c7d97c5SJed Brown 
55590c7d97c5SJed Brown   PetscFunctionReturn(0);
55600c7d97c5SJed Brown }
5561