xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 3828260ed7989e836bc716d10ba1e9ca16d506fb)
153cdbc3dSStefano Zampini /* TODOLIST
253cdbc3dSStefano Zampini    remove // commments
353cdbc3dSStefano Zampini    remove coarse enums -> allows use of PCBDDCGetCoarseKSP
453cdbc3dSStefano Zampini    code refactoring
553cdbc3dSStefano Zampini    remove metis dependency -> use MatPartitioning for multilevel
653cdbc3dSStefano Zampini    analyze MatSetNearNullSpace as suggested by Jed
753cdbc3dSStefano Zampini    options structure
853cdbc3dSStefano Zampini */
90c7d97c5SJed Brown 
1053cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
110c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
120c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
1353cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
1453cdbc3dSStefano Zampini 
1553cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
160c7d97c5SJed Brown 
170c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
180c7d97c5SJed Brown #undef __FUNCT__
190c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
200c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
210c7d97c5SJed Brown {
220c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
230c7d97c5SJed Brown   PetscErrorCode ierr;
240c7d97c5SJed Brown 
250c7d97c5SJed Brown   PetscFunctionBegin;
260c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
270c7d97c5SJed Brown   /* Verbose debugging of main data structures */
28e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
290c7d97c5SJed Brown   /* Some customization for default primal space */
300c7d97c5SJed 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);
310c7d97c5SJed 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);
320c7d97c5SJed 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);
330c7d97c5SJed 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);
340c7d97c5SJed Brown   /* Coarse solver context */
350c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
360c7d97c5SJed 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);
370c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
380c7d97c5SJed 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);
390c7d97c5SJed 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);
400c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
410c7d97c5SJed Brown   PetscFunctionReturn(0);
420c7d97c5SJed Brown }
430c7d97c5SJed Brown 
440c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
450c7d97c5SJed Brown EXTERN_C_BEGIN
460c7d97c5SJed Brown #undef __FUNCT__
470c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
4853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
490c7d97c5SJed Brown {
500c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
510c7d97c5SJed Brown 
520c7d97c5SJed Brown   PetscFunctionBegin;
530c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
540c7d97c5SJed Brown   PetscFunctionReturn(0);
550c7d97c5SJed Brown }
560c7d97c5SJed Brown EXTERN_C_END
570c7d97c5SJed Brown 
580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
590c7d97c5SJed Brown #undef __FUNCT__
600c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
6153cdbc3dSStefano Zampini /*@
6253cdbc3dSStefano Zampini  PCBDDCSetCoarseProblemType - brief explanation
6353cdbc3dSStefano Zampini 
6453cdbc3dSStefano Zampini    Collective on PC
6553cdbc3dSStefano Zampini 
6653cdbc3dSStefano Zampini    Input Parameters:
6753cdbc3dSStefano Zampini +  pc - the preconditioning context
6853cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
6953cdbc3dSStefano Zampini 
7053cdbc3dSStefano Zampini    Level: intermediate
7153cdbc3dSStefano Zampini 
7253cdbc3dSStefano Zampini    Notes:
7353cdbc3dSStefano Zampini    usage notes, perhaps an example
7453cdbc3dSStefano Zampini 
7553cdbc3dSStefano Zampini .seealso: PCBDDC
7653cdbc3dSStefano Zampini @*/
770c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
780c7d97c5SJed Brown {
790c7d97c5SJed Brown   PetscErrorCode ierr;
800c7d97c5SJed Brown 
810c7d97c5SJed Brown   PetscFunctionBegin;
820c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
830c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
840c7d97c5SJed Brown   PetscFunctionReturn(0);
850c7d97c5SJed Brown }
860c7d97c5SJed Brown 
870c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
880c7d97c5SJed Brown EXTERN_C_BEGIN
890c7d97c5SJed Brown #undef __FUNCT__
900c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
9153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
920c7d97c5SJed Brown {
930c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
9453cdbc3dSStefano Zampini   PetscErrorCode ierr;
950c7d97c5SJed Brown 
960c7d97c5SJed Brown   PetscFunctionBegin;
9753cdbc3dSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
9853cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
9953cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
10053cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1010c7d97c5SJed Brown   PetscFunctionReturn(0);
1020c7d97c5SJed Brown }
1030c7d97c5SJed Brown EXTERN_C_END
1040c7d97c5SJed Brown 
1050c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1060c7d97c5SJed Brown #undef __FUNCT__
1070c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
10857527edcSJed Brown /*@
10953cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
11053cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
11157527edcSJed Brown 
11253cdbc3dSStefano Zampini    Logically Collective on PC
11357527edcSJed Brown 
11457527edcSJed Brown    Input Parameters:
11557527edcSJed Brown +  pc - the preconditioning context
11653cdbc3dSStefano Zampini -  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
11757527edcSJed Brown 
11857527edcSJed Brown    Level: intermediate
11957527edcSJed Brown 
12057527edcSJed Brown    Notes:
12157527edcSJed Brown    usage notes, perhaps an example
12257527edcSJed Brown 
12357527edcSJed Brown .seealso: PCBDDC
12457527edcSJed Brown @*/
12553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1260c7d97c5SJed Brown {
1270c7d97c5SJed Brown   PetscErrorCode ierr;
1280c7d97c5SJed Brown 
1290c7d97c5SJed Brown   PetscFunctionBegin;
1300c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
13153cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
13253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
13353cdbc3dSStefano Zampini }
13453cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
13553cdbc3dSStefano Zampini EXTERN_C_BEGIN
13653cdbc3dSStefano Zampini #undef __FUNCT__
13753cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
13853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
13953cdbc3dSStefano Zampini {
14053cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
14153cdbc3dSStefano Zampini 
14253cdbc3dSStefano Zampini   PetscFunctionBegin;
14353cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
14453cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
14553cdbc3dSStefano Zampini   } else {
14653cdbc3dSStefano Zampini     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
14753cdbc3dSStefano Zampini   }
14853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
14953cdbc3dSStefano Zampini }
15053cdbc3dSStefano Zampini EXTERN_C_END
15153cdbc3dSStefano Zampini 
15253cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
15353cdbc3dSStefano Zampini #undef __FUNCT__
15453cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
15553cdbc3dSStefano Zampini /*@
15653cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
15753cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
15853cdbc3dSStefano Zampini 
15953cdbc3dSStefano Zampini    Logically Collective on PC
16053cdbc3dSStefano Zampini 
16153cdbc3dSStefano Zampini    Input Parameters:
16253cdbc3dSStefano Zampini +  pc - the preconditioning context
16353cdbc3dSStefano Zampini 
16453cdbc3dSStefano Zampini    Output Parameters:
16553cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
16653cdbc3dSStefano Zampini 
16753cdbc3dSStefano Zampini    Level: intermediate
16853cdbc3dSStefano Zampini 
16953cdbc3dSStefano Zampini    Notes:
17053cdbc3dSStefano Zampini    usage notes, perhaps an example
17153cdbc3dSStefano Zampini 
17253cdbc3dSStefano Zampini .seealso: PCBDDC
17353cdbc3dSStefano Zampini @*/
17453cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
17553cdbc3dSStefano Zampini {
17653cdbc3dSStefano Zampini   PetscErrorCode ierr;
17753cdbc3dSStefano Zampini 
17853cdbc3dSStefano Zampini   PetscFunctionBegin;
17953cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18053cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1810c7d97c5SJed Brown   PetscFunctionReturn(0);
1820c7d97c5SJed Brown }
1830c7d97c5SJed Brown 
18453cdbc3dSStefano Zampini #undef __FUNCT__
18553cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
1860c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1870c7d97c5SJed Brown /*
1880c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
1890c7d97c5SJed Brown                   by setting data structures and options.
1900c7d97c5SJed Brown 
1910c7d97c5SJed Brown    Input Parameter:
19253cdbc3dSStefano Zampini +  pc - the preconditioner context
1930c7d97c5SJed Brown 
1940c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
1950c7d97c5SJed Brown 
1960c7d97c5SJed Brown    Notes:
1970c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
1980c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
1990c7d97c5SJed Brown */
20053cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
2010c7d97c5SJed Brown {
2020c7d97c5SJed Brown   PetscErrorCode ierr;
2030c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
2040c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
2050c7d97c5SJed Brown 
2060c7d97c5SJed Brown   PetscFunctionBegin;
2070c7d97c5SJed Brown   if (!pc->setupcalled) {
2080c7d97c5SJed Brown 
2090c7d97c5SJed Brown     /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup
2100c7d97c5SJed Brown        So, we set to pcnone the Neumann problem of pcid in order to avoid unneeded computation
2110c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
2120c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
2130c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
2140c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
2150c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
2160c7d97c5SJed Brown     /* Destroy some PC_IS data which is not needed by BDDC */
2170c7d97c5SJed Brown     //if (pcis->ksp_D)  {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);}
2180c7d97c5SJed Brown     //if (pcis->ksp_N)  {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);}
2190c7d97c5SJed Brown     //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);}
2200c7d97c5SJed Brown     //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);}
2210c7d97c5SJed Brown     //pcis->ksp_D  = 0;
2220c7d97c5SJed Brown     //pcis->ksp_N  = 0;
2230c7d97c5SJed Brown     //pcis->vec2_B = 0;
2240c7d97c5SJed Brown     //pcis->vec3_B = 0;
225e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
226e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
227e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
228e269702eSStefano Zampini     }
2290c7d97c5SJed Brown 
2300c7d97c5SJed Brown     //TODO MOVE CODE FRAGMENT
2310c7d97c5SJed Brown     PetscInt im_active=0;
2320c7d97c5SJed Brown     if(pcis->n) im_active = 1;
23353cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
2340c7d97c5SJed Brown     //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active);
2350c7d97c5SJed Brown     /* Set up grid quantities for BDDC */
2360c7d97c5SJed Brown     //TODO only active procs must call this -> remove synchronized print inside (the only point of sync)
2370c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
2380c7d97c5SJed Brown 
2390c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
2400c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
2410c7d97c5SJed Brown 
2420c7d97c5SJed Brown     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo
2430c7d97c5SJed Brown     /* We no more need this matrix */
2440c7d97c5SJed Brown     //if (pcis->A_BB)  {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);}
2450c7d97c5SJed Brown     //pcis->A_BB   = 0;
2460c7d97c5SJed Brown 
2470c7d97c5SJed Brown     //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type);
2480c7d97c5SJed Brown     //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type);
2490c7d97c5SJed Brown     //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio);
2500c7d97c5SJed Brown   }
2510c7d97c5SJed Brown 
2520c7d97c5SJed Brown   PetscFunctionReturn(0);
2530c7d97c5SJed Brown }
2540c7d97c5SJed Brown 
2550c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2560c7d97c5SJed Brown /*
2570c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
2580c7d97c5SJed Brown 
2590c7d97c5SJed Brown    Input Parameters:
2600c7d97c5SJed Brown .  pc - the preconditioner context
2610c7d97c5SJed Brown .  r - input vector (global)
2620c7d97c5SJed Brown 
2630c7d97c5SJed Brown    Output Parameter:
2640c7d97c5SJed Brown .  z - output vector (global)
2650c7d97c5SJed Brown 
2660c7d97c5SJed Brown    Application Interface Routine: PCApply()
2670c7d97c5SJed Brown  */
2680c7d97c5SJed Brown #undef __FUNCT__
2690c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
27053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
2710c7d97c5SJed Brown {
2720c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)(pc->data);
2730c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2740c7d97c5SJed Brown   PetscErrorCode ierr;
2750c7d97c5SJed Brown   PetscScalar    one = 1.0;
2760c7d97c5SJed Brown   PetscScalar    m_one = -1.0;
2770c7d97c5SJed Brown 
2780c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
2790c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
2800c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
2810c7d97c5SJed Brown 
2820c7d97c5SJed Brown   PetscFunctionBegin;
2830c7d97c5SJed Brown   /* First Dirichlet solve */
2840c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2850c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
28653cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2870c7d97c5SJed Brown   /*
2880c7d97c5SJed Brown     Assembling right hand side for BDDC operator
2890c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
2900c7d97c5SJed Brown     - the interface part of the global vector z
2910c7d97c5SJed Brown   */
2920c7d97c5SJed Brown   //ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2930c7d97c5SJed Brown   //ierr = VecScatterEnd  (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2940c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
2950c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
2960c7d97c5SJed Brown   //ierr = MatMultAdd(pcis->A_BI,pcis->vec2_D,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2970c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2980c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
2990c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
3000c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3010c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3020c7d97c5SJed Brown 
3030c7d97c5SJed Brown   /*
3040c7d97c5SJed Brown     Apply interface preconditioner
3050c7d97c5SJed Brown     Results are stored in:
3060c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
3070c7d97c5SJed Brown     -  the interface part of the global vector z
3080c7d97c5SJed Brown   */
3090c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
3100c7d97c5SJed Brown 
3110c7d97c5SJed Brown   /* Second Dirichlet solves and assembling of output */
3120c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3130c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3140c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
3150c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
31653cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
3170c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
3180c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
3190c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
3200c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3210c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3220c7d97c5SJed Brown 
3230c7d97c5SJed Brown   PetscFunctionReturn(0);
3240c7d97c5SJed Brown 
3250c7d97c5SJed Brown }
3260c7d97c5SJed Brown 
3270c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3280c7d97c5SJed Brown /*
3290c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
3300c7d97c5SJed Brown 
3310c7d97c5SJed Brown */
3320c7d97c5SJed Brown #undef __FUNCT__
3330c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
33453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
3350c7d97c5SJed Brown {
3360c7d97c5SJed Brown   PetscErrorCode ierr;
3370c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
3380c7d97c5SJed Brown   PC_IS*         pcis =   (PC_IS*)  (pc->data);
3390c7d97c5SJed Brown   PetscScalar    zero = 0.0;
3400c7d97c5SJed Brown 
3410c7d97c5SJed Brown   PetscFunctionBegin;
3420c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
3430c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3440c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3450c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3460c7d97c5SJed Brown 
3470c7d97c5SJed Brown   /* Application of PHI^T  */
3480c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3490c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3500c7d97c5SJed Brown 
3510c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
3520c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
3530c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3540c7d97c5SJed Brown 
3550c7d97c5SJed Brown   /* Local solution on R nodes */
3560c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
3570c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3580c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3590c7d97c5SJed Brown   if(pcbddc->prec_type) {
3600c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3610c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3620c7d97c5SJed Brown   }
3630c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
3640c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
3650c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3660c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3670c7d97c5SJed Brown   if(pcbddc->prec_type) {
3680c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3690c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3700c7d97c5SJed Brown   }
3710c7d97c5SJed Brown 
3720c7d97c5SJed Brown   /* Coarse solution */
3730c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
37453cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3750c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3760c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3770c7d97c5SJed Brown 
3780c7d97c5SJed Brown   /* Sum contributions from two levels */
3790c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
3800c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3810c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3820c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3830c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
3840c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3850c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3860c7d97c5SJed Brown 
3870c7d97c5SJed Brown   PetscFunctionReturn(0);
3880c7d97c5SJed Brown }
3890c7d97c5SJed Brown 
3900c7d97c5SJed Brown 
3910c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3920c7d97c5SJed Brown /*
3930c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
3940c7d97c5SJed Brown 
3950c7d97c5SJed Brown */
3960c7d97c5SJed Brown #undef __FUNCT__
3970c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
39853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
3990c7d97c5SJed Brown {
4000c7d97c5SJed Brown   PetscErrorCode ierr;
4010c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4020c7d97c5SJed Brown 
4030c7d97c5SJed Brown   PetscFunctionBegin;
4040c7d97c5SJed Brown 
40553cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4060c7d97c5SJed Brown   if(pcbddc->n_constraints) {
4070c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
4080c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
4090c7d97c5SJed Brown   }
4100c7d97c5SJed Brown 
4110c7d97c5SJed Brown   PetscFunctionReturn(0);
4120c7d97c5SJed Brown }
4130c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4140c7d97c5SJed Brown /*
4150c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
4160c7d97c5SJed Brown 
4170c7d97c5SJed Brown */
4180c7d97c5SJed Brown #undef __FUNCT__
4190c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
42053cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4210c7d97c5SJed Brown {
4220c7d97c5SJed Brown   PetscErrorCode ierr;
4230c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4240c7d97c5SJed Brown 
4250c7d97c5SJed Brown   PetscFunctionBegin;
4260c7d97c5SJed Brown 
4270c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4280c7d97c5SJed Brown     case SCATTERS_BDDC:
4290c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4300c7d97c5SJed Brown       break;
4310c7d97c5SJed Brown     case GATHERS_BDDC:
4320c7d97c5SJed Brown       break;
4330c7d97c5SJed Brown   }
4340c7d97c5SJed Brown   PetscFunctionReturn(0);
4350c7d97c5SJed Brown 
4360c7d97c5SJed Brown }
4370c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4380c7d97c5SJed Brown /*
4390c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
4400c7d97c5SJed Brown 
4410c7d97c5SJed Brown */
4420c7d97c5SJed Brown #undef __FUNCT__
4430c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
44453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4450c7d97c5SJed Brown {
4460c7d97c5SJed Brown   PetscErrorCode ierr;
4470c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4480c7d97c5SJed Brown   PetscScalar*   array_to;
4490c7d97c5SJed Brown   PetscScalar*   array_from;
4500c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
4510c7d97c5SJed Brown   PetscInt i;
4520c7d97c5SJed Brown 
4530c7d97c5SJed Brown   PetscFunctionBegin;
4540c7d97c5SJed Brown 
4550c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4560c7d97c5SJed Brown     case SCATTERS_BDDC:
4570c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4580c7d97c5SJed Brown       break;
4590c7d97c5SJed Brown     case GATHERS_BDDC:
4600c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
4610c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
4620c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
4630c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
4640c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
46553cdbc3dSStefano 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);
4660c7d97c5SJed Brown             if(vec_to) {
4670c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4680c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4690c7d97c5SJed Brown             }
4700c7d97c5SJed Brown           } else {
4710c7d97c5SJed Brown             if(vec_from)
4720c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4730c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
47453cdbc3dSStefano 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);
4750c7d97c5SJed Brown           }
4760c7d97c5SJed Brown           break;
4770c7d97c5SJed Brown         case REPLICATED_BDDC:
4780c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
47953cdbc3dSStefano 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);
4800c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
4810c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4820c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
4830c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
4840c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
4850c7d97c5SJed Brown           }
4860c7d97c5SJed Brown           break;
48753cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
48853cdbc3dSStefano Zampini           break;
48953cdbc3dSStefano Zampini         case PARALLEL_BDDC:
49053cdbc3dSStefano Zampini           break;
4910c7d97c5SJed Brown       }
4920c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
4930c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
4940c7d97c5SJed Brown       break;
4950c7d97c5SJed Brown   }
4960c7d97c5SJed Brown   PetscFunctionReturn(0);
4970c7d97c5SJed Brown 
4980c7d97c5SJed Brown }
4990c7d97c5SJed Brown 
5000c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5010c7d97c5SJed Brown /*
5020c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
5030c7d97c5SJed Brown    that was created with PCCreate_BDDC().
5040c7d97c5SJed Brown 
5050c7d97c5SJed Brown    Input Parameter:
5060c7d97c5SJed Brown .  pc - the preconditioner context
5070c7d97c5SJed Brown 
5080c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
5090c7d97c5SJed Brown */
5100c7d97c5SJed Brown #undef __FUNCT__
5110c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
51253cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
5130c7d97c5SJed Brown {
5140c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
5150c7d97c5SJed Brown   PetscErrorCode ierr;
5160c7d97c5SJed Brown 
5170c7d97c5SJed Brown   PetscFunctionBegin;
5180c7d97c5SJed Brown   /* free data created by PCIS */
5190c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
5200c7d97c5SJed Brown   /* free BDDC data  */
52153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
52253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
52353cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
52453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
52553cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
52653cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
52753cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
52853cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
52953cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
53053cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
53153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
53253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
53353cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
53453cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
53553cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
53653cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
53753cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
53853cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
53953cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
54053cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr);
54153cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
54253cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
5430c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
54453cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
54553cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
5460c7d97c5SJed Brown   if (pcbddc->n_constraints) {
5470c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
5480c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr);
5490c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
5500c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr);
5510c7d97c5SJed Brown     ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr);
5520c7d97c5SJed Brown   }
5530c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
5540c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
5550c7d97c5SJed Brown   PetscFunctionReturn(0);
5560c7d97c5SJed Brown }
5570c7d97c5SJed Brown 
5580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5590c7d97c5SJed Brown /*MC
5600c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
5610c7d97c5SJed Brown 
5620c7d97c5SJed Brown    Options Database Keys:
5630c7d97c5SJed Brown .    -pc_is_damp_fixed <fact> -
5640c7d97c5SJed Brown .    -pc_is_remove_nullspace_fixed -
5650c7d97c5SJed Brown .    -pc_is_set_damping_factor_floating <fact> -
5660c7d97c5SJed Brown .    -pc_is_not_damp_floating -
5670c7d97c5SJed Brown 
5680c7d97c5SJed Brown    Level: intermediate
5690c7d97c5SJed Brown 
5700c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
5710c7d97c5SJed Brown 
5720c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
5730c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
5740c7d97c5SJed Brown           on the subdomains).
5750c7d97c5SJed Brown 
5760c7d97c5SJed Brown           Options for the coarse grid preconditioner can be set with -pc_bddc_coarse_pc_xxx
5770c7d97c5SJed Brown           Options for the Dirichlet subproblem can be set with -pc_bddc_localD_xxx
5780c7d97c5SJed Brown           Options for the Neumann subproblem can be set with -pc_bddc_localN_xxx
5790c7d97c5SJed Brown 
5800c7d97c5SJed Brown    Contributed by Stefano Zampini
5810c7d97c5SJed Brown 
5820c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
5830c7d97c5SJed Brown M*/
5840c7d97c5SJed Brown EXTERN_C_BEGIN
5850c7d97c5SJed Brown #undef __FUNCT__
5860c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
5870c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
5880c7d97c5SJed Brown {
5890c7d97c5SJed Brown   PetscErrorCode ierr;
5900c7d97c5SJed Brown   PC_BDDC          *pcbddc;
5910c7d97c5SJed Brown 
5920c7d97c5SJed Brown   PetscFunctionBegin;
5930c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
5940c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
5950c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
5960c7d97c5SJed Brown   /* create PCIS data structure */
5970c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
5980c7d97c5SJed Brown   /* BDDC specific */
5990c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
6000c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
60153cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
6020c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
6030c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
6040c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
6050c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
6060c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
6070c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
6080c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
6090c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
6100c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
61153cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
61253cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
6130c7d97c5SJed Brown   pcbddc->n_constraints              = 0;
6140c7d97c5SJed Brown   pcbddc->n_vertices                 = 0;
6150c7d97c5SJed Brown   pcbddc->vertices                   = 0;
6160c7d97c5SJed Brown   pcbddc->indices_to_constraint      = 0;
6170c7d97c5SJed Brown   pcbddc->quadrature_constraint      = 0;
6180c7d97c5SJed Brown   pcbddc->sizes_of_constraint        = 0;
6190c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
6200c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
62153cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
6220c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
6230c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
6240c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
6250c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
6260c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
627e269702eSStefano Zampini   pcbddc->dbg_flag                 = PETSC_FALSE;
6280c7d97c5SJed Brown   pcbddc->vertices_flag              = PETSC_FALSE;
6290c7d97c5SJed Brown   pcbddc->constraints_flag           = PETSC_FALSE;
6300c7d97c5SJed Brown   pcbddc->faces_flag                 = PETSC_FALSE;
6310c7d97c5SJed Brown   pcbddc->edges_flag                 = PETSC_FALSE;
6320c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
6330c7d97c5SJed Brown   /* function pointers */
6340c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
6350c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
6360c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
6370c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
6380c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
6390c7d97c5SJed Brown   pc->ops->view                = 0;
6400c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
6410c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
6420c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
6430c7d97c5SJed Brown   /* composing function */
6440c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
6450c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
64653cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
64753cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
6480c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
6490c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
6500c7d97c5SJed Brown   PetscFunctionReturn(0);
6510c7d97c5SJed Brown }
6520c7d97c5SJed Brown EXTERN_C_END
6530c7d97c5SJed Brown 
6540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6550c7d97c5SJed Brown /*
6560c7d97c5SJed Brown    PCBDDCCoarseSetUp -
6570c7d97c5SJed Brown */
6580c7d97c5SJed Brown #undef __FUNCT__
6590c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
66053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
6610c7d97c5SJed Brown {
6620c7d97c5SJed Brown   PetscErrorCode  ierr;
6630c7d97c5SJed Brown 
6640c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
6650c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6660c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
6670c7d97c5SJed Brown   IS                is_R_local;
6680c7d97c5SJed Brown   IS                is_V_local;
6690c7d97c5SJed Brown   IS                is_C_local;
6700c7d97c5SJed Brown   IS                is_aux1;
6710c7d97c5SJed Brown   IS                is_aux2;
6720c7d97c5SJed Brown   const VecType     impVecType;
6730c7d97c5SJed Brown   const MatType     impMatType;
6740c7d97c5SJed Brown   PetscInt          n_R=0;
6750c7d97c5SJed Brown   PetscInt          n_D=0;
6760c7d97c5SJed Brown   PetscInt          n_B=0;
6770c7d97c5SJed Brown   PetscMPIInt       totprocs;
6780c7d97c5SJed Brown   PetscScalar       zero=0.0;
6790c7d97c5SJed Brown   PetscScalar       one=1.0;
6800c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
6810c7d97c5SJed Brown   PetscScalar*      array;
6820c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
6830c7d97c5SJed Brown   PetscInt          *idx_R_local;
6840c7d97c5SJed Brown   PetscInt          *idx_V_B;
6850c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
6860c7d97c5SJed Brown   PetscScalar       *constraints_errors;
6870c7d97c5SJed Brown   /* auxiliary indices */
6880c7d97c5SJed Brown   PetscInt s,i,j,k;
689e269702eSStefano Zampini   /* for verbose output of bddc */
690e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
691e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
6920c7d97c5SJed Brown 
6930c7d97c5SJed Brown   PetscFunctionBegin;
6940c7d97c5SJed Brown 
6950c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
6960c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
6970c7d97c5SJed Brown   /* Set local primal size */
6980c7d97c5SJed Brown   pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints;
6990c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
7000c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
7010c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7020c7d97c5SJed Brown   for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; }
7030c7d97c5SJed Brown   ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
7040c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
7050c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
706e269702eSStefano Zampini   if(dbg_flag) {
7070c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7080c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7090c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
7100c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
7110c7d97c5SJed 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);
7120c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7130c7d97c5SJed Brown   }
7140c7d97c5SJed Brown   /* Allocate needed vectors */
7150c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
7160c7d97c5SJed Brown //  ierr = MatGetType(matis->A,&impMatType);CHKERRQ(ierr);
7170c7d97c5SJed Brown   //ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
7180c7d97c5SJed Brown   impMatType = MATSEQDENSE;
7190c7d97c5SJed Brown   impVecType = VECSEQ;
7200c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
7210c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
7220c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
7230c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
7240c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
725d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
7260c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
7270c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
7280c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
7290c7d97c5SJed Brown 
7300c7d97c5SJed Brown   /* Creating some index sets needed  */
7310c7d97c5SJed Brown   /* For submatrices */
7320c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
7330c7d97c5SJed Brown   if(pcbddc->n_vertices)    { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); }
7340c7d97c5SJed Brown   if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); }
7350c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
7360c7d97c5SJed Brown   {
7370c7d97c5SJed Brown     PetscInt   *aux_array1;
7380c7d97c5SJed Brown     PetscInt   *aux_array2;
7390c7d97c5SJed Brown     PetscScalar      value;
7400c7d97c5SJed Brown 
7410c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
7420c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
7430c7d97c5SJed Brown 
744d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
7450c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7460c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7470c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7480c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7490c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7500c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7510c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7520c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
7530c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7540c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
7550c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
7560c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
757*3828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
7580c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
7590c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
7600c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
7610c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
7620c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
7630c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
7640c7d97c5SJed Brown 
765e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
7660c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
7670c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7680c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
7690c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7700c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
7710c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
7720c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
7730c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
7740c7d97c5SJed Brown     }
7750c7d97c5SJed Brown 
7760c7d97c5SJed Brown     /* Check scatters */
777e269702eSStefano Zampini     if(dbg_flag) {
7780c7d97c5SJed Brown 
7790c7d97c5SJed Brown       Vec            vec_aux;
7800c7d97c5SJed Brown 
7810c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7820c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
7830c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
784d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
785d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
786d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
787d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
788d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
789d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
790d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
791d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
792d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
793d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
7940c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
795d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
7960c7d97c5SJed Brown 
797d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
798d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
799d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
800d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
801d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
802d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
803d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
804d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
805d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
806d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8070c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
808d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8090c7d97c5SJed Brown 
8100c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8110c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
8120c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8130c7d97c5SJed Brown 
814d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
815d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
816d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
817d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
818d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
819d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
820d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
821d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
822d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
823d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8240c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
825d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8260c7d97c5SJed Brown 
827d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
828d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
829d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
830d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
831d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
832d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
833d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
834d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
835d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
836d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8370c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
838d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
8390c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8400c7d97c5SJed Brown 
8410c7d97c5SJed Brown     }
8420c7d97c5SJed Brown   }
8430c7d97c5SJed Brown 
8440c7d97c5SJed Brown   /* vertices in boundary numbering */
8450c7d97c5SJed Brown   if(pcbddc->n_vertices) {
846d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
8470c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8480c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; }
8490c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
850d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
851d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8520c7d97c5SJed Brown     ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
8530c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8540c7d97c5SJed Brown     //printf("vertices in boundary numbering\n");
8550c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) {
8560c7d97c5SJed Brown       s=0;
8570c7d97c5SJed Brown       while (array[s] != i ) {s++;}
8580c7d97c5SJed Brown       idx_V_B[i]=s;
8590c7d97c5SJed Brown       //printf("idx_V_B[%d]=%d\n",i,s);
8600c7d97c5SJed Brown     }
8610c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8620c7d97c5SJed Brown   }
8630c7d97c5SJed Brown 
8640c7d97c5SJed Brown 
8650c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
8660c7d97c5SJed Brown   {
8670c7d97c5SJed Brown     Mat  A_RR;
86853cdbc3dSStefano Zampini     PC   pc_temp;
8690c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
87053cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
87153cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
87253cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
87353cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
87453cdbc3dSStefano Zampini     //ierr = KSPSetOptionsPrefix(pcbddc->pc_D,"pc_bddc_localD_");CHKERRQ(ierr);
8750c7d97c5SJed Brown     /* default */
87653cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
87753cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
8780c7d97c5SJed Brown     /* Allow user's customization */
87953cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
88053cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
88153cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
8820c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
8830c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
88453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
88553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
88653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
88753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
88853cdbc3dSStefano Zampini     //ierr = PCSetOptionsPrefix(pcbddc->pc_R,"pc_bddc_localN_");CHKERRQ(ierr);
8890c7d97c5SJed Brown     /* default */
89053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
89153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
8920c7d97c5SJed Brown     /* Allow user's customization */
89353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
89453cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
89553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
8960c7d97c5SJed Brown     /* check Neumann solve */
897e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
8980c7d97c5SJed Brown       Vec temp_vec;
8990c7d97c5SJed Brown       PetscScalar value;
9000c7d97c5SJed Brown 
901d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
902d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
903d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
904d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
905d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
906d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
907e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
908d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9090c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
9100c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Neumann problem\n");CHKERRQ(ierr);
9110c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
912d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9130c7d97c5SJed Brown     }
9140c7d97c5SJed Brown     /* free Neumann problem's matrix */
9150c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
9160c7d97c5SJed Brown   }
9170c7d97c5SJed Brown 
9180c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
9190c7d97c5SJed Brown   {
9200c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
9210c7d97c5SJed Brown     Mat          M1,M2;
9220c7d97c5SJed Brown     Mat          C_CR;
9230c7d97c5SJed Brown     Mat          CMAT,AUXMAT;
9240c7d97c5SJed Brown     Vec          vec1_C;
9250c7d97c5SJed Brown     Vec          vec2_C;
9260c7d97c5SJed Brown     Vec          vec1_V;
9270c7d97c5SJed Brown     Vec          vec2_V;
9280c7d97c5SJed Brown     PetscInt     *nnz;
9290c7d97c5SJed Brown     PetscInt     *auxindices;
93053cdbc3dSStefano Zampini     PetscInt     index;
9310c7d97c5SJed Brown     PetscScalar* array2;
9320c7d97c5SJed Brown     MatFactorInfo matinfo;
9330c7d97c5SJed Brown 
9340c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
9350c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
9360c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
9370c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
9380c7d97c5SJed Brown 
9390c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
9400c7d97c5SJed Brown     if(pcbddc->n_vertices) {
9410c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
9420c7d97c5SJed Brown       ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr);
9430c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
9440c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
9450c7d97c5SJed Brown     }
9460c7d97c5SJed Brown     if(pcbddc->n_constraints) {
9470c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
9480c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
9490c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
9500c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
9510c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
9520c7d97c5SJed Brown     }
9530c7d97c5SJed Brown     /* Create C matrix [I 0; 0 const] */
954d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&CMAT);CHKERRQ(ierr);
9550c7d97c5SJed Brown     ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr);
9560c7d97c5SJed Brown     ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
9570c7d97c5SJed Brown     /* nonzeros */
9580c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; }
9590c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];}
9600c7d97c5SJed Brown     ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr);
9610c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
9620c7d97c5SJed Brown       ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
9630c7d97c5SJed Brown     }
9640c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
96553cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
96653cdbc3dSStefano Zampini       ierr = MatSetValues(CMAT,1,&index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES);CHKERRQ(ierr);
9670c7d97c5SJed Brown     }
968e269702eSStefano Zampini     //if(dbg_flag) printf("CMAT assembling\n");
9690c7d97c5SJed Brown     ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9700c7d97c5SJed Brown     ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9710c7d97c5SJed Brown     //ierr = MatView(CMAT,PETSC_VIEWER_STDOUT_SELF);
9720c7d97c5SJed Brown 
9730c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
9740c7d97c5SJed Brown 
9750c7d97c5SJed Brown     if(pcbddc->n_constraints) {
9760c7d97c5SJed Brown       /* some work vectors */
9770c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
9780c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr);
9790c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
9800c7d97c5SJed Brown 
9810c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
9820c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
983d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
9840c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9850c7d97c5SJed Brown         for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; }
9860c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
9870c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
9880c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9890c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
99053cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
9910c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
99253cdbc3dSStefano Zampini         index=i;
99353cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
9940c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
9950c7d97c5SJed Brown       }
996e269702eSStefano Zampini       //if(dbg_flag) printf("pcbddc->local_auxmat2 assembling\n");
9970c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9980c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9990c7d97c5SJed Brown 
10000c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
10010c7d97c5SJed Brown       ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
10020c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
10030c7d97c5SJed Brown 
10040c7d97c5SJed Brown         /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
10050c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1006d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
10070c7d97c5SJed Brown       ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
10080c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
10090c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
10100c7d97c5SJed Brown 
10110c7d97c5SJed Brown         /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */
1012d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
10130c7d97c5SJed Brown       ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
10140c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
10150c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
10160c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
10170c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
10180c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
10190c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
10200c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
10210c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
10220c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
102353cdbc3dSStefano Zampini         index=i;
102453cdbc3dSStefano Zampini         ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
10250c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
10260c7d97c5SJed Brown       }
1027e269702eSStefano Zampini       //if(dbg_flag) printf("M1 assembling\n");
10280c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10290c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10300c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
10310c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
1032e269702eSStefano Zampini       //if(dbg_flag) printf("pcbddc->local_auxmat1 computing and assembling\n");
10330c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
10340c7d97c5SJed Brown 
10350c7d97c5SJed Brown     }
10360c7d97c5SJed Brown 
10370c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
10380c7d97c5SJed Brown     if(pcbddc->n_vertices){
10390c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
10400c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
10410c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
10420c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1043d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
10440c7d97c5SJed Brown       ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr);
10450c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
10460c7d97c5SJed Brown       for(i=0;i<pcbddc->n_vertices;i++) {
10470c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
10480c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
10490c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
10500c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
10510c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
105253cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
105353cdbc3dSStefano Zampini         index=i;
10540c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
105553cdbc3dSStefano Zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
10560c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
10570c7d97c5SJed Brown       }
1058e269702eSStefano Zampini       //if(dbg_flag) printf("M2 assembling\n");
10590c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10600c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10610c7d97c5SJed Brown     }
10620c7d97c5SJed Brown 
10630c7d97c5SJed Brown /* Matrix of coarse basis functions (local) */
1064d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
10650c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
10660c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
1067e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1068d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
10690c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
10700c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
10710c7d97c5SJed Brown     }
10720c7d97c5SJed Brown 
10730c7d97c5SJed Brown /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1074e269702eSStefano Zampini     if(dbg_flag) {
10750c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
10760c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
10770c7d97c5SJed Brown     }
10780c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
10790c7d97c5SJed Brown 
10800c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
10810c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
10820c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
10830c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
10840c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
10850c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
10860c7d97c5SJed Brown       /* solution of saddle point problem */
10870c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
10880c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
10890c7d97c5SJed Brown       if(pcbddc->n_constraints) {
10900c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
10910c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
10920c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
10930c7d97c5SJed Brown       }
10940c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
10950c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
10960c7d97c5SJed Brown 
10970c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
10980c7d97c5SJed Brown       /* coarse basis functions */
109953cdbc3dSStefano Zampini       index=i;
11000c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
11010c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11020c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11030c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
110453cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11050c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
11060c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1107e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
11080c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11090c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11100c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
111153cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11120c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
11130c7d97c5SJed Brown       }
11140c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
11150c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
11160c7d97c5SJed Brown       for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
11170c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
11180c7d97c5SJed Brown       if( pcbddc->n_constraints) {
11190c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
11200c7d97c5SJed 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
11210c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
11220c7d97c5SJed Brown       }
11230c7d97c5SJed Brown 
1124e269702eSStefano Zampini       if( dbg_flag ) {
11250c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1126d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
11270c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11280c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
11290c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
11300c7d97c5SJed Brown         array[ pcbddc->vertices[i] ] = one;
11310c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
11320c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11330c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1134d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
11350c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
11360c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
11370c7d97c5SJed Brown         for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; }
11380c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
11390c7d97c5SJed Brown         if(pcbddc->n_constraints) {
11400c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
11410c7d97c5SJed Brown           for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; }
11420c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
11430c7d97c5SJed Brown         }
11440c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
11450c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
11460c7d97c5SJed Brown         /* check saddle point solution */
11470c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
114853cdbc3dSStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
114953cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
11500c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
11510c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
115253cdbc3dSStefano Zampini         array[index]=array[index]+m_one;  /* shift by the identity matrix */
11530c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
115453cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
11550c7d97c5SJed Brown       }
11560c7d97c5SJed Brown     }
11570c7d97c5SJed Brown 
11580c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++){
1159d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
11600c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
11610c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
11620c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
11630c7d97c5SJed Brown       /* solution of saddle point problem */
11640c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
11650c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
11660c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
11670c7d97c5SJed Brown       if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
11680c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
11690c7d97c5SJed Brown       /* coarse basis functions */
117053cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
11710c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
11720c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11730c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11740c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
117553cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11760c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1177e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
11780c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11790c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11800c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
118153cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11820c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
11830c7d97c5SJed Brown       }
11840c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
11850c7d97c5SJed Brown       if(pcbddc->n_vertices) {
11860c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
118753cdbc3dSStefano Zampini         for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
11880c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
11890c7d97c5SJed Brown       }
11900c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
119153cdbc3dSStefano 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
11920c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
11930c7d97c5SJed Brown 
1194e269702eSStefano Zampini       if( dbg_flag ) {
11950c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
119653cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
11970c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11980c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
11990c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
12000c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12010c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12020c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
120353cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
12040c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12050c7d97c5SJed Brown         if( pcbddc->n_vertices) {
12060c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12070c7d97c5SJed Brown           for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];}
12080c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12090c7d97c5SJed Brown         }
12100c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12110c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];}
12120c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12130c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12140c7d97c5SJed Brown         /* check saddle point solution */
12150c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1216d49ef151SStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
121753cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
12180c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
12190c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
122053cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
12210c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
122253cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
12230c7d97c5SJed Brown       }
12240c7d97c5SJed Brown     }
12250c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12260c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1227e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
12280c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12290c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12300c7d97c5SJed Brown     }
12310c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
12320c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1233e269702eSStefano Zampini     if(dbg_flag) {
12340c7d97c5SJed Brown 
12350c7d97c5SJed Brown       Mat coarse_sub_mat;
12360c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
12370c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
12380c7d97c5SJed Brown       const MatType checkmattype;
12390c7d97c5SJed Brown       PetscScalar      value;
12400c7d97c5SJed Brown 
12410c7d97c5SJed Brown       ierr = MatGetType(matis->A,&checkmattype);CHKERRQ(ierr);
12420c7d97c5SJed Brown       ierr = MatGetType(pcis->A_II,&checkmattype);CHKERRQ(ierr);
12430c7d97c5SJed Brown       checkmattype = MATSEQAIJ;
1244c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1245c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1246c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1247c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1248c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1249c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1250c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1251c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
12520c7d97c5SJed Brown 
12530c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12540c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
12550c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
125653cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
125753cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
125853cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1259c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
126053cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
126153cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1262c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
126353cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
126453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
126553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
126653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
126753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
126853cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
12690c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
12700c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
12710c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
12720c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
127353cdbc3dSStefano 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); }
12740c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
127553cdbc3dSStefano 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); }
12760c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
127753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
127853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
127953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
128053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
128153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
128253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
128353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
128453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
128553cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
128653cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
128753cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
12880c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
12890c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
12900c7d97c5SJed Brown     }
12910c7d97c5SJed Brown 
12920c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
12930c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
12940c7d97c5SJed Brown     /* free memory */
12950c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
12960c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
12970c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
12980c7d97c5SJed Brown     if(pcbddc->n_vertices) {
12990c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
13000c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
13010c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
13020c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
13030c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
13040c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
13050c7d97c5SJed Brown     }
13060c7d97c5SJed Brown     if(pcbddc->n_constraints) {
13070c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
13080c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
13090c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
13100c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
13110c7d97c5SJed Brown     }
13120c7d97c5SJed Brown     ierr = MatDestroy(&CMAT);CHKERRQ(ierr);
13130c7d97c5SJed Brown   }
13140c7d97c5SJed Brown   /* free memory */
13150c7d97c5SJed Brown   if(pcbddc->n_vertices) {
13160c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
13170c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
13180c7d97c5SJed Brown   }
13190c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
13200c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
13210c7d97c5SJed Brown 
13220c7d97c5SJed Brown   PetscFunctionReturn(0);
13230c7d97c5SJed Brown }
13240c7d97c5SJed Brown 
13250c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13260c7d97c5SJed Brown 
13270c7d97c5SJed Brown #undef __FUNCT__
13280c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
132953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
13300c7d97c5SJed Brown {
13310c7d97c5SJed Brown 
13320c7d97c5SJed Brown 
13330c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
13340c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
13350c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
13360c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
13370c7d97c5SJed Brown   MPI_Comm  coarse_comm;
13380c7d97c5SJed Brown 
13390c7d97c5SJed Brown   /* common to all choiches */
13400c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
13410c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
13420c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
13430c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
13440c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
13450c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
13460c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
13470c7d97c5SJed Brown   PetscMPIInt master_proc=0;
13480c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
13490c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
13500c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
13510c7d97c5SJed Brown   PetscMPIInt count_recv=0;
13520c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
13530c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
13540c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
13550c7d97c5SJed Brown   /* some other variables */
13560c7d97c5SJed Brown   PetscErrorCode ierr;
13570c7d97c5SJed Brown   const MatType coarse_mat_type;
13580c7d97c5SJed Brown   const PCType  coarse_pc_type;
135953cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
136053cdbc3dSStefano Zampini   PC pc_temp;
13610c7d97c5SJed Brown   PetscInt i,j,k,bs;
1362e269702eSStefano Zampini   /* verbose output viewer */
1363e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1364e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
13650c7d97c5SJed Brown 
13660c7d97c5SJed Brown   PetscFunctionBegin;
13670c7d97c5SJed Brown 
13680c7d97c5SJed Brown   ins_local_primal_indices = 0;
13690c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
13700c7d97c5SJed Brown   localsizes2              = 0;
13710c7d97c5SJed Brown   localdispl2              = 0;
13720c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
13730c7d97c5SJed Brown   coarse_ISLG              = 0;
13740c7d97c5SJed Brown 
137553cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
137653cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
13770c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
13780c7d97c5SJed Brown 
1379beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1380beed3852SStefano Zampini   {
1381beed3852SStefano Zampini     PetscScalar    coarsesum,one=1.,zero=0.;
1382beed3852SStefano Zampini     PetscScalar    *array;
1383beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1384beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1385beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1386beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1387beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1388beed3852SStefano Zampini 
1389beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1390beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1391beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1392beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1393beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
13945619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1395beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1396beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1397beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1398beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1399beed3852SStefano Zampini     }
14005619798eSStefano Zampini     if(rank_prec_comm == 0) {
1401beed3852SStefano Zampini       /* allocate some auxiliary space */
1402beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1403beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1404beed3852SStefano Zampini     }
1405beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1406beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1407beed3852SStefano Zampini 
1408beed3852SStefano 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)
1409beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1410beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1411beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1412beed3852SStefano Zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) */
1413beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1414beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1415beed3852SStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++) {
1416beed3852SStefano Zampini       array[ pcbddc->vertices[i] ] = one;
1417beed3852SStefano Zampini       auxlocal_primal[i] = pcbddc->vertices[i];
1418beed3852SStefano Zampini     }
1419beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
1420beed3852SStefano Zampini       for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) {
1421beed3852SStefano Zampini         k = pcbddc->indices_to_constraint[i][j];
1422beed3852SStefano Zampini         if( array[k] == zero ) {
1423beed3852SStefano Zampini           array[k] = one;
1424beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1425beed3852SStefano Zampini           break;
1426beed3852SStefano Zampini         }
1427beed3852SStefano Zampini       }
1428beed3852SStefano Zampini     }
1429beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1430beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1431beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1432beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1433beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1434beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1435beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1436d49ef151SStefano Zampini     for(i=0;i<pcis->n;i++) { if(array[i] > 0.0) array[i] = one/array[i]; }
1437beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1438beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1439beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1440beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1441beed3852SStefano Zampini 
1442beed3852SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1443beed3852SStefano Zampini     pcbddc->coarse_size = (PetscInt) coarsesum;
1444e269702eSStefano Zampini     if(dbg_flag) {
1445e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1446*3828260eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1447e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1448e269702eSStefano Zampini     }
1449beed3852SStefano Zampini     /* Now assign them a global numbering */
1450beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1451beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1452beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1453beed3852SStefano 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);
1454beed3852SStefano Zampini 
1455beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1456beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1457beed3852SStefano Zampini     if(rank_prec_comm==0) {
1458beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1459beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1460beed3852SStefano Zampini       k=1;
1461beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1462beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1463beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1464beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1465beed3852SStefano Zampini           k++;
1466beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1467beed3852SStefano Zampini         }
1468beed3852SStefano Zampini       }
1469beed3852SStefano Zampini     } else {
1470beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1471beed3852SStefano Zampini     }
14725619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1473beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1474beed3852SStefano Zampini 
1475beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1476beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1477beed3852SStefano Zampini       k=0;
1478beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1479beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1480beed3852SStefano Zampini     }
1481e269702eSStefano Zampini     if(dbg_flag) {
1482e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1483e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1484e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1485e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1486e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1487e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1488e269702eSStefano Zampini       }
1489e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1490e269702eSStefano Zampini     }
1491beed3852SStefano Zampini     /* free allocated memory */
1492beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1493beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1494beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1495e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1496beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1497beed3852SStefano Zampini     }
1498e269702eSStefano Zampini   }
1499beed3852SStefano Zampini 
15000c7d97c5SJed Brown   /* adapt coarse problem type */
15010c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
15020c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
15030c7d97c5SJed Brown 
15040c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
15050c7d97c5SJed Brown 
15060c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
15070c7d97c5SJed Brown     {
15080c7d97c5SJed Brown       /* we need additional variables */
15090c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15100c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
15110c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
15120c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15130c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15140c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15150c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15160c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15170c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15180c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15190c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15200c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15210c7d97c5SJed Brown       MetisInt    *faces_xadj;
15220c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15230c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15240c7d97c5SJed Brown       PetscInt    *array_int;
15250c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15260c7d97c5SJed Brown       PetscMPIInt total_faces=0;
1527*3828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
15280c7d97c5SJed Brown 
15290c7d97c5SJed Brown       /* define some quantities */
15300c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15310c7d97c5SJed Brown       coarse_mat_type = MATIS;
15320c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
153353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPRICHARDSON;
15340c7d97c5SJed Brown 
15350c7d97c5SJed Brown       /* details of coarse decomposition */
15360c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
15370c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1538*3828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
1539*3828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
1540*3828260eSStefano Zampini 
1541*3828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1542*3828260eSStefano Zampini       printf("n_subdomains %d, n_parts %d\nstretch %d,jumps %d,coarse_ratio %d\nlevel should be %d\n",n_subdomains,n_parts,ranks_stretching_ratio,procs_jumps_coarse_comm,pcbddc->coarsening_ratio,ranks_stretching_ratio/pcbddc->coarsening_ratio);
15430c7d97c5SJed Brown 
15440c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
15450c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
1546*3828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
15470c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
15480c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15490c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
15500c7d97c5SJed Brown         }
15510c7d97c5SJed Brown       }
15520c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
15530c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15540c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
15550c7d97c5SJed Brown             my_faces++;
15560c7d97c5SJed Brown             break;
15570c7d97c5SJed Brown           }
15580c7d97c5SJed Brown         }
15590c7d97c5SJed Brown       }
15600c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
15610c7d97c5SJed Brown 
156253cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
15630c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
15640c7d97c5SJed Brown       my_faces=0;
15650c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
15660c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15670c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
15680c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
15690c7d97c5SJed Brown             my_faces++;
15700c7d97c5SJed Brown             break;
15710c7d97c5SJed Brown           }
15720c7d97c5SJed Brown         }
15730c7d97c5SJed Brown       }
15740c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
15750c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
15760c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
15770c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
15780c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
15790c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
15800c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
15810c7d97c5SJed Brown       }
158253cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
15830c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
15840c7d97c5SJed Brown         faces_xadj[0]=0;
15850c7d97c5SJed Brown         faces_displacements[0]=0;
15860c7d97c5SJed Brown         j=0;
15870c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
15880c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
15890c7d97c5SJed Brown           if(number_of_faces[i-1]) {
15900c7d97c5SJed Brown             j++;
15910c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
15920c7d97c5SJed Brown           }
15930c7d97c5SJed Brown         }
15940c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
15950c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
15960c7d97c5SJed Brown       }
159753cdbc3dSStefano 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);
15980c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
15990c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
16000c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
1601*3828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
1602*3828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
16030c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
16040c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
16050c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
16060c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
16070c7d97c5SJed Brown           printf("\n");
16080c7d97c5SJed Brown         }
16090c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16100c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16110c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16120c7d97c5SJed Brown       }
16130c7d97c5SJed Brown 
16140c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
16150c7d97c5SJed Brown 
1616*3828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
1617*3828260eSStefano Zampini 
16180c7d97c5SJed Brown         ncon=1;
16190c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16200c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16210c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16220c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16230c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16240c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16250c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
16260c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16270c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
1628*3828260eSStefano Zampini         printf("METIS PART GRAPH\n");
1629*3828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
1630*3828260eSStefano Zampini           printf("Using Kway\n");
1631*3828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
1632*3828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16330c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1634*3828260eSStefano Zampini         } else {
1635*3828260eSStefano Zampini           printf("Using Recursive\n");
1636*3828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1637*3828260eSStefano Zampini         }
16380c7d97c5SJed 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);
1639*3828260eSStefano Zampini         printf("Partition done!\n");
16400c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
16410c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
16420c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
16430c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
1644*3828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
1645*3828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
16460c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
16470c7d97c5SJed Brown       }
16480c7d97c5SJed Brown 
16490c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
16500c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
16510c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
16520c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
16530c7d97c5SJed Brown       }
16540c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
16550c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
165653cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
16570c7d97c5SJed Brown 
16580c7d97c5SJed Brown       if( coarse_color == 0 ) {
165953cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
166053cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
1661*3828260eSStefano Zampini         printf("Details of coarse comm\n");
1662*3828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
1663*3828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
16640c7d97c5SJed Brown       } else {
16650c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
16660c7d97c5SJed Brown       }
16670c7d97c5SJed Brown 
16680c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
16690c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
16700c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
16710c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
16720c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
16730c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
16740c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
16750c7d97c5SJed Brown         /* some initializations */
16760c7d97c5SJed Brown         displacements_recv[0]=0;
16770c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
16780c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
16790c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
1680*3828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
16810c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
16820c7d97c5SJed Brown               total_count_recv[j]++;
16830c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
16840c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
16850c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
16860c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
16870c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
1688*3828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
16890c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
16900c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
1691*3828260eSStefano Zampini               total_count_recv[j]+=1;
16920c7d97c5SJed Brown             }
16930c7d97c5SJed Brown           }
16940c7d97c5SJed Brown         }
1695*3828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
1696*3828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
1697*3828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
1698*3828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
1699*3828260eSStefano Zampini           }
1700*3828260eSStefano Zampini           printf("\n");
1701*3828260eSStefano Zampini         }
17020c7d97c5SJed Brown 
17030c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
1704*3828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
17050c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
17060c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
1707*3828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
1708*3828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
1709*3828260eSStefano Zampini           } else {
1710*3828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
1711*3828260eSStefano Zampini           }
17120c7d97c5SJed Brown         printf("\n");
17130c7d97c5SJed Brown       }
17140c7d97c5SJed Brown 
17150c7d97c5SJed Brown       /* Scatter new decomposition for send details */
171653cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
17170c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17180c7d97c5SJed Brown       if( coarse_color == 0) {
171953cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17200c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
172153cdbc3dSStefano 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);
17220c7d97c5SJed Brown       }
17230c7d97c5SJed Brown 
17240c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
17250c7d97c5SJed Brown       //if(coarse_color == 0) {
17260c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
17270c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
17280c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
17290c7d97c5SJed Brown       //  printf("\n");
17300c7d97c5SJed Brown       //}
17310c7d97c5SJed Brown 
17320c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
17330c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
17340c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17350c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17360c7d97c5SJed Brown         free(coarse_subdivision);
17370c7d97c5SJed Brown         free(total_count_recv);
17380c7d97c5SJed Brown         free(total_ranks_recv);
17390c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17400c7d97c5SJed Brown       }
17410c7d97c5SJed Brown       break;
17420c7d97c5SJed Brown     }
17430c7d97c5SJed Brown 
17440c7d97c5SJed Brown     case(REPLICATED_BDDC):
17450c7d97c5SJed Brown 
17460c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17470c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17480c7d97c5SJed Brown       coarse_pc_type  = PCLU;
174953cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17500c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
17510c7d97c5SJed Brown       active_rank = rank_prec_comm;
17520c7d97c5SJed Brown       break;
17530c7d97c5SJed Brown 
17540c7d97c5SJed Brown     case(PARALLEL_BDDC):
17550c7d97c5SJed Brown 
17560c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
17570c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
17580c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
175953cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17600c7d97c5SJed Brown       coarse_comm = prec_comm;
17610c7d97c5SJed Brown       active_rank = rank_prec_comm;
17620c7d97c5SJed Brown       break;
17630c7d97c5SJed Brown 
17640c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
17650c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17660c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17670c7d97c5SJed Brown       coarse_pc_type = PCLU;
176853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17690c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
17700c7d97c5SJed Brown       active_rank = master_proc;
17710c7d97c5SJed Brown       break;
17720c7d97c5SJed Brown   }
17730c7d97c5SJed Brown 
17740c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
17750c7d97c5SJed Brown 
17760c7d97c5SJed Brown     case(SCATTERS_BDDC):
17770c7d97c5SJed Brown       {
17780c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
17790c7d97c5SJed Brown 
17800c7d97c5SJed Brown           PetscMPIInt send_size;
17810c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
17820c7d97c5SJed Brown           PetscInt    ii,jj;
17830c7d97c5SJed Brown           MPI_Request *requests;
17840c7d97c5SJed Brown 
17850c7d97c5SJed Brown           /* allocate auxiliary space */
17865619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
17875619798eSStefano 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);
17880c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
17890c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
17900c7d97c5SJed Brown           /* allocate stuffs for message massing */
17910c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
17920c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
17930c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
17940c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
17950c7d97c5SJed Brown           /* fill up quantities */
17960c7d97c5SJed Brown           j=0;
17970c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
17980c7d97c5SJed Brown             ii = ranks_recv[i];
17990c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
18000c7d97c5SJed Brown             localdispl2[i]=j;
18010c7d97c5SJed Brown             j+=localsizes2[i];
18020c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
18030c7d97c5SJed 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
18040c7d97c5SJed Brown           }
18050c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
18060c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
18070c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
18080c7d97c5SJed Brown           //printf("\n");
18090c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
18100c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
18110c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
18120c7d97c5SJed Brown           ins_local_primal_size=0;
18130c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
18140c7d97c5SJed Brown             if(aux_ins_indices[i])
18150c7d97c5SJed Brown               ins_local_primal_size++;
18160c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
18170c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
18180c7d97c5SJed Brown           j=0;
18190c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
18200c7d97c5SJed Brown             if(aux_ins_indices[i])
18210c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
18220c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
18230c7d97c5SJed Brown           j=0;
18240c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
18250c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
18260c7d97c5SJed Brown               aux_ins_indices[i]=-1;
18270c7d97c5SJed Brown             } else {
18280c7d97c5SJed Brown               aux_ins_indices[i]=j;
18290c7d97c5SJed Brown               j++;
18300c7d97c5SJed Brown             }
18310c7d97c5SJed Brown           }
18320c7d97c5SJed Brown 
18330c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
18340c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
18350c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
18360c7d97c5SJed Brown           //printf("\n");
18370c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
18380c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
18390c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
18400c7d97c5SJed Brown           //printf("\n");
18410c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
18420c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
18430c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
18440c7d97c5SJed Brown           //printf("\n");
18450c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
18460c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
18470c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
18480c7d97c5SJed 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]);
18490c7d97c5SJed Brown           //printf("\n");
18500c7d97c5SJed Brown 
18510c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
185253cdbc3dSStefano 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);
18530c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
18540c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
185553cdbc3dSStefano 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);
18560c7d97c5SJed Brown           }
185753cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
18580c7d97c5SJed Brown 
18590c7d97c5SJed Brown           //if(coarse_color == 0) {
18600c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
18610c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
18620c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
18630c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
18640c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
18650c7d97c5SJed 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]);
18660c7d97c5SJed Brown           //    printf("\n");
18670c7d97c5SJed Brown           //  }
18680c7d97c5SJed Brown           //}
18690c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
18700c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
18710c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
18720c7d97c5SJed Brown 
18730c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
18740c7d97c5SJed Brown           PetscInt row_ind,col_ind;
18750c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
18760c7d97c5SJed Brown             rr = ranks_recv[k];
18770c7d97c5SJed Brown             kk = localdispl2[k];
18780c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
18790c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
18800c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
18810c7d97c5SJed Brown             for(j=0;j<lps;j++){
18820c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
18830c7d97c5SJed Brown               for(i=0;i<lps;i++){
18840c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
18850c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
18860c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
18870c7d97c5SJed Brown               }
18880c7d97c5SJed Brown             }
18890c7d97c5SJed Brown           }
18900c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
18910c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
18920c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
18930c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
18940c7d97c5SJed Brown 
18950c7d97c5SJed Brown             /* create local to global mapping needed by coarse MATIS */
18960c7d97c5SJed Brown           {
18970c7d97c5SJed Brown             IS coarse_IS;
189853cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
18990c7d97c5SJed Brown             coarse_comm = prec_comm;
19000c7d97c5SJed Brown             active_rank=rank_prec_comm;
19010c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
19020c7d97c5SJed Brown             //ierr = ISSetBlockSize(coarse_IS,bs);CHKERRQ(ierr);
19030c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
19040c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
19050c7d97c5SJed Brown           }
19060c7d97c5SJed Brown         }
19070c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
19080c7d97c5SJed Brown           /* arrays for values insertion */
19090c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
19100c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
19110c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19120c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
19130c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
19140c7d97c5SJed 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];
19150c7d97c5SJed Brown           }
19160c7d97c5SJed Brown         }
19170c7d97c5SJed Brown         break;
19180c7d97c5SJed Brown 
19190c7d97c5SJed Brown     }
19200c7d97c5SJed Brown 
19210c7d97c5SJed Brown     case(GATHERS_BDDC):
19220c7d97c5SJed Brown       {
19230c7d97c5SJed Brown 
19240c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
19250c7d97c5SJed Brown 
19260c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
19270c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19280c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
19290c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19300c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19310c7d97c5SJed Brown           /* arrays for values insertion */
19320c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
19330c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
19340c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19350c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19360c7d97c5SJed Brown           localdispl2[0]=0;
19370c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
19380c7d97c5SJed Brown           j=0;
19390c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
19400c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19410c7d97c5SJed Brown         }
19420c7d97c5SJed Brown 
19430c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
19440c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
19450c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
194653cdbc3dSStefano 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);
194753cdbc3dSStefano 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);
19480c7d97c5SJed Brown         } else {
194953cdbc3dSStefano 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);
195053cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
19510c7d97c5SJed Brown         }
19520c7d97c5SJed Brown 
19530c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
19540c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
19550c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
19560c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
19570c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
19580c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
19590c7d97c5SJed Brown           }
19600c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
19610c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
19620c7d97c5SJed Brown             offset2=localdispl2[k];
19630c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
19640c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
19650c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
19660c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
19670c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
19680c7d97c5SJed Brown               }
19690c7d97c5SJed Brown             }
19700c7d97c5SJed Brown           }
19710c7d97c5SJed Brown         }
19720c7d97c5SJed Brown         break;
19730c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
19740c7d97c5SJed Brown   }
19750c7d97c5SJed Brown 
19760c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
19770c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
19780c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
19790c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
19800c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
19810c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
19820c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
19830c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
19840c7d97c5SJed Brown     } else {
19850c7d97c5SJed Brown       Mat matis_coarse_local_mat;
19860c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
19870c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
19880c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
1989*3828260eSStefano Zampini       //ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
19900c7d97c5SJed Brown     }
19910c7d97c5SJed 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);
19920c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19930c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19940c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
19950c7d97c5SJed Brown       Mat matis_coarse_local_mat;
19960c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
19970c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
19980c7d97c5SJed Brown     }
19990c7d97c5SJed Brown 
20000c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
20010c7d97c5SJed Brown     /* Preconditioner for coarse problem */
200253cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
200353cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
200453cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
20055619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
200653cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
200753cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
200853cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
200953cdbc3dSStefano Zampini     //ierr = PCSetOptionsPrefix(pcbddc->coarse_pc,"pc_bddc_coarse_");CHKERRQ(ierr);
20100c7d97c5SJed Brown     /* Allow user's customization */
201153cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
20120c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
2013e269702eSStefano Zampini     //if(pcbddc->dbg_flag && pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
201453cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2015e269702eSStefano Zampini       if(dbg_flag) {
2016e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2017e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2018e269702eSStefano Zampini       }
201953cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
202053cdbc3dSStefano Zampini     }
202153cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
20225619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
20235619798eSStefano Zampini       if(dbg_flag) {
20245619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
20255619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
20265619798eSStefano Zampini       }
20275619798eSStefano Zampini     }
20280c7d97c5SJed Brown   }
20290c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
20300c7d97c5SJed Brown      IS local_IS,global_IS;
20310c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
20320c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
20330c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
20340c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
20350c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
20360c7d97c5SJed Brown   }
20370c7d97c5SJed Brown 
20380c7d97c5SJed Brown 
20390c7d97c5SJed Brown   /* Check condition number of coarse problem */
2040e269702eSStefano Zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && dbg_flag && rank_prec_comm == active_rank ) {
20410c7d97c5SJed Brown     PetscScalar m_one=-1.0;
20425619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
20430c7d97c5SJed Brown 
20445619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
2045d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
20465619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,KSPGMRES);CHKERRQ(ierr);
20475619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
20485619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2049d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2050d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2051d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2052d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2053d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
20545619798eSStefano Zampini     kappa_2=lambda_max/lambda_min;
20555619798eSStefano Zampini     ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2056d49ef151SStefano Zampini     ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2057d49ef151SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
20585619798eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem condition number estimated with %d iterations of gmres is: % 1.14e\n",k,kappa_2);CHKERRQ(ierr);
2059e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2060e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
20615619798eSStefano Zampini     /* restore coarse ksp to default values */
2062d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
20635619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
20645619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
20655619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
20665619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
206753cdbc3dSStefano Zampini   }
20680c7d97c5SJed Brown 
20690c7d97c5SJed Brown   /* free data structures no longer needed */
20700c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
20710c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
20720c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
20730c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
20740c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
20750c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
20760c7d97c5SJed Brown 
20770c7d97c5SJed Brown   PetscFunctionReturn(0);
20780c7d97c5SJed Brown }
20790c7d97c5SJed Brown 
20800c7d97c5SJed Brown #undef __FUNCT__
20810c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
208253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
20830c7d97c5SJed Brown {
20840c7d97c5SJed Brown 
20850c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
20860c7d97c5SJed Brown   PC_IS      *pcis = (PC_IS*)pc->data;
20870c7d97c5SJed Brown   Mat_IS   *matis  = (Mat_IS*)pc->pmat->data;
20880c7d97c5SJed Brown   PetscInt *distinct_values;
208953cdbc3dSStefano Zampini   PetscInt **neighbours_set;
209053cdbc3dSStefano Zampini   PetscInt bs,ierr,i,j,s,k,iindex;
20910c7d97c5SJed Brown   PetscInt total_counts;
20920c7d97c5SJed Brown   PetscBool flg_row;
20930c7d97c5SJed Brown   PCBDDCGraph mat_graph;
209453cdbc3dSStefano Zampini   PetscInt   neumann_bsize;
209553cdbc3dSStefano Zampini   const PetscInt*  neumann_nodes;
20960c7d97c5SJed Brown   Mat        mat_adj;
20970c7d97c5SJed Brown 
20980c7d97c5SJed Brown   PetscFunctionBegin;
20990c7d97c5SJed Brown 
21000c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
21010c7d97c5SJed Brown   // allocate and initialize needed graph structure
21020c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
21030c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
21040c7d97c5SJed Brown   ierr = MatGetRowIJ(mat_adj,0,PETSC_FALSE,PETSC_FALSE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
21050c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
21060c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->where);CHKERRQ(ierr);
2107*3828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
21080c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->count);CHKERRQ(ierr);
2109*3828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
21100c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->which_dof);CHKERRQ(ierr);
2111*3828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
21120c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->queue);CHKERRQ(ierr);
2113*3828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
21140c7d97c5SJed Brown   ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->cptr);CHKERRQ(ierr);
2115*3828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
21160c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscBool),&mat_graph->touched);CHKERRQ(ierr);
2117*3828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
21180c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs/bs;i++) {
21190c7d97c5SJed Brown     for(s=0;s<bs;s++) {
21200c7d97c5SJed Brown       mat_graph->which_dof[i*bs+s]=s;
21210c7d97c5SJed Brown     }
21220c7d97c5SJed Brown   }
21230c7d97c5SJed Brown   //printf("nvtxs = %d\n",mat_graph->nvtxs);
21240c7d97c5SJed Brown   //printf("these are my IS data with n_neigh = %d\n",pcis->n_neigh);
21250c7d97c5SJed Brown   //for(i=0;i<pcis->n_neigh;i++){
21260c7d97c5SJed Brown   //  printf("number of shared nodes with rank %d is %d \n",pcis->neigh[i],pcis->n_shared[i]);
21270c7d97c5SJed Brown   // }
21280c7d97c5SJed Brown 
21290c7d97c5SJed Brown   total_counts=0;
21300c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
21310c7d97c5SJed Brown     s=pcis->n_shared[i];
21320c7d97c5SJed Brown     total_counts+=s;
21330c7d97c5SJed Brown     //printf("computing neigh %d (rank = %d, n_shared = %d)\n",i,pcis->neigh[i],s);
213453cdbc3dSStefano Zampini     for(j=0;j<s;j++){
21350c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
21360c7d97c5SJed Brown     }
21370c7d97c5SJed Brown   }
21380c7d97c5SJed Brown   /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */
213953cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
214053cdbc3dSStefano Zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
214153cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
214253cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
214353cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
214453cdbc3dSStefano Zampini       if(mat_graph->count[iindex] > 2){
214553cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
21460c7d97c5SJed Brown         total_counts++;
21470c7d97c5SJed Brown       }
21480c7d97c5SJed Brown     }
21490c7d97c5SJed Brown   }
21500c7d97c5SJed Brown 
215153cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
215253cdbc3dSStefano Zampini   if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr);
215353cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
21540c7d97c5SJed Brown 
21550c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++) mat_graph->count[i]=0;
21560c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
21570c7d97c5SJed Brown     s=pcis->n_shared[i];
21580c7d97c5SJed Brown     for(j=0;j<s;j++) {
21590c7d97c5SJed Brown       k=pcis->shared[i][j];
216053cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
21610c7d97c5SJed Brown       mat_graph->count[k]+=1;
21620c7d97c5SJed Brown     }
21630c7d97c5SJed Brown   }
21640c7d97c5SJed Brown   /* set -1 fake neighbour */
216553cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
216653cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
216753cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
216853cdbc3dSStefano Zampini       if( mat_graph->count[iindex] > 2){
216953cdbc3dSStefano Zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1; //An additional fake neighbour (with rank -1)
217053cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
21710c7d97c5SJed Brown       }
21720c7d97c5SJed Brown     }
217353cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
21740c7d97c5SJed Brown   }
21750c7d97c5SJed Brown 
21760c7d97c5SJed Brown   /* sort sharing subdomains */
217753cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
21780c7d97c5SJed Brown 
217953cdbc3dSStefano Zampini   /* Prepare for FindConnectedComponents
218053cdbc3dSStefano Zampini      Vertices will be eliminated later (if needed) */
21810c7d97c5SJed Brown   PetscInt nodes_touched=0;
21820c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
21830c7d97c5SJed Brown     if(!mat_graph->count[i]){  //internal nodes
21840c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
21850c7d97c5SJed Brown       mat_graph->where[i]=0;
21860c7d97c5SJed Brown       nodes_touched++;
21870c7d97c5SJed Brown     }
21880c7d97c5SJed Brown     if(pcbddc->faces_flag){
21890c7d97c5SJed Brown       if(mat_graph->count[i]>2){  //all but faces
21900c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
21910c7d97c5SJed Brown         mat_graph->where[i]=0;
21920c7d97c5SJed Brown         nodes_touched++;
21930c7d97c5SJed Brown       }
21940c7d97c5SJed Brown     }
21950c7d97c5SJed Brown     if(pcbddc->edges_flag){
21960c7d97c5SJed Brown       if(mat_graph->count[i]==2){  //faces
21970c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
21980c7d97c5SJed Brown         mat_graph->where[i]=0;
21990c7d97c5SJed Brown         nodes_touched++;
22000c7d97c5SJed Brown       }
22010c7d97c5SJed Brown     }
22020c7d97c5SJed Brown   }
22030c7d97c5SJed Brown 
22040c7d97c5SJed Brown   PetscInt rvalue=1;
22050c7d97c5SJed Brown   PetscBool same_set;
22060c7d97c5SJed Brown   mat_graph->ncmps = 0;
22070c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
22080c7d97c5SJed Brown     // find first untouched node in local ordering
22090c7d97c5SJed Brown     i=0;
22100c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
22110c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
22120c7d97c5SJed Brown     mat_graph->where[i]=rvalue;
22130c7d97c5SJed Brown     nodes_touched++;
22140c7d97c5SJed Brown     // now find other connected nodes shared by the same set of subdomains
22150c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
22160c7d97c5SJed Brown       // check for same number of sharing subdomains and dof number
22170c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
22180c7d97c5SJed Brown         // check for same set of sharing subdomains
22190c7d97c5SJed Brown         same_set=PETSC_TRUE;
22200c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
222153cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
22220c7d97c5SJed Brown             same_set=PETSC_FALSE;
22230c7d97c5SJed Brown           }
22240c7d97c5SJed Brown         }
22250c7d97c5SJed Brown         // OK, I found a friend of mine
22260c7d97c5SJed Brown         if(same_set) {
22270c7d97c5SJed Brown           mat_graph->where[j]=rvalue;
22280c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
22290c7d97c5SJed Brown           nodes_touched++;
22300c7d97c5SJed Brown         }
22310c7d97c5SJed Brown       }
22320c7d97c5SJed Brown     }
22330c7d97c5SJed Brown     rvalue++;
22340c7d97c5SJed Brown   }
22350c7d97c5SJed Brown //  printf("where and count contains %d distinct values\n",rvalue);
22360c7d97c5SJed Brown //  for(j=0;j<mat_graph->nvtxs;j++)
22370c7d97c5SJed Brown //    printf("[%d %d %d]\n",j,mat_graph->where[j],mat_graph->count[j]);
22380c7d97c5SJed Brown 
22390c7d97c5SJed Brown   if(mat_graph->nvtxs) {
224053cdbc3dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
224153cdbc3dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
22420c7d97c5SJed Brown   }
22430c7d97c5SJed Brown 
22440c7d97c5SJed Brown   rvalue--;
22450c7d97c5SJed Brown   ierr  = PetscMalloc ( rvalue*sizeof(PetscInt),&distinct_values);CHKERRQ(ierr);
22460c7d97c5SJed Brown   for(i=0;i<rvalue;i++) distinct_values[i]=i+1;  //initializiation
22470c7d97c5SJed Brown   if(rvalue) ierr = PCBDDCFindConnectedComponents(mat_graph, rvalue, distinct_values);
22480c7d97c5SJed Brown   //printf("total number of connected components %d \n",mat_graph->ncmps);
22490c7d97c5SJed Brown   //for (i=0; i<mat_graph->ncmps; i++) {
22500c7d97c5SJed Brown   //  printf("[queue num %d] ptr %d, length %d, start index %d\n",i,mat_graph->cptr[i],mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->queue[mat_graph->cptr[i]]);
22510c7d97c5SJed Brown   //}
22520c7d97c5SJed Brown   PetscInt nfc=0;
22530c7d97c5SJed Brown   PetscInt nec=0;
22540c7d97c5SJed Brown   PetscInt nvc=0;
22550c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
22560c7d97c5SJed Brown     // sort each connected component (by local ordering)
22570c7d97c5SJed Brown     ierr = PetscSortInt(mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
22580c7d97c5SJed Brown     // count edge and faces
22590c7d97c5SJed Brown     if( !pcbddc->vertices_flag ) {
22600c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
22610c7d97c5SJed Brown         if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){
22620c7d97c5SJed Brown           nfc++;
22630c7d97c5SJed Brown         } else {
22640c7d97c5SJed Brown           nec++;
22650c7d97c5SJed Brown         }
22660c7d97c5SJed Brown       }
22670c7d97c5SJed Brown     }
22680c7d97c5SJed Brown     // count vertices
22690c7d97c5SJed Brown     if( !pcbddc->constraints_flag ){
22700c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
22710c7d97c5SJed Brown         nvc++;
22720c7d97c5SJed Brown       }
22730c7d97c5SJed Brown     }
22740c7d97c5SJed Brown   }
22750c7d97c5SJed Brown 
22760c7d97c5SJed Brown   pcbddc->n_constraints = nec+nfc;
22770c7d97c5SJed Brown   pcbddc->n_vertices    = nvc;
22780c7d97c5SJed Brown 
22790c7d97c5SJed Brown   if(pcbddc->n_constraints){
22800c7d97c5SJed Brown     /* allocate space for local constraints of BDDC */
22810c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr);
22820c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr);
22830c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr);
22840c7d97c5SJed Brown     k=0;
22850c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
22860c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
22870c7d97c5SJed Brown         pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i];
22880c7d97c5SJed Brown         k++;
22890c7d97c5SJed Brown       }
22900c7d97c5SJed Brown     }
22910c7d97c5SJed Brown //    printf("check constraints %d (should be %d)\n",k,pcbddc->n_constraints);
22920c7d97c5SJed Brown //    for(i=0;i<k;i++)
22930c7d97c5SJed Brown //      printf("%d ",pcbddc->sizes_of_constraint[i]);
22940c7d97c5SJed Brown //    printf("\n");
22950c7d97c5SJed Brown     k=0;
22960c7d97c5SJed Brown     for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i];
22970c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
22980c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
22990c7d97c5SJed Brown     for (i=1; i<pcbddc->n_constraints; i++) {
23000c7d97c5SJed Brown       pcbddc->indices_to_constraint[i]  = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
23010c7d97c5SJed Brown       pcbddc->quadrature_constraint[i]  = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
23020c7d97c5SJed Brown     }
23030c7d97c5SJed Brown     k=0;
23040c7d97c5SJed Brown     PetscScalar quad_value;
23050c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
23060c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
23070c7d97c5SJed Brown         quad_value=1.0/( (PetscScalar) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) );
23080c7d97c5SJed Brown         for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
23090c7d97c5SJed Brown           pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j];
23100c7d97c5SJed Brown           pcbddc->quadrature_constraint[k][j] = quad_value;
23110c7d97c5SJed Brown         }
23120c7d97c5SJed Brown         k++;
23130c7d97c5SJed Brown       }
23140c7d97c5SJed Brown     }
23150c7d97c5SJed Brown   }
23160c7d97c5SJed Brown   if(pcbddc->n_vertices){
23170c7d97c5SJed Brown     /* allocate space for local vertices of BDDC */
23180c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr);
23190c7d97c5SJed Brown     k=0;
23200c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
23210c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
23220c7d97c5SJed Brown         pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]];
23230c7d97c5SJed Brown         k++;
23240c7d97c5SJed Brown       }
23250c7d97c5SJed Brown     }
23260c7d97c5SJed Brown     // sort vertex set (by local ordering)
23270c7d97c5SJed Brown     ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr);
23280c7d97c5SJed Brown   }
23290c7d97c5SJed Brown 
2330e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
2331e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
2332*3828260eSStefano Zampini     PetscInt*   queue_in_global_numbering;
2333e269702eSStefano Zampini 
2334d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2335d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2336d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2337*3828260eSStefano Zampini     PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");
2338e269702eSStefano Zampini     PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
2339e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
2340e269702eSStefano Zampini       PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);
2341e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
2342e269702eSStefano Zampini         PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);
2343e269702eSStefano Zampini       }
2344e269702eSStefano Zampini       PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");
2345*3828260eSStefano Zampini     }
2346d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
2347*3828260eSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&queue_in_global_numbering);CHKERRQ(ierr);
2348*3828260eSStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->nvtxs,mat_graph->queue,queue_in_global_numbering);CHKERRQ(ierr);
23490c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
2350d49ef151SStefano 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);
23510c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
2352*3828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
23530c7d97c5SJed Brown       }
23540c7d97c5SJed Brown     }
2355d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
2356d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
2357d49ef151SStefano Zampini     if( nfc )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr); }
2358d49ef151SStefano Zampini     if( nec )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr); }
2359e269702eSStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Indices for subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
2360*3828260eSStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->n_vertices,pcbddc->vertices,queue_in_global_numbering);CHKERRQ(ierr);
2361*3828260eSStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++){ ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",queue_in_global_numbering[i]);CHKERRQ(ierr); }
2362d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); }
2363e269702eSStefano Zampini /*    if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"Indices and quadrature constraints");
2364e269702eSStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++){
2365e269702eSStefano Zampini       PetscViewerASCIISynchronizedPrintf(viewer,"\nConstraint number %d\n",i);
2366e269702eSStefano Zampini       for(j=0;j<pcbddc->sizes_of_constraint[i];j++) {
2367e269702eSStefano Zampini         PetscViewerASCIISynchronizedPrintf(viewer,"(%d, %f) ",pcbddc->indices_to_constraint[i][j],pcbddc->quadrature_constraint[i][j]);
2368e269702eSStefano Zampini       }
2369e269702eSStefano Zampini     }
2370e269702eSStefano Zampini     if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"\n");*/
2371d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2372*3828260eSStefano Zampini     ierr = PetscFree(queue_in_global_numbering);CHKERRQ(ierr);
23730c7d97c5SJed Brown   }
23740c7d97c5SJed Brown 
23750c7d97c5SJed Brown   // Restore CSR structure into sequantial matrix and free memory space no longer needed
23760c7d97c5SJed Brown   ierr = MatRestoreRowIJ(mat_adj,0,PETSC_FALSE,PETSC_TRUE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
23770c7d97c5SJed Brown   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
23780c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
23790c7d97c5SJed Brown   ierr = PetscFree(distinct_values);CHKERRQ(ierr);
23800c7d97c5SJed Brown   // Free graph structure
23810c7d97c5SJed Brown   if(mat_graph->nvtxs){
23820c7d97c5SJed Brown     ierr = PetscFree(mat_graph->where);CHKERRQ(ierr);
23830c7d97c5SJed Brown     ierr = PetscFree(mat_graph->touched);CHKERRQ(ierr);
23840c7d97c5SJed Brown     ierr = PetscFree(mat_graph->which_dof);CHKERRQ(ierr);
23850c7d97c5SJed Brown     ierr = PetscFree(mat_graph->queue);CHKERRQ(ierr);
23860c7d97c5SJed Brown     ierr = PetscFree(mat_graph->cptr);CHKERRQ(ierr);
23870c7d97c5SJed Brown     ierr = PetscFree(mat_graph->count);CHKERRQ(ierr);
23880c7d97c5SJed Brown   }
23890c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
23900c7d97c5SJed Brown 
23910c7d97c5SJed Brown   PetscFunctionReturn(0);
23920c7d97c5SJed Brown 
23930c7d97c5SJed Brown }
23940c7d97c5SJed Brown 
23950c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
23960c7d97c5SJed Brown 
23970c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
23980c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
23990c7d97c5SJed Brown 
24000c7d97c5SJed Brown #undef __FUNCT__
24010c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
240253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist, PetscInt *dist_vals)
24030c7d97c5SJed Brown {
24040c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
24050c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
24060c7d97c5SJed Brown   PetscInt *cptr;
24070c7d97c5SJed Brown   PetscBool *touched;
24080c7d97c5SJed Brown 
24090c7d97c5SJed Brown   PetscFunctionBegin;
24100c7d97c5SJed Brown 
24110c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
24120c7d97c5SJed Brown   xadj    = graph->xadj;
24130c7d97c5SJed Brown   adjncy  = graph->adjncy;
24140c7d97c5SJed Brown   where   = graph->where;
24150c7d97c5SJed Brown   touched = graph->touched;
24160c7d97c5SJed Brown   queue   = graph->queue;
24170c7d97c5SJed Brown   cptr    = graph->cptr;
24180c7d97c5SJed Brown 
24190c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
24200c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
24210c7d97c5SJed Brown 
24220c7d97c5SJed Brown   cum_queue=0;
24230c7d97c5SJed Brown   ncmps=0;
24240c7d97c5SJed Brown 
24250c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
24260c7d97c5SJed Brown     pid = dist_vals[n];
24270c7d97c5SJed Brown     nleft = 0;
24280c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
24290c7d97c5SJed Brown       if (where[i] == pid)
24300c7d97c5SJed Brown         nleft++;
24310c7d97c5SJed Brown     }
24320c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
24330c7d97c5SJed Brown       if (where[i] == pid)
24340c7d97c5SJed Brown         break;
24350c7d97c5SJed Brown     }
24360c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
24370c7d97c5SJed Brown     queue[cum_queue] = i;
24380c7d97c5SJed Brown     first = 0; last = 1;
24390c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
24400c7d97c5SJed Brown     ncmps_pid = 0;
24410c7d97c5SJed Brown     while (first != nleft) {
24420c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
24430c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
24440c7d97c5SJed Brown         ncmps_pid++;
24450c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
24460c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
24470c7d97c5SJed Brown             break;
24480c7d97c5SJed Brown         }
24490c7d97c5SJed Brown         queue[cum_queue+last] = i;
24500c7d97c5SJed Brown         last++;
24510c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
24520c7d97c5SJed Brown       }
24530c7d97c5SJed Brown       i = queue[cum_queue+first];
24540c7d97c5SJed Brown       first++;
24550c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
24560c7d97c5SJed Brown         k = adjncy[j];
24570c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
24580c7d97c5SJed Brown           queue[cum_queue+last] = k;
24590c7d97c5SJed Brown           last++;
24600c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
24610c7d97c5SJed Brown         }
24620c7d97c5SJed Brown       }
24630c7d97c5SJed Brown     }
24640c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
24650c7d97c5SJed Brown     ncmps_pid++;
24660c7d97c5SJed Brown     cum_queue=cptr[ncmps];
24670c7d97c5SJed Brown   }
24680c7d97c5SJed Brown   graph->ncmps = ncmps;
24690c7d97c5SJed Brown 
24700c7d97c5SJed Brown   PetscFunctionReturn(0);
24710c7d97c5SJed Brown }
24720c7d97c5SJed Brown 
2473