xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision a0ba757d816460f033888a5e23e4f07a26a6ab1a)
153cdbc3dSStefano Zampini /* TODOLIST
2*a0ba757dSStefano Zampini    allow passing array of IS to identify dof splitting per node (see which_dof array)
3*a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
4*a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
5*a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
6*a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
7*a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
8*a0ba757dSStefano Zampini      - Add level slot to bddc data structure and associated Set/Get functions
9*a0ba757dSStefano Zampini    code refactoring:
10*a0ba757dSStefano Zampini      - removing indices to constraints, quadrature constrainsts and similar from PCBDDCManageLocalBoundaries
11*a0ba757dSStefano Zampini      - analyze MatSetNearNullSpace as suggested by Jed
12*a0ba757dSStefano Zampini      - build constraint matrix after SVD on local connected components
13*a0ba757dSStefano Zampini      - pick up better names for static functions
14*a0ba757dSStefano Zampini    check log_summary for leaking (actually: 1 Vector per level plus only 1 IS)
15*a0ba757dSStefano Zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
16*a0ba757dSStefano Zampini    change options structure:
17*a0ba757dSStefano Zampini      - insert BDDC into MG framework?
18*a0ba757dSStefano Zampini    provide other ops? Ask to developers
19*a0ba757dSStefano Zampini    remove all unused printf
20*a0ba757dSStefano Zampini    remove // commments and adhere to PETSc code requirements
21*a0ba757dSStefano Zampini    man pages
2253cdbc3dSStefano Zampini */
230c7d97c5SJed Brown 
2453cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
250c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
260c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2753cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2853cdbc3dSStefano Zampini 
2953cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
300c7d97c5SJed Brown 
310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
320c7d97c5SJed Brown #undef __FUNCT__
330c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
340c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
350c7d97c5SJed Brown {
360c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
370c7d97c5SJed Brown   PetscErrorCode ierr;
380c7d97c5SJed Brown 
390c7d97c5SJed Brown   PetscFunctionBegin;
400c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Verbose debugging of main data structures */
42e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
430c7d97c5SJed Brown   /* Some customization for default primal space */
440c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
450c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
460c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use faces only in coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
470c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use edges only in coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
480c7d97c5SJed Brown   /* Coarse solver context */
490c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
500c7d97c5SJed 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);
510c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
520c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->prec_type,&pcbddc->prec_type,PETSC_NULL);CHKERRQ(ierr);
530c7d97c5SJed 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);
540c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
550c7d97c5SJed Brown   PetscFunctionReturn(0);
560c7d97c5SJed Brown }
570c7d97c5SJed Brown 
580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
590c7d97c5SJed Brown EXTERN_C_BEGIN
600c7d97c5SJed Brown #undef __FUNCT__
610c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
630c7d97c5SJed Brown {
640c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
650c7d97c5SJed Brown 
660c7d97c5SJed Brown   PetscFunctionBegin;
670c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
680c7d97c5SJed Brown   PetscFunctionReturn(0);
690c7d97c5SJed Brown }
700c7d97c5SJed Brown EXTERN_C_END
710c7d97c5SJed Brown 
720c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
730c7d97c5SJed Brown #undef __FUNCT__
740c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7553cdbc3dSStefano Zampini /*@
7653cdbc3dSStefano Zampini  PCBDDCSetCoarseProblemType - brief explanation
7753cdbc3dSStefano Zampini 
7853cdbc3dSStefano Zampini    Collective on PC
7953cdbc3dSStefano Zampini 
8053cdbc3dSStefano Zampini    Input Parameters:
8153cdbc3dSStefano Zampini +  pc - the preconditioning context
8253cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8353cdbc3dSStefano Zampini 
8453cdbc3dSStefano Zampini    Level: intermediate
8553cdbc3dSStefano Zampini 
8653cdbc3dSStefano Zampini    Notes:
8753cdbc3dSStefano Zampini    usage notes, perhaps an example
8853cdbc3dSStefano Zampini 
8953cdbc3dSStefano Zampini .seealso: PCBDDC
9053cdbc3dSStefano Zampini @*/
910c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
920c7d97c5SJed Brown {
930c7d97c5SJed Brown   PetscErrorCode ierr;
940c7d97c5SJed Brown 
950c7d97c5SJed Brown   PetscFunctionBegin;
960c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
970c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
980c7d97c5SJed Brown   PetscFunctionReturn(0);
990c7d97c5SJed Brown }
1000c7d97c5SJed Brown 
1010c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1020c7d97c5SJed Brown EXTERN_C_BEGIN
1030c7d97c5SJed Brown #undef __FUNCT__
1040c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
10553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1060c7d97c5SJed Brown {
1070c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
10853cdbc3dSStefano Zampini   PetscErrorCode ierr;
1090c7d97c5SJed Brown 
1100c7d97c5SJed Brown   PetscFunctionBegin;
11153cdbc3dSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
11253cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
11353cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
11453cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1150c7d97c5SJed Brown   PetscFunctionReturn(0);
1160c7d97c5SJed Brown }
1170c7d97c5SJed Brown EXTERN_C_END
1180c7d97c5SJed Brown 
1190c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1200c7d97c5SJed Brown #undef __FUNCT__
1210c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
12257527edcSJed Brown /*@
12353cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
12453cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
12557527edcSJed Brown 
12653cdbc3dSStefano Zampini    Logically Collective on PC
12757527edcSJed Brown 
12857527edcSJed Brown    Input Parameters:
12957527edcSJed Brown +  pc - the preconditioning context
13053cdbc3dSStefano Zampini -  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
13157527edcSJed Brown 
13257527edcSJed Brown    Level: intermediate
13357527edcSJed Brown 
13457527edcSJed Brown    Notes:
13557527edcSJed Brown    usage notes, perhaps an example
13657527edcSJed Brown 
13757527edcSJed Brown .seealso: PCBDDC
13857527edcSJed Brown @*/
13953cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1400c7d97c5SJed Brown {
1410c7d97c5SJed Brown   PetscErrorCode ierr;
1420c7d97c5SJed Brown 
1430c7d97c5SJed Brown   PetscFunctionBegin;
1440c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
14553cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
14653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
14753cdbc3dSStefano Zampini }
14853cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
14953cdbc3dSStefano Zampini EXTERN_C_BEGIN
15053cdbc3dSStefano Zampini #undef __FUNCT__
15153cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
15253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
15353cdbc3dSStefano Zampini {
15453cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15553cdbc3dSStefano Zampini 
15653cdbc3dSStefano Zampini   PetscFunctionBegin;
15753cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
15853cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
15953cdbc3dSStefano Zampini   } else {
16053cdbc3dSStefano Zampini     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
16153cdbc3dSStefano Zampini   }
16253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
16353cdbc3dSStefano Zampini }
16453cdbc3dSStefano Zampini EXTERN_C_END
16553cdbc3dSStefano Zampini 
16653cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
16753cdbc3dSStefano Zampini #undef __FUNCT__
16853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
16953cdbc3dSStefano Zampini /*@
17053cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
17153cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
17253cdbc3dSStefano Zampini 
17353cdbc3dSStefano Zampini    Logically Collective on PC
17453cdbc3dSStefano Zampini 
17553cdbc3dSStefano Zampini    Input Parameters:
17653cdbc3dSStefano Zampini +  pc - the preconditioning context
17753cdbc3dSStefano Zampini 
17853cdbc3dSStefano Zampini    Output Parameters:
17953cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
18053cdbc3dSStefano Zampini 
18153cdbc3dSStefano Zampini    Level: intermediate
18253cdbc3dSStefano Zampini 
18353cdbc3dSStefano Zampini    Notes:
18453cdbc3dSStefano Zampini    usage notes, perhaps an example
18553cdbc3dSStefano Zampini 
18653cdbc3dSStefano Zampini .seealso: PCBDDC
18753cdbc3dSStefano Zampini @*/
18853cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
18953cdbc3dSStefano Zampini {
19053cdbc3dSStefano Zampini   PetscErrorCode ierr;
19153cdbc3dSStefano Zampini 
19253cdbc3dSStefano Zampini   PetscFunctionBegin;
19353cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
19453cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1950c7d97c5SJed Brown   PetscFunctionReturn(0);
1960c7d97c5SJed Brown }
1970c7d97c5SJed Brown 
19853cdbc3dSStefano Zampini #undef __FUNCT__
19953cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
2000c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2010c7d97c5SJed Brown /*
2020c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
2030c7d97c5SJed Brown                   by setting data structures and options.
2040c7d97c5SJed Brown 
2050c7d97c5SJed Brown    Input Parameter:
20653cdbc3dSStefano Zampini +  pc - the preconditioner context
2070c7d97c5SJed Brown 
2080c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
2090c7d97c5SJed Brown 
2100c7d97c5SJed Brown    Notes:
2110c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
2120c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
2130c7d97c5SJed Brown */
21453cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
2150c7d97c5SJed Brown {
2160c7d97c5SJed Brown   PetscErrorCode ierr;
2170c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
2180c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
2190c7d97c5SJed Brown 
2200c7d97c5SJed Brown   PetscFunctionBegin;
2210c7d97c5SJed Brown   if (!pc->setupcalled) {
2220c7d97c5SJed Brown 
2230c7d97c5SJed Brown     /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup
2240c7d97c5SJed Brown        So, we set to pcnone the Neumann problem of pcid in order to avoid unneeded computation
2250c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
2260c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
2270c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
2280c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
2290c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
2300c7d97c5SJed Brown     /* Destroy some PC_IS data which is not needed by BDDC */
2310c7d97c5SJed Brown     //if (pcis->ksp_D)  {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);}
2320c7d97c5SJed Brown     //if (pcis->ksp_N)  {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);}
2330c7d97c5SJed Brown     //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);}
2340c7d97c5SJed Brown     //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);}
2350c7d97c5SJed Brown     //pcis->ksp_D  = 0;
2360c7d97c5SJed Brown     //pcis->ksp_N  = 0;
2370c7d97c5SJed Brown     //pcis->vec2_B = 0;
2380c7d97c5SJed Brown     //pcis->vec3_B = 0;
239e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
240e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
241e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
242e269702eSStefano Zampini     }
2430c7d97c5SJed Brown 
2440c7d97c5SJed Brown     //TODO MOVE CODE FRAGMENT
2450c7d97c5SJed Brown     PetscInt im_active=0;
2460c7d97c5SJed Brown     if(pcis->n) im_active = 1;
24753cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
2480c7d97c5SJed Brown     //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active);
2490c7d97c5SJed Brown     /* Set up grid quantities for BDDC */
2500c7d97c5SJed Brown     //TODO only active procs must call this -> remove synchronized print inside (the only point of sync)
2510c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
2520c7d97c5SJed Brown 
2530c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
2540c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
2550c7d97c5SJed Brown 
2560c7d97c5SJed Brown     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo
2570c7d97c5SJed Brown     /* We no more need this matrix */
2580c7d97c5SJed Brown     //if (pcis->A_BB)  {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);}
2590c7d97c5SJed Brown     //pcis->A_BB   = 0;
2600c7d97c5SJed Brown 
2610c7d97c5SJed Brown     //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type);
2620c7d97c5SJed Brown     //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type);
2630c7d97c5SJed Brown     //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio);
2640c7d97c5SJed Brown   }
2650c7d97c5SJed Brown 
2660c7d97c5SJed Brown   PetscFunctionReturn(0);
2670c7d97c5SJed Brown }
2680c7d97c5SJed Brown 
2690c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2700c7d97c5SJed Brown /*
2710c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
2720c7d97c5SJed Brown 
2730c7d97c5SJed Brown    Input Parameters:
2740c7d97c5SJed Brown .  pc - the preconditioner context
2750c7d97c5SJed Brown .  r - input vector (global)
2760c7d97c5SJed Brown 
2770c7d97c5SJed Brown    Output Parameter:
2780c7d97c5SJed Brown .  z - output vector (global)
2790c7d97c5SJed Brown 
2800c7d97c5SJed Brown    Application Interface Routine: PCApply()
2810c7d97c5SJed Brown  */
2820c7d97c5SJed Brown #undef __FUNCT__
2830c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
28453cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
2850c7d97c5SJed Brown {
2860c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)(pc->data);
2870c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2880c7d97c5SJed Brown   PetscErrorCode ierr;
2890c7d97c5SJed Brown   PetscScalar    one = 1.0;
2900c7d97c5SJed Brown   PetscScalar    m_one = -1.0;
2910c7d97c5SJed Brown 
2920c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
2930c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
2940c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
2950c7d97c5SJed Brown 
2960c7d97c5SJed Brown   PetscFunctionBegin;
2970c7d97c5SJed Brown   /* First Dirichlet solve */
2980c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2990c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
30053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3010c7d97c5SJed Brown   /*
3020c7d97c5SJed Brown     Assembling right hand side for BDDC operator
3030c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
3040c7d97c5SJed Brown     - the interface part of the global vector z
3050c7d97c5SJed Brown   */
3060c7d97c5SJed Brown   //ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3070c7d97c5SJed Brown   //ierr = VecScatterEnd  (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3080c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3090c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
3100c7d97c5SJed Brown   //ierr = MatMultAdd(pcis->A_BI,pcis->vec2_D,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3110c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3120c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3130c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
3140c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3150c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3160c7d97c5SJed Brown 
3170c7d97c5SJed Brown   /*
3180c7d97c5SJed Brown     Apply interface preconditioner
3190c7d97c5SJed Brown     Results are stored in:
3200c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
3210c7d97c5SJed Brown     -  the interface part of the global vector z
3220c7d97c5SJed Brown   */
3230c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
3240c7d97c5SJed Brown 
3250c7d97c5SJed Brown   /* Second Dirichlet solves and assembling of output */
3260c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3270c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3280c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
3290c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
33053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
3310c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
3320c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
3330c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
3340c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3350c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3360c7d97c5SJed Brown 
3370c7d97c5SJed Brown   PetscFunctionReturn(0);
3380c7d97c5SJed Brown 
3390c7d97c5SJed Brown }
3400c7d97c5SJed Brown 
3410c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3420c7d97c5SJed Brown /*
3430c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
3440c7d97c5SJed Brown 
3450c7d97c5SJed Brown */
3460c7d97c5SJed Brown #undef __FUNCT__
3470c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
34853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
3490c7d97c5SJed Brown {
3500c7d97c5SJed Brown   PetscErrorCode ierr;
3510c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
3520c7d97c5SJed Brown   PC_IS*         pcis =   (PC_IS*)  (pc->data);
3530c7d97c5SJed Brown   PetscScalar    zero = 0.0;
3540c7d97c5SJed Brown 
3550c7d97c5SJed Brown   PetscFunctionBegin;
3560c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
3570c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3580c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3590c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3600c7d97c5SJed Brown 
3610c7d97c5SJed Brown   /* Application of PHI^T  */
3620c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3630c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3640c7d97c5SJed Brown 
3650c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
3660c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
3670c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3680c7d97c5SJed Brown 
3690c7d97c5SJed Brown   /* Local solution on R nodes */
3700c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
3710c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3720c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3730c7d97c5SJed Brown   if(pcbddc->prec_type) {
3740c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3750c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3760c7d97c5SJed Brown   }
3770c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
3780c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
3790c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3800c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3810c7d97c5SJed Brown   if(pcbddc->prec_type) {
3820c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3830c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3840c7d97c5SJed Brown   }
3850c7d97c5SJed Brown 
3860c7d97c5SJed Brown   /* Coarse solution */
3870c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
38853cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3890c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3900c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3910c7d97c5SJed Brown 
3920c7d97c5SJed Brown   /* Sum contributions from two levels */
3930c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
3940c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3950c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3960c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3970c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
3980c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3990c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4000c7d97c5SJed Brown 
4010c7d97c5SJed Brown   PetscFunctionReturn(0);
4020c7d97c5SJed Brown }
4030c7d97c5SJed Brown 
4040c7d97c5SJed Brown 
4050c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4060c7d97c5SJed Brown /*
4070c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
4080c7d97c5SJed Brown 
4090c7d97c5SJed Brown */
4100c7d97c5SJed Brown #undef __FUNCT__
4110c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
41253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
4130c7d97c5SJed Brown {
4140c7d97c5SJed Brown   PetscErrorCode ierr;
4150c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4160c7d97c5SJed Brown 
4170c7d97c5SJed Brown   PetscFunctionBegin;
4180c7d97c5SJed Brown 
41953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4200c7d97c5SJed Brown   if(pcbddc->n_constraints) {
4210c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
4220c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
4230c7d97c5SJed Brown   }
4240c7d97c5SJed Brown 
4250c7d97c5SJed Brown   PetscFunctionReturn(0);
4260c7d97c5SJed Brown }
4270c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4280c7d97c5SJed Brown /*
4290c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
4300c7d97c5SJed Brown 
4310c7d97c5SJed Brown */
4320c7d97c5SJed Brown #undef __FUNCT__
4330c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
43453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4350c7d97c5SJed Brown {
4360c7d97c5SJed Brown   PetscErrorCode ierr;
4370c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4380c7d97c5SJed Brown 
4390c7d97c5SJed Brown   PetscFunctionBegin;
4400c7d97c5SJed Brown 
4410c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4420c7d97c5SJed Brown     case SCATTERS_BDDC:
4430c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4440c7d97c5SJed Brown       break;
4450c7d97c5SJed Brown     case GATHERS_BDDC:
4460c7d97c5SJed Brown       break;
4470c7d97c5SJed Brown   }
4480c7d97c5SJed Brown   PetscFunctionReturn(0);
4490c7d97c5SJed Brown 
4500c7d97c5SJed Brown }
4510c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4520c7d97c5SJed Brown /*
4530c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
4540c7d97c5SJed Brown 
4550c7d97c5SJed Brown */
4560c7d97c5SJed Brown #undef __FUNCT__
4570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
45853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4590c7d97c5SJed Brown {
4600c7d97c5SJed Brown   PetscErrorCode ierr;
4610c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4620c7d97c5SJed Brown   PetscScalar*   array_to;
4630c7d97c5SJed Brown   PetscScalar*   array_from;
4640c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
4650c7d97c5SJed Brown   PetscInt i;
4660c7d97c5SJed Brown 
4670c7d97c5SJed Brown   PetscFunctionBegin;
4680c7d97c5SJed Brown 
4690c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4700c7d97c5SJed Brown     case SCATTERS_BDDC:
4710c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4720c7d97c5SJed Brown       break;
4730c7d97c5SJed Brown     case GATHERS_BDDC:
4740c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
4750c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
4760c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
4770c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
4780c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
47953cdbc3dSStefano 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);
4800c7d97c5SJed Brown             if(vec_to) {
4810c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4820c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4830c7d97c5SJed Brown             }
4840c7d97c5SJed Brown           } else {
4850c7d97c5SJed Brown             if(vec_from)
4860c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4870c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
48853cdbc3dSStefano 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);
4890c7d97c5SJed Brown           }
4900c7d97c5SJed Brown           break;
4910c7d97c5SJed Brown         case REPLICATED_BDDC:
4920c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
49353cdbc3dSStefano 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);
4940c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
4950c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4960c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
4970c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
4980c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
4990c7d97c5SJed Brown           }
5000c7d97c5SJed Brown           break;
50153cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
50253cdbc3dSStefano Zampini           break;
50353cdbc3dSStefano Zampini         case PARALLEL_BDDC:
50453cdbc3dSStefano Zampini           break;
5050c7d97c5SJed Brown       }
5060c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
5070c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
5080c7d97c5SJed Brown       break;
5090c7d97c5SJed Brown   }
5100c7d97c5SJed Brown   PetscFunctionReturn(0);
5110c7d97c5SJed Brown 
5120c7d97c5SJed Brown }
5130c7d97c5SJed Brown 
5140c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5150c7d97c5SJed Brown /*
5160c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
5170c7d97c5SJed Brown    that was created with PCCreate_BDDC().
5180c7d97c5SJed Brown 
5190c7d97c5SJed Brown    Input Parameter:
5200c7d97c5SJed Brown .  pc - the preconditioner context
5210c7d97c5SJed Brown 
5220c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
5230c7d97c5SJed Brown */
5240c7d97c5SJed Brown #undef __FUNCT__
5250c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
52653cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
5270c7d97c5SJed Brown {
5280c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
5290c7d97c5SJed Brown   PetscErrorCode ierr;
5300c7d97c5SJed Brown 
5310c7d97c5SJed Brown   PetscFunctionBegin;
5320c7d97c5SJed Brown   /* free data created by PCIS */
5330c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
5340c7d97c5SJed Brown   /* free BDDC data  */
53553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
53653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
53753cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
53853cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
53953cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
54053cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
54153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
54253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
54353cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
54453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
54553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
54653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
54753cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
54853cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
54953cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
55053cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
55153cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
55253cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
55353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
55453cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr);
55553cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
55653cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
5570c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
55853cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
55953cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
5600c7d97c5SJed Brown   if (pcbddc->n_constraints) {
5610c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
5620c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr);
5630c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
5640c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr);
5650c7d97c5SJed Brown     ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr);
5660c7d97c5SJed Brown   }
5670c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
5680c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
5690c7d97c5SJed Brown   PetscFunctionReturn(0);
5700c7d97c5SJed Brown }
5710c7d97c5SJed Brown 
5720c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5730c7d97c5SJed Brown /*MC
5740c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
5750c7d97c5SJed Brown 
5760c7d97c5SJed Brown    Options Database Keys:
577*a0ba757dSStefano Zampini .    -pcbddc ??? -
5780c7d97c5SJed Brown 
5790c7d97c5SJed Brown    Level: intermediate
5800c7d97c5SJed Brown 
5810c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
5820c7d97c5SJed Brown 
5830c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
5840c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
5850c7d97c5SJed Brown           on the subdomains).
5860c7d97c5SJed Brown 
587*a0ba757dSStefano Zampini           Options for the coarse grid preconditioner can be set with -
588*a0ba757dSStefano Zampini           Options for the Dirichlet subproblem can be set with -
589*a0ba757dSStefano Zampini           Options for the Neumann subproblem can be set with -
5900c7d97c5SJed Brown 
5910c7d97c5SJed Brown    Contributed by Stefano Zampini
5920c7d97c5SJed Brown 
5930c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
5940c7d97c5SJed Brown M*/
5950c7d97c5SJed Brown EXTERN_C_BEGIN
5960c7d97c5SJed Brown #undef __FUNCT__
5970c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
5980c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
5990c7d97c5SJed Brown {
6000c7d97c5SJed Brown   PetscErrorCode ierr;
6010c7d97c5SJed Brown   PC_BDDC          *pcbddc;
6020c7d97c5SJed Brown 
6030c7d97c5SJed Brown   PetscFunctionBegin;
6040c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
6050c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
6060c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
6070c7d97c5SJed Brown   /* create PCIS data structure */
6080c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
6090c7d97c5SJed Brown   /* BDDC specific */
6100c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
6110c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
61253cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
6130c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
6140c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
6150c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
6160c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
6170c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
6180c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
6190c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
6200c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
6210c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
62253cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
62353cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
6240c7d97c5SJed Brown   pcbddc->n_constraints              = 0;
6250c7d97c5SJed Brown   pcbddc->n_vertices                 = 0;
6260c7d97c5SJed Brown   pcbddc->vertices                   = 0;
6270c7d97c5SJed Brown   pcbddc->indices_to_constraint      = 0;
6280c7d97c5SJed Brown   pcbddc->quadrature_constraint      = 0;
6290c7d97c5SJed Brown   pcbddc->sizes_of_constraint        = 0;
6300c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
6310c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
63253cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
6330c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
6340c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
6350c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
6360c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
6370c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
638e269702eSStefano Zampini   pcbddc->dbg_flag                 = PETSC_FALSE;
6390c7d97c5SJed Brown   pcbddc->vertices_flag              = PETSC_FALSE;
6400c7d97c5SJed Brown   pcbddc->constraints_flag           = PETSC_FALSE;
6410c7d97c5SJed Brown   pcbddc->faces_flag                 = PETSC_FALSE;
6420c7d97c5SJed Brown   pcbddc->edges_flag                 = PETSC_FALSE;
6430c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
6440c7d97c5SJed Brown   /* function pointers */
6450c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
6460c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
6470c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
6480c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
6490c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
6500c7d97c5SJed Brown   pc->ops->view                = 0;
6510c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
6520c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
6530c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
6540c7d97c5SJed Brown   /* composing function */
6550c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
6560c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
65753cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
65853cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
6590c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
6600c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
6610c7d97c5SJed Brown   PetscFunctionReturn(0);
6620c7d97c5SJed Brown }
6630c7d97c5SJed Brown EXTERN_C_END
6640c7d97c5SJed Brown 
6650c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6660c7d97c5SJed Brown /*
6670c7d97c5SJed Brown    PCBDDCCoarseSetUp -
6680c7d97c5SJed Brown */
6690c7d97c5SJed Brown #undef __FUNCT__
6700c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
67153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
6720c7d97c5SJed Brown {
6730c7d97c5SJed Brown   PetscErrorCode  ierr;
6740c7d97c5SJed Brown 
6750c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
6760c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6770c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
6780c7d97c5SJed Brown   IS                is_R_local;
6790c7d97c5SJed Brown   IS                is_V_local;
6800c7d97c5SJed Brown   IS                is_C_local;
6810c7d97c5SJed Brown   IS                is_aux1;
6820c7d97c5SJed Brown   IS                is_aux2;
6830c7d97c5SJed Brown   const VecType     impVecType;
6840c7d97c5SJed Brown   const MatType     impMatType;
6850c7d97c5SJed Brown   PetscInt          n_R=0;
6860c7d97c5SJed Brown   PetscInt          n_D=0;
6870c7d97c5SJed Brown   PetscInt          n_B=0;
6880c7d97c5SJed Brown   PetscMPIInt       totprocs;
6890c7d97c5SJed Brown   PetscScalar       zero=0.0;
6900c7d97c5SJed Brown   PetscScalar       one=1.0;
6910c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
6920c7d97c5SJed Brown   PetscScalar*      array;
6930c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
6940c7d97c5SJed Brown   PetscInt          *idx_R_local;
6950c7d97c5SJed Brown   PetscInt          *idx_V_B;
6960c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
6970c7d97c5SJed Brown   PetscScalar       *constraints_errors;
6980c7d97c5SJed Brown   /* auxiliary indices */
6990c7d97c5SJed Brown   PetscInt s,i,j,k;
700e269702eSStefano Zampini   /* for verbose output of bddc */
701e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
702e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
703*a0ba757dSStefano Zampini   /* for counting coarse dofs */
704*a0ba757dSStefano Zampini   PetscScalar       coarsesum;
7050c7d97c5SJed Brown 
7060c7d97c5SJed Brown   PetscFunctionBegin;
7070c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
7080c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
7090c7d97c5SJed Brown   /* Set local primal size */
7100c7d97c5SJed Brown   pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints;
711*a0ba757dSStefano Zampini   /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants) */
712*a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
713*a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
714*a0ba757dSStefano Zampini   for(i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = one; }
715*a0ba757dSStefano Zampini   for(i=0;i<pcbddc->n_constraints;i++) {
716*a0ba757dSStefano Zampini     for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) {
717*a0ba757dSStefano Zampini       k = pcbddc->indices_to_constraint[i][j];
718*a0ba757dSStefano Zampini       if( array[k] == zero ) {
719*a0ba757dSStefano Zampini         array[k] = one;
720*a0ba757dSStefano Zampini         break;
721*a0ba757dSStefano Zampini       }
722*a0ba757dSStefano Zampini     }
723*a0ba757dSStefano Zampini   }
724*a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
725*a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
726*a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
727*a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
728*a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
729*a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
730*a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
731*a0ba757dSStefano Zampini   for(i=0;i<pcis->n;i++) { if(array[i] > zero) array[i] = one/array[i]; }
732*a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
733*a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
734*a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
735*a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
736*a0ba757dSStefano Zampini   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
737*a0ba757dSStefano Zampini   pcbddc->coarse_size = (PetscInt) coarsesum;
738*a0ba757dSStefano Zampini 
7390c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
7400c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
7410c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7420c7d97c5SJed Brown   for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; }
7430c7d97c5SJed Brown   ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
7440c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
7450c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
746e269702eSStefano Zampini   if(dbg_flag) {
7470c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7480c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7490c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
7500c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
7510c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,pcbddc->n_vertices,pcbddc->n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr);
7520c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
753*a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
754*a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
755*a0ba757dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7560c7d97c5SJed Brown   }
7570c7d97c5SJed Brown   /* Allocate needed vectors */
7580c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
7590c7d97c5SJed Brown   impMatType = MATSEQDENSE;
7600c7d97c5SJed Brown   impVecType = VECSEQ;
7610c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
7620c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
7630c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
7640c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
7650c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
766d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
7670c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
7680c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
7690c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
7700c7d97c5SJed Brown 
7710c7d97c5SJed Brown   /* Creating some index sets needed  */
7720c7d97c5SJed Brown   /* For submatrices */
7730c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
7740c7d97c5SJed Brown   if(pcbddc->n_vertices)    { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); }
7750c7d97c5SJed Brown   if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); }
7760c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
7770c7d97c5SJed Brown   {
7780c7d97c5SJed Brown     PetscInt   *aux_array1;
7790c7d97c5SJed Brown     PetscInt   *aux_array2;
7800c7d97c5SJed Brown     PetscScalar      value;
7810c7d97c5SJed Brown 
7820c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
7830c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
7840c7d97c5SJed Brown 
785d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
7860c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7870c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7880c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7890c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7900c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7910c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7920c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7930c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
7940c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7950c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
7960c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
7970c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
7983828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
7990c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
8000c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
8010c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
8020c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
8030c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
8040c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
8050c7d97c5SJed Brown 
806e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
8070c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
8080c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8090c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
8100c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8110c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
8120c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
8130c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
8140c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
8150c7d97c5SJed Brown     }
8160c7d97c5SJed Brown 
8170c7d97c5SJed Brown     /* Check scatters */
818e269702eSStefano Zampini     if(dbg_flag) {
8190c7d97c5SJed Brown 
8200c7d97c5SJed Brown       Vec            vec_aux;
8210c7d97c5SJed Brown 
8220c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8230c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
8240c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
825d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
826d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
827d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
828d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
829d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
830d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
831d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
832d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
833d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
834d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8350c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
836d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8370c7d97c5SJed Brown 
838d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
839d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
840d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
841d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
842d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
843d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
844d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
845d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
846d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
847d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8480c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
849d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8500c7d97c5SJed Brown 
8510c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8520c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
8530c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8540c7d97c5SJed Brown 
855d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
856d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
857d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
858d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
859d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
860d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
861d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
862d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
863d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
864d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8650c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
866d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8670c7d97c5SJed Brown 
868d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
869d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
870d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
871d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
872d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
873d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
874d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
875d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
876d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
877d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8780c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
879d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8800c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8810c7d97c5SJed Brown 
8820c7d97c5SJed Brown     }
8830c7d97c5SJed Brown   }
8840c7d97c5SJed Brown 
8850c7d97c5SJed Brown   /* vertices in boundary numbering */
8860c7d97c5SJed Brown   if(pcbddc->n_vertices) {
887d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
8880c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8890c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; }
8900c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
891d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
892d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8930c7d97c5SJed Brown     ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
8940c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8950c7d97c5SJed Brown     //printf("vertices in boundary numbering\n");
8960c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) {
8970c7d97c5SJed Brown       s=0;
8980c7d97c5SJed Brown       while (array[s] != i ) {s++;}
8990c7d97c5SJed Brown       idx_V_B[i]=s;
9000c7d97c5SJed Brown       //printf("idx_V_B[%d]=%d\n",i,s);
9010c7d97c5SJed Brown     }
9020c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
9030c7d97c5SJed Brown   }
9040c7d97c5SJed Brown 
9050c7d97c5SJed Brown 
9060c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
9070c7d97c5SJed Brown   {
9080c7d97c5SJed Brown     Mat  A_RR;
90953cdbc3dSStefano Zampini     PC   pc_temp;
9100c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
91153cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
91253cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
91353cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
91453cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
915*a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
9160c7d97c5SJed Brown     /* default */
91753cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
91853cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
9190c7d97c5SJed Brown     /* Allow user's customization */
92053cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
92153cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
92253cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
9230c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
9240c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
92553cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
92653cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
92753cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
92853cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
929*a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
9300c7d97c5SJed Brown     /* default */
93153cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
93253cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
9330c7d97c5SJed Brown     /* Allow user's customization */
93453cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
93553cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
93653cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
937*a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
938e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
9390c7d97c5SJed Brown       Vec temp_vec;
9400c7d97c5SJed Brown       PetscScalar value;
9410c7d97c5SJed Brown 
942*a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
943*a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
944*a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
945*a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
946*a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
947*a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
948*a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
949*a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
950*a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
951*a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
952*a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
953d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
954d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
955d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
956d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
957d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
958d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
959e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
9600c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
961d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9620c7d97c5SJed Brown     }
9630c7d97c5SJed Brown     /* free Neumann problem's matrix */
9640c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
9650c7d97c5SJed Brown   }
9660c7d97c5SJed Brown 
9670c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
9680c7d97c5SJed Brown   {
9690c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
9700c7d97c5SJed Brown     Mat          M1,M2;
9710c7d97c5SJed Brown     Mat          C_CR;
9720c7d97c5SJed Brown     Mat          CMAT,AUXMAT;
9730c7d97c5SJed Brown     Vec          vec1_C;
9740c7d97c5SJed Brown     Vec          vec2_C;
9750c7d97c5SJed Brown     Vec          vec1_V;
9760c7d97c5SJed Brown     Vec          vec2_V;
9770c7d97c5SJed Brown     PetscInt     *nnz;
9780c7d97c5SJed Brown     PetscInt     *auxindices;
97953cdbc3dSStefano Zampini     PetscInt     index;
9800c7d97c5SJed Brown     PetscScalar* array2;
9810c7d97c5SJed Brown     MatFactorInfo matinfo;
9820c7d97c5SJed Brown 
9830c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
9840c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
9850c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
9860c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
9870c7d97c5SJed Brown 
9880c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
9890c7d97c5SJed Brown     if(pcbddc->n_vertices) {
9900c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
9910c7d97c5SJed Brown       ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr);
9920c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
9930c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
9940c7d97c5SJed Brown     }
9950c7d97c5SJed Brown     if(pcbddc->n_constraints) {
9960c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
9970c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
9980c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
9990c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
10000c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
10010c7d97c5SJed Brown     }
10020c7d97c5SJed Brown     /* Create C matrix [I 0; 0 const] */
1003d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&CMAT);CHKERRQ(ierr);
10040c7d97c5SJed Brown     ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr);
10050c7d97c5SJed Brown     ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
10060c7d97c5SJed Brown     /* nonzeros */
10070c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; }
10080c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];}
10090c7d97c5SJed Brown     ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr);
10100c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
10110c7d97c5SJed Brown       ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
10120c7d97c5SJed Brown     }
10130c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
101453cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
101553cdbc3dSStefano Zampini       ierr = MatSetValues(CMAT,1,&index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES);CHKERRQ(ierr);
10160c7d97c5SJed Brown     }
1017e269702eSStefano Zampini     //if(dbg_flag) printf("CMAT assembling\n");
10180c7d97c5SJed Brown     ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10190c7d97c5SJed Brown     ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10200c7d97c5SJed Brown     //ierr = MatView(CMAT,PETSC_VIEWER_STDOUT_SELF);
10210c7d97c5SJed Brown 
10220c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
10230c7d97c5SJed Brown 
10240c7d97c5SJed Brown     if(pcbddc->n_constraints) {
10250c7d97c5SJed Brown       /* some work vectors */
10260c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
10270c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr);
10280c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
10290c7d97c5SJed Brown 
10300c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
10310c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
1032d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
10330c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10340c7d97c5SJed Brown         for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; }
10350c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
10360c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
10370c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10380c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
103953cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
10400c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
104153cdbc3dSStefano Zampini         index=i;
104253cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
10430c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
10440c7d97c5SJed Brown       }
1045e269702eSStefano Zampini       //if(dbg_flag) printf("pcbddc->local_auxmat2 assembling\n");
10460c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10470c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10480c7d97c5SJed Brown 
10490c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
10500c7d97c5SJed Brown       ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
10510c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
10520c7d97c5SJed Brown 
10530c7d97c5SJed Brown         /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
10540c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1055d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
10560c7d97c5SJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
10570c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
10580c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
10590c7d97c5SJed Brown 
10600c7d97c5SJed Brown         /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */
1061d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
10620c7d97c5SJed Brown       ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
10630c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
10640c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
10650c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
10660c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
10670c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
10680c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
10690c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
10700c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
10710c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
107253cdbc3dSStefano Zampini         index=i;
107353cdbc3dSStefano Zampini         ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
10740c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
10750c7d97c5SJed Brown       }
1076e269702eSStefano Zampini       //if(dbg_flag) printf("M1 assembling\n");
10770c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10780c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10790c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
10800c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
1081e269702eSStefano Zampini       //if(dbg_flag) printf("pcbddc->local_auxmat1 computing and assembling\n");
10820c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
10830c7d97c5SJed Brown 
10840c7d97c5SJed Brown     }
10850c7d97c5SJed Brown 
10860c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
10870c7d97c5SJed Brown     if(pcbddc->n_vertices){
10880c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
10890c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
10900c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
10910c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1092d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
10930c7d97c5SJed Brown       ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr);
10940c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
10950c7d97c5SJed Brown       for(i=0;i<pcbddc->n_vertices;i++) {
10960c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
10970c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
10980c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
10990c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11000c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
110153cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
110253cdbc3dSStefano Zampini         index=i;
11030c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
110453cdbc3dSStefano Zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11050c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
11060c7d97c5SJed Brown       }
1107e269702eSStefano Zampini       //if(dbg_flag) printf("M2 assembling\n");
11080c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11090c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11100c7d97c5SJed Brown     }
11110c7d97c5SJed Brown 
11120c7d97c5SJed Brown /* Matrix of coarse basis functions (local) */
1113d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
11140c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
11150c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
1116e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1117d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
11180c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
11190c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
11200c7d97c5SJed Brown     }
11210c7d97c5SJed Brown 
11220c7d97c5SJed Brown /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1123e269702eSStefano Zampini     if(dbg_flag) {
11240c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
11250c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
11260c7d97c5SJed Brown     }
11270c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
11280c7d97c5SJed Brown 
11290c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
11300c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
11310c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
11320c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
11330c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
11340c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11350c7d97c5SJed Brown       /* solution of saddle point problem */
11360c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
11370c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
11380c7d97c5SJed Brown       if(pcbddc->n_constraints) {
11390c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
11400c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
11410c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
11420c7d97c5SJed Brown       }
11430c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
11440c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
11450c7d97c5SJed Brown 
11460c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
11470c7d97c5SJed Brown       /* coarse basis functions */
114853cdbc3dSStefano Zampini       index=i;
11490c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
11500c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11510c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11520c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
115353cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11540c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
11550c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1156e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
11570c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11580c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11590c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
116053cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11610c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
11620c7d97c5SJed Brown       }
11630c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
11640c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
11650c7d97c5SJed Brown       for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
11660c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
11670c7d97c5SJed Brown       if( pcbddc->n_constraints) {
11680c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
11690c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j+pcbddc->n_vertices]=array[j];} //WARNING -> column major ordering
11700c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
11710c7d97c5SJed Brown       }
11720c7d97c5SJed Brown 
1173e269702eSStefano Zampini       if( dbg_flag ) {
11740c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1175d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
11760c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11770c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
11780c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
11790c7d97c5SJed Brown         array[ pcbddc->vertices[i] ] = one;
11800c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
11810c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11820c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1183d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
11840c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
11850c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
11860c7d97c5SJed Brown         for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; }
11870c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
11880c7d97c5SJed Brown         if(pcbddc->n_constraints) {
11890c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
11900c7d97c5SJed Brown           for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; }
11910c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
11920c7d97c5SJed Brown         }
11930c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
11940c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
11950c7d97c5SJed Brown         /* check saddle point solution */
11960c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
119753cdbc3dSStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
119853cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
11990c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
12000c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
120153cdbc3dSStefano Zampini         array[index]=array[index]+m_one;  /* shift by the identity matrix */
12020c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
120353cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
12040c7d97c5SJed Brown       }
12050c7d97c5SJed Brown     }
12060c7d97c5SJed Brown 
12070c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++){
1208d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
12090c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
12100c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
12110c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
12120c7d97c5SJed Brown       /* solution of saddle point problem */
12130c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
12140c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
12150c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
12160c7d97c5SJed Brown       if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
12170c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
12180c7d97c5SJed Brown       /* coarse basis functions */
121953cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
12200c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
12210c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12220c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12230c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
122453cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12250c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1226e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
12270c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12280c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12290c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
123053cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12310c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
12320c7d97c5SJed Brown       }
12330c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
12340c7d97c5SJed Brown       if(pcbddc->n_vertices) {
12350c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
123653cdbc3dSStefano Zampini         for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
12370c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12380c7d97c5SJed Brown       }
12390c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
124053cdbc3dSStefano Zampini       for(j=0;j<pcbddc->n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+pcbddc->n_vertices]=array[j];} //WARNING -> column major ordering
12410c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12420c7d97c5SJed Brown 
1243e269702eSStefano Zampini       if( dbg_flag ) {
12440c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
124553cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
12460c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12470c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12480c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
12490c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12500c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12510c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
125253cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
12530c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12540c7d97c5SJed Brown         if( pcbddc->n_vertices) {
12550c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12560c7d97c5SJed Brown           for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];}
12570c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12580c7d97c5SJed Brown         }
12590c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12600c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];}
12610c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12620c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12630c7d97c5SJed Brown         /* check saddle point solution */
12640c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1265d49ef151SStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
126653cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
12670c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
12680c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
126953cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
12700c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
127153cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
12720c7d97c5SJed Brown       }
12730c7d97c5SJed Brown     }
12740c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12750c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1276e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
12770c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12780c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12790c7d97c5SJed Brown     }
12800c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
12810c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1282*a0ba757dSStefano Zampini     //if(dbg_flag) {
1283*a0ba757dSStefano Zampini     if(PETSC_FALSE) { /* waiting for patch on conversion from SEQDENSE to SEQAIJ with new nonzero location errors */
12840c7d97c5SJed Brown 
12850c7d97c5SJed Brown       Mat coarse_sub_mat;
12860c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
12870c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1288*a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
12890c7d97c5SJed Brown       PetscScalar      value;
12900c7d97c5SJed Brown 
1291c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1292c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1293c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1294c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1295c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1296c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1297c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1298c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
12990c7d97c5SJed Brown 
13000c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13010c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
13020c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
130353cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
130453cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
130553cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1306c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
130753cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
130853cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1309c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
131053cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
131153cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
131253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
131353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
131453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
131553cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
13160c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
13170c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
13180c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
13190c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
132053cdbc3dSStefano 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); }
13210c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
132253cdbc3dSStefano 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); }
13230c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
132453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
132553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
132653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
132753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
132853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
132953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
133053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
133153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
133253cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
133353cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
133453cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
13350c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
13360c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
13370c7d97c5SJed Brown     }
13380c7d97c5SJed Brown 
13390c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
13400c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
13410c7d97c5SJed Brown     /* free memory */
13420c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
13430c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
13440c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
13450c7d97c5SJed Brown     if(pcbddc->n_vertices) {
13460c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
13470c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
13480c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
13490c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
13500c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
13510c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
13520c7d97c5SJed Brown     }
13530c7d97c5SJed Brown     if(pcbddc->n_constraints) {
13540c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
13550c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
13560c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
13570c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
13580c7d97c5SJed Brown     }
13590c7d97c5SJed Brown     ierr = MatDestroy(&CMAT);CHKERRQ(ierr);
13600c7d97c5SJed Brown   }
13610c7d97c5SJed Brown   /* free memory */
13620c7d97c5SJed Brown   if(pcbddc->n_vertices) {
13630c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
13640c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
13650c7d97c5SJed Brown   }
13660c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
13670c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
13680c7d97c5SJed Brown 
13690c7d97c5SJed Brown   PetscFunctionReturn(0);
13700c7d97c5SJed Brown }
13710c7d97c5SJed Brown 
13720c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13730c7d97c5SJed Brown 
13740c7d97c5SJed Brown #undef __FUNCT__
13750c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
137653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
13770c7d97c5SJed Brown {
13780c7d97c5SJed Brown 
13790c7d97c5SJed Brown 
13800c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
13810c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
13820c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
13830c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
13840c7d97c5SJed Brown   MPI_Comm  coarse_comm;
13850c7d97c5SJed Brown 
13860c7d97c5SJed Brown   /* common to all choiches */
13870c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
13880c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
13890c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
13900c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
13910c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
13920c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
13930c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
13940c7d97c5SJed Brown   PetscMPIInt master_proc=0;
13950c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
13960c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
13970c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
13980c7d97c5SJed Brown   PetscMPIInt count_recv=0;
13990c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
14000c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
14010c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
14020c7d97c5SJed Brown   /* some other variables */
14030c7d97c5SJed Brown   PetscErrorCode ierr;
14040c7d97c5SJed Brown   const MatType coarse_mat_type;
14050c7d97c5SJed Brown   const PCType  coarse_pc_type;
140653cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
140753cdbc3dSStefano Zampini   PC pc_temp;
14080c7d97c5SJed Brown   PetscInt i,j,k,bs;
1409e269702eSStefano Zampini   /* verbose output viewer */
1410e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1411e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
14120c7d97c5SJed Brown 
14130c7d97c5SJed Brown   PetscFunctionBegin;
14140c7d97c5SJed Brown 
14150c7d97c5SJed Brown   ins_local_primal_indices = 0;
14160c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
14170c7d97c5SJed Brown   localsizes2              = 0;
14180c7d97c5SJed Brown   localdispl2              = 0;
14190c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
14200c7d97c5SJed Brown   coarse_ISLG              = 0;
14210c7d97c5SJed Brown 
142253cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
142353cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
14240c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
14250c7d97c5SJed Brown 
1426beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1427beed3852SStefano Zampini   {
1428*a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1429beed3852SStefano Zampini     PetscScalar    *array;
1430beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1431beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1432beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1433beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1434beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1435beed3852SStefano Zampini 
1436beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1437beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1438beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1439beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1440beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
14415619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1442beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1443beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1444beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1445beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1446beed3852SStefano Zampini     }
14475619798eSStefano Zampini     if(rank_prec_comm == 0) {
1448beed3852SStefano Zampini       /* allocate some auxiliary space */
1449beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1450beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1451beed3852SStefano Zampini     }
1452beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1453beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1454beed3852SStefano Zampini 
1455beed3852SStefano Zampini     /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants)
1456beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1457beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1458beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1459beed3852SStefano Zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) */
1460beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1461beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1462beed3852SStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++) {
1463beed3852SStefano Zampini       array[ pcbddc->vertices[i] ] = one;
1464beed3852SStefano Zampini       auxlocal_primal[i] = pcbddc->vertices[i];
1465beed3852SStefano Zampini     }
1466beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
1467beed3852SStefano Zampini       for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) {
1468beed3852SStefano Zampini         k = pcbddc->indices_to_constraint[i][j];
1469beed3852SStefano Zampini         if( array[k] == zero ) {
1470beed3852SStefano Zampini           array[k] = one;
1471beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1472beed3852SStefano Zampini           break;
1473beed3852SStefano Zampini         }
1474beed3852SStefano Zampini       }
1475beed3852SStefano Zampini     }
1476beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1477*a0ba757dSStefano Zampini 
1478*a0ba757dSStefano Zampini     /*ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1479beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1480beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1481beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1482beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1483beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1484d49ef151SStefano Zampini     for(i=0;i<pcis->n;i++) { if(array[i] > 0.0) array[i] = one/array[i]; }
1485beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1486beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1487beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1488beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1489beed3852SStefano Zampini 
1490beed3852SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1491beed3852SStefano Zampini     pcbddc->coarse_size = (PetscInt) coarsesum;
1492e269702eSStefano Zampini     if(dbg_flag) {
1493e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
14943828260eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1495e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1496*a0ba757dSStefano Zampini     }*/
1497*a0ba757dSStefano Zampini 
1498beed3852SStefano Zampini     /* Now assign them a global numbering */
1499beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1500beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1501beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1502beed3852SStefano Zampini     ierr = MPI_Gatherv(&auxglobal_primal[0],pcbddc->local_primal_size,MPIU_INT,&all_auxglobal_primal[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1503beed3852SStefano Zampini 
1504beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1505beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1506beed3852SStefano Zampini     if(rank_prec_comm==0) {
1507beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1508beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1509beed3852SStefano Zampini       k=1;
1510beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1511beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1512beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1513beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1514beed3852SStefano Zampini           k++;
1515beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1516beed3852SStefano Zampini         }
1517beed3852SStefano Zampini       }
1518beed3852SStefano Zampini     } else {
1519beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1520beed3852SStefano Zampini     }
15215619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1522beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1523beed3852SStefano Zampini 
1524beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1525beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1526beed3852SStefano Zampini       k=0;
1527beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1528beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1529beed3852SStefano Zampini     }
1530e269702eSStefano Zampini     if(dbg_flag) {
1531e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1532e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1533e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1534e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1535e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1536e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1537e269702eSStefano Zampini       }
1538e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1539e269702eSStefano Zampini     }
1540beed3852SStefano Zampini     /* free allocated memory */
1541beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1542beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1543beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1544e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1545beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1546beed3852SStefano Zampini     }
1547e269702eSStefano Zampini   }
1548beed3852SStefano Zampini 
15490c7d97c5SJed Brown   /* adapt coarse problem type */
15500c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
15510c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
15520c7d97c5SJed Brown 
15530c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
15540c7d97c5SJed Brown 
15550c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
15560c7d97c5SJed Brown     {
15570c7d97c5SJed Brown       /* we need additional variables */
15580c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15590c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
15600c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
15610c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15620c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15630c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15640c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15650c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15660c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15670c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15680c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15690c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15700c7d97c5SJed Brown       MetisInt    *faces_xadj;
15710c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15720c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15730c7d97c5SJed Brown       PetscInt    *array_int;
15740c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15750c7d97c5SJed Brown       PetscMPIInt total_faces=0;
15763828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
15770c7d97c5SJed Brown 
15780c7d97c5SJed Brown       /* define some quantities */
15790c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15800c7d97c5SJed Brown       coarse_mat_type = MATIS;
15810c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
158253cdbc3dSStefano Zampini       coarse_ksp_type  = KSPRICHARDSON;
15830c7d97c5SJed Brown 
15840c7d97c5SJed Brown       /* details of coarse decomposition */
15850c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
15860c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
15873828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
15883828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
15893828260eSStefano Zampini 
15903828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1591*a0ba757dSStefano Zampini       printf("n_subdomains %d, n_parts %d\nstretch %d,jumps %d,coarse_ratio %d\nlevel should be log_%d(%d)\n",n_subdomains,n_parts,ranks_stretching_ratio,procs_jumps_coarse_comm,pcbddc->coarsening_ratio,pcbddc->coarsening_ratio,(ranks_stretching_ratio/pcbddc->coarsening_ratio+1));
15920c7d97c5SJed Brown 
15930c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
15940c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
15953828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
15960c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
15970c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15980c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
15990c7d97c5SJed Brown         }
16000c7d97c5SJed Brown       }
16010c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
16020c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
16030c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
16040c7d97c5SJed Brown             my_faces++;
16050c7d97c5SJed Brown             break;
16060c7d97c5SJed Brown           }
16070c7d97c5SJed Brown         }
16080c7d97c5SJed Brown       }
16090c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
16100c7d97c5SJed Brown 
161153cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
16120c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
16130c7d97c5SJed Brown       my_faces=0;
16140c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
16150c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
16160c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
16170c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
16180c7d97c5SJed Brown             my_faces++;
16190c7d97c5SJed Brown             break;
16200c7d97c5SJed Brown           }
16210c7d97c5SJed Brown         }
16220c7d97c5SJed Brown       }
16230c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
16240c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
16250c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
16260c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
16270c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
16280c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
16290c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
16300c7d97c5SJed Brown       }
163153cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16320c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
16330c7d97c5SJed Brown         faces_xadj[0]=0;
16340c7d97c5SJed Brown         faces_displacements[0]=0;
16350c7d97c5SJed Brown         j=0;
16360c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
16370c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
16380c7d97c5SJed Brown           if(number_of_faces[i-1]) {
16390c7d97c5SJed Brown             j++;
16400c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
16410c7d97c5SJed Brown           }
16420c7d97c5SJed Brown         }
16430c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
16440c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
16450c7d97c5SJed Brown       }
164653cdbc3dSStefano 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);
16470c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
16480c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
16490c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
16503828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
16513828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
16520c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
16530c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
16540c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
16550c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
16560c7d97c5SJed Brown           printf("\n");
16570c7d97c5SJed Brown         }
16580c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16590c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16600c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16610c7d97c5SJed Brown       }
16620c7d97c5SJed Brown 
16630c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
16640c7d97c5SJed Brown 
16653828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
16663828260eSStefano Zampini 
16670c7d97c5SJed Brown         ncon=1;
16680c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16690c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16700c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16710c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16720c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16730c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16740c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
16750c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16760c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
16773828260eSStefano Zampini         printf("METIS PART GRAPH\n");
16783828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
16793828260eSStefano Zampini           printf("Using Kway\n");
16803828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
16813828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16820c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
16833828260eSStefano Zampini         } else {
16843828260eSStefano Zampini           printf("Using Recursive\n");
16853828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
16863828260eSStefano Zampini         }
16870c7d97c5SJed Brown         if(ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetupCoarseEnvironment\n",ierr);
16883828260eSStefano Zampini         printf("Partition done!\n");
16890c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
16900c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
16910c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
16920c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
16933828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
16943828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
16950c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
16960c7d97c5SJed Brown       }
16970c7d97c5SJed Brown 
16980c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
16990c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
17000c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
17010c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
17020c7d97c5SJed Brown       }
17030c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
17040c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
170553cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
17060c7d97c5SJed Brown 
17070c7d97c5SJed Brown       if( coarse_color == 0 ) {
170853cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
170953cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
17103828260eSStefano Zampini         printf("Details of coarse comm\n");
17113828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
17123828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
17130c7d97c5SJed Brown       } else {
17140c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
17150c7d97c5SJed Brown       }
17160c7d97c5SJed Brown 
17170c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
17180c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
17190c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
17200c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
17210c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
17220c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
17230c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
17240c7d97c5SJed Brown         /* some initializations */
17250c7d97c5SJed Brown         displacements_recv[0]=0;
17260c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
17270c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
17280c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
17293828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
17300c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
17310c7d97c5SJed Brown               total_count_recv[j]++;
17320c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
17330c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
17340c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
17350c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17360c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
17373828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
17380c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
17390c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
17403828260eSStefano Zampini               total_count_recv[j]+=1;
17410c7d97c5SJed Brown             }
17420c7d97c5SJed Brown           }
17430c7d97c5SJed Brown         }
17443828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
17453828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
17463828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
17473828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
17483828260eSStefano Zampini           }
17493828260eSStefano Zampini           printf("\n");
17503828260eSStefano Zampini         }
17510c7d97c5SJed Brown 
17520c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
17533828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
17540c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
17550c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
17563828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
17573828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
17583828260eSStefano Zampini           } else {
17593828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
17603828260eSStefano Zampini           }
17610c7d97c5SJed Brown         printf("\n");
17620c7d97c5SJed Brown       }
17630c7d97c5SJed Brown 
17640c7d97c5SJed Brown       /* Scatter new decomposition for send details */
176553cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
17660c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17670c7d97c5SJed Brown       if( coarse_color == 0) {
176853cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17690c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
177053cdbc3dSStefano 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);
17710c7d97c5SJed Brown       }
17720c7d97c5SJed Brown 
17730c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
17740c7d97c5SJed Brown       //if(coarse_color == 0) {
17750c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
17760c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
17770c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
17780c7d97c5SJed Brown       //  printf("\n");
17790c7d97c5SJed Brown       //}
17800c7d97c5SJed Brown 
17810c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
17820c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
17830c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17840c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17850c7d97c5SJed Brown         free(coarse_subdivision);
17860c7d97c5SJed Brown         free(total_count_recv);
17870c7d97c5SJed Brown         free(total_ranks_recv);
17880c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17890c7d97c5SJed Brown       }
17900c7d97c5SJed Brown       break;
17910c7d97c5SJed Brown     }
17920c7d97c5SJed Brown 
17930c7d97c5SJed Brown     case(REPLICATED_BDDC):
17940c7d97c5SJed Brown 
17950c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17960c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17970c7d97c5SJed Brown       coarse_pc_type  = PCLU;
179853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17990c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18000c7d97c5SJed Brown       active_rank = rank_prec_comm;
18010c7d97c5SJed Brown       break;
18020c7d97c5SJed Brown 
18030c7d97c5SJed Brown     case(PARALLEL_BDDC):
18040c7d97c5SJed Brown 
18050c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
18060c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
18070c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
180853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18090c7d97c5SJed Brown       coarse_comm = prec_comm;
18100c7d97c5SJed Brown       active_rank = rank_prec_comm;
18110c7d97c5SJed Brown       break;
18120c7d97c5SJed Brown 
18130c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
18140c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
18150c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
18160c7d97c5SJed Brown       coarse_pc_type = PCLU;
181753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18180c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18190c7d97c5SJed Brown       active_rank = master_proc;
18200c7d97c5SJed Brown       break;
18210c7d97c5SJed Brown   }
18220c7d97c5SJed Brown 
18230c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
18240c7d97c5SJed Brown 
18250c7d97c5SJed Brown     case(SCATTERS_BDDC):
18260c7d97c5SJed Brown       {
18270c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
18280c7d97c5SJed Brown 
18290c7d97c5SJed Brown           PetscMPIInt send_size;
18300c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
18310c7d97c5SJed Brown           PetscInt    ii,jj;
18320c7d97c5SJed Brown           MPI_Request *requests;
18330c7d97c5SJed Brown 
18340c7d97c5SJed Brown           /* allocate auxiliary space */
18355619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
18365619798eSStefano Zampini           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],pcbddc->local_primal_size,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
18370c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
18380c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
18390c7d97c5SJed Brown           /* allocate stuffs for message massing */
18400c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
18410c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
18420c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
18430c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
18440c7d97c5SJed Brown           /* fill up quantities */
18450c7d97c5SJed Brown           j=0;
18460c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
18470c7d97c5SJed Brown             ii = ranks_recv[i];
18480c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
18490c7d97c5SJed Brown             localdispl2[i]=j;
18500c7d97c5SJed Brown             j+=localsizes2[i];
18510c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
18520c7d97c5SJed Brown             for(k=0;k<pcbddc->local_primal_sizes[ii];k++) aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]]+=1;  // it counts the coarse subdomains sharing the coarse node
18530c7d97c5SJed Brown           }
18540c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
18550c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
18560c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
18570c7d97c5SJed Brown           //printf("\n");
18580c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
18590c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
18600c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
18610c7d97c5SJed Brown           ins_local_primal_size=0;
18620c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
18630c7d97c5SJed Brown             if(aux_ins_indices[i])
18640c7d97c5SJed Brown               ins_local_primal_size++;
18650c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
18660c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
18670c7d97c5SJed Brown           j=0;
18680c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
18690c7d97c5SJed Brown             if(aux_ins_indices[i])
18700c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
18710c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
18720c7d97c5SJed Brown           j=0;
18730c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
18740c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
18750c7d97c5SJed Brown               aux_ins_indices[i]=-1;
18760c7d97c5SJed Brown             } else {
18770c7d97c5SJed Brown               aux_ins_indices[i]=j;
18780c7d97c5SJed Brown               j++;
18790c7d97c5SJed Brown             }
18800c7d97c5SJed Brown           }
18810c7d97c5SJed Brown 
18820c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
18830c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
18840c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
18850c7d97c5SJed Brown           //printf("\n");
18860c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
18870c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
18880c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
18890c7d97c5SJed Brown           //printf("\n");
18900c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
18910c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
18920c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
18930c7d97c5SJed Brown           //printf("\n");
18940c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
18950c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
18960c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
18970c7d97c5SJed Brown           //    printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]);
18980c7d97c5SJed Brown           //printf("\n");
18990c7d97c5SJed Brown 
19000c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
190153cdbc3dSStefano Zampini           for(i=0;i<count_recv;i++) ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
19020c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
19030c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
190453cdbc3dSStefano 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);
19050c7d97c5SJed Brown           }
190653cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
19070c7d97c5SJed Brown 
19080c7d97c5SJed Brown           //if(coarse_color == 0) {
19090c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
19100c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
19110c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
19120c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
19130c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
19140c7d97c5SJed Brown           //        printf("(%lf %d %d)\n",temp_coarse_mat_vals[localdispl2[k]+j*pcbddc->local_primal_sizes[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+j]);
19150c7d97c5SJed Brown           //    printf("\n");
19160c7d97c5SJed Brown           //  }
19170c7d97c5SJed Brown           //}
19180c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
19190c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19200c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
19210c7d97c5SJed Brown 
19220c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
19230c7d97c5SJed Brown           PetscInt row_ind,col_ind;
19240c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
19250c7d97c5SJed Brown             rr = ranks_recv[k];
19260c7d97c5SJed Brown             kk = localdispl2[k];
19270c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
19280c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
19290c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
19300c7d97c5SJed Brown             for(j=0;j<lps;j++){
19310c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
19320c7d97c5SJed Brown               for(i=0;i<lps;i++){
19330c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
19340c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
19350c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
19360c7d97c5SJed Brown               }
19370c7d97c5SJed Brown             }
19380c7d97c5SJed Brown           }
19390c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
19400c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
19410c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
19420c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
19430c7d97c5SJed Brown 
19440c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
19450c7d97c5SJed Brown           {
19460c7d97c5SJed Brown             IS coarse_IS;
194753cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
19480c7d97c5SJed Brown             coarse_comm = prec_comm;
19490c7d97c5SJed Brown             active_rank=rank_prec_comm;
19500c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
19510c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
19520c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
19530c7d97c5SJed Brown           }
19540c7d97c5SJed Brown         }
19550c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
19560c7d97c5SJed Brown           /* arrays for values insertion */
19570c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
19580c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
19590c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19600c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
19610c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
19620c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
19630c7d97c5SJed Brown           }
19640c7d97c5SJed Brown         }
19650c7d97c5SJed Brown         break;
19660c7d97c5SJed Brown 
19670c7d97c5SJed Brown     }
19680c7d97c5SJed Brown 
19690c7d97c5SJed Brown     case(GATHERS_BDDC):
19700c7d97c5SJed Brown       {
19710c7d97c5SJed Brown 
19720c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
19730c7d97c5SJed Brown 
19740c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
19750c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19760c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
19770c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19780c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19790c7d97c5SJed Brown           /* arrays for values insertion */
19800c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
19810c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
19820c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19830c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19840c7d97c5SJed Brown           localdispl2[0]=0;
19850c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
19860c7d97c5SJed Brown           j=0;
19870c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
19880c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19890c7d97c5SJed Brown         }
19900c7d97c5SJed Brown 
19910c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
19920c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
19930c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
199453cdbc3dSStefano Zampini           ierr = MPI_Gatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
199553cdbc3dSStefano Zampini           ierr = MPI_Gatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,master_proc,prec_comm);CHKERRQ(ierr);
19960c7d97c5SJed Brown         } else {
199753cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
199853cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
19990c7d97c5SJed Brown         }
20000c7d97c5SJed Brown 
20010c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
20020c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
20030c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
20040c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
20050c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
20060c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
20070c7d97c5SJed Brown           }
20080c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
20090c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
20100c7d97c5SJed Brown             offset2=localdispl2[k];
20110c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
20120c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
20130c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
20140c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
20150c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
20160c7d97c5SJed Brown               }
20170c7d97c5SJed Brown             }
20180c7d97c5SJed Brown           }
20190c7d97c5SJed Brown         }
20200c7d97c5SJed Brown         break;
20210c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
20220c7d97c5SJed Brown   }
20230c7d97c5SJed Brown 
20240c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
20250c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
20260c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
20270c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
20280c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
20290c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
20300c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20310c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
20320c7d97c5SJed Brown     } else {
20330c7d97c5SJed Brown       Mat matis_coarse_local_mat;
20340c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
20350c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
20360c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2037*a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20380c7d97c5SJed Brown     }
2039*a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
20400c7d97c5SJed 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);
20410c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20420c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20430c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20440c7d97c5SJed Brown       Mat matis_coarse_local_mat;
20450c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
20460c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
20470c7d97c5SJed Brown     }
20480c7d97c5SJed Brown 
20490c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
20500c7d97c5SJed Brown     /* Preconditioner for coarse problem */
205153cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
205253cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
205353cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
20545619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
205553cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
205653cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
205753cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
20580c7d97c5SJed Brown     /* Allow user's customization */
205953cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
20600c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
206153cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2062e269702eSStefano Zampini       if(dbg_flag) {
2063e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2064e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2065e269702eSStefano Zampini       }
206653cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
206753cdbc3dSStefano Zampini     }
206853cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
20695619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20705619798eSStefano Zampini       if(dbg_flag) {
20715619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
20725619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20735619798eSStefano Zampini       }
20745619798eSStefano Zampini     }
20750c7d97c5SJed Brown   }
20760c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
20770c7d97c5SJed Brown      IS local_IS,global_IS;
20780c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
20790c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
20800c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
20810c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
20820c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
20830c7d97c5SJed Brown   }
20840c7d97c5SJed Brown 
20850c7d97c5SJed Brown 
20860c7d97c5SJed Brown   /* Check condition number of coarse problem */
2087e269702eSStefano Zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && dbg_flag && rank_prec_comm == active_rank ) {
20880c7d97c5SJed Brown     PetscScalar m_one=-1.0;
20895619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
20900c7d97c5SJed Brown 
20915619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
2092d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
20935619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,KSPGMRES);CHKERRQ(ierr);
20945619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
20955619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2096d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2097d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2098d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2099d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2100d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
21015619798eSStefano Zampini     kappa_2=lambda_max/lambda_min;
21025619798eSStefano Zampini     ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2103d49ef151SStefano Zampini     ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2104d49ef151SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
21055619798eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem condition number estimated with %d iterations of gmres is: % 1.14e\n",k,kappa_2);CHKERRQ(ierr);
2106e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2107e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
21085619798eSStefano Zampini     /* restore coarse ksp to default values */
2109d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
21105619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
21115619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
21125619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
21135619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
211453cdbc3dSStefano Zampini   }
21150c7d97c5SJed Brown 
21160c7d97c5SJed Brown   /* free data structures no longer needed */
21170c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
21180c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
21190c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
21200c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
21210c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
21220c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
21230c7d97c5SJed Brown 
21240c7d97c5SJed Brown   PetscFunctionReturn(0);
21250c7d97c5SJed Brown }
21260c7d97c5SJed Brown 
21270c7d97c5SJed Brown #undef __FUNCT__
21280c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
212953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
21300c7d97c5SJed Brown {
21310c7d97c5SJed Brown 
21320c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
21330c7d97c5SJed Brown   PC_IS      *pcis = (PC_IS*)pc->data;
21340c7d97c5SJed Brown   Mat_IS   *matis  = (Mat_IS*)pc->pmat->data;
213553cdbc3dSStefano Zampini   PetscInt **neighbours_set;
213653cdbc3dSStefano Zampini   PetscInt bs,ierr,i,j,s,k,iindex;
21370c7d97c5SJed Brown   PetscInt total_counts;
21380c7d97c5SJed Brown   PetscBool flg_row;
21390c7d97c5SJed Brown   PCBDDCGraph mat_graph;
214053cdbc3dSStefano Zampini   PetscInt   neumann_bsize;
214153cdbc3dSStefano Zampini   const PetscInt*  neumann_nodes;
21420c7d97c5SJed Brown   Mat        mat_adj;
2143*a0ba757dSStefano Zampini   PetscBool  symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2144*a0ba757dSStefano Zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
2145*a0ba757dSStefano Zampini   PetscInt*   queue_in_global_numbering;
2146*a0ba757dSStefano Zampini   MPI_Comm interface_comm=((PetscObject)pc)->comm;
21470c7d97c5SJed Brown 
21480c7d97c5SJed Brown   PetscFunctionBegin;
21490c7d97c5SJed Brown 
2150*a0ba757dSStefano Zampini   /* allocate and initialize needed graph structure */
21510c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
21520c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2153*a0ba757dSStefano Zampini   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2154*a0ba757dSStefano Zampini   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
21550c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2156*a0ba757dSStefano Zampini   /* ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->where);CHKERRQ(ierr);
21570c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->count);CHKERRQ(ierr);
21580c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->which_dof);CHKERRQ(ierr);
21590c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->queue);CHKERRQ(ierr);
21600c7d97c5SJed Brown   ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->cptr);CHKERRQ(ierr);
2161*a0ba757dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&queue_in_global_numbering);CHKERRQ(ierr);
2162*a0ba757dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscBool),&mat_graph->touched);CHKERRQ(ierr); */
2163*a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2164*a0ba757dSStefano 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);
2165*a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2166*a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2167*a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2168*a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2169*a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
21703828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
21713828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2172*a0ba757dSStefano Zampini 
2173*a0ba757dSStefano Zampini   /* TODO: IS for dof splitting */
2174*a0ba757dSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
21750c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs/bs;i++) {
21760c7d97c5SJed Brown     for(s=0;s<bs;s++) {
21770c7d97c5SJed Brown       mat_graph->which_dof[i*bs+s]=s;
21780c7d97c5SJed Brown     }
21790c7d97c5SJed Brown   }
21800c7d97c5SJed Brown 
21810c7d97c5SJed Brown   total_counts=0;
21820c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
21830c7d97c5SJed Brown     s=pcis->n_shared[i];
21840c7d97c5SJed Brown     total_counts+=s;
218553cdbc3dSStefano Zampini     for(j=0;j<s;j++){
21860c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
21870c7d97c5SJed Brown     }
21880c7d97c5SJed Brown   }
21890c7d97c5SJed Brown   /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */
219053cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
219153cdbc3dSStefano Zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
219253cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
219353cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
219453cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
219553cdbc3dSStefano Zampini       if(mat_graph->count[iindex] > 2){
219653cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
21970c7d97c5SJed Brown         total_counts++;
21980c7d97c5SJed Brown       }
21990c7d97c5SJed Brown     }
22000c7d97c5SJed Brown   }
22010c7d97c5SJed Brown 
2202*a0ba757dSStefano Zampini   /* allocate space for storing neighbours' set */
220353cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
220453cdbc3dSStefano Zampini   if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr);
220553cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2206*a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
22070c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
22080c7d97c5SJed Brown     s=pcis->n_shared[i];
22090c7d97c5SJed Brown     for(j=0;j<s;j++) {
22100c7d97c5SJed Brown       k=pcis->shared[i][j];
221153cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
22120c7d97c5SJed Brown       mat_graph->count[k]+=1;
22130c7d97c5SJed Brown     }
22140c7d97c5SJed Brown   }
22150c7d97c5SJed Brown   /* set -1 fake neighbour */
221653cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
221753cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
221853cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
221953cdbc3dSStefano Zampini       if( mat_graph->count[iindex] > 2){
2220*a0ba757dSStefano Zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1; /* An additional fake neighbour (with rank -1) */
222153cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
22220c7d97c5SJed Brown       }
22230c7d97c5SJed Brown     }
222453cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
22250c7d97c5SJed Brown   }
2226*a0ba757dSStefano Zampini   /* sort set of sharing subdomains for comparison */
222753cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
2228*a0ba757dSStefano Zampini   /* start analyzing local interface */
22290c7d97c5SJed Brown   PetscInt nodes_touched=0;
22300c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
2231*a0ba757dSStefano Zampini     if(!mat_graph->count[i]){  /* internal nodes */
22320c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
22330c7d97c5SJed Brown       mat_graph->where[i]=0;
22340c7d97c5SJed Brown       nodes_touched++;
22350c7d97c5SJed Brown     }
22360c7d97c5SJed Brown   }
2237*a0ba757dSStefano Zampini   PetscInt where_values=1;
22380c7d97c5SJed Brown   PetscBool same_set;
22390c7d97c5SJed Brown   mat_graph->ncmps = 0;
22400c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2241*a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
22420c7d97c5SJed Brown     i=0;
22430c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
22440c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2245*a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
22460c7d97c5SJed Brown     nodes_touched++;
2247*a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
22480c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2249*a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
22500c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2251*a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
22520c7d97c5SJed Brown         same_set=PETSC_TRUE;
22530c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
225453cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
22550c7d97c5SJed Brown             same_set=PETSC_FALSE;
22560c7d97c5SJed Brown           }
22570c7d97c5SJed Brown         }
2258*a0ba757dSStefano Zampini         /* I found a friend of mine */
22590c7d97c5SJed Brown         if(same_set) {
2260*a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
22610c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
22620c7d97c5SJed Brown           nodes_touched++;
22630c7d97c5SJed Brown         }
22640c7d97c5SJed Brown       }
22650c7d97c5SJed Brown     }
2266*a0ba757dSStefano Zampini     where_values++;
22670c7d97c5SJed Brown   }
2268*a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2269*a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2270*a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2271*a0ba757dSStefano Zampini   if(where_values) {
2272*a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2273*a0ba757dSStefano Zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component contained in the global queue (and carring together the local queue)  */
2274*a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2275*a0ba757dSStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2276*a0ba757dSStefano Zampini       ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2277*a0ba757dSStefano Zampini     }
2278*a0ba757dSStefano Zampini /*    for(i=0;i<mat_graph->ncmps;i++) {
2279*a0ba757dSStefano Zampini       printf("[queue num %d] ptr %d, length %d: global node (local node)\n",i,mat_graph->cptr[i],mat_graph->cptr[i+1]-mat_graph->cptr[i]);
2280*a0ba757dSStefano Zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++){
2281*a0ba757dSStefano Zampini         printf("%d (%d) ",queue_in_global_numbering[mat_graph->cptr[i]+j],mat_graph->queue[mat_graph->cptr[i]+j]);
2282*a0ba757dSStefano Zampini       }
2283*a0ba757dSStefano Zampini       printf("\n");
2284*a0ba757dSStefano Zampini     }  */
2285*a0ba757dSStefano Zampini   }
2286*a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2287*a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
2288*a0ba757dSStefano Zampini     if(mat_graph->where_ncmps[i]>1) {  /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
2289*a0ba757dSStefano Zampini       adapt_interface=1;
2290*a0ba757dSStefano Zampini       break;
2291*a0ba757dSStefano Zampini     }
2292*a0ba757dSStefano Zampini   }
2293*a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2294*a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
22950c7d97c5SJed Brown 
2296*a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2297*a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2298*a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2299*a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2300*a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2301*a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2302*a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2303*a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2304*a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2305*a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2306*a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2307*a0ba757dSStefano Zampini     MPI_Request *send_requests;
2308*a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2309*a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2310*a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2311*a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2312*a0ba757dSStefano Zampini     PetscInt *add_to_where;
2313*a0ba757dSStefano Zampini 
2314*a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2315*a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2316*a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2317*a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2318*a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2319*a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2320*a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2321*a0ba757dSStefano Zampini       j=0;
2322*a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2323*a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
2324*a0ba757dSStefano Zampini       if(neighbours_set[j][0]!=-1) { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; } /* We don't want sends/recvs_to/from_self -> here I don't count myself  */
2325*a0ba757dSStefano Zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-2; }
2326*a0ba757dSStefano Zampini     }
2327*a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2328*a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2329*a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2330*a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2331*a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2332*a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2333*a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2334*a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2335*a0ba757dSStefano Zampini     }
2336*a0ba757dSStefano Zampini     /* printf("MPI sizes: buffer size for send %d, number of requests %d\n",buffer_size,cum_recv_counts[where_values]); */
2337*a0ba757dSStefano Zampini 
2338*a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2339*a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2340*a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2341*a0ba757dSStefano Zampini       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2342*a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2343*a0ba757dSStefano Zampini         if(neighbours_set[j][k] != my_rank) {
2344*a0ba757dSStefano Zampini           ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2345*a0ba757dSStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2346*a0ba757dSStefano Zampini           /*printf("SENDREQ[%d]: to %d (tag %d) the value %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],mat_graph->where_ncmps[i]);
2347*a0ba757dSStefano Zampini           printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],sum_requests);*/
2348*a0ba757dSStefano Zampini           sum_requests++;
2349*a0ba757dSStefano Zampini         }
2350*a0ba757dSStefano Zampini       }
2351*a0ba757dSStefano Zampini     }
2352*a0ba757dSStefano Zampini     /* printf("Final number of request: s=r=%d (should be equal to %d)\n",sum_requests,cum_recv_counts[where_values]); */
2353*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2354*a0ba757dSStefano Zampini     /*for(i=0;i<where_values;i++){
2355*a0ba757dSStefano Zampini       printf("my where_ncmps[%d]=%d\n",i,mat_graph->where_ncmps[i]);
2356*a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
2357*a0ba757dSStefano Zampini         printf("   recv where_ncmps[%d]=%d\n",j,recv_buffer_where[j]);
2358*a0ba757dSStefano Zampini       }
2359*a0ba757dSStefano Zampini     }*/
2360*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2361*a0ba757dSStefano Zampini 
2362*a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2363*a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2364*a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2365*a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2366*a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
2367*a0ba757dSStefano Zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) { /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
2368*a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2369*a0ba757dSStefano Zampini           break;
2370*a0ba757dSStefano Zampini         }
2371*a0ba757dSStefano Zampini       }
2372*a0ba757dSStefano Zampini     }
2373*a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2374*a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2375*a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2376*a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2377*a0ba757dSStefano Zampini     sum_requests=0;
2378*a0ba757dSStefano Zampini     start_of_send=0;
2379*a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2380*a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2381*a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2382*a0ba757dSStefano Zampini         size_of_send=0;
2383*a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2384*a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2385*a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2386*a0ba757dSStefano Zampini             size_of_send+=1;
2387*a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2388*a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2389*a0ba757dSStefano Zampini             }
2390*a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2391*a0ba757dSStefano Zampini           }
2392*a0ba757dSStefano Zampini         }
2393*a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2394*a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2395*a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2396*a0ba757dSStefano Zampini           if(neighbours_set[j][k] != my_rank) {
2397*a0ba757dSStefano Zampini             /* printf("SENDREQ[%d]: to %d (tag %d) the value %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],size_of_send);
2398*a0ba757dSStefano Zampini             printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],sum_requests+start_of_recv);*/
2399*a0ba757dSStefano Zampini             ierr = MPI_Isend(&size_of_send,1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2400*a0ba757dSStefano Zampini             ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2401*a0ba757dSStefano Zampini             sum_requests++;
2402*a0ba757dSStefano Zampini           }
2403*a0ba757dSStefano Zampini         }
2404*a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2405*a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2406*a0ba757dSStefano Zampini       }
2407*a0ba757dSStefano Zampini     }
2408*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2409*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2410*a0ba757dSStefano Zampini     /*j=0;
2411*a0ba757dSStefano Zampini     for(k=0;k<where_values;k++) { j+=sizes_of_sends[k]; }
2412*a0ba757dSStefano Zampini     printf("This is the send buffer (size %d): \n",j);
2413*a0ba757dSStefano Zampini     for(k=0;k<j;k++) { printf("%d ",send_buffer[k]); }
2414*a0ba757dSStefano Zampini     printf("\n");*/
2415*a0ba757dSStefano Zampini     buffer_size=0;
2416*a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2417*a0ba757dSStefano Zampini     /* printf("Allocating recv buffer of size %d\n",buffer_size); */
2418*a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2419*a0ba757dSStefano Zampini     /* now exchange the data */
2420*a0ba757dSStefano Zampini     start_of_recv=0;
2421*a0ba757dSStefano Zampini     start_of_send=0;
2422*a0ba757dSStefano Zampini     sum_requests=0;
2423*a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2424*a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2425*a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2426*a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2427*a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2428*a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2429*a0ba757dSStefano Zampini           if(neighbours_set[j][k] != my_rank) {
2430*a0ba757dSStefano Zampini             /* printf("SENDREQ[%d]: to %d (tag %d) with size %d at buffer address %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],size_of_send,start_of_send);
2431*a0ba757dSStefano Zampini             printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],start_of_recv); */
2432*a0ba757dSStefano Zampini             ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2433*a0ba757dSStefano Zampini             size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2434*a0ba757dSStefano Zampini             ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2435*a0ba757dSStefano Zampini             start_of_recv+=size_of_recv;
2436*a0ba757dSStefano Zampini             sum_requests++;
2437*a0ba757dSStefano Zampini           }
2438*a0ba757dSStefano Zampini         }
2439*a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2440*a0ba757dSStefano Zampini       }
2441*a0ba757dSStefano Zampini     }
2442*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2443*a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2444*a0ba757dSStefano Zampini     /*printf("This is what I received (size %d): \n",start_of_recv);
2445*a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { printf("%d ",recv_buffer[k]); }
2446*a0ba757dSStefano Zampini     printf("\n");*/
2447*a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2448*a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2449*a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2450*a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2451*a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2452*a0ba757dSStefano Zampini        j+=k;
2453*a0ba757dSStefano Zampini     }
2454*a0ba757dSStefano Zampini     /*printf("This is what I received in local numbering (unrolled): \n");
2455*a0ba757dSStefano Zampini     i=0;
2456*a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2457*a0ba757dSStefano Zampini        printf("queue num %d (j=%d)\n",i,j);
2458*a0ba757dSStefano Zampini        for(k=1;k<petsc_buffer[j]+1;k++) { printf("%d ",petsc_buffer[k+j]); }
2459*a0ba757dSStefano Zampini        printf("\n");
2460*a0ba757dSStefano Zampini        i++;j+=k;
2461*a0ba757dSStefano Zampini     }*/
2462*a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2463*a0ba757dSStefano Zampini     start_of_recv=0;
2464*a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2465*a0ba757dSStefano Zampini     global_where_counter=0;
2466*a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2467*a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2468*a0ba757dSStefano Zampini         temp_buffer_size=0;
2469*a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2470*a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2471*a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2472*a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2473*a0ba757dSStefano Zampini             temp_buffer_size++;
2474*a0ba757dSStefano Zampini           } else {
2475*a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2476*a0ba757dSStefano Zampini           }
2477*a0ba757dSStefano Zampini         }
2478*a0ba757dSStefano Zampini         /* allocate some temporary space */
2479*a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2480*a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2481*a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2482*a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2483*a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2484*a0ba757dSStefano Zampini         }
2485*a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2486*a0ba757dSStefano Zampini            temp buffer structure:
2487*a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2488*a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2489*a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2490*a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2491*a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2492*a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2493*a0ba757dSStefano Zampini              [ 0, 0, 0;
2494*a0ba757dSStefano Zampini                0, 0, 1;
2495*a0ba757dSStefano Zampini                1, 1, 2;
2496*a0ba757dSStefano Zampini                1, 1, 2;
2497*a0ba757dSStefano Zampini                0, 1, 0; ];
2498*a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2499*a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2500*a0ba757dSStefano Zampini                                                                                                                                    */
2501*a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2502*a0ba757dSStefano Zampini           ins_val=0;
2503*a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2504*a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2505*a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2506*a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2507*a0ba757dSStefano Zampini             }
2508*a0ba757dSStefano Zampini             buffer_size+=k;
2509*a0ba757dSStefano Zampini             ins_val++;
2510*a0ba757dSStefano Zampini           }
2511*a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2512*a0ba757dSStefano Zampini           sum_requests++;
2513*a0ba757dSStefano Zampini         }
2514*a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2515*a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2516*a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2517*a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2518*a0ba757dSStefano Zampini             global_where_counter++;
2519*a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2520*a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2521*a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2522*a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2523*a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2524*a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2525*a0ba757dSStefano Zampini                   break;
2526*a0ba757dSStefano Zampini                 }
2527*a0ba757dSStefano Zampini               }
2528*a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2529*a0ba757dSStefano Zampini             }
2530*a0ba757dSStefano Zampini           }
2531*a0ba757dSStefano Zampini         }
2532*a0ba757dSStefano Zampini         /* insert new data in where array */
2533*a0ba757dSStefano Zampini         temp_buffer_size=0;
2534*a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2535*a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2536*a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2537*a0ba757dSStefano Zampini             temp_buffer_size++;
2538*a0ba757dSStefano Zampini           }
2539*a0ba757dSStefano Zampini         }
2540*a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2541*a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2542*a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2543*a0ba757dSStefano Zampini       }
2544*a0ba757dSStefano Zampini     }
2545*a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2546*a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2547*a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2548*a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2549*a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2550*a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2551*a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2552*a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2553*a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2554*a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2555*a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2556*a0ba757dSStefano Zampini     if(global_where_counter) {
2557*a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2558*a0ba757dSStefano Zampini       global_where_counter=0;
2559*a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
2560*a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2561*a0ba757dSStefano Zampini           global_where_counter++;
2562*a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
2563*a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2564*a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
2565*a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
2566*a0ba757dSStefano Zampini             }
2567*a0ba757dSStefano Zampini           }
2568*a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
2569*a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
2570*a0ba757dSStefano Zampini         }
2571*a0ba757dSStefano Zampini       }
2572*a0ba757dSStefano Zampini       where_values=global_where_counter;
2573*a0ba757dSStefano Zampini     }
2574*a0ba757dSStefano Zampini     if(global_where_counter) {
2575*a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2576*a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2577*a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2578*a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2579*a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2580*a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
2581*a0ba757dSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2582*a0ba757dSStefano Zampini         ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2583*a0ba757dSStefano Zampini       }
2584*a0ba757dSStefano Zampini     }
25850c7d97c5SJed Brown   }
25860c7d97c5SJed Brown 
2587*a0ba757dSStefano Zampini   /* count vertices, edges and faces */
25880c7d97c5SJed Brown   PetscInt nfc=0;
25890c7d97c5SJed Brown   PetscInt nec=0;
25900c7d97c5SJed Brown   PetscInt nvc=0;
25910c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
25920c7d97c5SJed Brown     if( !pcbddc->vertices_flag ) {
25930c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
25940c7d97c5SJed Brown         if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){
25950c7d97c5SJed Brown           nfc++;
25960c7d97c5SJed Brown         } else {
25970c7d97c5SJed Brown           nec++;
25980c7d97c5SJed Brown         }
25990c7d97c5SJed Brown       }
26000c7d97c5SJed Brown     }
26010c7d97c5SJed Brown     if( !pcbddc->constraints_flag ){
26020c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
26030c7d97c5SJed Brown         nvc++;
26040c7d97c5SJed Brown       }
26050c7d97c5SJed Brown     }
26060c7d97c5SJed Brown   }
26070c7d97c5SJed Brown 
26080c7d97c5SJed Brown   pcbddc->n_constraints = nec+nfc;
26090c7d97c5SJed Brown   pcbddc->n_vertices    = nvc;
26100c7d97c5SJed Brown 
26110c7d97c5SJed Brown   if(pcbddc->n_constraints){
26120c7d97c5SJed Brown     /* allocate space for local constraints of BDDC */
26130c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr);
26140c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr);
26150c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr);
26160c7d97c5SJed Brown     k=0;
26170c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
26180c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
26190c7d97c5SJed Brown         pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i];
26200c7d97c5SJed Brown         k++;
26210c7d97c5SJed Brown       }
26220c7d97c5SJed Brown     }
26230c7d97c5SJed Brown     k=0;
26240c7d97c5SJed Brown     for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i];
26250c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
26260c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
26270c7d97c5SJed Brown     for (i=1; i<pcbddc->n_constraints; i++) {
26280c7d97c5SJed Brown       pcbddc->indices_to_constraint[i]  = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
26290c7d97c5SJed Brown       pcbddc->quadrature_constraint[i]  = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
26300c7d97c5SJed Brown     }
26310c7d97c5SJed Brown     k=0;
26320c7d97c5SJed Brown     PetscScalar quad_value;
26330c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
26340c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
2635*a0ba757dSStefano Zampini         quad_value=1.0/( (PetscReal) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) );
26360c7d97c5SJed Brown         for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
26370c7d97c5SJed Brown           pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j];
26380c7d97c5SJed Brown           pcbddc->quadrature_constraint[k][j] = quad_value;
26390c7d97c5SJed Brown         }
26400c7d97c5SJed Brown         k++;
26410c7d97c5SJed Brown       }
26420c7d97c5SJed Brown     }
26430c7d97c5SJed Brown   }
26440c7d97c5SJed Brown   if(pcbddc->n_vertices){
26450c7d97c5SJed Brown     /* allocate space for local vertices of BDDC */
26460c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr);
26470c7d97c5SJed Brown     k=0;
26480c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
26490c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
26500c7d97c5SJed Brown         pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]];
26510c7d97c5SJed Brown         k++;
26520c7d97c5SJed Brown       }
26530c7d97c5SJed Brown     }
2654*a0ba757dSStefano Zampini     /* sort vertex set (by local ordering) */
26550c7d97c5SJed Brown     ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr);
26560c7d97c5SJed Brown   }
26570c7d97c5SJed Brown 
2658e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
2659e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
2660e269702eSStefano Zampini 
2661d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2662d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2663d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2664*a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
2665*a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2666e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
2667*a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);CHKERRQ(ierr);
2668e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
2669*a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
2670e269702eSStefano Zampini       }
2671*a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
2672*a0ba757dSStefano Zampini     }*/
2673d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
26740c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
2675d49ef151SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nSize and count for connected component %02d : %04d %01d\n", i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
26760c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
26773828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
26780c7d97c5SJed Brown       }
26790c7d97c5SJed Brown     }
2680d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
2681d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
2682d49ef151SStefano Zampini     if( nfc )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr); }
2683d49ef151SStefano Zampini     if( nec )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr); }
2684*a0ba757dSStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Global indices for subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
26853828260eSStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->n_vertices,pcbddc->vertices,queue_in_global_numbering);CHKERRQ(ierr);
26863828260eSStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++){ ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",queue_in_global_numbering[i]);CHKERRQ(ierr); }
2687d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); }
2688d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
26890c7d97c5SJed Brown   }
26900c7d97c5SJed Brown 
2691*a0ba757dSStefano Zampini   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
2692*a0ba757dSStefano Zampini   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
26930c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
2694*a0ba757dSStefano Zampini   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2695*a0ba757dSStefano Zampini   /* Free graph structure */
26960c7d97c5SJed Brown   if(mat_graph->nvtxs){
2697*a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
2698*a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
2699*a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
2700*a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
2701*a0ba757dSStefano Zampini     /* ierr = PetscFree(mat_graph->where);CHKERRQ(ierr);
27020c7d97c5SJed Brown     ierr = PetscFree(mat_graph->touched);CHKERRQ(ierr);
27030c7d97c5SJed Brown     ierr = PetscFree(mat_graph->which_dof);CHKERRQ(ierr);
27040c7d97c5SJed Brown     ierr = PetscFree(mat_graph->queue);CHKERRQ(ierr);
27050c7d97c5SJed Brown     ierr = PetscFree(mat_graph->cptr);CHKERRQ(ierr);
27060c7d97c5SJed Brown     ierr = PetscFree(mat_graph->count);CHKERRQ(ierr);
2707*a0ba757dSStefano Zampini     ierr = PetscFree(queue_in_global_numbering);CHKERRQ(ierr);*/
2708*a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
27090c7d97c5SJed Brown   }
27100c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
27110c7d97c5SJed Brown 
27120c7d97c5SJed Brown   PetscFunctionReturn(0);
27130c7d97c5SJed Brown 
27140c7d97c5SJed Brown }
27150c7d97c5SJed Brown 
27160c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
27170c7d97c5SJed Brown 
27180c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
27190c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
27200c7d97c5SJed Brown 
27210c7d97c5SJed Brown #undef __FUNCT__
27220c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
2723*a0ba757dSStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )//, PetscInt *dist_vals)
27240c7d97c5SJed Brown {
27250c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
27260c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
27270c7d97c5SJed Brown   PetscInt *cptr;
27280c7d97c5SJed Brown   PetscBool *touched;
27290c7d97c5SJed Brown 
27300c7d97c5SJed Brown   PetscFunctionBegin;
27310c7d97c5SJed Brown 
27320c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
27330c7d97c5SJed Brown   xadj    = graph->xadj;
27340c7d97c5SJed Brown   adjncy  = graph->adjncy;
27350c7d97c5SJed Brown   where   = graph->where;
27360c7d97c5SJed Brown   touched = graph->touched;
27370c7d97c5SJed Brown   queue   = graph->queue;
27380c7d97c5SJed Brown   cptr    = graph->cptr;
27390c7d97c5SJed Brown 
27400c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
27410c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
27420c7d97c5SJed Brown 
27430c7d97c5SJed Brown   cum_queue=0;
27440c7d97c5SJed Brown   ncmps=0;
27450c7d97c5SJed Brown 
27460c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
2747*a0ba757dSStefano Zampini     //pid = dist_vals[n];
2748*a0ba757dSStefano Zampini     pid = n+1;
27490c7d97c5SJed Brown     nleft = 0;
27500c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
27510c7d97c5SJed Brown       if (where[i] == pid)
27520c7d97c5SJed Brown         nleft++;
27530c7d97c5SJed Brown     }
27540c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
27550c7d97c5SJed Brown       if (where[i] == pid)
27560c7d97c5SJed Brown         break;
27570c7d97c5SJed Brown     }
27580c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
27590c7d97c5SJed Brown     queue[cum_queue] = i;
27600c7d97c5SJed Brown     first = 0; last = 1;
27610c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
27620c7d97c5SJed Brown     ncmps_pid = 0;
27630c7d97c5SJed Brown     while (first != nleft) {
27640c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
27650c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
27660c7d97c5SJed Brown         ncmps_pid++;
27670c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
27680c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
27690c7d97c5SJed Brown             break;
27700c7d97c5SJed Brown         }
27710c7d97c5SJed Brown         queue[cum_queue+last] = i;
27720c7d97c5SJed Brown         last++;
27730c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
27740c7d97c5SJed Brown       }
27750c7d97c5SJed Brown       i = queue[cum_queue+first];
27760c7d97c5SJed Brown       first++;
27770c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
27780c7d97c5SJed Brown         k = adjncy[j];
27790c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
27800c7d97c5SJed Brown           queue[cum_queue+last] = k;
27810c7d97c5SJed Brown           last++;
27820c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
27830c7d97c5SJed Brown         }
27840c7d97c5SJed Brown       }
27850c7d97c5SJed Brown     }
27860c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
27870c7d97c5SJed Brown     ncmps_pid++;
27880c7d97c5SJed Brown     cum_queue=cptr[ncmps];
2789*a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
27900c7d97c5SJed Brown   }
27910c7d97c5SJed Brown   graph->ncmps = ncmps;
27920c7d97c5SJed Brown 
27930c7d97c5SJed Brown   PetscFunctionReturn(0);
27940c7d97c5SJed Brown }
27950c7d97c5SJed Brown 
2796