xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 9c0446d6b852862223a8a3448d9d0bc8b1fd6989)
153cdbc3dSStefano Zampini /* TODOLIST
2a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
3a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
4a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
5a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
6a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
7a0ba757dSStefano Zampini      - Add level slot to bddc data structure and associated Set/Get functions
8a0ba757dSStefano Zampini    code refactoring:
9a0ba757dSStefano Zampini      - removing indices to constraints, quadrature constrainsts and similar from PCBDDCManageLocalBoundaries
10a0ba757dSStefano Zampini      - analyze MatSetNearNullSpace as suggested by Jed
11a0ba757dSStefano Zampini      - build constraint matrix after SVD on local connected components
12a0ba757dSStefano Zampini      - pick up better names for static functions
13a0ba757dSStefano Zampini    check log_summary for leaking (actually: 1 Vector per level plus only 1 IS)
14a0ba757dSStefano Zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
15a0ba757dSStefano Zampini    change options structure:
16a0ba757dSStefano Zampini      - insert BDDC into MG framework?
17a0ba757dSStefano Zampini    provide other ops? Ask to developers
18a0ba757dSStefano Zampini    remove all unused printf
19a0ba757dSStefano Zampini    remove // commments and adhere to PETSc code requirements
20a0ba757dSStefano Zampini    man pages
2153cdbc3dSStefano Zampini */
220c7d97c5SJed Brown 
2353cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
240c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
250c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2653cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2753cdbc3dSStefano Zampini 
2853cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
290c7d97c5SJed Brown 
300c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
310c7d97c5SJed Brown #undef __FUNCT__
320c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
330c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
340c7d97c5SJed Brown {
350c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
360c7d97c5SJed Brown   PetscErrorCode ierr;
370c7d97c5SJed Brown 
380c7d97c5SJed Brown   PetscFunctionBegin;
390c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
400c7d97c5SJed Brown   /* Verbose debugging of main data structures */
41e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
420c7d97c5SJed Brown   /* Some customization for default primal space */
430c7d97c5SJed 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);
440c7d97c5SJed 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);
450c7d97c5SJed 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);
460c7d97c5SJed 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);
470c7d97c5SJed Brown   /* Coarse solver context */
480c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
490c7d97c5SJed 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);
500c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
510c7d97c5SJed 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);
520c7d97c5SJed 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);
530c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
540c7d97c5SJed Brown   PetscFunctionReturn(0);
550c7d97c5SJed Brown }
560c7d97c5SJed Brown 
570c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
580c7d97c5SJed Brown EXTERN_C_BEGIN
590c7d97c5SJed Brown #undef __FUNCT__
600c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
620c7d97c5SJed Brown {
630c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
640c7d97c5SJed Brown 
650c7d97c5SJed Brown   PetscFunctionBegin;
660c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
670c7d97c5SJed Brown   PetscFunctionReturn(0);
680c7d97c5SJed Brown }
690c7d97c5SJed Brown EXTERN_C_END
700c7d97c5SJed Brown 
710c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
720c7d97c5SJed Brown #undef __FUNCT__
730c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7453cdbc3dSStefano Zampini /*@
75*9c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7653cdbc3dSStefano Zampini 
77*9c0446d6SStefano Zampini    Not collective
7853cdbc3dSStefano Zampini 
7953cdbc3dSStefano Zampini    Input Parameters:
8053cdbc3dSStefano Zampini +  pc - the preconditioning context
8153cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8253cdbc3dSStefano Zampini 
8353cdbc3dSStefano Zampini    Level: intermediate
8453cdbc3dSStefano Zampini 
8553cdbc3dSStefano Zampini    Notes:
86*9c0446d6SStefano Zampini    Not collective but all procs must call this.
8753cdbc3dSStefano Zampini 
8853cdbc3dSStefano Zampini .seealso: PCBDDC
8953cdbc3dSStefano Zampini @*/
900c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
910c7d97c5SJed Brown {
920c7d97c5SJed Brown   PetscErrorCode ierr;
930c7d97c5SJed Brown 
940c7d97c5SJed Brown   PetscFunctionBegin;
950c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
960c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
970c7d97c5SJed Brown   PetscFunctionReturn(0);
980c7d97c5SJed Brown }
990c7d97c5SJed Brown 
1000c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1010c7d97c5SJed Brown EXTERN_C_BEGIN
1020c7d97c5SJed Brown #undef __FUNCT__
1030c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
10453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1050c7d97c5SJed Brown {
1060c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
10753cdbc3dSStefano Zampini   PetscErrorCode ierr;
1080c7d97c5SJed Brown 
1090c7d97c5SJed Brown   PetscFunctionBegin;
110*9c0446d6SStefano Zampini   //ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
11153cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
11253cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
11353cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1140c7d97c5SJed Brown   PetscFunctionReturn(0);
1150c7d97c5SJed Brown }
1160c7d97c5SJed Brown EXTERN_C_END
1170c7d97c5SJed Brown 
1180c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1190c7d97c5SJed Brown #undef __FUNCT__
1200c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
12157527edcSJed Brown /*@
12253cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
12353cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
12457527edcSJed Brown 
125*9c0446d6SStefano Zampini    Not collective
12657527edcSJed Brown 
12757527edcSJed Brown    Input Parameters:
12857527edcSJed Brown +  pc - the preconditioning context
129*9c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
13057527edcSJed Brown 
13157527edcSJed Brown    Level: intermediate
13257527edcSJed Brown 
13357527edcSJed Brown    Notes:
134*9c0446d6SStefano Zampini    The sequential IS is copied; the user must destroy the IS object passed in.
13557527edcSJed Brown 
13657527edcSJed Brown .seealso: PCBDDC
13757527edcSJed Brown @*/
13853cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1390c7d97c5SJed Brown {
1400c7d97c5SJed Brown   PetscErrorCode ierr;
1410c7d97c5SJed Brown 
1420c7d97c5SJed Brown   PetscFunctionBegin;
1430c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
14453cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
14553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
14653cdbc3dSStefano Zampini }
14753cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
14853cdbc3dSStefano Zampini EXTERN_C_BEGIN
14953cdbc3dSStefano Zampini #undef __FUNCT__
15053cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
15153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
15253cdbc3dSStefano Zampini {
15353cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15453cdbc3dSStefano Zampini 
15553cdbc3dSStefano Zampini   PetscFunctionBegin;
15653cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
15753cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
15853cdbc3dSStefano Zampini   } else {
159*9c0446d6SStefano Zampini     *NeumannBoundaries = PETSC_NULL;
160*9c0446d6SStefano Zampini     //SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
16153cdbc3dSStefano Zampini   }
16253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
16353cdbc3dSStefano Zampini }
16453cdbc3dSStefano Zampini EXTERN_C_END
16553cdbc3dSStefano Zampini 
16653cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
16753cdbc3dSStefano Zampini #undef __FUNCT__
16853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
16953cdbc3dSStefano Zampini /*@
17053cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
17153cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
17253cdbc3dSStefano Zampini 
173*9c0446d6SStefano Zampini    Not collective
17453cdbc3dSStefano Zampini 
17553cdbc3dSStefano Zampini    Input Parameters:
17653cdbc3dSStefano Zampini +  pc - the preconditioning context
17753cdbc3dSStefano Zampini 
17853cdbc3dSStefano Zampini    Output Parameters:
17953cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
18053cdbc3dSStefano Zampini 
18153cdbc3dSStefano Zampini    Level: intermediate
18253cdbc3dSStefano Zampini 
18353cdbc3dSStefano Zampini    Notes:
184*9c0446d6SStefano Zampini    If the user has not yet provided such information, PETSC_NULL is returned.
18553cdbc3dSStefano Zampini 
18653cdbc3dSStefano Zampini .seealso: PCBDDC
18753cdbc3dSStefano Zampini @*/
18853cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
18953cdbc3dSStefano Zampini {
19053cdbc3dSStefano Zampini   PetscErrorCode ierr;
19153cdbc3dSStefano Zampini 
19253cdbc3dSStefano Zampini   PetscFunctionBegin;
19353cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
19453cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1950c7d97c5SJed Brown   PetscFunctionReturn(0);
1960c7d97c5SJed Brown }
1970c7d97c5SJed Brown 
198*9c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
199*9c0446d6SStefano Zampini EXTERN_C_BEGIN
200*9c0446d6SStefano Zampini #undef __FUNCT__
201*9c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
202*9c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
203*9c0446d6SStefano Zampini {
204*9c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
205*9c0446d6SStefano Zampini   PetscInt i;
206*9c0446d6SStefano Zampini   PetscErrorCode ierr;
207*9c0446d6SStefano Zampini 
208*9c0446d6SStefano Zampini   PetscFunctionBegin;
209*9c0446d6SStefano Zampini   /* Destroy IS if already set */
210*9c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
211*9c0446d6SStefano Zampini     //ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
212*9c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
213*9c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
214*9c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
215*9c0446d6SStefano Zampini   }
216*9c0446d6SStefano Zampini   /* allocate space then copy ISs */
217*9c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
218*9c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
219*9c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
220*9c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
221*9c0446d6SStefano Zampini   }
222*9c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
223*9c0446d6SStefano Zampini   PetscFunctionReturn(0);
224*9c0446d6SStefano Zampini }
225*9c0446d6SStefano Zampini EXTERN_C_END
226*9c0446d6SStefano Zampini 
227*9c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
228*9c0446d6SStefano Zampini #undef __FUNCT__
229*9c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
230*9c0446d6SStefano Zampini /*@
231*9c0446d6SStefano Zampini  PCBDDCSetDofsSplitting - Set index set defining how dofs are splitted.
232*9c0446d6SStefano Zampini 
233*9c0446d6SStefano Zampini    Not collective
234*9c0446d6SStefano Zampini 
235*9c0446d6SStefano Zampini    Input Parameters:
236*9c0446d6SStefano Zampini +  pc - the preconditioning context
237*9c0446d6SStefano Zampini -  n - number of index sets defining dofs spltting
238*9c0446d6SStefano Zampini -  IS[] - array of IS describing dofs splitting
239*9c0446d6SStefano Zampini 
240*9c0446d6SStefano Zampini    Level: intermediate
241*9c0446d6SStefano Zampini 
242*9c0446d6SStefano Zampini    Notes:
243*9c0446d6SStefano Zampini    Sequential ISs are copied, the user must destroy the array of IS passed in.
244*9c0446d6SStefano Zampini 
245*9c0446d6SStefano Zampini .seealso: PCBDDC
246*9c0446d6SStefano Zampini @*/
247*9c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
248*9c0446d6SStefano Zampini {
249*9c0446d6SStefano Zampini   PetscErrorCode ierr;
250*9c0446d6SStefano Zampini 
251*9c0446d6SStefano Zampini   PetscFunctionBegin;
252*9c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
253*9c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
254*9c0446d6SStefano Zampini   PetscFunctionReturn(0);
255*9c0446d6SStefano Zampini }
256*9c0446d6SStefano Zampini 
25753cdbc3dSStefano Zampini #undef __FUNCT__
25853cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
2590c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2600c7d97c5SJed Brown /*
2610c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
2620c7d97c5SJed Brown                   by setting data structures and options.
2630c7d97c5SJed Brown 
2640c7d97c5SJed Brown    Input Parameter:
26553cdbc3dSStefano Zampini +  pc - the preconditioner context
2660c7d97c5SJed Brown 
2670c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
2680c7d97c5SJed Brown 
2690c7d97c5SJed Brown    Notes:
2700c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
2710c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
2720c7d97c5SJed Brown */
27353cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
2740c7d97c5SJed Brown {
2750c7d97c5SJed Brown   PetscErrorCode ierr;
2760c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
2770c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
2780c7d97c5SJed Brown 
2790c7d97c5SJed Brown   PetscFunctionBegin;
2800c7d97c5SJed Brown   if (!pc->setupcalled) {
2810c7d97c5SJed Brown 
2820c7d97c5SJed Brown     /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup
283*9c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
2840c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
2850c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
2860c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
2870c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
2880c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
2890c7d97c5SJed Brown     /* Destroy some PC_IS data which is not needed by BDDC */
2900c7d97c5SJed Brown     //if (pcis->ksp_D)  {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);}
2910c7d97c5SJed Brown     //if (pcis->ksp_N)  {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);}
2920c7d97c5SJed Brown     //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);}
2930c7d97c5SJed Brown     //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);}
2940c7d97c5SJed Brown     //pcis->ksp_D  = 0;
2950c7d97c5SJed Brown     //pcis->ksp_N  = 0;
2960c7d97c5SJed Brown     //pcis->vec2_B = 0;
2970c7d97c5SJed Brown     //pcis->vec3_B = 0;
298e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
299e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
300e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
301e269702eSStefano Zampini     }
3020c7d97c5SJed Brown 
3030c7d97c5SJed Brown     //TODO MOVE CODE FRAGMENT
3040c7d97c5SJed Brown     PetscInt im_active=0;
3050c7d97c5SJed Brown     if(pcis->n) im_active = 1;
30653cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
3070c7d97c5SJed Brown     //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active);
3080c7d97c5SJed Brown     /* Set up grid quantities for BDDC */
3090c7d97c5SJed Brown     //TODO only active procs must call this -> remove synchronized print inside (the only point of sync)
3100c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
3110c7d97c5SJed Brown 
3120c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
3130c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
3140c7d97c5SJed Brown 
3150c7d97c5SJed Brown     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo
3160c7d97c5SJed Brown     /* We no more need this matrix */
3170c7d97c5SJed Brown     //if (pcis->A_BB)  {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);}
3180c7d97c5SJed Brown     //pcis->A_BB   = 0;
3190c7d97c5SJed Brown 
3200c7d97c5SJed Brown     //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type);
3210c7d97c5SJed Brown     //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type);
3220c7d97c5SJed Brown     //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio);
3230c7d97c5SJed Brown   }
3240c7d97c5SJed Brown 
3250c7d97c5SJed Brown   PetscFunctionReturn(0);
3260c7d97c5SJed Brown }
3270c7d97c5SJed Brown 
3280c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3290c7d97c5SJed Brown /*
3300c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
3310c7d97c5SJed Brown 
3320c7d97c5SJed Brown    Input Parameters:
3330c7d97c5SJed Brown .  pc - the preconditioner context
3340c7d97c5SJed Brown .  r - input vector (global)
3350c7d97c5SJed Brown 
3360c7d97c5SJed Brown    Output Parameter:
3370c7d97c5SJed Brown .  z - output vector (global)
3380c7d97c5SJed Brown 
3390c7d97c5SJed Brown    Application Interface Routine: PCApply()
3400c7d97c5SJed Brown  */
3410c7d97c5SJed Brown #undef __FUNCT__
3420c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
34353cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
3440c7d97c5SJed Brown {
3450c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)(pc->data);
3460c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
3470c7d97c5SJed Brown   PetscErrorCode ierr;
3480c7d97c5SJed Brown   PetscScalar    one = 1.0;
3490c7d97c5SJed Brown   PetscScalar    m_one = -1.0;
3500c7d97c5SJed Brown 
3510c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
3520c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
3530c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
3540c7d97c5SJed Brown 
3550c7d97c5SJed Brown   PetscFunctionBegin;
3560c7d97c5SJed Brown   /* First Dirichlet solve */
3570c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3580c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
35953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3600c7d97c5SJed Brown   /*
3610c7d97c5SJed Brown     Assembling right hand side for BDDC operator
3620c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
3630c7d97c5SJed Brown     - the interface part of the global vector z
3640c7d97c5SJed Brown   */
3650c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3660c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
3670c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3680c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3690c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
3700c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3710c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3720c7d97c5SJed Brown 
3730c7d97c5SJed Brown   /*
3740c7d97c5SJed Brown     Apply interface preconditioner
3750c7d97c5SJed Brown     Results are stored in:
3760c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
3770c7d97c5SJed Brown     -  the interface part of the global vector z
3780c7d97c5SJed Brown   */
3790c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
3800c7d97c5SJed Brown 
3810c7d97c5SJed Brown   /* Second Dirichlet solves and assembling of output */
3820c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3830c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3840c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
3850c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
38653cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
3870c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
3880c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
3890c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
3900c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3910c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3920c7d97c5SJed Brown 
3930c7d97c5SJed Brown   PetscFunctionReturn(0);
3940c7d97c5SJed Brown 
3950c7d97c5SJed Brown }
3960c7d97c5SJed Brown 
3970c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3980c7d97c5SJed Brown /*
3990c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
4000c7d97c5SJed Brown 
4010c7d97c5SJed Brown */
4020c7d97c5SJed Brown #undef __FUNCT__
4030c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
40453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
4050c7d97c5SJed Brown {
4060c7d97c5SJed Brown   PetscErrorCode ierr;
4070c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4080c7d97c5SJed Brown   PC_IS*         pcis =   (PC_IS*)  (pc->data);
4090c7d97c5SJed Brown   PetscScalar    zero = 0.0;
4100c7d97c5SJed Brown 
4110c7d97c5SJed Brown   PetscFunctionBegin;
4120c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
4130c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4140c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4150c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4160c7d97c5SJed Brown 
4170c7d97c5SJed Brown   /* Application of PHI^T  */
4180c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4190c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4200c7d97c5SJed Brown 
4210c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
4220c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
4230c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4240c7d97c5SJed Brown 
4250c7d97c5SJed Brown   /* Local solution on R nodes */
4260c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
4270c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4280c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4290c7d97c5SJed Brown   if(pcbddc->prec_type) {
4300c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4310c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4320c7d97c5SJed Brown   }
4330c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
4340c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
4350c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4360c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4370c7d97c5SJed Brown   if(pcbddc->prec_type) {
4380c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4390c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4400c7d97c5SJed Brown   }
4410c7d97c5SJed Brown 
4420c7d97c5SJed Brown   /* Coarse solution */
4430c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
44453cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
4450c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4460c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4470c7d97c5SJed Brown 
4480c7d97c5SJed Brown   /* Sum contributions from two levels */
4490c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
4500c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4510c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4520c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4530c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
4540c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4550c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4560c7d97c5SJed Brown 
4570c7d97c5SJed Brown   PetscFunctionReturn(0);
4580c7d97c5SJed Brown }
4590c7d97c5SJed Brown 
4600c7d97c5SJed Brown 
4610c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4620c7d97c5SJed Brown /*
4630c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
4640c7d97c5SJed Brown 
4650c7d97c5SJed Brown */
4660c7d97c5SJed Brown #undef __FUNCT__
4670c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
46853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
4690c7d97c5SJed Brown {
4700c7d97c5SJed Brown   PetscErrorCode ierr;
4710c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4720c7d97c5SJed Brown 
4730c7d97c5SJed Brown   PetscFunctionBegin;
4740c7d97c5SJed Brown 
47553cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4760c7d97c5SJed Brown   if(pcbddc->n_constraints) {
4770c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
4780c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
4790c7d97c5SJed Brown   }
4800c7d97c5SJed Brown 
4810c7d97c5SJed Brown   PetscFunctionReturn(0);
4820c7d97c5SJed Brown }
4830c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4840c7d97c5SJed Brown /*
4850c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
4860c7d97c5SJed Brown 
4870c7d97c5SJed Brown */
4880c7d97c5SJed Brown #undef __FUNCT__
4890c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
49053cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4910c7d97c5SJed Brown {
4920c7d97c5SJed Brown   PetscErrorCode ierr;
4930c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4940c7d97c5SJed Brown 
4950c7d97c5SJed Brown   PetscFunctionBegin;
4960c7d97c5SJed Brown 
4970c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4980c7d97c5SJed Brown     case SCATTERS_BDDC:
4990c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5000c7d97c5SJed Brown       break;
5010c7d97c5SJed Brown     case GATHERS_BDDC:
5020c7d97c5SJed Brown       break;
5030c7d97c5SJed Brown   }
5040c7d97c5SJed Brown   PetscFunctionReturn(0);
5050c7d97c5SJed Brown 
5060c7d97c5SJed Brown }
5070c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5080c7d97c5SJed Brown /*
5090c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
5100c7d97c5SJed Brown 
5110c7d97c5SJed Brown */
5120c7d97c5SJed Brown #undef __FUNCT__
5130c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
51453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5150c7d97c5SJed Brown {
5160c7d97c5SJed Brown   PetscErrorCode ierr;
5170c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5180c7d97c5SJed Brown   PetscScalar*   array_to;
5190c7d97c5SJed Brown   PetscScalar*   array_from;
5200c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
5210c7d97c5SJed Brown   PetscInt i;
5220c7d97c5SJed Brown 
5230c7d97c5SJed Brown   PetscFunctionBegin;
5240c7d97c5SJed Brown 
5250c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5260c7d97c5SJed Brown     case SCATTERS_BDDC:
5270c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5280c7d97c5SJed Brown       break;
5290c7d97c5SJed Brown     case GATHERS_BDDC:
5300c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
5310c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
5320c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
5330c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
5340c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
53553cdbc3dSStefano 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);
5360c7d97c5SJed Brown             if(vec_to) {
5370c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5380c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5390c7d97c5SJed Brown             }
5400c7d97c5SJed Brown           } else {
5410c7d97c5SJed Brown             if(vec_from)
5420c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5430c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
54453cdbc3dSStefano 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);
5450c7d97c5SJed Brown           }
5460c7d97c5SJed Brown           break;
5470c7d97c5SJed Brown         case REPLICATED_BDDC:
5480c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
54953cdbc3dSStefano 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);
5500c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
5510c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5520c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
5530c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
5540c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
5550c7d97c5SJed Brown           }
5560c7d97c5SJed Brown           break;
55753cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
55853cdbc3dSStefano Zampini           break;
55953cdbc3dSStefano Zampini         case PARALLEL_BDDC:
56053cdbc3dSStefano Zampini           break;
5610c7d97c5SJed Brown       }
5620c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
5630c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
5640c7d97c5SJed Brown       break;
5650c7d97c5SJed Brown   }
5660c7d97c5SJed Brown   PetscFunctionReturn(0);
5670c7d97c5SJed Brown 
5680c7d97c5SJed Brown }
5690c7d97c5SJed Brown 
5700c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5710c7d97c5SJed Brown /*
5720c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
5730c7d97c5SJed Brown    that was created with PCCreate_BDDC().
5740c7d97c5SJed Brown 
5750c7d97c5SJed Brown    Input Parameter:
5760c7d97c5SJed Brown .  pc - the preconditioner context
5770c7d97c5SJed Brown 
5780c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
5790c7d97c5SJed Brown */
5800c7d97c5SJed Brown #undef __FUNCT__
5810c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
58253cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
5830c7d97c5SJed Brown {
5840c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
5850c7d97c5SJed Brown   PetscErrorCode ierr;
5860c7d97c5SJed Brown 
5870c7d97c5SJed Brown   PetscFunctionBegin;
5880c7d97c5SJed Brown   /* free data created by PCIS */
5890c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
5900c7d97c5SJed Brown   /* free BDDC data  */
59153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
59253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
59353cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
59453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
59553cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
59653cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
59753cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
59853cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
59953cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
60053cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
60153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
60253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
60353cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
60453cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
60553cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
60653cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
60753cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
60853cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
60953cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
61053cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr);
61153cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
61253cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
6130c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
61453cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
61553cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
6160c7d97c5SJed Brown   if (pcbddc->n_constraints) {
6170c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
6180c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr);
6190c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
6200c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr);
6210c7d97c5SJed Brown     ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr);
6220c7d97c5SJed Brown   }
623*9c0446d6SStefano Zampini   PetscInt i;
624*9c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
625*9c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
626*9c0446d6SStefano Zampini   }
627*9c0446d6SStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);
6280c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
6290c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
6300c7d97c5SJed Brown   PetscFunctionReturn(0);
6310c7d97c5SJed Brown }
6320c7d97c5SJed Brown 
6330c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6340c7d97c5SJed Brown /*MC
6350c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
6360c7d97c5SJed Brown 
6370c7d97c5SJed Brown    Options Database Keys:
638a0ba757dSStefano Zampini .    -pcbddc ??? -
6390c7d97c5SJed Brown 
6400c7d97c5SJed Brown    Level: intermediate
6410c7d97c5SJed Brown 
6420c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
6430c7d97c5SJed Brown 
6440c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
6450c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
6460c7d97c5SJed Brown           on the subdomains).
6470c7d97c5SJed Brown 
648a0ba757dSStefano Zampini           Options for the coarse grid preconditioner can be set with -
649a0ba757dSStefano Zampini           Options for the Dirichlet subproblem can be set with -
650a0ba757dSStefano Zampini           Options for the Neumann subproblem can be set with -
6510c7d97c5SJed Brown 
6520c7d97c5SJed Brown    Contributed by Stefano Zampini
6530c7d97c5SJed Brown 
6540c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
6550c7d97c5SJed Brown M*/
6560c7d97c5SJed Brown EXTERN_C_BEGIN
6570c7d97c5SJed Brown #undef __FUNCT__
6580c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
6590c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
6600c7d97c5SJed Brown {
6610c7d97c5SJed Brown   PetscErrorCode ierr;
6620c7d97c5SJed Brown   PC_BDDC          *pcbddc;
6630c7d97c5SJed Brown 
6640c7d97c5SJed Brown   PetscFunctionBegin;
6650c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
6660c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
6670c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
6680c7d97c5SJed Brown   /* create PCIS data structure */
6690c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
6700c7d97c5SJed Brown   /* BDDC specific */
6710c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
6720c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
67353cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
6740c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
6750c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
6760c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
6770c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
6780c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
6790c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
6800c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
6810c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
6820c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
68353cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
68453cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
6850c7d97c5SJed Brown   pcbddc->n_constraints              = 0;
6860c7d97c5SJed Brown   pcbddc->n_vertices                 = 0;
6870c7d97c5SJed Brown   pcbddc->vertices                   = 0;
6880c7d97c5SJed Brown   pcbddc->indices_to_constraint      = 0;
6890c7d97c5SJed Brown   pcbddc->quadrature_constraint      = 0;
6900c7d97c5SJed Brown   pcbddc->sizes_of_constraint        = 0;
6910c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
6920c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
69353cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
6940c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
6950c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
6960c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
6970c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
6980c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
699e269702eSStefano Zampini   pcbddc->dbg_flag                 = PETSC_FALSE;
7000c7d97c5SJed Brown   pcbddc->vertices_flag              = PETSC_FALSE;
7010c7d97c5SJed Brown   pcbddc->constraints_flag           = PETSC_FALSE;
7020c7d97c5SJed Brown   pcbddc->faces_flag                 = PETSC_FALSE;
7030c7d97c5SJed Brown   pcbddc->edges_flag                 = PETSC_FALSE;
7040c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
7050c7d97c5SJed Brown   /* function pointers */
7060c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
7070c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
7080c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
7090c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
7100c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
7110c7d97c5SJed Brown   pc->ops->view                = 0;
7120c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
7130c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
7140c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
7150c7d97c5SJed Brown   /* composing function */
7160c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
7170c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
71853cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
71953cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
7200c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
7210c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
722*9c0446d6SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
723*9c0446d6SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
7240c7d97c5SJed Brown   PetscFunctionReturn(0);
7250c7d97c5SJed Brown }
7260c7d97c5SJed Brown EXTERN_C_END
7270c7d97c5SJed Brown 
7280c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7290c7d97c5SJed Brown /*
7300c7d97c5SJed Brown    PCBDDCCoarseSetUp -
7310c7d97c5SJed Brown */
7320c7d97c5SJed Brown #undef __FUNCT__
7330c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
73453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
7350c7d97c5SJed Brown {
7360c7d97c5SJed Brown   PetscErrorCode  ierr;
7370c7d97c5SJed Brown 
7380c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
7390c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
7400c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
7410c7d97c5SJed Brown   IS                is_R_local;
7420c7d97c5SJed Brown   IS                is_V_local;
7430c7d97c5SJed Brown   IS                is_C_local;
7440c7d97c5SJed Brown   IS                is_aux1;
7450c7d97c5SJed Brown   IS                is_aux2;
7460c7d97c5SJed Brown   const VecType     impVecType;
7470c7d97c5SJed Brown   const MatType     impMatType;
7480c7d97c5SJed Brown   PetscInt          n_R=0;
7490c7d97c5SJed Brown   PetscInt          n_D=0;
7500c7d97c5SJed Brown   PetscInt          n_B=0;
7510c7d97c5SJed Brown   PetscMPIInt       totprocs;
7520c7d97c5SJed Brown   PetscScalar       zero=0.0;
7530c7d97c5SJed Brown   PetscScalar       one=1.0;
7540c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
7550c7d97c5SJed Brown   PetscScalar*      array;
7560c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
7570c7d97c5SJed Brown   PetscInt          *idx_R_local;
7580c7d97c5SJed Brown   PetscInt          *idx_V_B;
7590c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
7600c7d97c5SJed Brown   PetscScalar       *constraints_errors;
7610c7d97c5SJed Brown   /* auxiliary indices */
7620c7d97c5SJed Brown   PetscInt s,i,j,k;
763e269702eSStefano Zampini   /* for verbose output of bddc */
764e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
765e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
766a0ba757dSStefano Zampini   /* for counting coarse dofs */
767a0ba757dSStefano Zampini   PetscScalar       coarsesum;
7680c7d97c5SJed Brown 
7690c7d97c5SJed Brown   PetscFunctionBegin;
7700c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
7710c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
7720c7d97c5SJed Brown   /* Set local primal size */
7730c7d97c5SJed Brown   pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints;
774a0ba757dSStefano 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) */
775a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
776a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
777a0ba757dSStefano Zampini   for(i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = one; }
778a0ba757dSStefano Zampini   for(i=0;i<pcbddc->n_constraints;i++) {
779a0ba757dSStefano Zampini     for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) {
780a0ba757dSStefano Zampini       k = pcbddc->indices_to_constraint[i][j];
781a0ba757dSStefano Zampini       if( array[k] == zero ) {
782a0ba757dSStefano Zampini         array[k] = one;
783a0ba757dSStefano Zampini         break;
784a0ba757dSStefano Zampini       }
785a0ba757dSStefano Zampini     }
786a0ba757dSStefano Zampini   }
787a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
788a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
789a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
790a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
791a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
792a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
793a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
794a0ba757dSStefano Zampini   for(i=0;i<pcis->n;i++) { if(array[i] > zero) array[i] = one/array[i]; }
795a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
796a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
797a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
798a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
799a0ba757dSStefano Zampini   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
800a0ba757dSStefano Zampini   pcbddc->coarse_size = (PetscInt) coarsesum;
801a0ba757dSStefano Zampini 
8020c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
8030c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
8040c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8050c7d97c5SJed Brown   for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; }
8060c7d97c5SJed Brown   ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
8070c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
8080c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
809e269702eSStefano Zampini   if(dbg_flag) {
8100c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8110c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8120c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
8130c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
8140c7d97c5SJed 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);
8150c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
816a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
817a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
818a0ba757dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8190c7d97c5SJed Brown   }
8200c7d97c5SJed Brown   /* Allocate needed vectors */
8210c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
8220c7d97c5SJed Brown   impMatType = MATSEQDENSE;
8230c7d97c5SJed Brown   impVecType = VECSEQ;
8240c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
8250c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
8260c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
8270c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
8280c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
829d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
8300c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
8310c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
8320c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
8330c7d97c5SJed Brown 
8340c7d97c5SJed Brown   /* Creating some index sets needed  */
8350c7d97c5SJed Brown   /* For submatrices */
8360c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
8370c7d97c5SJed Brown   if(pcbddc->n_vertices)    { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); }
8380c7d97c5SJed Brown   if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); }
8390c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
8400c7d97c5SJed Brown   {
8410c7d97c5SJed Brown     PetscInt   *aux_array1;
8420c7d97c5SJed Brown     PetscInt   *aux_array2;
8430c7d97c5SJed Brown     PetscScalar      value;
8440c7d97c5SJed Brown 
8450c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
8460c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
8470c7d97c5SJed Brown 
848d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
8490c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8500c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8510c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8520c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8530c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8540c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8550c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8560c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
8570c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8580c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
8590c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8600c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
8613828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8620c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
8630c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
8640c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
8650c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
8660c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
8670c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
8680c7d97c5SJed Brown 
869e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
8700c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
8710c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8720c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
8730c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8740c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
8750c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
8760c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
8770c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
8780c7d97c5SJed Brown     }
8790c7d97c5SJed Brown 
8800c7d97c5SJed Brown     /* Check scatters */
881e269702eSStefano Zampini     if(dbg_flag) {
8820c7d97c5SJed Brown 
8830c7d97c5SJed Brown       Vec            vec_aux;
8840c7d97c5SJed Brown 
8850c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
8860c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
8870c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
888d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
889d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
890d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
891d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
892d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
893d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
894d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
895d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
896d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
897d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
8980c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
899d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
9000c7d97c5SJed Brown 
901d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
902d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
903d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
904d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
905d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
906d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
907d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
908d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
909d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
910d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
9110c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
912d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
9130c7d97c5SJed Brown 
9140c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9150c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
9160c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9170c7d97c5SJed Brown 
918d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
919d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
920d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
921d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
922d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
923d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
924d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
925d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
926d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
927d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
9280c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
929d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
9300c7d97c5SJed Brown 
931d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
932d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
933d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
934d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
935d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
936d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
937d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
938d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
939d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
940d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
9410c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
942d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
9430c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9440c7d97c5SJed Brown 
9450c7d97c5SJed Brown     }
9460c7d97c5SJed Brown   }
9470c7d97c5SJed Brown 
9480c7d97c5SJed Brown   /* vertices in boundary numbering */
9490c7d97c5SJed Brown   if(pcbddc->n_vertices) {
950d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
9510c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9520c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; }
9530c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
954d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
955d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9560c7d97c5SJed Brown     ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
9570c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
9580c7d97c5SJed Brown     //printf("vertices in boundary numbering\n");
9590c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) {
9600c7d97c5SJed Brown       s=0;
9610c7d97c5SJed Brown       while (array[s] != i ) {s++;}
9620c7d97c5SJed Brown       idx_V_B[i]=s;
9630c7d97c5SJed Brown       //printf("idx_V_B[%d]=%d\n",i,s);
9640c7d97c5SJed Brown     }
9650c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
9660c7d97c5SJed Brown   }
9670c7d97c5SJed Brown 
9680c7d97c5SJed Brown 
9690c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
9700c7d97c5SJed Brown   {
9710c7d97c5SJed Brown     Mat  A_RR;
97253cdbc3dSStefano Zampini     PC   pc_temp;
9730c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
97453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
97553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
97653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
97753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
978a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
9790c7d97c5SJed Brown     /* default */
98053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
98153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
9820c7d97c5SJed Brown     /* Allow user's customization */
98353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
98453cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
98553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
9860c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
9870c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
98853cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
98953cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
99053cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
99153cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
992a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
9930c7d97c5SJed Brown     /* default */
99453cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
99553cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
9960c7d97c5SJed Brown     /* Allow user's customization */
99753cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
99853cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
99953cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1000a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1001e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
10020c7d97c5SJed Brown       Vec temp_vec;
10030c7d97c5SJed Brown       PetscScalar value;
10040c7d97c5SJed Brown 
1005a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1006a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1007a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1008a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1009a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1010a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1011a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1012a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1013a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1014a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1015a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1016d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1017d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1018d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1019d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1020d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1021d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1022e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
10230c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1024d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10250c7d97c5SJed Brown     }
10260c7d97c5SJed Brown     /* free Neumann problem's matrix */
10270c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
10280c7d97c5SJed Brown   }
10290c7d97c5SJed Brown 
10300c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
10310c7d97c5SJed Brown   {
10320c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
10330c7d97c5SJed Brown     Mat          M1,M2;
10340c7d97c5SJed Brown     Mat          C_CR;
10350c7d97c5SJed Brown     Mat          CMAT,AUXMAT;
10360c7d97c5SJed Brown     Vec          vec1_C;
10370c7d97c5SJed Brown     Vec          vec2_C;
10380c7d97c5SJed Brown     Vec          vec1_V;
10390c7d97c5SJed Brown     Vec          vec2_V;
10400c7d97c5SJed Brown     PetscInt     *nnz;
10410c7d97c5SJed Brown     PetscInt     *auxindices;
104253cdbc3dSStefano Zampini     PetscInt     index;
10430c7d97c5SJed Brown     PetscScalar* array2;
10440c7d97c5SJed Brown     MatFactorInfo matinfo;
10450c7d97c5SJed Brown 
10460c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
10470c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
10480c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
10490c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
10500c7d97c5SJed Brown 
10510c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
10520c7d97c5SJed Brown     if(pcbddc->n_vertices) {
10530c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
10540c7d97c5SJed Brown       ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr);
10550c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
10560c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
10570c7d97c5SJed Brown     }
10580c7d97c5SJed Brown     if(pcbddc->n_constraints) {
10590c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
10600c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
10610c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
10620c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
10630c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
10640c7d97c5SJed Brown     }
10650c7d97c5SJed Brown     /* Create C matrix [I 0; 0 const] */
1066d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&CMAT);CHKERRQ(ierr);
10670c7d97c5SJed Brown     ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr);
10680c7d97c5SJed Brown     ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
10690c7d97c5SJed Brown     /* nonzeros */
10700c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; }
10710c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];}
10720c7d97c5SJed Brown     ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr);
10730c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
10740c7d97c5SJed Brown       ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
10750c7d97c5SJed Brown     }
10760c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
107753cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
107853cdbc3dSStefano Zampini       ierr = MatSetValues(CMAT,1,&index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES);CHKERRQ(ierr);
10790c7d97c5SJed Brown     }
10800c7d97c5SJed Brown     ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10810c7d97c5SJed Brown     ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10820c7d97c5SJed Brown 
10830c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
10840c7d97c5SJed Brown 
10850c7d97c5SJed Brown     if(pcbddc->n_constraints) {
10860c7d97c5SJed Brown       /* some work vectors */
10870c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
10880c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr);
10890c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
10900c7d97c5SJed Brown 
10910c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
10920c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
1093d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
10940c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10950c7d97c5SJed Brown         for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; }
10960c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
10970c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
10980c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10990c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
110053cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
11010c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
110253cdbc3dSStefano Zampini         index=i;
110353cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11040c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
11050c7d97c5SJed Brown       }
11060c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11070c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11080c7d97c5SJed Brown 
11090c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
11100c7d97c5SJed Brown       ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
11110c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
11120c7d97c5SJed Brown 
11130c7d97c5SJed Brown         /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
11140c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1115d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
11160c7d97c5SJed Brown       ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
11170c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
11180c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
11190c7d97c5SJed Brown 
11200c7d97c5SJed Brown         /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */
1121d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
11220c7d97c5SJed Brown       ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
11230c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
11240c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
11250c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
11260c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
11270c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
11280c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
11290c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
11300c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
11310c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
113253cdbc3dSStefano Zampini         index=i;
113353cdbc3dSStefano Zampini         ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11340c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
11350c7d97c5SJed Brown       }
11360c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11370c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11380c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
11390c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
11400c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
11410c7d97c5SJed Brown 
11420c7d97c5SJed Brown     }
11430c7d97c5SJed Brown 
11440c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
11450c7d97c5SJed Brown     if(pcbddc->n_vertices){
11460c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
11470c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
11480c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
11490c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1150d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
11510c7d97c5SJed Brown       ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr);
11520c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
11530c7d97c5SJed Brown       for(i=0;i<pcbddc->n_vertices;i++) {
11540c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
11550c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
11560c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
11570c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11580c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
115953cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
116053cdbc3dSStefano Zampini         index=i;
11610c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
116253cdbc3dSStefano Zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11630c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
11640c7d97c5SJed Brown       }
11650c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11660c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11670c7d97c5SJed Brown     }
11680c7d97c5SJed Brown 
11690c7d97c5SJed Brown /* Matrix of coarse basis functions (local) */
1170d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
11710c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
11720c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
1173e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1174d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
11750c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
11760c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
11770c7d97c5SJed Brown     }
11780c7d97c5SJed Brown 
11790c7d97c5SJed Brown /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1180e269702eSStefano Zampini     if(dbg_flag) {
11810c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
11820c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
11830c7d97c5SJed Brown     }
11840c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
11850c7d97c5SJed Brown 
11860c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
11870c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
11880c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
11890c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
11900c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
11910c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11920c7d97c5SJed Brown       /* solution of saddle point problem */
11930c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
11940c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
11950c7d97c5SJed Brown       if(pcbddc->n_constraints) {
11960c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
11970c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
11980c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
11990c7d97c5SJed Brown       }
12000c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
12010c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
12020c7d97c5SJed Brown 
12030c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
12040c7d97c5SJed Brown       /* coarse basis functions */
120553cdbc3dSStefano Zampini       index=i;
12060c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
12070c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12080c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12090c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
121053cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12110c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12120c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1213e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
12140c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12150c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12160c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
121753cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12180c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
12190c7d97c5SJed Brown       }
12200c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
12210c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12220c7d97c5SJed Brown       for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
12230c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12240c7d97c5SJed Brown       if( pcbddc->n_constraints) {
12250c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12260c7d97c5SJed 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
12270c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12280c7d97c5SJed Brown       }
12290c7d97c5SJed Brown 
1230e269702eSStefano Zampini       if( dbg_flag ) {
12310c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1232d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
12330c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12340c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12350c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
12360c7d97c5SJed Brown         array[ pcbddc->vertices[i] ] = one;
12370c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12380c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12390c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1240d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
12410c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12420c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12430c7d97c5SJed Brown         for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; }
12440c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12450c7d97c5SJed Brown         if(pcbddc->n_constraints) {
12460c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12470c7d97c5SJed Brown           for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; }
12480c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12490c7d97c5SJed Brown         }
12500c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12510c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
12520c7d97c5SJed Brown         /* check saddle point solution */
12530c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
125453cdbc3dSStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
125553cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
12560c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
12570c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
125853cdbc3dSStefano Zampini         array[index]=array[index]+m_one;  /* shift by the identity matrix */
12590c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
126053cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
12610c7d97c5SJed Brown       }
12620c7d97c5SJed Brown     }
12630c7d97c5SJed Brown 
12640c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++){
1265d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
12660c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
12670c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
12680c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
12690c7d97c5SJed Brown       /* solution of saddle point problem */
12700c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
12710c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
12720c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
12730c7d97c5SJed Brown       if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
12740c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
12750c7d97c5SJed Brown       /* coarse basis functions */
127653cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
12770c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
12780c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12790c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12800c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
128153cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12820c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1283e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
12840c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12850c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12860c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
128753cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12880c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
12890c7d97c5SJed Brown       }
12900c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
12910c7d97c5SJed Brown       if(pcbddc->n_vertices) {
12920c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
129353cdbc3dSStefano Zampini         for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
12940c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12950c7d97c5SJed Brown       }
12960c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
129753cdbc3dSStefano 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
12980c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12990c7d97c5SJed Brown 
1300e269702eSStefano Zampini       if( dbg_flag ) {
13010c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
130253cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
13030c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13040c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
13050c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
13060c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
13070c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13080c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
130953cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
13100c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
13110c7d97c5SJed Brown         if( pcbddc->n_vertices) {
13120c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
13130c7d97c5SJed Brown           for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];}
13140c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
13150c7d97c5SJed Brown         }
13160c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
13170c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];}
13180c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
13190c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
13200c7d97c5SJed Brown         /* check saddle point solution */
13210c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1322d49ef151SStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
132353cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
13240c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
13250c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
132653cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
13270c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
132853cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
13290c7d97c5SJed Brown       }
13300c7d97c5SJed Brown     }
13310c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13320c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1333e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
13340c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13350c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13360c7d97c5SJed Brown     }
13370c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
13380c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
13399d2fce94SStefano Zampini     if(dbg_flag) {
13400c7d97c5SJed Brown 
13410c7d97c5SJed Brown       Mat coarse_sub_mat;
13420c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
13430c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1344a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
13450c7d97c5SJed Brown       PetscScalar      value;
13460c7d97c5SJed Brown 
1347c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1348c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1349c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1350c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1351c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1352c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1353c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1354c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
13550c7d97c5SJed Brown 
13560c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13570c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
13580c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
135953cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
136053cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
136153cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1362c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
136353cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
136453cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1365c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
136653cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
136753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
136853cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
136953cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
137053cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
137153cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
13720c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
13730c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
13740c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
13750c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
137653cdbc3dSStefano 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); }
13770c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
137853cdbc3dSStefano 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); }
13790c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
138053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
138153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
138253cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
138353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
138453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
138553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
138653cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
138753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
138853cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
138953cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
139053cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
13910c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
13920c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
13930c7d97c5SJed Brown     }
13940c7d97c5SJed Brown 
13950c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
13960c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
13970c7d97c5SJed Brown     /* free memory */
13980c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
13990c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
14000c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
14010c7d97c5SJed Brown     if(pcbddc->n_vertices) {
14020c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
14030c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
14040c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
14050c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
14060c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
14070c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
14080c7d97c5SJed Brown     }
14090c7d97c5SJed Brown     if(pcbddc->n_constraints) {
14100c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
14110c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
14120c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
14130c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
14140c7d97c5SJed Brown     }
14150c7d97c5SJed Brown     ierr = MatDestroy(&CMAT);CHKERRQ(ierr);
14160c7d97c5SJed Brown   }
14170c7d97c5SJed Brown   /* free memory */
14180c7d97c5SJed Brown   if(pcbddc->n_vertices) {
14190c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
14200c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
14210c7d97c5SJed Brown   }
14220c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
14230c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
14240c7d97c5SJed Brown 
14250c7d97c5SJed Brown   PetscFunctionReturn(0);
14260c7d97c5SJed Brown }
14270c7d97c5SJed Brown 
14280c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
14290c7d97c5SJed Brown 
14300c7d97c5SJed Brown #undef __FUNCT__
14310c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
143253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
14330c7d97c5SJed Brown {
14340c7d97c5SJed Brown 
14350c7d97c5SJed Brown 
14360c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
14370c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
14380c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
14390c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
14400c7d97c5SJed Brown   MPI_Comm  coarse_comm;
14410c7d97c5SJed Brown 
14420c7d97c5SJed Brown   /* common to all choiches */
14430c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
14440c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
14450c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
14460c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
14470c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
14480c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
14490c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
14500c7d97c5SJed Brown   PetscMPIInt master_proc=0;
14510c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
14520c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
14530c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
14540c7d97c5SJed Brown   PetscMPIInt count_recv=0;
14550c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
14560c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
14570c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
14580c7d97c5SJed Brown   /* some other variables */
14590c7d97c5SJed Brown   PetscErrorCode ierr;
14600c7d97c5SJed Brown   const MatType coarse_mat_type;
14610c7d97c5SJed Brown   const PCType  coarse_pc_type;
146253cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
146353cdbc3dSStefano Zampini   PC pc_temp;
14640c7d97c5SJed Brown   PetscInt i,j,k,bs;
1465e269702eSStefano Zampini   /* verbose output viewer */
1466e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1467e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
14680c7d97c5SJed Brown 
14690c7d97c5SJed Brown   PetscFunctionBegin;
14700c7d97c5SJed Brown 
14710c7d97c5SJed Brown   ins_local_primal_indices = 0;
14720c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
14730c7d97c5SJed Brown   localsizes2              = 0;
14740c7d97c5SJed Brown   localdispl2              = 0;
14750c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
14760c7d97c5SJed Brown   coarse_ISLG              = 0;
14770c7d97c5SJed Brown 
147853cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
147953cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
14800c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
14810c7d97c5SJed Brown 
1482beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1483beed3852SStefano Zampini   {
1484a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1485beed3852SStefano Zampini     PetscScalar    *array;
1486beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1487beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1488beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1489beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1490beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1491beed3852SStefano Zampini 
1492beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1493beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1494beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1495beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1496beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
14975619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1498beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1499beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1500beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1501beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1502beed3852SStefano Zampini     }
15035619798eSStefano Zampini     if(rank_prec_comm == 0) {
1504beed3852SStefano Zampini       /* allocate some auxiliary space */
1505beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1506beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1507beed3852SStefano Zampini     }
1508beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1509beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1510beed3852SStefano Zampini 
1511beed3852SStefano 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)
1512beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1513beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1514beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1515beed3852SStefano Zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) */
1516beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1517beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1518beed3852SStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++) {
1519beed3852SStefano Zampini       array[ pcbddc->vertices[i] ] = one;
1520beed3852SStefano Zampini       auxlocal_primal[i] = pcbddc->vertices[i];
1521beed3852SStefano Zampini     }
1522beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
1523beed3852SStefano Zampini       for (j=0; j<pcbddc->sizes_of_constraint[i]; j++) {
1524beed3852SStefano Zampini         k = pcbddc->indices_to_constraint[i][j];
1525beed3852SStefano Zampini         if( array[k] == zero ) {
1526beed3852SStefano Zampini           array[k] = one;
1527beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1528beed3852SStefano Zampini           break;
1529beed3852SStefano Zampini         }
1530beed3852SStefano Zampini       }
1531beed3852SStefano Zampini     }
1532beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1533a0ba757dSStefano Zampini 
1534a0ba757dSStefano Zampini     /*ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1535beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1536beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1537beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1538beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1539beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1540d49ef151SStefano Zampini     for(i=0;i<pcis->n;i++) { if(array[i] > 0.0) array[i] = one/array[i]; }
1541beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1542beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1543beed3852SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1544beed3852SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1545beed3852SStefano Zampini 
1546beed3852SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1547beed3852SStefano Zampini     pcbddc->coarse_size = (PetscInt) coarsesum;
1548e269702eSStefano Zampini     if(dbg_flag) {
1549e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
15503828260eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1551e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1552a0ba757dSStefano Zampini     }*/
1553a0ba757dSStefano Zampini 
1554beed3852SStefano Zampini     /* Now assign them a global numbering */
1555beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1556beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1557beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1558beed3852SStefano 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);
1559beed3852SStefano Zampini 
1560beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1561beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1562beed3852SStefano Zampini     if(rank_prec_comm==0) {
1563beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1564beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1565beed3852SStefano Zampini       k=1;
1566beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1567beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1568beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1569beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1570beed3852SStefano Zampini           k++;
1571beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1572beed3852SStefano Zampini         }
1573beed3852SStefano Zampini       }
1574beed3852SStefano Zampini     } else {
1575beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1576beed3852SStefano Zampini     }
15775619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1578beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1579beed3852SStefano Zampini 
1580beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1581beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1582beed3852SStefano Zampini       k=0;
1583beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1584beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1585beed3852SStefano Zampini     }
1586e269702eSStefano Zampini     if(dbg_flag) {
1587e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1588e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1589e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1590e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1591e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1592e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1593e269702eSStefano Zampini       }
1594e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1595e269702eSStefano Zampini     }
1596beed3852SStefano Zampini     /* free allocated memory */
1597beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1598beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1599beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1600e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1601beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1602beed3852SStefano Zampini     }
1603e269702eSStefano Zampini   }
1604beed3852SStefano Zampini 
16050c7d97c5SJed Brown   /* adapt coarse problem type */
16060c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
16070c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
16080c7d97c5SJed Brown 
16090c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
16100c7d97c5SJed Brown 
16110c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
16120c7d97c5SJed Brown     {
16130c7d97c5SJed Brown       /* we need additional variables */
16140c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
16150c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
16160c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
16170c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
16180c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
16190c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
16200c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
16210c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
16220c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
16230c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
16240c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
16250c7d97c5SJed Brown       MetisInt    *faces_adjncy;
16260c7d97c5SJed Brown       MetisInt    *faces_xadj;
16270c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
16280c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
16290c7d97c5SJed Brown       PetscInt    *array_int;
16300c7d97c5SJed Brown       PetscMPIInt my_faces=0;
16310c7d97c5SJed Brown       PetscMPIInt total_faces=0;
16323828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
16330c7d97c5SJed Brown 
16340c7d97c5SJed Brown       /* define some quantities */
16350c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
16360c7d97c5SJed Brown       coarse_mat_type = MATIS;
16370c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
163853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPRICHARDSON;
16390c7d97c5SJed Brown 
16400c7d97c5SJed Brown       /* details of coarse decomposition */
16410c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
16420c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
16433828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
16443828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
16453828260eSStefano Zampini 
16463828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1647a0ba757dSStefano Zampini       printf("n_subdomains %d, n_parts %d\nstretch %d,jumps %d,coarse_ratio %d\nlevel should be log_%d(%d)\n",n_subdomains,n_parts,ranks_stretching_ratio,procs_jumps_coarse_comm,pcbddc->coarsening_ratio,pcbddc->coarsening_ratio,(ranks_stretching_ratio/pcbddc->coarsening_ratio+1));
16480c7d97c5SJed Brown 
16490c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
16500c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
16513828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
16520c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
16530c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
16540c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
16550c7d97c5SJed Brown         }
16560c7d97c5SJed Brown       }
16570c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
16580c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
16590c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
16600c7d97c5SJed Brown             my_faces++;
16610c7d97c5SJed Brown             break;
16620c7d97c5SJed Brown           }
16630c7d97c5SJed Brown         }
16640c7d97c5SJed Brown       }
16650c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
16660c7d97c5SJed Brown 
166753cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
16680c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
16690c7d97c5SJed Brown       my_faces=0;
16700c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
16710c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
16720c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
16730c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
16740c7d97c5SJed Brown             my_faces++;
16750c7d97c5SJed Brown             break;
16760c7d97c5SJed Brown           }
16770c7d97c5SJed Brown         }
16780c7d97c5SJed Brown       }
16790c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
16800c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
16810c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
16820c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
16830c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
16840c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
16850c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
16860c7d97c5SJed Brown       }
168753cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16880c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
16890c7d97c5SJed Brown         faces_xadj[0]=0;
16900c7d97c5SJed Brown         faces_displacements[0]=0;
16910c7d97c5SJed Brown         j=0;
16920c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
16930c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
16940c7d97c5SJed Brown           if(number_of_faces[i-1]) {
16950c7d97c5SJed Brown             j++;
16960c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
16970c7d97c5SJed Brown           }
16980c7d97c5SJed Brown         }
16990c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
17000c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
17010c7d97c5SJed Brown       }
170253cdbc3dSStefano 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);
17030c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
17040c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
17050c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
17063828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
17073828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
17080c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
17090c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
17100c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
17110c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
17120c7d97c5SJed Brown           printf("\n");
17130c7d97c5SJed Brown         }
17140c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
17150c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
17160c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
17170c7d97c5SJed Brown       }
17180c7d97c5SJed Brown 
17190c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
17200c7d97c5SJed Brown 
17213828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
17223828260eSStefano Zampini 
17230c7d97c5SJed Brown         ncon=1;
17240c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
17250c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
17260c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
17270c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
17280c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
17290c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
17300c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
17310c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
17320c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
17333828260eSStefano Zampini         printf("METIS PART GRAPH\n");
17343828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
17353828260eSStefano Zampini           printf("Using Kway\n");
17363828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
17373828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
17380c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
17393828260eSStefano Zampini         } else {
17403828260eSStefano Zampini           printf("Using Recursive\n");
17413828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
17423828260eSStefano Zampini         }
17430c7d97c5SJed 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);
17443828260eSStefano Zampini         printf("Partition done!\n");
17450c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
17460c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
17470c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
17480c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
17493828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
17503828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
17510c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
17520c7d97c5SJed Brown       }
17530c7d97c5SJed Brown 
17540c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
17550c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
17560c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
17570c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
17580c7d97c5SJed Brown       }
17590c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
17600c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
176153cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
17620c7d97c5SJed Brown 
17630c7d97c5SJed Brown       if( coarse_color == 0 ) {
176453cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
176553cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
17663828260eSStefano Zampini         printf("Details of coarse comm\n");
17673828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
17683828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
17690c7d97c5SJed Brown       } else {
17700c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
17710c7d97c5SJed Brown       }
17720c7d97c5SJed Brown 
17730c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
17740c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
17750c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
17760c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
17770c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
17780c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
17790c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
17800c7d97c5SJed Brown         /* some initializations */
17810c7d97c5SJed Brown         displacements_recv[0]=0;
17820c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
17830c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
17840c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
17853828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
17860c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
17870c7d97c5SJed Brown               total_count_recv[j]++;
17880c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
17890c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
17900c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
17910c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
17920c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
17933828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
17940c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
17950c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
17963828260eSStefano Zampini               total_count_recv[j]+=1;
17970c7d97c5SJed Brown             }
17980c7d97c5SJed Brown           }
17990c7d97c5SJed Brown         }
18003828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
18013828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
18023828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
18033828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
18043828260eSStefano Zampini           }
18053828260eSStefano Zampini           printf("\n");
18063828260eSStefano Zampini         }
18070c7d97c5SJed Brown 
18080c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
18093828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
18100c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
18110c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
18123828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
18133828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
18143828260eSStefano Zampini           } else {
18153828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
18163828260eSStefano Zampini           }
18170c7d97c5SJed Brown         printf("\n");
18180c7d97c5SJed Brown       }
18190c7d97c5SJed Brown 
18200c7d97c5SJed Brown       /* Scatter new decomposition for send details */
182153cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
18220c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
18230c7d97c5SJed Brown       if( coarse_color == 0) {
182453cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
18250c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
182653cdbc3dSStefano 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);
18270c7d97c5SJed Brown       }
18280c7d97c5SJed Brown 
18290c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
18300c7d97c5SJed Brown       //if(coarse_color == 0) {
18310c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
18320c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
18330c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
18340c7d97c5SJed Brown       //  printf("\n");
18350c7d97c5SJed Brown       //}
18360c7d97c5SJed Brown 
18370c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
18380c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
18390c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
18400c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
18410c7d97c5SJed Brown         free(coarse_subdivision);
18420c7d97c5SJed Brown         free(total_count_recv);
18430c7d97c5SJed Brown         free(total_ranks_recv);
18440c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
18450c7d97c5SJed Brown       }
18460c7d97c5SJed Brown       break;
18470c7d97c5SJed Brown     }
18480c7d97c5SJed Brown 
18490c7d97c5SJed Brown     case(REPLICATED_BDDC):
18500c7d97c5SJed Brown 
18510c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
18520c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
18530c7d97c5SJed Brown       coarse_pc_type  = PCLU;
185453cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18550c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18560c7d97c5SJed Brown       active_rank = rank_prec_comm;
18570c7d97c5SJed Brown       break;
18580c7d97c5SJed Brown 
18590c7d97c5SJed Brown     case(PARALLEL_BDDC):
18600c7d97c5SJed Brown 
18610c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
18620c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
18630c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
186453cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18650c7d97c5SJed Brown       coarse_comm = prec_comm;
18660c7d97c5SJed Brown       active_rank = rank_prec_comm;
18670c7d97c5SJed Brown       break;
18680c7d97c5SJed Brown 
18690c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
18700c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
18710c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
18720c7d97c5SJed Brown       coarse_pc_type = PCLU;
187353cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
18740c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
18750c7d97c5SJed Brown       active_rank = master_proc;
18760c7d97c5SJed Brown       break;
18770c7d97c5SJed Brown   }
18780c7d97c5SJed Brown 
18790c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
18800c7d97c5SJed Brown 
18810c7d97c5SJed Brown     case(SCATTERS_BDDC):
18820c7d97c5SJed Brown       {
18830c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
18840c7d97c5SJed Brown 
18850c7d97c5SJed Brown           PetscMPIInt send_size;
18860c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
18870c7d97c5SJed Brown           PetscInt    ii,jj;
18880c7d97c5SJed Brown           MPI_Request *requests;
18890c7d97c5SJed Brown 
18900c7d97c5SJed Brown           /* allocate auxiliary space */
18915619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
18925619798eSStefano 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);
18930c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
18940c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
18950c7d97c5SJed Brown           /* allocate stuffs for message massing */
18960c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
18970c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
18980c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
18990c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19000c7d97c5SJed Brown           /* fill up quantities */
19010c7d97c5SJed Brown           j=0;
19020c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
19030c7d97c5SJed Brown             ii = ranks_recv[i];
19040c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
19050c7d97c5SJed Brown             localdispl2[i]=j;
19060c7d97c5SJed Brown             j+=localsizes2[i];
19070c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
19080c7d97c5SJed 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
19090c7d97c5SJed Brown           }
19100c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
19110c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
19120c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
19130c7d97c5SJed Brown           //printf("\n");
19140c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
19150c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19160c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
19170c7d97c5SJed Brown           ins_local_primal_size=0;
19180c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
19190c7d97c5SJed Brown             if(aux_ins_indices[i])
19200c7d97c5SJed Brown               ins_local_primal_size++;
19210c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
19220c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
19230c7d97c5SJed Brown           j=0;
19240c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
19250c7d97c5SJed Brown             if(aux_ins_indices[i])
19260c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
19270c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
19280c7d97c5SJed Brown           j=0;
19290c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
19300c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
19310c7d97c5SJed Brown               aux_ins_indices[i]=-1;
19320c7d97c5SJed Brown             } else {
19330c7d97c5SJed Brown               aux_ins_indices[i]=j;
19340c7d97c5SJed Brown               j++;
19350c7d97c5SJed Brown             }
19360c7d97c5SJed Brown           }
19370c7d97c5SJed Brown 
19380c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
19390c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
19400c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
19410c7d97c5SJed Brown           //printf("\n");
19420c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
19430c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
19440c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
19450c7d97c5SJed Brown           //printf("\n");
19460c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
19470c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
19480c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
19490c7d97c5SJed Brown           //printf("\n");
19500c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
19510c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
19520c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
19530c7d97c5SJed 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]);
19540c7d97c5SJed Brown           //printf("\n");
19550c7d97c5SJed Brown 
19560c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
195753cdbc3dSStefano 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);
19580c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
19590c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
196053cdbc3dSStefano 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);
19610c7d97c5SJed Brown           }
196253cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
19630c7d97c5SJed Brown 
19640c7d97c5SJed Brown           //if(coarse_color == 0) {
19650c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
19660c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
19670c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
19680c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
19690c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
19700c7d97c5SJed 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]);
19710c7d97c5SJed Brown           //    printf("\n");
19720c7d97c5SJed Brown           //  }
19730c7d97c5SJed Brown           //}
19740c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
19750c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19760c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
19770c7d97c5SJed Brown 
19780c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
19790c7d97c5SJed Brown           PetscInt row_ind,col_ind;
19800c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
19810c7d97c5SJed Brown             rr = ranks_recv[k];
19820c7d97c5SJed Brown             kk = localdispl2[k];
19830c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
19840c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
19850c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
19860c7d97c5SJed Brown             for(j=0;j<lps;j++){
19870c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
19880c7d97c5SJed Brown               for(i=0;i<lps;i++){
19890c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
19900c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
19910c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
19920c7d97c5SJed Brown               }
19930c7d97c5SJed Brown             }
19940c7d97c5SJed Brown           }
19950c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
19960c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
19970c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
19980c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
19990c7d97c5SJed Brown 
20000c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
20010c7d97c5SJed Brown           {
20020c7d97c5SJed Brown             IS coarse_IS;
200353cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
20040c7d97c5SJed Brown             coarse_comm = prec_comm;
20050c7d97c5SJed Brown             active_rank=rank_prec_comm;
20060c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
20070c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
20080c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
20090c7d97c5SJed Brown           }
20100c7d97c5SJed Brown         }
20110c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
20120c7d97c5SJed Brown           /* arrays for values insertion */
20130c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
20140c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
20150c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
20160c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
20170c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
20180c7d97c5SJed 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];
20190c7d97c5SJed Brown           }
20200c7d97c5SJed Brown         }
20210c7d97c5SJed Brown         break;
20220c7d97c5SJed Brown 
20230c7d97c5SJed Brown     }
20240c7d97c5SJed Brown 
20250c7d97c5SJed Brown     case(GATHERS_BDDC):
20260c7d97c5SJed Brown       {
20270c7d97c5SJed Brown 
20280c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
20290c7d97c5SJed Brown 
20300c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
20310c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
20320c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
20330c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
20340c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
20350c7d97c5SJed Brown           /* arrays for values insertion */
20360c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
20370c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
20380c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
20390c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
20400c7d97c5SJed Brown           localdispl2[0]=0;
20410c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
20420c7d97c5SJed Brown           j=0;
20430c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
20440c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
20450c7d97c5SJed Brown         }
20460c7d97c5SJed Brown 
20470c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
20480c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
20490c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
205053cdbc3dSStefano 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);
205153cdbc3dSStefano 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);
20520c7d97c5SJed Brown         } else {
205353cdbc3dSStefano 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);
205453cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
20550c7d97c5SJed Brown         }
20560c7d97c5SJed Brown 
20570c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
20580c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
20590c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
20600c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
20610c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
20620c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
20630c7d97c5SJed Brown           }
20640c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
20650c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
20660c7d97c5SJed Brown             offset2=localdispl2[k];
20670c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
20680c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
20690c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
20700c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
20710c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
20720c7d97c5SJed Brown               }
20730c7d97c5SJed Brown             }
20740c7d97c5SJed Brown           }
20750c7d97c5SJed Brown         }
20760c7d97c5SJed Brown         break;
20770c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
20780c7d97c5SJed Brown   }
20790c7d97c5SJed Brown 
20800c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
20810c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
20820c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
20830c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
20840c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
20850c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
20860c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20870c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
20880c7d97c5SJed Brown     } else {
20890c7d97c5SJed Brown       Mat matis_coarse_local_mat;
20900c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
20910c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
20920c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2093a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
20940c7d97c5SJed Brown     }
2095a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
20960c7d97c5SJed 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);
20970c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20980c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20990c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
21000c7d97c5SJed Brown       Mat matis_coarse_local_mat;
21010c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
21020c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
21030c7d97c5SJed Brown     }
21040c7d97c5SJed Brown 
21050c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
21060c7d97c5SJed Brown     /* Preconditioner for coarse problem */
210753cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
210853cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
210953cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
21105619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
211153cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
211253cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
211353cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
21140c7d97c5SJed Brown     /* Allow user's customization */
211553cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
21160c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
211753cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2118e269702eSStefano Zampini       if(dbg_flag) {
2119e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2120e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2121e269702eSStefano Zampini       }
212253cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
212353cdbc3dSStefano Zampini     }
212453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
21255619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
21265619798eSStefano Zampini       if(dbg_flag) {
21275619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
21285619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
21295619798eSStefano Zampini       }
21305619798eSStefano Zampini     }
21310c7d97c5SJed Brown   }
21320c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
21330c7d97c5SJed Brown      IS local_IS,global_IS;
21340c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
21350c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
21360c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
21370c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
21380c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
21390c7d97c5SJed Brown   }
21400c7d97c5SJed Brown 
21410c7d97c5SJed Brown 
21420c7d97c5SJed Brown   /* Check condition number of coarse problem */
2143e269702eSStefano Zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && dbg_flag && rank_prec_comm == active_rank ) {
21440c7d97c5SJed Brown     PetscScalar m_one=-1.0;
21455619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
21460c7d97c5SJed Brown 
21475619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
2148d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
21495619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,KSPGMRES);CHKERRQ(ierr);
21505619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
21515619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2152d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2153d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2154d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2155d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2156d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
21575619798eSStefano Zampini     kappa_2=lambda_max/lambda_min;
21585619798eSStefano Zampini     ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2159d49ef151SStefano Zampini     ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2160d49ef151SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
21615619798eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem condition number estimated with %d iterations of gmres is: % 1.14e\n",k,kappa_2);CHKERRQ(ierr);
2162e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2163e269702eSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
21645619798eSStefano Zampini     /* restore coarse ksp to default values */
2165d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
21665619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
21675619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
21685619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
21695619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
217053cdbc3dSStefano Zampini   }
21710c7d97c5SJed Brown 
21720c7d97c5SJed Brown   /* free data structures no longer needed */
21730c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
21740c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
21750c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
21760c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
21770c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
21780c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
21790c7d97c5SJed Brown 
21800c7d97c5SJed Brown   PetscFunctionReturn(0);
21810c7d97c5SJed Brown }
21820c7d97c5SJed Brown 
21830c7d97c5SJed Brown #undef __FUNCT__
21840c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
218553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
21860c7d97c5SJed Brown {
21870c7d97c5SJed Brown 
21880c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
21890c7d97c5SJed Brown   PC_IS      *pcis = (PC_IS*)pc->data;
21900c7d97c5SJed Brown   Mat_IS   *matis  = (Mat_IS*)pc->pmat->data;
219153cdbc3dSStefano Zampini   PetscInt **neighbours_set;
219253cdbc3dSStefano Zampini   PetscInt bs,ierr,i,j,s,k,iindex;
21930c7d97c5SJed Brown   PetscInt total_counts;
21940c7d97c5SJed Brown   PetscBool flg_row;
21950c7d97c5SJed Brown   PCBDDCGraph mat_graph;
219653cdbc3dSStefano Zampini   PetscInt   neumann_bsize;
219753cdbc3dSStefano Zampini   const PetscInt*  neumann_nodes;
21980c7d97c5SJed Brown   Mat        mat_adj;
2199a0ba757dSStefano Zampini   PetscBool  symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2200a0ba757dSStefano Zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
2201a0ba757dSStefano Zampini   PetscInt*   queue_in_global_numbering;
2202a0ba757dSStefano Zampini   MPI_Comm interface_comm=((PetscObject)pc)->comm;
22030c7d97c5SJed Brown 
22040c7d97c5SJed Brown   PetscFunctionBegin;
22050c7d97c5SJed Brown 
2206a0ba757dSStefano Zampini   /* allocate and initialize needed graph structure */
22070c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
22080c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2209a0ba757dSStefano Zampini   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2210a0ba757dSStefano Zampini   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
22110c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2212a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2213a0ba757dSStefano Zampini   ierr = PetscMalloc4(i,PetscInt,&mat_graph->where,i,PetscInt,&mat_graph->count,i+1,PetscInt,&mat_graph->cptr,i,PetscInt,&mat_graph->queue);CHKERRQ(ierr);
2214a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2215a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2216a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2217a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2218a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
22193828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
22203828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2221a0ba757dSStefano Zampini 
2222*9c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
2223*9c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
2224*9c0446d6SStefano Zampini     PetscInt *is_indices;
2225*9c0446d6SStefano Zampini     PetscInt is_size;
2226*9c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
2227*9c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
2228*9c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
2229*9c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
2230*9c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
2231*9c0446d6SStefano Zampini       }
2232*9c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
2233*9c0446d6SStefano Zampini     }
2234*9c0446d6SStefano Zampini   } else { /* otherwise assume constant block size */
2235a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
22360c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
22370c7d97c5SJed Brown       for(s=0;s<bs;s++) {
22380c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
22390c7d97c5SJed Brown       }
22400c7d97c5SJed Brown     }
2241*9c0446d6SStefano Zampini   }
22420c7d97c5SJed Brown 
22430c7d97c5SJed Brown   total_counts=0;
22440c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
22450c7d97c5SJed Brown     s=pcis->n_shared[i];
22460c7d97c5SJed Brown     total_counts+=s;
224753cdbc3dSStefano Zampini     for(j=0;j<s;j++){
22480c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
22490c7d97c5SJed Brown     }
22500c7d97c5SJed Brown   }
22510c7d97c5SJed Brown   /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */
225253cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
2253*9c0446d6SStefano Zampini     ierr = ISGetSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
225453cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
225553cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
225653cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
225753cdbc3dSStefano Zampini       if(mat_graph->count[iindex] > 2){
225853cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
22590c7d97c5SJed Brown         total_counts++;
22600c7d97c5SJed Brown       }
22610c7d97c5SJed Brown     }
22620c7d97c5SJed Brown   }
22630c7d97c5SJed Brown 
2264a0ba757dSStefano Zampini   /* allocate space for storing neighbours' set */
226553cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
226653cdbc3dSStefano Zampini   if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr);
226753cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2268a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
22690c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
22700c7d97c5SJed Brown     s=pcis->n_shared[i];
22710c7d97c5SJed Brown     for(j=0;j<s;j++) {
22720c7d97c5SJed Brown       k=pcis->shared[i][j];
227353cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
22740c7d97c5SJed Brown       mat_graph->count[k]+=1;
22750c7d97c5SJed Brown     }
22760c7d97c5SJed Brown   }
22770c7d97c5SJed Brown   /* set -1 fake neighbour */
227853cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
227953cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
228053cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
228153cdbc3dSStefano Zampini       if( mat_graph->count[iindex] > 2){
2282a0ba757dSStefano Zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1; /* An additional fake neighbour (with rank -1) */
228353cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
22840c7d97c5SJed Brown       }
22850c7d97c5SJed Brown     }
228653cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
22870c7d97c5SJed Brown   }
2288a0ba757dSStefano Zampini   /* sort set of sharing subdomains for comparison */
228953cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
2290a0ba757dSStefano Zampini   /* start analyzing local interface */
22910c7d97c5SJed Brown   PetscInt nodes_touched=0;
22920c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
2293a0ba757dSStefano Zampini     if(!mat_graph->count[i]){  /* internal nodes */
22940c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
22950c7d97c5SJed Brown       mat_graph->where[i]=0;
22960c7d97c5SJed Brown       nodes_touched++;
22970c7d97c5SJed Brown     }
22980c7d97c5SJed Brown   }
2299a0ba757dSStefano Zampini   PetscInt where_values=1;
23000c7d97c5SJed Brown   PetscBool same_set;
23010c7d97c5SJed Brown   mat_graph->ncmps = 0;
23020c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2303a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
23040c7d97c5SJed Brown     i=0;
23050c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
23060c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2307a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
23080c7d97c5SJed Brown     nodes_touched++;
2309a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
23100c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2311a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
23120c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2313a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
23140c7d97c5SJed Brown         same_set=PETSC_TRUE;
23150c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
231653cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
23170c7d97c5SJed Brown             same_set=PETSC_FALSE;
23180c7d97c5SJed Brown           }
23190c7d97c5SJed Brown         }
2320a0ba757dSStefano Zampini         /* I found a friend of mine */
23210c7d97c5SJed Brown         if(same_set) {
2322a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
23230c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
23240c7d97c5SJed Brown           nodes_touched++;
23250c7d97c5SJed Brown         }
23260c7d97c5SJed Brown       }
23270c7d97c5SJed Brown     }
2328a0ba757dSStefano Zampini     where_values++;
23290c7d97c5SJed Brown   }
2330a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2331a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2332a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2333a0ba757dSStefano Zampini   if(where_values) {
2334a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2335a0ba757dSStefano Zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component contained in the global queue (and carring together the local queue)  */
2336a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2337a0ba757dSStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2338a0ba757dSStefano Zampini       ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2339a0ba757dSStefano Zampini     }
2340a0ba757dSStefano Zampini /*    for(i=0;i<mat_graph->ncmps;i++) {
2341a0ba757dSStefano Zampini       printf("[queue num %d] ptr %d, length %d: global node (local node)\n",i,mat_graph->cptr[i],mat_graph->cptr[i+1]-mat_graph->cptr[i]);
2342a0ba757dSStefano Zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++){
2343a0ba757dSStefano Zampini         printf("%d (%d) ",queue_in_global_numbering[mat_graph->cptr[i]+j],mat_graph->queue[mat_graph->cptr[i]+j]);
2344a0ba757dSStefano Zampini       }
2345a0ba757dSStefano Zampini       printf("\n");
2346a0ba757dSStefano Zampini     }  */
2347a0ba757dSStefano Zampini   }
2348a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2349a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
2350a0ba757dSStefano Zampini     if(mat_graph->where_ncmps[i]>1) {  /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
2351a0ba757dSStefano Zampini       adapt_interface=1;
2352a0ba757dSStefano Zampini       break;
2353a0ba757dSStefano Zampini     }
2354a0ba757dSStefano Zampini   }
2355a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2356a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
23570c7d97c5SJed Brown 
2358a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2359a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2360a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2361a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2362a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2363a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2364a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2365a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2366a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2367a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2368a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2369a0ba757dSStefano Zampini     MPI_Request *send_requests;
2370a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2371a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2372a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2373a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2374a0ba757dSStefano Zampini     PetscInt *add_to_where;
2375a0ba757dSStefano Zampini 
2376a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2377a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2378a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2379a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2380a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2381a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2382a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2383a0ba757dSStefano Zampini       j=0;
2384a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2385a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
2386a0ba757dSStefano Zampini       if(neighbours_set[j][0]!=-1) { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; } /* We don't want sends/recvs_to/from_self -> here I don't count myself  */
2387a0ba757dSStefano Zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-2; }
2388a0ba757dSStefano Zampini     }
2389a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2390a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2391a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2392a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2393a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2394a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2395a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2396a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2397a0ba757dSStefano Zampini     }
2398a0ba757dSStefano Zampini     /* printf("MPI sizes: buffer size for send %d, number of requests %d\n",buffer_size,cum_recv_counts[where_values]); */
2399a0ba757dSStefano Zampini 
2400a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2401a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2402a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2403a0ba757dSStefano Zampini       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2404a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2405a0ba757dSStefano Zampini         if(neighbours_set[j][k] != my_rank) {
2406a0ba757dSStefano Zampini           ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2407a0ba757dSStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2408a0ba757dSStefano Zampini           /*printf("SENDREQ[%d]: to %d (tag %d) the value %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],mat_graph->where_ncmps[i]);
2409a0ba757dSStefano Zampini           printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],sum_requests);*/
2410a0ba757dSStefano Zampini           sum_requests++;
2411a0ba757dSStefano Zampini         }
2412a0ba757dSStefano Zampini       }
2413a0ba757dSStefano Zampini     }
2414a0ba757dSStefano Zampini     /* printf("Final number of request: s=r=%d (should be equal to %d)\n",sum_requests,cum_recv_counts[where_values]); */
2415a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2416a0ba757dSStefano Zampini     /*for(i=0;i<where_values;i++){
2417a0ba757dSStefano Zampini       printf("my where_ncmps[%d]=%d\n",i,mat_graph->where_ncmps[i]);
2418a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
2419a0ba757dSStefano Zampini         printf("   recv where_ncmps[%d]=%d\n",j,recv_buffer_where[j]);
2420a0ba757dSStefano Zampini       }
2421a0ba757dSStefano Zampini     }*/
2422a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2423a0ba757dSStefano Zampini 
2424a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2425a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2426a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2427a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2428a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
2429a0ba757dSStefano Zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) { /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
2430a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2431a0ba757dSStefano Zampini           break;
2432a0ba757dSStefano Zampini         }
2433a0ba757dSStefano Zampini       }
2434a0ba757dSStefano Zampini     }
2435a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2436a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2437a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2438a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2439a0ba757dSStefano Zampini     sum_requests=0;
2440a0ba757dSStefano Zampini     start_of_send=0;
2441a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2442a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2443a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2444a0ba757dSStefano Zampini         size_of_send=0;
2445a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2446a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2447a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2448a0ba757dSStefano Zampini             size_of_send+=1;
2449a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2450a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2451a0ba757dSStefano Zampini             }
2452a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2453a0ba757dSStefano Zampini           }
2454a0ba757dSStefano Zampini         }
2455a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2456a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2457a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2458a0ba757dSStefano Zampini           if(neighbours_set[j][k] != my_rank) {
2459a0ba757dSStefano Zampini             /* printf("SENDREQ[%d]: to %d (tag %d) the value %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],size_of_send);
2460a0ba757dSStefano Zampini             printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],sum_requests+start_of_recv);*/
2461a0ba757dSStefano Zampini             ierr = MPI_Isend(&size_of_send,1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2462a0ba757dSStefano Zampini             ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2463a0ba757dSStefano Zampini             sum_requests++;
2464a0ba757dSStefano Zampini           }
2465a0ba757dSStefano Zampini         }
2466a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2467a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2468a0ba757dSStefano Zampini       }
2469a0ba757dSStefano Zampini     }
2470a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2471a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2472a0ba757dSStefano Zampini     /*j=0;
2473a0ba757dSStefano Zampini     for(k=0;k<where_values;k++) { j+=sizes_of_sends[k]; }
2474a0ba757dSStefano Zampini     printf("This is the send buffer (size %d): \n",j);
2475a0ba757dSStefano Zampini     for(k=0;k<j;k++) { printf("%d ",send_buffer[k]); }
2476a0ba757dSStefano Zampini     printf("\n");*/
2477a0ba757dSStefano Zampini     buffer_size=0;
2478a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2479a0ba757dSStefano Zampini     /* printf("Allocating recv buffer of size %d\n",buffer_size); */
2480a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2481a0ba757dSStefano Zampini     /* now exchange the data */
2482a0ba757dSStefano Zampini     start_of_recv=0;
2483a0ba757dSStefano Zampini     start_of_send=0;
2484a0ba757dSStefano Zampini     sum_requests=0;
2485a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2486a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2487a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2488a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2489a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2490a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2491a0ba757dSStefano Zampini           if(neighbours_set[j][k] != my_rank) {
2492a0ba757dSStefano Zampini             /* printf("SENDREQ[%d]: to %d (tag %d) with size %d at buffer address %d\n",sum_requests,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],size_of_send,start_of_send);
2493a0ba757dSStefano Zampini             printf("RECVREQ[%d]: from %d (tag %d) at buffer address %d\n",sum_requests,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],start_of_recv); */
2494a0ba757dSStefano Zampini             ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2495a0ba757dSStefano Zampini             size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2496a0ba757dSStefano Zampini             ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2497a0ba757dSStefano Zampini             start_of_recv+=size_of_recv;
2498a0ba757dSStefano Zampini             sum_requests++;
2499a0ba757dSStefano Zampini           }
2500a0ba757dSStefano Zampini         }
2501a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2502a0ba757dSStefano Zampini       }
2503a0ba757dSStefano Zampini     }
2504a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2505a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2506a0ba757dSStefano Zampini     /*printf("This is what I received (size %d): \n",start_of_recv);
2507a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { printf("%d ",recv_buffer[k]); }
2508a0ba757dSStefano Zampini     printf("\n");*/
2509a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2510a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2511a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2512a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2513a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2514a0ba757dSStefano Zampini        j+=k;
2515a0ba757dSStefano Zampini     }
2516a0ba757dSStefano Zampini     /*printf("This is what I received in local numbering (unrolled): \n");
2517a0ba757dSStefano Zampini     i=0;
2518a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2519a0ba757dSStefano Zampini        printf("queue num %d (j=%d)\n",i,j);
2520a0ba757dSStefano Zampini        for(k=1;k<petsc_buffer[j]+1;k++) { printf("%d ",petsc_buffer[k+j]); }
2521a0ba757dSStefano Zampini        printf("\n");
2522a0ba757dSStefano Zampini        i++;j+=k;
2523a0ba757dSStefano Zampini     }*/
2524a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2525a0ba757dSStefano Zampini     start_of_recv=0;
2526a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2527a0ba757dSStefano Zampini     global_where_counter=0;
2528a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2529a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2530a0ba757dSStefano Zampini         temp_buffer_size=0;
2531a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2532a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2533a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2534a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2535a0ba757dSStefano Zampini             temp_buffer_size++;
2536a0ba757dSStefano Zampini           } else {
2537a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2538a0ba757dSStefano Zampini           }
2539a0ba757dSStefano Zampini         }
2540a0ba757dSStefano Zampini         /* allocate some temporary space */
2541a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2542a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2543a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2544a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2545a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2546a0ba757dSStefano Zampini         }
2547a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2548a0ba757dSStefano Zampini            temp buffer structure:
2549a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2550a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2551a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2552a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2553a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2554a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2555a0ba757dSStefano Zampini              [ 0, 0, 0;
2556a0ba757dSStefano Zampini                0, 0, 1;
2557a0ba757dSStefano Zampini                1, 1, 2;
2558a0ba757dSStefano Zampini                1, 1, 2;
2559a0ba757dSStefano Zampini                0, 1, 0; ];
2560a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2561a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2562a0ba757dSStefano Zampini                                                                                                                                    */
2563a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2564a0ba757dSStefano Zampini           ins_val=0;
2565a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2566a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2567a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2568a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2569a0ba757dSStefano Zampini             }
2570a0ba757dSStefano Zampini             buffer_size+=k;
2571a0ba757dSStefano Zampini             ins_val++;
2572a0ba757dSStefano Zampini           }
2573a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2574a0ba757dSStefano Zampini           sum_requests++;
2575a0ba757dSStefano Zampini         }
2576a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2577a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2578a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2579a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2580a0ba757dSStefano Zampini             global_where_counter++;
2581a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2582a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2583a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2584a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2585a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2586a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2587a0ba757dSStefano Zampini                   break;
2588a0ba757dSStefano Zampini                 }
2589a0ba757dSStefano Zampini               }
2590a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2591a0ba757dSStefano Zampini             }
2592a0ba757dSStefano Zampini           }
2593a0ba757dSStefano Zampini         }
2594a0ba757dSStefano Zampini         /* insert new data in where array */
2595a0ba757dSStefano Zampini         temp_buffer_size=0;
2596a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2597a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2598a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2599a0ba757dSStefano Zampini             temp_buffer_size++;
2600a0ba757dSStefano Zampini           }
2601a0ba757dSStefano Zampini         }
2602a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2603a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2604a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2605a0ba757dSStefano Zampini       }
2606a0ba757dSStefano Zampini     }
2607a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2608a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2609a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2610a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2611a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2612a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2613a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2614a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2615a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2616a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2617a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2618a0ba757dSStefano Zampini     if(global_where_counter) {
2619a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2620a0ba757dSStefano Zampini       global_where_counter=0;
2621a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
2622a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2623a0ba757dSStefano Zampini           global_where_counter++;
2624a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
2625a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2626a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
2627a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
2628a0ba757dSStefano Zampini             }
2629a0ba757dSStefano Zampini           }
2630a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
2631a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
2632a0ba757dSStefano Zampini         }
2633a0ba757dSStefano Zampini       }
2634a0ba757dSStefano Zampini       where_values=global_where_counter;
2635a0ba757dSStefano Zampini     }
2636a0ba757dSStefano Zampini     if(global_where_counter) {
2637a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2638a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2639a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2640a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2641a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2642a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
2643a0ba757dSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2644a0ba757dSStefano Zampini         ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2645a0ba757dSStefano Zampini       }
2646a0ba757dSStefano Zampini     }
26470c7d97c5SJed Brown   }
26480c7d97c5SJed Brown 
2649a0ba757dSStefano Zampini   /* count vertices, edges and faces */
26500c7d97c5SJed Brown   PetscInt nfc=0;
26510c7d97c5SJed Brown   PetscInt nec=0;
26520c7d97c5SJed Brown   PetscInt nvc=0;
26530c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
26540c7d97c5SJed Brown     if( !pcbddc->vertices_flag ) {
26550c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
26560c7d97c5SJed Brown         if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){
26570c7d97c5SJed Brown           nfc++;
26580c7d97c5SJed Brown         } else {
26590c7d97c5SJed Brown           nec++;
26600c7d97c5SJed Brown         }
26610c7d97c5SJed Brown       }
26620c7d97c5SJed Brown     }
26630c7d97c5SJed Brown     if( !pcbddc->constraints_flag ){
26640c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
26650c7d97c5SJed Brown         nvc++;
26660c7d97c5SJed Brown       }
26670c7d97c5SJed Brown     }
26680c7d97c5SJed Brown   }
26690c7d97c5SJed Brown 
26700c7d97c5SJed Brown   pcbddc->n_constraints = nec+nfc;
26710c7d97c5SJed Brown   pcbddc->n_vertices    = nvc;
26720c7d97c5SJed Brown 
26730c7d97c5SJed Brown   if(pcbddc->n_constraints){
26740c7d97c5SJed Brown     /* allocate space for local constraints of BDDC */
26750c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr);
26760c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr);
26770c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr);
26780c7d97c5SJed Brown     k=0;
26790c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
26800c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
26810c7d97c5SJed Brown         pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i];
26820c7d97c5SJed Brown         k++;
26830c7d97c5SJed Brown       }
26840c7d97c5SJed Brown     }
26850c7d97c5SJed Brown     k=0;
26860c7d97c5SJed Brown     for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i];
26870c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
26880c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
26890c7d97c5SJed Brown     for (i=1; i<pcbddc->n_constraints; i++) {
26900c7d97c5SJed Brown       pcbddc->indices_to_constraint[i]  = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
26910c7d97c5SJed Brown       pcbddc->quadrature_constraint[i]  = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
26920c7d97c5SJed Brown     }
26930c7d97c5SJed Brown     k=0;
26940c7d97c5SJed Brown     PetscScalar quad_value;
26950c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
26960c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
2697a0ba757dSStefano Zampini         quad_value=1.0/( (PetscReal) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) );
26980c7d97c5SJed Brown         for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
26990c7d97c5SJed Brown           pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j];
27000c7d97c5SJed Brown           pcbddc->quadrature_constraint[k][j] = quad_value;
27010c7d97c5SJed Brown         }
27020c7d97c5SJed Brown         k++;
27030c7d97c5SJed Brown       }
27040c7d97c5SJed Brown     }
27050c7d97c5SJed Brown   }
27060c7d97c5SJed Brown   if(pcbddc->n_vertices){
27070c7d97c5SJed Brown     /* allocate space for local vertices of BDDC */
27080c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr);
27090c7d97c5SJed Brown     k=0;
27100c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
27110c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
27120c7d97c5SJed Brown         pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]];
27130c7d97c5SJed Brown         k++;
27140c7d97c5SJed Brown       }
27150c7d97c5SJed Brown     }
2716a0ba757dSStefano Zampini     /* sort vertex set (by local ordering) */
27170c7d97c5SJed Brown     ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr);
27180c7d97c5SJed Brown   }
27190c7d97c5SJed Brown 
2720e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
2721e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
2722e269702eSStefano Zampini 
2723d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2724d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2725d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2726a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
2727a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2728e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
2729a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);CHKERRQ(ierr);
2730e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
2731a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
2732e269702eSStefano Zampini       }
2733a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
2734a0ba757dSStefano Zampini     }*/
2735d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
27360c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
2737d49ef151SStefano 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);
27380c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
27393828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
27400c7d97c5SJed Brown       }
27410c7d97c5SJed Brown     }
2742d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
2743d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
2744d49ef151SStefano Zampini     if( nfc )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr); }
2745d49ef151SStefano Zampini     if( nec )                { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr); }
2746a0ba757dSStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Global indices for subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);CHKERRQ(ierr); }
27473828260eSStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->n_vertices,pcbddc->vertices,queue_in_global_numbering);CHKERRQ(ierr);
27483828260eSStefano Zampini     for(i=0;i<pcbddc->n_vertices;i++){ ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",queue_in_global_numbering[i]);CHKERRQ(ierr); }
2749d49ef151SStefano Zampini     if( pcbddc->n_vertices ) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");CHKERRQ(ierr); }
2750d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
27510c7d97c5SJed Brown   }
27520c7d97c5SJed Brown 
2753a0ba757dSStefano Zampini   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
2754a0ba757dSStefano Zampini   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
27550c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
2756a0ba757dSStefano Zampini   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2757a0ba757dSStefano Zampini   /* Free graph structure */
27580c7d97c5SJed Brown   if(mat_graph->nvtxs){
2759a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
2760a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
2761a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
2762a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
2763a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
27640c7d97c5SJed Brown   }
27650c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
27660c7d97c5SJed Brown 
27670c7d97c5SJed Brown   PetscFunctionReturn(0);
27680c7d97c5SJed Brown 
27690c7d97c5SJed Brown }
27700c7d97c5SJed Brown 
27710c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
27720c7d97c5SJed Brown 
27730c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
27740c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
27750c7d97c5SJed Brown 
27760c7d97c5SJed Brown #undef __FUNCT__
27770c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
2778*9c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
27790c7d97c5SJed Brown {
27800c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
27810c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
27820c7d97c5SJed Brown   PetscInt *cptr;
27830c7d97c5SJed Brown   PetscBool *touched;
27840c7d97c5SJed Brown 
27850c7d97c5SJed Brown   PetscFunctionBegin;
27860c7d97c5SJed Brown 
27870c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
27880c7d97c5SJed Brown   xadj    = graph->xadj;
27890c7d97c5SJed Brown   adjncy  = graph->adjncy;
27900c7d97c5SJed Brown   where   = graph->where;
27910c7d97c5SJed Brown   touched = graph->touched;
27920c7d97c5SJed Brown   queue   = graph->queue;
27930c7d97c5SJed Brown   cptr    = graph->cptr;
27940c7d97c5SJed Brown 
27950c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
27960c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
27970c7d97c5SJed Brown 
27980c7d97c5SJed Brown   cum_queue=0;
27990c7d97c5SJed Brown   ncmps=0;
28000c7d97c5SJed Brown 
28010c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
2802a0ba757dSStefano Zampini     //pid = dist_vals[n];
2803a0ba757dSStefano Zampini     pid = n+1;
28040c7d97c5SJed Brown     nleft = 0;
28050c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
28060c7d97c5SJed Brown       if (where[i] == pid)
28070c7d97c5SJed Brown         nleft++;
28080c7d97c5SJed Brown     }
28090c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
28100c7d97c5SJed Brown       if (where[i] == pid)
28110c7d97c5SJed Brown         break;
28120c7d97c5SJed Brown     }
28130c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
28140c7d97c5SJed Brown     queue[cum_queue] = i;
28150c7d97c5SJed Brown     first = 0; last = 1;
28160c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
28170c7d97c5SJed Brown     ncmps_pid = 0;
28180c7d97c5SJed Brown     while (first != nleft) {
28190c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
28200c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
28210c7d97c5SJed Brown         ncmps_pid++;
28220c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
28230c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
28240c7d97c5SJed Brown             break;
28250c7d97c5SJed Brown         }
28260c7d97c5SJed Brown         queue[cum_queue+last] = i;
28270c7d97c5SJed Brown         last++;
28280c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
28290c7d97c5SJed Brown       }
28300c7d97c5SJed Brown       i = queue[cum_queue+first];
28310c7d97c5SJed Brown       first++;
28320c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
28330c7d97c5SJed Brown         k = adjncy[j];
28340c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
28350c7d97c5SJed Brown           queue[cum_queue+last] = k;
28360c7d97c5SJed Brown           last++;
28370c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
28380c7d97c5SJed Brown         }
28390c7d97c5SJed Brown       }
28400c7d97c5SJed Brown     }
28410c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
28420c7d97c5SJed Brown     ncmps_pid++;
28430c7d97c5SJed Brown     cum_queue=cptr[ncmps];
2844a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
28450c7d97c5SJed Brown   }
28460c7d97c5SJed Brown   graph->ncmps = ncmps;
28470c7d97c5SJed Brown 
28480c7d97c5SJed Brown   PetscFunctionReturn(0);
28490c7d97c5SJed Brown }
28500c7d97c5SJed Brown 
2851