xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 53cdbc3d281cc8eb53283cb18545426080d929fc)
1*53cdbc3dSStefano Zampini /* TODOLIST
2*53cdbc3dSStefano Zampini    remove // commments
3*53cdbc3dSStefano Zampini    remove coarse enums -> allows use of PCBDDCGetCoarseKSP
4*53cdbc3dSStefano Zampini    code refactoring
5*53cdbc3dSStefano Zampini    remove metis dependency -> use MatPartitioning for multilevel
6*53cdbc3dSStefano Zampini    analyze MatSetNearNullSpace as suggested by Jed
7*53cdbc3dSStefano Zampini    options structure
8*53cdbc3dSStefano Zampini */
90c7d97c5SJed Brown 
10*53cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
110c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
120c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
13*53cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
14*53cdbc3dSStefano Zampini 
15*53cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
160c7d97c5SJed Brown 
170c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
180c7d97c5SJed Brown #undef __FUNCT__
190c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
200c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
210c7d97c5SJed Brown {
220c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
230c7d97c5SJed Brown   PetscErrorCode ierr;
240c7d97c5SJed Brown 
250c7d97c5SJed Brown   PetscFunctionBegin;
260c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
270c7d97c5SJed Brown   /* Verbose debugging of main data structures */
280c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                            ,"none",pcbddc->check_flag      ,&pcbddc->check_flag      ,PETSC_NULL);CHKERRQ(ierr);
290c7d97c5SJed Brown   /* Some customization for default primal space */
300c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
310c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
320c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use faces only in coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
330c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use edges only in coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
340c7d97c5SJed Brown   /* Coarse solver context */
350c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
360c7d97c5SJed Brown   ierr = PetscOptionsEnum("-pc_bddc_coarse_problem_type","Set coarse problem type","none",avail_coarse_problems,(PetscEnum)pcbddc->coarse_problem_type,(PetscEnum*)&pcbddc->coarse_problem_type,PETSC_NULL);CHKERRQ(ierr);
370c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
380c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->prec_type,&pcbddc->prec_type,PETSC_NULL);CHKERRQ(ierr);
390c7d97c5SJed Brown   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr);
400c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
410c7d97c5SJed Brown   PetscFunctionReturn(0);
420c7d97c5SJed Brown }
430c7d97c5SJed Brown 
440c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
450c7d97c5SJed Brown EXTERN_C_BEGIN
460c7d97c5SJed Brown #undef __FUNCT__
470c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
48*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
490c7d97c5SJed Brown {
500c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
510c7d97c5SJed Brown 
520c7d97c5SJed Brown   PetscFunctionBegin;
530c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
540c7d97c5SJed Brown   PetscFunctionReturn(0);
550c7d97c5SJed Brown }
560c7d97c5SJed Brown EXTERN_C_END
570c7d97c5SJed Brown 
580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
590c7d97c5SJed Brown #undef __FUNCT__
600c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
61*53cdbc3dSStefano Zampini /*@
62*53cdbc3dSStefano Zampini  PCBDDCSetCoarseProblemType - brief explanation
63*53cdbc3dSStefano Zampini 
64*53cdbc3dSStefano Zampini    Collective on PC
65*53cdbc3dSStefano Zampini 
66*53cdbc3dSStefano Zampini    Input Parameters:
67*53cdbc3dSStefano Zampini +  pc - the preconditioning context
68*53cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
69*53cdbc3dSStefano Zampini 
70*53cdbc3dSStefano Zampini    Level: intermediate
71*53cdbc3dSStefano Zampini 
72*53cdbc3dSStefano Zampini    Notes:
73*53cdbc3dSStefano Zampini    usage notes, perhaps an example
74*53cdbc3dSStefano Zampini 
75*53cdbc3dSStefano Zampini .seealso: PCBDDC
76*53cdbc3dSStefano Zampini @*/
770c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
780c7d97c5SJed Brown {
790c7d97c5SJed Brown   PetscErrorCode ierr;
800c7d97c5SJed Brown 
810c7d97c5SJed Brown   PetscFunctionBegin;
820c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
830c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
840c7d97c5SJed Brown   PetscFunctionReturn(0);
850c7d97c5SJed Brown }
860c7d97c5SJed Brown 
870c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
880c7d97c5SJed Brown EXTERN_C_BEGIN
890c7d97c5SJed Brown #undef __FUNCT__
900c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
91*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
920c7d97c5SJed Brown {
930c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
94*53cdbc3dSStefano Zampini   PetscErrorCode ierr;
950c7d97c5SJed Brown 
960c7d97c5SJed Brown   PetscFunctionBegin;
97*53cdbc3dSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
98*53cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
99*53cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
100*53cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1010c7d97c5SJed Brown   PetscFunctionReturn(0);
1020c7d97c5SJed Brown }
1030c7d97c5SJed Brown EXTERN_C_END
1040c7d97c5SJed Brown 
1050c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1060c7d97c5SJed Brown #undef __FUNCT__
1070c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
10857527edcSJed Brown /*@
109*53cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
110*53cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
11157527edcSJed Brown 
112*53cdbc3dSStefano Zampini    Logically Collective on PC
11357527edcSJed Brown 
11457527edcSJed Brown    Input Parameters:
11557527edcSJed Brown +  pc - the preconditioning context
116*53cdbc3dSStefano Zampini -  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
11757527edcSJed Brown 
11857527edcSJed Brown    Level: intermediate
11957527edcSJed Brown 
12057527edcSJed Brown    Notes:
12157527edcSJed Brown    usage notes, perhaps an example
12257527edcSJed Brown 
12357527edcSJed Brown .seealso: PCBDDC
12457527edcSJed Brown @*/
125*53cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1260c7d97c5SJed Brown {
1270c7d97c5SJed Brown   PetscErrorCode ierr;
1280c7d97c5SJed Brown 
1290c7d97c5SJed Brown   PetscFunctionBegin;
1300c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
131*53cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
132*53cdbc3dSStefano Zampini   PetscFunctionReturn(0);
133*53cdbc3dSStefano Zampini }
134*53cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
135*53cdbc3dSStefano Zampini EXTERN_C_BEGIN
136*53cdbc3dSStefano Zampini #undef __FUNCT__
137*53cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
138*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
139*53cdbc3dSStefano Zampini {
140*53cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
141*53cdbc3dSStefano Zampini 
142*53cdbc3dSStefano Zampini   PetscFunctionBegin;
143*53cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
144*53cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
145*53cdbc3dSStefano Zampini   } else {
146*53cdbc3dSStefano Zampini     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
147*53cdbc3dSStefano Zampini   }
148*53cdbc3dSStefano Zampini   PetscFunctionReturn(0);
149*53cdbc3dSStefano Zampini }
150*53cdbc3dSStefano Zampini EXTERN_C_END
151*53cdbc3dSStefano Zampini 
152*53cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
153*53cdbc3dSStefano Zampini #undef __FUNCT__
154*53cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
155*53cdbc3dSStefano Zampini /*@
156*53cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
157*53cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
158*53cdbc3dSStefano Zampini 
159*53cdbc3dSStefano Zampini    Logically Collective on PC
160*53cdbc3dSStefano Zampini 
161*53cdbc3dSStefano Zampini    Input Parameters:
162*53cdbc3dSStefano Zampini +  pc - the preconditioning context
163*53cdbc3dSStefano Zampini 
164*53cdbc3dSStefano Zampini    Output Parameters:
165*53cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
166*53cdbc3dSStefano Zampini 
167*53cdbc3dSStefano Zampini    Level: intermediate
168*53cdbc3dSStefano Zampini 
169*53cdbc3dSStefano Zampini    Notes:
170*53cdbc3dSStefano Zampini    usage notes, perhaps an example
171*53cdbc3dSStefano Zampini 
172*53cdbc3dSStefano Zampini .seealso: PCBDDC
173*53cdbc3dSStefano Zampini @*/
174*53cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
175*53cdbc3dSStefano Zampini {
176*53cdbc3dSStefano Zampini   PetscErrorCode ierr;
177*53cdbc3dSStefano Zampini 
178*53cdbc3dSStefano Zampini   PetscFunctionBegin;
179*53cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
180*53cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
1810c7d97c5SJed Brown   PetscFunctionReturn(0);
1820c7d97c5SJed Brown }
1830c7d97c5SJed Brown 
184*53cdbc3dSStefano Zampini #undef __FUNCT__
185*53cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
1860c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1870c7d97c5SJed Brown /*
1880c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
1890c7d97c5SJed Brown                   by setting data structures and options.
1900c7d97c5SJed Brown 
1910c7d97c5SJed Brown    Input Parameter:
192*53cdbc3dSStefano Zampini +  pc - the preconditioner context
1930c7d97c5SJed Brown 
1940c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
1950c7d97c5SJed Brown 
1960c7d97c5SJed Brown    Notes:
1970c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
1980c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
1990c7d97c5SJed Brown */
200*53cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
2010c7d97c5SJed Brown {
2020c7d97c5SJed Brown   PetscErrorCode ierr;
2030c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
2040c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
2050c7d97c5SJed Brown 
2060c7d97c5SJed Brown   PetscFunctionBegin;
2070c7d97c5SJed Brown   if (!pc->setupcalled) {
2080c7d97c5SJed Brown 
2090c7d97c5SJed Brown     /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup
2100c7d97c5SJed Brown        So, we set to pcnone the Neumann problem of pcid in order to avoid unneeded computation
2110c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
2120c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
2130c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
2140c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
2150c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
2160c7d97c5SJed Brown     /* Destroy some PC_IS data which is not needed by BDDC */
2170c7d97c5SJed Brown     //if (pcis->ksp_D)  {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);}
2180c7d97c5SJed Brown     //if (pcis->ksp_N)  {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);}
2190c7d97c5SJed Brown     //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);}
2200c7d97c5SJed Brown     //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);}
2210c7d97c5SJed Brown     //pcis->ksp_D  = 0;
2220c7d97c5SJed Brown     //pcis->ksp_N  = 0;
2230c7d97c5SJed Brown     //pcis->vec2_B = 0;
2240c7d97c5SJed Brown     //pcis->vec3_B = 0;
2250c7d97c5SJed Brown 
2260c7d97c5SJed Brown     //TODO MOVE CODE FRAGMENT
2270c7d97c5SJed Brown     PetscInt im_active=0;
2280c7d97c5SJed Brown     if(pcis->n) im_active = 1;
229*53cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
2300c7d97c5SJed Brown     //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active);
2310c7d97c5SJed Brown     /* Set up grid quantities for BDDC */
2320c7d97c5SJed Brown     //TODO only active procs must call this -> remove synchronized print inside (the only point of sync)
2330c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
2340c7d97c5SJed Brown 
2350c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
2360c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
2370c7d97c5SJed Brown 
2380c7d97c5SJed Brown     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo
2390c7d97c5SJed Brown     /* We no more need this matrix */
2400c7d97c5SJed Brown     //if (pcis->A_BB)  {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);}
2410c7d97c5SJed Brown     //pcis->A_BB   = 0;
2420c7d97c5SJed Brown 
2430c7d97c5SJed Brown     //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type);
2440c7d97c5SJed Brown     //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type);
2450c7d97c5SJed Brown     //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio);
2460c7d97c5SJed Brown   }
2470c7d97c5SJed Brown 
2480c7d97c5SJed Brown   PetscFunctionReturn(0);
2490c7d97c5SJed Brown }
2500c7d97c5SJed Brown 
2510c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2520c7d97c5SJed Brown /*
2530c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
2540c7d97c5SJed Brown 
2550c7d97c5SJed Brown    Input Parameters:
2560c7d97c5SJed Brown .  pc - the preconditioner context
2570c7d97c5SJed Brown .  r - input vector (global)
2580c7d97c5SJed Brown 
2590c7d97c5SJed Brown    Output Parameter:
2600c7d97c5SJed Brown .  z - output vector (global)
2610c7d97c5SJed Brown 
2620c7d97c5SJed Brown    Application Interface Routine: PCApply()
2630c7d97c5SJed Brown  */
2640c7d97c5SJed Brown #undef __FUNCT__
2650c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
266*53cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
2670c7d97c5SJed Brown {
2680c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)(pc->data);
2690c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2700c7d97c5SJed Brown   PetscErrorCode ierr;
2710c7d97c5SJed Brown   PetscScalar    one = 1.0;
2720c7d97c5SJed Brown   PetscScalar    m_one = -1.0;
2730c7d97c5SJed Brown 
2740c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
2750c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
2760c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
2770c7d97c5SJed Brown 
2780c7d97c5SJed Brown   PetscFunctionBegin;
2790c7d97c5SJed Brown   /* First Dirichlet solve */
2800c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2810c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
282*53cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
2830c7d97c5SJed Brown   /*
2840c7d97c5SJed Brown     Assembling right hand side for BDDC operator
2850c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
2860c7d97c5SJed Brown     - the interface part of the global vector z
2870c7d97c5SJed Brown   */
2880c7d97c5SJed Brown   //ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2890c7d97c5SJed Brown   //ierr = VecScatterEnd  (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2900c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
2910c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
2920c7d97c5SJed Brown   //ierr = MatMultAdd(pcis->A_BI,pcis->vec2_D,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
2930c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
2940c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
2950c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
2960c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2970c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2980c7d97c5SJed Brown 
2990c7d97c5SJed Brown   /*
3000c7d97c5SJed Brown     Apply interface preconditioner
3010c7d97c5SJed Brown     Results are stored in:
3020c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
3030c7d97c5SJed Brown     -  the interface part of the global vector z
3040c7d97c5SJed Brown   */
3050c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
3060c7d97c5SJed Brown 
3070c7d97c5SJed Brown   /* Second Dirichlet solves and assembling of output */
3080c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3090c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3100c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
3110c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
312*53cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
3130c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
3140c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
3150c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
3160c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3170c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3180c7d97c5SJed Brown 
3190c7d97c5SJed Brown   PetscFunctionReturn(0);
3200c7d97c5SJed Brown 
3210c7d97c5SJed Brown }
3220c7d97c5SJed Brown 
3230c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3240c7d97c5SJed Brown /*
3250c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
3260c7d97c5SJed Brown 
3270c7d97c5SJed Brown */
3280c7d97c5SJed Brown #undef __FUNCT__
3290c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
330*53cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
3310c7d97c5SJed Brown {
3320c7d97c5SJed Brown   PetscErrorCode ierr;
3330c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
3340c7d97c5SJed Brown   PC_IS*         pcis =   (PC_IS*)  (pc->data);
3350c7d97c5SJed Brown   PetscScalar    zero = 0.0;
3360c7d97c5SJed Brown 
3370c7d97c5SJed Brown   PetscFunctionBegin;
3380c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
3390c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3400c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3410c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3420c7d97c5SJed Brown 
3430c7d97c5SJed Brown   /* Application of PHI^T  */
3440c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
3450c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
3460c7d97c5SJed Brown 
3470c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
3480c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
3490c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3500c7d97c5SJed Brown 
3510c7d97c5SJed Brown   /* Local solution on R nodes */
3520c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
3530c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3540c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3550c7d97c5SJed Brown   if(pcbddc->prec_type) {
3560c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3570c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3580c7d97c5SJed Brown   }
3590c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
3600c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
3610c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3620c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3630c7d97c5SJed Brown   if(pcbddc->prec_type) {
3640c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3650c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3660c7d97c5SJed Brown   }
3670c7d97c5SJed Brown 
3680c7d97c5SJed Brown   /* Coarse solution */
3690c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
370*53cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3710c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3720c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3730c7d97c5SJed Brown 
3740c7d97c5SJed Brown   /* Sum contributions from two levels */
3750c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
3760c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
3770c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
3780c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3790c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
3800c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3810c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3820c7d97c5SJed Brown 
3830c7d97c5SJed Brown   PetscFunctionReturn(0);
3840c7d97c5SJed Brown }
3850c7d97c5SJed Brown 
3860c7d97c5SJed Brown 
3870c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3880c7d97c5SJed Brown /*
3890c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
3900c7d97c5SJed Brown 
3910c7d97c5SJed Brown */
3920c7d97c5SJed Brown #undef __FUNCT__
3930c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
394*53cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
3950c7d97c5SJed Brown {
3960c7d97c5SJed Brown   PetscErrorCode ierr;
3970c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
3980c7d97c5SJed Brown 
3990c7d97c5SJed Brown   PetscFunctionBegin;
4000c7d97c5SJed Brown 
401*53cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
4020c7d97c5SJed Brown   if(pcbddc->n_constraints) {
4030c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
4040c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
4050c7d97c5SJed Brown   }
4060c7d97c5SJed Brown 
4070c7d97c5SJed Brown   PetscFunctionReturn(0);
4080c7d97c5SJed Brown }
4090c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4100c7d97c5SJed Brown /*
4110c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
4120c7d97c5SJed Brown 
4130c7d97c5SJed Brown */
4140c7d97c5SJed Brown #undef __FUNCT__
4150c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
416*53cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4170c7d97c5SJed Brown {
4180c7d97c5SJed Brown   PetscErrorCode ierr;
4190c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4200c7d97c5SJed Brown 
4210c7d97c5SJed Brown   PetscFunctionBegin;
4220c7d97c5SJed Brown 
4230c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4240c7d97c5SJed Brown     case SCATTERS_BDDC:
4250c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4260c7d97c5SJed Brown       break;
4270c7d97c5SJed Brown     case GATHERS_BDDC:
4280c7d97c5SJed Brown       break;
4290c7d97c5SJed Brown   }
4300c7d97c5SJed Brown   PetscFunctionReturn(0);
4310c7d97c5SJed Brown 
4320c7d97c5SJed Brown }
4330c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4340c7d97c5SJed Brown /*
4350c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
4360c7d97c5SJed Brown 
4370c7d97c5SJed Brown */
4380c7d97c5SJed Brown #undef __FUNCT__
4390c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
440*53cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
4410c7d97c5SJed Brown {
4420c7d97c5SJed Brown   PetscErrorCode ierr;
4430c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4440c7d97c5SJed Brown   PetscScalar*   array_to;
4450c7d97c5SJed Brown   PetscScalar*   array_from;
4460c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
4470c7d97c5SJed Brown   PetscInt i;
4480c7d97c5SJed Brown 
4490c7d97c5SJed Brown   PetscFunctionBegin;
4500c7d97c5SJed Brown 
4510c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
4520c7d97c5SJed Brown     case SCATTERS_BDDC:
4530c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
4540c7d97c5SJed Brown       break;
4550c7d97c5SJed Brown     case GATHERS_BDDC:
4560c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
4570c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
4580c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
4590c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
4600c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
461*53cdbc3dSStefano 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);
4620c7d97c5SJed Brown             if(vec_to) {
4630c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4640c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4650c7d97c5SJed Brown             }
4660c7d97c5SJed Brown           } else {
4670c7d97c5SJed Brown             if(vec_from)
4680c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
4690c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
470*53cdbc3dSStefano 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);
4710c7d97c5SJed Brown           }
4720c7d97c5SJed Brown           break;
4730c7d97c5SJed Brown         case REPLICATED_BDDC:
4740c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
475*53cdbc3dSStefano 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);
4760c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
4770c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
4780c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
4790c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
4800c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
4810c7d97c5SJed Brown           }
4820c7d97c5SJed Brown           break;
483*53cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
484*53cdbc3dSStefano Zampini           break;
485*53cdbc3dSStefano Zampini         case PARALLEL_BDDC:
486*53cdbc3dSStefano Zampini           break;
4870c7d97c5SJed Brown       }
4880c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
4890c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
4900c7d97c5SJed Brown       break;
4910c7d97c5SJed Brown   }
4920c7d97c5SJed Brown   PetscFunctionReturn(0);
4930c7d97c5SJed Brown 
4940c7d97c5SJed Brown }
4950c7d97c5SJed Brown 
4960c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4970c7d97c5SJed Brown /*
4980c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
4990c7d97c5SJed Brown    that was created with PCCreate_BDDC().
5000c7d97c5SJed Brown 
5010c7d97c5SJed Brown    Input Parameter:
5020c7d97c5SJed Brown .  pc - the preconditioner context
5030c7d97c5SJed Brown 
5040c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
5050c7d97c5SJed Brown */
5060c7d97c5SJed Brown #undef __FUNCT__
5070c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
508*53cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
5090c7d97c5SJed Brown {
5100c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
5110c7d97c5SJed Brown   PetscErrorCode ierr;
5120c7d97c5SJed Brown 
5130c7d97c5SJed Brown   PetscFunctionBegin;
5140c7d97c5SJed Brown   /* free data created by PCIS */
5150c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
5160c7d97c5SJed Brown   /* free BDDC data  */
517*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
518*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
519*53cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
520*53cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
521*53cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
522*53cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
523*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
524*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
525*53cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
526*53cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
527*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
528*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
529*53cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
530*53cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
531*53cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
532*53cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
533*53cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
534*53cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
535*53cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
536*53cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr);
537*53cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
538*53cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
5390c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
540*53cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
541*53cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
5420c7d97c5SJed Brown   if (pcbddc->n_constraints) {
5430c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
5440c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr);
5450c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
5460c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr);
5470c7d97c5SJed Brown     ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr);
5480c7d97c5SJed Brown   }
5490c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
5500c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
5510c7d97c5SJed Brown   PetscFunctionReturn(0);
5520c7d97c5SJed Brown }
5530c7d97c5SJed Brown 
5540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5550c7d97c5SJed Brown /*MC
5560c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
5570c7d97c5SJed Brown 
5580c7d97c5SJed Brown    Options Database Keys:
5590c7d97c5SJed Brown .    -pc_is_damp_fixed <fact> -
5600c7d97c5SJed Brown .    -pc_is_remove_nullspace_fixed -
5610c7d97c5SJed Brown .    -pc_is_set_damping_factor_floating <fact> -
5620c7d97c5SJed Brown .    -pc_is_not_damp_floating -
5630c7d97c5SJed Brown 
5640c7d97c5SJed Brown    Level: intermediate
5650c7d97c5SJed Brown 
5660c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
5670c7d97c5SJed Brown 
5680c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
5690c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
5700c7d97c5SJed Brown           on the subdomains).
5710c7d97c5SJed Brown 
5720c7d97c5SJed Brown           Options for the coarse grid preconditioner can be set with -pc_bddc_coarse_pc_xxx
5730c7d97c5SJed Brown           Options for the Dirichlet subproblem can be set with -pc_bddc_localD_xxx
5740c7d97c5SJed Brown           Options for the Neumann subproblem can be set with -pc_bddc_localN_xxx
5750c7d97c5SJed Brown 
5760c7d97c5SJed Brown    Contributed by Stefano Zampini
5770c7d97c5SJed Brown 
5780c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
5790c7d97c5SJed Brown M*/
5800c7d97c5SJed Brown EXTERN_C_BEGIN
5810c7d97c5SJed Brown #undef __FUNCT__
5820c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
5830c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
5840c7d97c5SJed Brown {
5850c7d97c5SJed Brown   PetscErrorCode ierr;
5860c7d97c5SJed Brown   PC_BDDC          *pcbddc;
5870c7d97c5SJed Brown 
5880c7d97c5SJed Brown   PetscFunctionBegin;
5890c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
5900c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
5910c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
5920c7d97c5SJed Brown   /* create PCIS data structure */
5930c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
5940c7d97c5SJed Brown   /* BDDC specific */
5950c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
5960c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
597*53cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
5980c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
5990c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
6000c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
6010c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
6020c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
6030c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
6040c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
6050c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
6060c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
607*53cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
608*53cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
6090c7d97c5SJed Brown   pcbddc->n_constraints              = 0;
6100c7d97c5SJed Brown   pcbddc->n_vertices                 = 0;
6110c7d97c5SJed Brown   pcbddc->vertices                   = 0;
6120c7d97c5SJed Brown   pcbddc->indices_to_constraint      = 0;
6130c7d97c5SJed Brown   pcbddc->quadrature_constraint      = 0;
6140c7d97c5SJed Brown   pcbddc->sizes_of_constraint        = 0;
6150c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
6160c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
617*53cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
6180c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
6190c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
6200c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
6210c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
6220c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
6230c7d97c5SJed Brown   pcbddc->check_flag                 = PETSC_FALSE;
6240c7d97c5SJed Brown   pcbddc->vertices_flag              = PETSC_FALSE;
6250c7d97c5SJed Brown   pcbddc->constraints_flag           = PETSC_FALSE;
6260c7d97c5SJed Brown   pcbddc->faces_flag                 = PETSC_FALSE;
6270c7d97c5SJed Brown   pcbddc->edges_flag                 = PETSC_FALSE;
6280c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
6290c7d97c5SJed Brown   /* function pointers */
6300c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
6310c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
6320c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
6330c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
6340c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
6350c7d97c5SJed Brown   pc->ops->view                = 0;
6360c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
6370c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
6380c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
6390c7d97c5SJed Brown   /* composing function */
6400c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
6410c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
642*53cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
643*53cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
6440c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
6450c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
6460c7d97c5SJed Brown   PetscFunctionReturn(0);
6470c7d97c5SJed Brown }
6480c7d97c5SJed Brown EXTERN_C_END
6490c7d97c5SJed Brown 
6500c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6510c7d97c5SJed Brown /*
6520c7d97c5SJed Brown    PCBDDCCoarseSetUp -
6530c7d97c5SJed Brown */
6540c7d97c5SJed Brown #undef __FUNCT__
6550c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
656*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
6570c7d97c5SJed Brown {
6580c7d97c5SJed Brown   PetscErrorCode  ierr;
6590c7d97c5SJed Brown 
6600c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
6610c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
6620c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
6630c7d97c5SJed Brown   IS                is_R_local;
6640c7d97c5SJed Brown   IS                is_V_local;
6650c7d97c5SJed Brown   IS                is_C_local;
6660c7d97c5SJed Brown   IS                is_aux1;
6670c7d97c5SJed Brown   IS                is_aux2;
6680c7d97c5SJed Brown   PetscViewer       viewer;
6690c7d97c5SJed Brown   PetscBool         check_flag=pcbddc->check_flag;
6700c7d97c5SJed Brown   const VecType     impVecType;
6710c7d97c5SJed Brown   const MatType     impMatType;
6720c7d97c5SJed Brown   PetscInt          n_R=0;
6730c7d97c5SJed Brown   PetscInt          n_D=0;
6740c7d97c5SJed Brown   PetscInt          n_B=0;
6750c7d97c5SJed Brown   PetscMPIInt       totprocs;
6760c7d97c5SJed Brown   PetscScalar       zero=0.0;
6770c7d97c5SJed Brown   PetscScalar       one=1.0;
6780c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
6790c7d97c5SJed Brown   PetscScalar*      array;
6800c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
6810c7d97c5SJed Brown   PetscInt          *idx_R_local;
6820c7d97c5SJed Brown   PetscInt          *idx_V_B;
6830c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
6840c7d97c5SJed Brown   PetscScalar       *constraints_errors;
6850c7d97c5SJed Brown   /* auxiliary indices */
6860c7d97c5SJed Brown   PetscInt s,i,j,k;
6870c7d97c5SJed Brown 
6880c7d97c5SJed Brown   PetscFunctionBegin;
6890c7d97c5SJed Brown   if(pcbddc->check_flag) {
6900c7d97c5SJed Brown     ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr);
6910c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
6920c7d97c5SJed Brown   }
6930c7d97c5SJed Brown 
6940c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
6950c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
6960c7d97c5SJed Brown   /* Set local primal size */
6970c7d97c5SJed Brown   pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints;
6980c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
6990c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
7000c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7010c7d97c5SJed Brown   for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; }
7020c7d97c5SJed Brown   ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
7030c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
7040c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7050c7d97c5SJed Brown   if(check_flag) {
7060c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7070c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7080c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
7090c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
7100c7d97c5SJed 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);
7110c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7120c7d97c5SJed Brown   }
7130c7d97c5SJed Brown   /* Allocate needed vectors */
7140c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
7150c7d97c5SJed Brown //  ierr = MatGetType(matis->A,&impMatType);CHKERRQ(ierr);
7160c7d97c5SJed Brown   //ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
7170c7d97c5SJed Brown   impMatType = MATSEQDENSE;
7180c7d97c5SJed Brown   impVecType = VECSEQ;
7190c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
7200c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
7210c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
7220c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
7230c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
7240c7d97c5SJed Brown   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);
7250c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
7260c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
7270c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
7280c7d97c5SJed Brown 
7290c7d97c5SJed Brown   /* Creating some index sets needed  */
7300c7d97c5SJed Brown   /* For submatrices */
7310c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
7320c7d97c5SJed Brown   if(pcbddc->n_vertices)    { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); }
7330c7d97c5SJed Brown   if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); }
7340c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
7350c7d97c5SJed Brown   {
7360c7d97c5SJed Brown     PetscInt   *aux_array1;
7370c7d97c5SJed Brown     PetscInt   *aux_array2;
7380c7d97c5SJed Brown     PetscScalar      value;
7390c7d97c5SJed Brown 
7400c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
7410c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
7420c7d97c5SJed Brown 
7430c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);
7440c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7450c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7460c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7470c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7480c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7490c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7500c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7510c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
7520c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7530c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
7540c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
7550c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
7560c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7570c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
7580c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
7590c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
7600c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
7610c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
7620c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
7630c7d97c5SJed Brown 
7640c7d97c5SJed Brown     if(pcbddc->prec_type || check_flag ) {
7650c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
7660c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7670c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
7680c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
7690c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
7700c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
7710c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
7720c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
7730c7d97c5SJed Brown     }
7740c7d97c5SJed Brown 
7750c7d97c5SJed Brown     /* Check scatters */
7760c7d97c5SJed Brown     if(check_flag) {
7770c7d97c5SJed Brown 
7780c7d97c5SJed Brown       Vec            vec_aux;
7790c7d97c5SJed Brown 
7800c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
7810c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
7820c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7830c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
7840c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);
7850c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);
7860c7d97c5SJed Brown       ierr = VecCopy(pcbddc->vec1_R,vec_aux);
7870c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
7880c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
7890c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
7900c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
7910c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);
7920c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
7930c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
7940c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
7950c7d97c5SJed Brown 
7960c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
7970c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);
7980c7d97c5SJed Brown       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);
7990c7d97c5SJed Brown       ierr = VecCopy(pcis->vec1_B,vec_aux);
8000c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
8010c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
8020c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
8030c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
8040c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);
8050c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
8060c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
8070c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
8080c7d97c5SJed Brown 
8090c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8100c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
8110c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8120c7d97c5SJed Brown 
8130c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
8140c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);
8150c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);
8160c7d97c5SJed Brown       ierr = VecCopy(pcbddc->vec1_R,vec_aux);
8170c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);
8180c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);
8190c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
8200c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
8210c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);
8220c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
8230c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
8240c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
8250c7d97c5SJed Brown 
8260c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
8270c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);
8280c7d97c5SJed Brown       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);
8290c7d97c5SJed Brown       ierr = VecCopy(pcis->vec1_D,vec_aux);
8300c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
8310c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
8320c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
8330c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
8340c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);
8350c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
8360c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
8370c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
8380c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
8390c7d97c5SJed Brown 
8400c7d97c5SJed Brown     }
8410c7d97c5SJed Brown   }
8420c7d97c5SJed Brown 
8430c7d97c5SJed Brown   /* vertices in boundary numbering */
8440c7d97c5SJed Brown   if(pcbddc->n_vertices) {
8450c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_N,m_one);
8460c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8470c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; }
8480c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8490c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
8500c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
8510c7d97c5SJed Brown     ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
8520c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8530c7d97c5SJed Brown     //printf("vertices in boundary numbering\n");
8540c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) {
8550c7d97c5SJed Brown       s=0;
8560c7d97c5SJed Brown       while (array[s] != i ) {s++;}
8570c7d97c5SJed Brown       idx_V_B[i]=s;
8580c7d97c5SJed Brown       //printf("idx_V_B[%d]=%d\n",i,s);
8590c7d97c5SJed Brown     }
8600c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
8610c7d97c5SJed Brown   }
8620c7d97c5SJed Brown 
8630c7d97c5SJed Brown 
8640c7d97c5SJed Brown   /* Assign global numbering to coarse dofs */
8650c7d97c5SJed Brown   // TODO move this block before calling SetupCoarseEnvironment
8660c7d97c5SJed Brown   {
8670c7d97c5SJed Brown     PetscScalar    coarsesum;
8680c7d97c5SJed Brown     PetscMPIInt    *auxlocal_primal;
8690c7d97c5SJed Brown     PetscMPIInt    *auxglobal_primal;
8700c7d97c5SJed Brown     PetscMPIInt    *all_auxglobal_primal;
8710c7d97c5SJed Brown     PetscMPIInt    *all_auxglobal_primal_type;  /* dummy */
8720c7d97c5SJed Brown 
8730c7d97c5SJed Brown     ierr = MPI_Comm_size(((PetscObject)pc)->comm,&totprocs);CHKERRQ(ierr);
8740c7d97c5SJed Brown     /* Construct needed data structures for message passing */
8750c7d97c5SJed Brown     ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
8760c7d97c5SJed Brown     ierr = PetscMalloc(          totprocs*sizeof(PetscMPIInt),          &pcbddc->local_primal_sizes);CHKERRQ(ierr);
8770c7d97c5SJed Brown     ierr = PetscMalloc(          totprocs*sizeof(PetscMPIInt),  &pcbddc->local_primal_displacements);CHKERRQ(ierr);
8780c7d97c5SJed Brown     /* Gather local_primal_size information to all processes  */
8790c7d97c5SJed Brown     ierr = MPI_Allgather(&pcbddc->local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT, ((PetscObject)pc)->comm );CHKERRQ(ierr);
8800c7d97c5SJed Brown     pcbddc->replicated_primal_size = 0;
8810c7d97c5SJed Brown     for (i=0; i<totprocs; i++) {
8820c7d97c5SJed Brown       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
8830c7d97c5SJed Brown       pcbddc->replicated_primal_size  += pcbddc->local_primal_sizes[i];
8840c7d97c5SJed Brown     }
8850c7d97c5SJed Brown     /* allocate some auxiliary space */
8860c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->local_primal_size)*sizeof(PetscMPIInt),          &auxlocal_primal);CHKERRQ(ierr);
8870c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->local_primal_size)*sizeof(PetscMPIInt),         &auxglobal_primal);CHKERRQ(ierr);
8880c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->replicated_primal_size)*sizeof(PetscMPIInt),     &all_auxglobal_primal);CHKERRQ(ierr);
8890c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->replicated_primal_size)*sizeof(PetscMPIInt),&all_auxglobal_primal_type);CHKERRQ(ierr);
8900c7d97c5SJed Brown 
8910c7d97c5SJed Brown     /* 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)
8920c7d97c5SJed Brown        This code fragment assumes that the number of local constraints per connected component
8930c7d97c5SJed Brown        is not greater than the number of nodes on the connected component (for each dof)
8940c7d97c5SJed Brown        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
8950c7d97c5SJed Brown     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) */
8960c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_N,zero);
8970c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
8980c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
8990c7d97c5SJed Brown       array[ pcbddc->vertices[i] ] = one;
9000c7d97c5SJed Brown       auxlocal_primal[i] = pcbddc->vertices[i];
9010c7d97c5SJed Brown     }
9020c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
9030c7d97c5SJed Brown       for (s=0; s<pcbddc->sizes_of_constraint[i]; s++) {
9040c7d97c5SJed Brown         k = pcbddc->indices_to_constraint[i][s];
9050c7d97c5SJed Brown         if( array[k] == zero ) {
9060c7d97c5SJed Brown           array[k] = one;
9070c7d97c5SJed Brown           auxlocal_primal[i+pcbddc->n_vertices] = k;
9080c7d97c5SJed Brown           break;
9090c7d97c5SJed Brown         }
9100c7d97c5SJed Brown       }
9110c7d97c5SJed Brown     }
9120c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9130c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
9140c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9150c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9160c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9170c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9180c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9190c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {
9200c7d97c5SJed Brown       if(array[i]) { array[i] = one/array[i]; }
9210c7d97c5SJed Brown     }
9220c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
9230c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
9240c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9250c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9260c7d97c5SJed Brown 
9270c7d97c5SJed Brown     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
9280c7d97c5SJed Brown     pcbddc->coarse_size = (PetscInt) coarsesum;
9290c7d97c5SJed Brown     if(check_flag) {
9300c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
9310c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
9320c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9330c7d97c5SJed Brown     }
9340c7d97c5SJed Brown     /* Now assign them a global numbering */
9350c7d97c5SJed Brown     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
9360c7d97c5SJed Brown     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
9370c7d97c5SJed Brown     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
9380c7d97c5SJed Brown     ierr = MPI_Allgatherv(&auxglobal_primal[0],pcbddc->local_primal_size,MPIU_INT,&all_auxglobal_primal[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT, ((PetscObject)pc)->comm );CHKERRQ(ierr);
9390c7d97c5SJed Brown     /* aux_global_type is a dummy argument (PetscSortMPIInt doesn't exist!) */
9400c7d97c5SJed Brown     ierr = PetscSortMPIIntWithArray( pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_type);CHKERRQ(ierr);
9410c7d97c5SJed Brown     k=1;
9420c7d97c5SJed Brown     j=all_auxglobal_primal[0];  /* first dof in global numbering */
9430c7d97c5SJed Brown     for(i=1;i< pcbddc->replicated_primal_size ;i++) {
9440c7d97c5SJed Brown       if(j != all_auxglobal_primal[i] ) {
9450c7d97c5SJed Brown         all_auxglobal_primal[k]=all_auxglobal_primal[i];
9460c7d97c5SJed Brown         k++;
9470c7d97c5SJed Brown         j=all_auxglobal_primal[i];
9480c7d97c5SJed Brown       }
9490c7d97c5SJed Brown     }
9500c7d97c5SJed Brown     /* At this point all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
9510c7d97c5SJed Brown     /* We need only the indices from 0 to pcbddc->coarse_size. Remaning elements of array are garbage. */
9520c7d97c5SJed Brown     /* Now get global coarse numbering of local primal nodes */
9530c7d97c5SJed Brown     for(i=0;i<pcbddc->local_primal_size;i++) {
9540c7d97c5SJed Brown       k=0;
9550c7d97c5SJed Brown       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
9560c7d97c5SJed Brown       pcbddc->local_primal_indices[i]=k;
9570c7d97c5SJed Brown     }
9580c7d97c5SJed Brown     if(check_flag) {
9590c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
9600c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
9610c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9620c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
9630c7d97c5SJed Brown       for(i=0;i<pcbddc->local_primal_size;i++) {
9640c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
9650c7d97c5SJed Brown       }
9660c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9670c7d97c5SJed Brown     }
9680c7d97c5SJed Brown     /* free allocated memory */
9690c7d97c5SJed Brown     ierr = PetscFree(          auxlocal_primal);CHKERRQ(ierr);
9700c7d97c5SJed Brown     ierr = PetscFree(         auxglobal_primal);CHKERRQ(ierr);
9710c7d97c5SJed Brown     ierr = PetscFree(     all_auxglobal_primal);CHKERRQ(ierr);
9720c7d97c5SJed Brown     ierr = PetscFree(all_auxglobal_primal_type);CHKERRQ(ierr);
9730c7d97c5SJed Brown 
9740c7d97c5SJed Brown   }
9750c7d97c5SJed Brown 
9760c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
9770c7d97c5SJed Brown   {
9780c7d97c5SJed Brown     Mat  A_RR;
979*53cdbc3dSStefano Zampini     PC   pc_temp;
9800c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
981*53cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
982*53cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
983*53cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
984*53cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
985*53cdbc3dSStefano Zampini     //ierr = KSPSetOptionsPrefix(pcbddc->pc_D,"pc_bddc_localD_");CHKERRQ(ierr);
9860c7d97c5SJed Brown     /* default */
987*53cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
988*53cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
9890c7d97c5SJed Brown     /* Allow user's customization */
990*53cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
991*53cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
992*53cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
9930c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
9940c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
995*53cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
996*53cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
997*53cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
998*53cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
999*53cdbc3dSStefano Zampini     //ierr = PCSetOptionsPrefix(pcbddc->pc_R,"pc_bddc_localN_");CHKERRQ(ierr);
10000c7d97c5SJed Brown     /* default */
1001*53cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1002*53cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
10030c7d97c5SJed Brown     /* Allow user's customization */
1004*53cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1005*53cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1006*53cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
10070c7d97c5SJed Brown     /* check Neumann solve */
10080c7d97c5SJed Brown     if(pcbddc->check_flag) {
10090c7d97c5SJed Brown       Vec temp_vec;
10100c7d97c5SJed Brown       PetscScalar value;
10110c7d97c5SJed Brown 
10120c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);
10130c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
10140c7d97c5SJed Brown       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);
1015*53cdbc3dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);
10160c7d97c5SJed Brown       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);
10170c7d97c5SJed Brown       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);
10180c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);
10190c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
10200c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Neumann problem\n");CHKERRQ(ierr);
10210c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
10220c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);
10230c7d97c5SJed Brown       ierr = VecDestroy(&temp_vec);
10240c7d97c5SJed Brown     }
10250c7d97c5SJed Brown     /* free Neumann problem's matrix */
10260c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
10270c7d97c5SJed Brown   }
10280c7d97c5SJed Brown 
10290c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
10300c7d97c5SJed Brown   {
10310c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
10320c7d97c5SJed Brown     Mat          M1,M2;
10330c7d97c5SJed Brown     Mat          C_CR;
10340c7d97c5SJed Brown     Mat          CMAT,AUXMAT;
10350c7d97c5SJed Brown     Vec          vec1_C;
10360c7d97c5SJed Brown     Vec          vec2_C;
10370c7d97c5SJed Brown     Vec          vec1_V;
10380c7d97c5SJed Brown     Vec          vec2_V;
10390c7d97c5SJed Brown     PetscInt     *nnz;
10400c7d97c5SJed Brown     PetscInt     *auxindices;
1041*53cdbc3dSStefano Zampini     PetscInt     index;
10420c7d97c5SJed Brown     PetscScalar* array2;
10430c7d97c5SJed Brown     MatFactorInfo matinfo;
10440c7d97c5SJed Brown 
10450c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
10460c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
10470c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
10480c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
10490c7d97c5SJed Brown 
10500c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
10510c7d97c5SJed Brown     if(pcbddc->n_vertices) {
10520c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
10530c7d97c5SJed Brown       ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr);
10540c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
10550c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
10560c7d97c5SJed Brown     }
10570c7d97c5SJed Brown     if(pcbddc->n_constraints) {
10580c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
10590c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
10600c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
10610c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
10620c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
10630c7d97c5SJed Brown     }
10640c7d97c5SJed Brown     /* Create C matrix [I 0; 0 const] */
10650c7d97c5SJed Brown     ierr = MatCreate(PETSC_COMM_SELF,&CMAT);
10660c7d97c5SJed Brown     ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr);
10670c7d97c5SJed Brown     ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
10680c7d97c5SJed Brown     /* nonzeros */
10690c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; }
10700c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];}
10710c7d97c5SJed Brown     ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr);
10720c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
10730c7d97c5SJed Brown       ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
10740c7d97c5SJed Brown     }
10750c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
1076*53cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
1077*53cdbc3dSStefano Zampini       ierr = MatSetValues(CMAT,1,&index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES);CHKERRQ(ierr);
10780c7d97c5SJed Brown     }
10790c7d97c5SJed Brown     //if(check_flag) printf("CMAT assembling\n");
10800c7d97c5SJed Brown     ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10810c7d97c5SJed Brown     ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10820c7d97c5SJed Brown     //ierr = MatView(CMAT,PETSC_VIEWER_STDOUT_SELF);
10830c7d97c5SJed Brown 
10840c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
10850c7d97c5SJed Brown 
10860c7d97c5SJed Brown     if(pcbddc->n_constraints) {
10870c7d97c5SJed Brown       /* some work vectors */
10880c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
10890c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr);
10900c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
10910c7d97c5SJed Brown 
10920c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
10930c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
10940c7d97c5SJed Brown         ierr = VecSet(pcis->vec1_N,zero);
10950c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10960c7d97c5SJed Brown         for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; }
10970c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
10980c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
10990c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11000c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1101*53cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
11020c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1103*53cdbc3dSStefano Zampini         index=i;
1104*53cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11050c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
11060c7d97c5SJed Brown       }
11070c7d97c5SJed Brown       //if(check_flag) printf("pcbddc->local_auxmat2 assembling\n");
11080c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11090c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11100c7d97c5SJed Brown 
11110c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
11120c7d97c5SJed Brown       ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
11130c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
11140c7d97c5SJed Brown 
11150c7d97c5SJed Brown         /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
11160c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
11170c7d97c5SJed Brown       ierr = MatFactorInfoInitialize(&matinfo);
11180c7d97c5SJed Brown       ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
11190c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
11200c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
11210c7d97c5SJed Brown 
11220c7d97c5SJed Brown         /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */
11230c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&M1);
11240c7d97c5SJed Brown       ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
11250c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
11260c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
11270c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
11280c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
11290c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
11300c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
11310c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
11320c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
11330c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
1134*53cdbc3dSStefano Zampini         index=i;
1135*53cdbc3dSStefano Zampini         ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11360c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
11370c7d97c5SJed Brown       }
11380c7d97c5SJed Brown       //if(check_flag) printf("M1 assembling\n");
11390c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11400c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11410c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
11420c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
11430c7d97c5SJed Brown       //if(check_flag) printf("pcbddc->local_auxmat1 computing and assembling\n");
11440c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
11450c7d97c5SJed Brown 
11460c7d97c5SJed Brown     }
11470c7d97c5SJed Brown 
11480c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
11490c7d97c5SJed Brown     if(pcbddc->n_vertices){
11500c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
11510c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
11520c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
11530c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
11540c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&M2);
11550c7d97c5SJed Brown       ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr);
11560c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
11570c7d97c5SJed Brown       for(i=0;i<pcbddc->n_vertices;i++) {
11580c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
11590c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
11600c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
11610c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11620c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
1163*53cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1164*53cdbc3dSStefano Zampini         index=i;
11650c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1166*53cdbc3dSStefano Zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
11670c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
11680c7d97c5SJed Brown       }
11690c7d97c5SJed Brown       //if(check_flag) printf("M2 assembling\n");
11700c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11710c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11720c7d97c5SJed Brown     }
11730c7d97c5SJed Brown 
11740c7d97c5SJed Brown /* Matrix of coarse basis functions (local) */
11750c7d97c5SJed Brown     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);
11760c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
11770c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
11780c7d97c5SJed Brown     if(pcbddc->prec_type || check_flag ) {
11790c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);
11800c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
11810c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
11820c7d97c5SJed Brown     }
11830c7d97c5SJed Brown 
11840c7d97c5SJed Brown /* Subdomain contribution (Non-overlapping) to coarse matrix  */
11850c7d97c5SJed Brown     if(check_flag) {
11860c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
11870c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
11880c7d97c5SJed Brown     }
11890c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
11900c7d97c5SJed Brown 
11910c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
11920c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
11930c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
11940c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
11950c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
11960c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
11970c7d97c5SJed Brown       /* solution of saddle point problem */
11980c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
11990c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
12000c7d97c5SJed Brown       if(pcbddc->n_constraints) {
12010c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
12020c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
12030c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
12040c7d97c5SJed Brown       }
12050c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
12060c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
12070c7d97c5SJed Brown 
12080c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
12090c7d97c5SJed Brown       /* coarse basis functions */
1210*53cdbc3dSStefano Zampini       index=i;
12110c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
12120c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12130c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12140c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1215*53cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12160c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12170c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
12180c7d97c5SJed Brown       if( pcbddc->prec_type || check_flag  ) {
12190c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12200c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12210c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1222*53cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12230c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
12240c7d97c5SJed Brown       }
12250c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
12260c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12270c7d97c5SJed Brown       for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
12280c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12290c7d97c5SJed Brown       if( pcbddc->n_constraints) {
12300c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12310c7d97c5SJed 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
12320c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12330c7d97c5SJed Brown       }
12340c7d97c5SJed Brown 
12350c7d97c5SJed Brown       if( check_flag ) {
12360c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
12370c7d97c5SJed Brown         ierr = VecSet(pcis->vec1_N,zero);
12380c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12390c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12400c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
12410c7d97c5SJed Brown         array[ pcbddc->vertices[i] ] = one;
12420c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
12430c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12440c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
12450c7d97c5SJed Brown         ierr = VecSet(pcbddc->vec1_P,zero);
12460c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12470c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
12480c7d97c5SJed Brown         for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; }
12490c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
12500c7d97c5SJed Brown         if(pcbddc->n_constraints) {
12510c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
12520c7d97c5SJed Brown           for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; }
12530c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
12540c7d97c5SJed Brown         }
12550c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
12560c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
12570c7d97c5SJed Brown         /* check saddle point solution */
12580c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
1259*53cdbc3dSStefano Zampini         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
1260*53cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
12610c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
12620c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1263*53cdbc3dSStefano Zampini         array[index]=array[index]+m_one;  /* shift by the identity matrix */
12640c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1265*53cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
12660c7d97c5SJed Brown       }
12670c7d97c5SJed Brown     }
12680c7d97c5SJed Brown 
12690c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++){
12700c7d97c5SJed Brown       ierr = VecSet(vec2_C,zero);
12710c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
12720c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
12730c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
12740c7d97c5SJed Brown       /* solution of saddle point problem */
12750c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
12760c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
12770c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
12780c7d97c5SJed Brown       if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
12790c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
12800c7d97c5SJed Brown       /* coarse basis functions */
1281*53cdbc3dSStefano Zampini       index=i+pcbddc->n_vertices;
12820c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
12830c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12840c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12850c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1286*53cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12870c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12880c7d97c5SJed Brown       if( pcbddc->prec_type || check_flag ) {
12890c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12900c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12910c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1292*53cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
12930c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
12940c7d97c5SJed Brown       }
12950c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
12960c7d97c5SJed Brown       if(pcbddc->n_vertices) {
12970c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1298*53cdbc3dSStefano Zampini         for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
12990c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
13000c7d97c5SJed Brown       }
13010c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1302*53cdbc3dSStefano 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
13030c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
13040c7d97c5SJed Brown 
13050c7d97c5SJed Brown       if( check_flag ) {
13060c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1307*53cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
13080c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13090c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
13100c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
13110c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
13120c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13130c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
1314*53cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
13150c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
13160c7d97c5SJed Brown         if( pcbddc->n_vertices) {
13170c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
13180c7d97c5SJed Brown           for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];}
13190c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
13200c7d97c5SJed Brown         }
13210c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
13220c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];}
13230c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
13240c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
13250c7d97c5SJed Brown         /* check saddle point solution */
13260c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
13270c7d97c5SJed Brown         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);
1328*53cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
13290c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
13300c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1331*53cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
13320c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1333*53cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
13340c7d97c5SJed Brown       }
13350c7d97c5SJed Brown     }
13360c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13370c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13380c7d97c5SJed Brown     if( pcbddc->prec_type || check_flag ) {
13390c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13400c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13410c7d97c5SJed Brown     }
13420c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
13430c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
13440c7d97c5SJed Brown     if(check_flag) {
13450c7d97c5SJed Brown 
13460c7d97c5SJed Brown       Mat coarse_sub_mat;
13470c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
13480c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
13490c7d97c5SJed Brown       const MatType checkmattype;
13500c7d97c5SJed Brown       PetscScalar      value;
13510c7d97c5SJed Brown       PetscInt bs;
13520c7d97c5SJed Brown 
13530c7d97c5SJed Brown       ierr = MatGetType(matis->A,&checkmattype);CHKERRQ(ierr);
13540c7d97c5SJed Brown       ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
13550c7d97c5SJed Brown       ierr = MatGetType(pcis->A_II,&checkmattype);CHKERRQ(ierr);
13560c7d97c5SJed Brown       ierr = MatGetBlockSize(pcis->A_II,&bs);CHKERRQ(ierr);
13570c7d97c5SJed Brown       checkmattype = MATSEQAIJ;
1358*53cdbc3dSStefano Zampini       MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1359*53cdbc3dSStefano Zampini       MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1360*53cdbc3dSStefano Zampini       MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1361*53cdbc3dSStefano Zampini       MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1362*53cdbc3dSStefano Zampini       MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1363*53cdbc3dSStefano Zampini       MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
13640c7d97c5SJed Brown       MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1365*53cdbc3dSStefano Zampini       MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
13660c7d97c5SJed Brown 
13670c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
13680c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
13690c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1370*53cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
1371*53cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
1372*53cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1373*53cdbc3dSStefano Zampini       ierr = MatMatTransposeMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
1374*53cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1375*53cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1376*53cdbc3dSStefano Zampini       ierr = MatMatTransposeMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
1377*53cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1378*53cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1379*53cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1380*53cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1381*53cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1382*53cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
13830c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
13840c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
13850c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
13860c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
1387*53cdbc3dSStefano 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); }
13880c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
1389*53cdbc3dSStefano 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); }
13900c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1391*53cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
1392*53cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
1393*53cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
1394*53cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
1395*53cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
1396*53cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
1397*53cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
1398*53cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
1399*53cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
1400*53cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
1401*53cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
14020c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
14030c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
14040c7d97c5SJed Brown     }
14050c7d97c5SJed Brown 
14060c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
14070c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
14080c7d97c5SJed Brown     /* free memory */
14090c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
14100c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
14110c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
14120c7d97c5SJed Brown     if(pcbddc->n_vertices) {
14130c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
14140c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
14150c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
14160c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
14170c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
14180c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
14190c7d97c5SJed Brown     }
14200c7d97c5SJed Brown     if(pcbddc->n_constraints) {
14210c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
14220c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
14230c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
14240c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
14250c7d97c5SJed Brown     }
14260c7d97c5SJed Brown     ierr = MatDestroy(&CMAT);CHKERRQ(ierr);
14270c7d97c5SJed Brown   }
14280c7d97c5SJed Brown   /* free memory */
14290c7d97c5SJed Brown   if(pcbddc->n_vertices) {
14300c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
14310c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
14320c7d97c5SJed Brown   }
14330c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
14340c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
14350c7d97c5SJed Brown 
14360c7d97c5SJed Brown   PetscFunctionReturn(0);
14370c7d97c5SJed Brown }
14380c7d97c5SJed Brown 
14390c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
14400c7d97c5SJed Brown 
14410c7d97c5SJed Brown #undef __FUNCT__
14420c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
1443*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
14440c7d97c5SJed Brown {
14450c7d97c5SJed Brown 
14460c7d97c5SJed Brown 
14470c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
14480c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
14490c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
14500c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
14510c7d97c5SJed Brown   MPI_Comm  coarse_comm;
14520c7d97c5SJed Brown 
14530c7d97c5SJed Brown   /* common to all choiches */
14540c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
14550c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
14560c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
14570c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
14580c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
14590c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
14600c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
14610c7d97c5SJed Brown   PetscMPIInt master_proc=0;
14620c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
14630c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
14640c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
14650c7d97c5SJed Brown   PetscMPIInt count_recv=0;
14660c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
14670c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
14680c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
14690c7d97c5SJed Brown   /* some other variables */
14700c7d97c5SJed Brown   PetscErrorCode ierr;
14710c7d97c5SJed Brown   const MatType coarse_mat_type;
14720c7d97c5SJed Brown   const PCType  coarse_pc_type;
1473*53cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
1474*53cdbc3dSStefano Zampini   PC pc_temp;
14750c7d97c5SJed Brown   PetscInt i,j,k,bs;
14760c7d97c5SJed Brown 
14770c7d97c5SJed Brown   PetscFunctionBegin;
14780c7d97c5SJed Brown 
14790c7d97c5SJed Brown   ins_local_primal_indices = 0;
14800c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
14810c7d97c5SJed Brown   localsizes2              = 0;
14820c7d97c5SJed Brown   localdispl2              = 0;
14830c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
14840c7d97c5SJed Brown   coarse_ISLG              = 0;
14850c7d97c5SJed Brown 
1486*53cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
1487*53cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
14880c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
14890c7d97c5SJed Brown 
14900c7d97c5SJed Brown   /* adapt coarse problem type */
14910c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
14920c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
14930c7d97c5SJed Brown 
14940c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
14950c7d97c5SJed Brown 
14960c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
14970c7d97c5SJed Brown     {
14980c7d97c5SJed Brown       /* we need additional variables */
14990c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
15000c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
15010c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
15020c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
15030c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
15040c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
15050c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
15060c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
15070c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
15080c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
15090c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
15100c7d97c5SJed Brown       MetisInt    *faces_adjncy;
15110c7d97c5SJed Brown       MetisInt    *faces_xadj;
15120c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
15130c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
15140c7d97c5SJed Brown       PetscInt    *array_int;
15150c7d97c5SJed Brown       PetscMPIInt my_faces=0;
15160c7d97c5SJed Brown       PetscMPIInt total_faces=0;
15170c7d97c5SJed Brown 
15180c7d97c5SJed Brown       /* this code has a bug (see below) for more then three levels -> I can solve it quickly */
15190c7d97c5SJed Brown 
15200c7d97c5SJed Brown       /* define some quantities */
15210c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
15220c7d97c5SJed Brown       coarse_mat_type = MATIS;
15230c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
1524*53cdbc3dSStefano Zampini       coarse_ksp_type  = KSPRICHARDSON;
15250c7d97c5SJed Brown 
15260c7d97c5SJed Brown       /* details of coarse decomposition */
15270c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
15280c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
15290c7d97c5SJed Brown       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*(size_prec_comm/pcbddc->active_procs);
15300c7d97c5SJed Brown 
15310c7d97c5SJed Brown       ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
1532*53cdbc3dSStefano 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);
15330c7d97c5SJed Brown 
15340c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
15350c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
15360c7d97c5SJed Brown       PetscMemzero(array_int,pcis->n*sizeof(PetscInt));
15370c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
15380c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15390c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
15400c7d97c5SJed Brown         }
15410c7d97c5SJed Brown       }
15420c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
15430c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15440c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
15450c7d97c5SJed Brown             my_faces++;
15460c7d97c5SJed Brown             break;
15470c7d97c5SJed Brown           }
15480c7d97c5SJed Brown         }
15490c7d97c5SJed Brown       }
15500c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
15510c7d97c5SJed Brown 
1552*53cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
15530c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
15540c7d97c5SJed Brown       my_faces=0;
15550c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
15560c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
15570c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
15580c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
15590c7d97c5SJed Brown             my_faces++;
15600c7d97c5SJed Brown             break;
15610c7d97c5SJed Brown           }
15620c7d97c5SJed Brown         }
15630c7d97c5SJed Brown       }
15640c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
15650c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
15660c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
15670c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
15680c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
15690c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
15700c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
15710c7d97c5SJed Brown       }
1572*53cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
15730c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
15740c7d97c5SJed Brown         faces_xadj[0]=0;
15750c7d97c5SJed Brown         faces_displacements[0]=0;
15760c7d97c5SJed Brown         j=0;
15770c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
15780c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
15790c7d97c5SJed Brown           if(number_of_faces[i-1]) {
15800c7d97c5SJed Brown             j++;
15810c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
15820c7d97c5SJed Brown           }
15830c7d97c5SJed Brown         }
15840c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
15850c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
15860c7d97c5SJed Brown       }
1587*53cdbc3dSStefano 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);
15880c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
15890c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
15900c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
15910c7d97c5SJed Brown         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]); ///procs_jumps_coarse_comm); // cast to MetisInt
15920c7d97c5SJed Brown         printf("This is the face connectivity (%d)\n",procs_jumps_coarse_comm);
15930c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
15940c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
15950c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
15960c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
15970c7d97c5SJed Brown           printf("\n");
15980c7d97c5SJed Brown         }
15990c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
16000c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
16010c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
16020c7d97c5SJed Brown       }
16030c7d97c5SJed Brown 
16040c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
16050c7d97c5SJed Brown 
16060c7d97c5SJed Brown         ncon=1;
16070c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
16080c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
16090c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
16100c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
16110c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
16120c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
16130c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
16140c7d97c5SJed Brown         options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
16150c7d97c5SJed Brown         options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
16160c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
16170c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
16180c7d97c5SJed Brown         //printf("METIS PART GRAPH\n");
16190c7d97c5SJed Brown         /* BUG: faces_xadj and faces_adjncy content must be adapted using the coarsening factor*/
16200c7d97c5SJed Brown         ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
16210c7d97c5SJed Brown         //printf("OKOKOKOKOKOKOKOK\n");
16220c7d97c5SJed 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);
16230c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
16240c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
16250c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
16260c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
16270c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;;
16280c7d97c5SJed Brown         k=size_prec_comm/pcbddc->active_procs;
16290c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=(PetscInt)(metis_coarse_subdivision[i]);
16300c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
16310c7d97c5SJed Brown 
16320c7d97c5SJed Brown       }
16330c7d97c5SJed Brown 
16340c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
16350c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
16360c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
16370c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
16380c7d97c5SJed Brown       }
16390c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
16400c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
1641*53cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
16420c7d97c5SJed Brown 
16430c7d97c5SJed Brown       if( coarse_color == 0 ) {
1644*53cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
1645*53cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
16460c7d97c5SJed Brown         //printf("Details of coarse comm\n");
16470c7d97c5SJed Brown         //printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
16480c7d97c5SJed Brown         //printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
16490c7d97c5SJed Brown       } else {
16500c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
16510c7d97c5SJed Brown       }
16520c7d97c5SJed Brown 
16530c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
16540c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
16550c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
16560c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
16570c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
16580c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
16590c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
16600c7d97c5SJed Brown         /* some initializations */
16610c7d97c5SJed Brown         displacements_recv[0]=0;
16620c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
16630c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
16640c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
16650c7d97c5SJed Brown           for(i=0;i<n_subdomains;i++)
16660c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
16670c7d97c5SJed Brown               total_count_recv[j]++;
16680c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
16690c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
16700c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
16710c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
16720c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
16730c7d97c5SJed Brown           for(i=0;i<n_subdomains;i++) {
16740c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
16750c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
16760c7d97c5SJed Brown               total_count_recv[j]=total_count_recv[j]+1;
16770c7d97c5SJed Brown             }
16780c7d97c5SJed Brown           }
16790c7d97c5SJed Brown         }
16800c7d97c5SJed Brown         //for(j=0;j<size_coarse_comm;j++) {
16810c7d97c5SJed Brown         //  printf("process %d in new rank will receive from %d processes (ranks follows)\n",j,total_count_recv[j]);
16820c7d97c5SJed Brown         //  for(i=0;i<total_count_recv[j];i++) {
16830c7d97c5SJed Brown         //    printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
16840c7d97c5SJed Brown         //  }
16850c7d97c5SJed Brown         //  printf("\n");
16860c7d97c5SJed Brown        // }
16870c7d97c5SJed Brown 
16880c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
16890c7d97c5SJed Brown         k=size_prec_comm/pcbddc->active_procs;
16900c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=coarse_subdivision[k*i]*procs_jumps_coarse_comm;
16910c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
16920c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
16930c7d97c5SJed Brown           printf("(%d %d) ",coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
16940c7d97c5SJed Brown         printf("\n");
16950c7d97c5SJed Brown       }
16960c7d97c5SJed Brown 
16970c7d97c5SJed Brown       /* Scatter new decomposition for send details */
1698*53cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
16990c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
17000c7d97c5SJed Brown       if( coarse_color == 0) {
1701*53cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
17020c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
1703*53cdbc3dSStefano 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);
17040c7d97c5SJed Brown       }
17050c7d97c5SJed Brown 
17060c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
17070c7d97c5SJed Brown       //if(coarse_color == 0) {
17080c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
17090c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
17100c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
17110c7d97c5SJed Brown       //  printf("\n");
17120c7d97c5SJed Brown       //}
17130c7d97c5SJed Brown 
17140c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
17150c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
17160c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
17170c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
17180c7d97c5SJed Brown         free(coarse_subdivision);
17190c7d97c5SJed Brown         free(total_count_recv);
17200c7d97c5SJed Brown         free(total_ranks_recv);
17210c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
17220c7d97c5SJed Brown       }
17230c7d97c5SJed Brown       break;
17240c7d97c5SJed Brown     }
17250c7d97c5SJed Brown 
17260c7d97c5SJed Brown     case(REPLICATED_BDDC):
17270c7d97c5SJed Brown 
17280c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17290c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17300c7d97c5SJed Brown       coarse_pc_type  = PCLU;
1731*53cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17320c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
17330c7d97c5SJed Brown       active_rank = rank_prec_comm;
17340c7d97c5SJed Brown       break;
17350c7d97c5SJed Brown 
17360c7d97c5SJed Brown     case(PARALLEL_BDDC):
17370c7d97c5SJed Brown 
17380c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
17390c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
17400c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
1741*53cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17420c7d97c5SJed Brown       coarse_comm = prec_comm;
17430c7d97c5SJed Brown       active_rank = rank_prec_comm;
17440c7d97c5SJed Brown       break;
17450c7d97c5SJed Brown 
17460c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
17470c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
17480c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
17490c7d97c5SJed Brown       coarse_pc_type = PCLU;
1750*53cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
17510c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
17520c7d97c5SJed Brown       active_rank = master_proc;
17530c7d97c5SJed Brown       break;
17540c7d97c5SJed Brown   }
17550c7d97c5SJed Brown 
17560c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
17570c7d97c5SJed Brown 
17580c7d97c5SJed Brown     case(SCATTERS_BDDC):
17590c7d97c5SJed Brown       {
17600c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
17610c7d97c5SJed Brown 
17620c7d97c5SJed Brown           PetscMPIInt send_size;
17630c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
17640c7d97c5SJed Brown           PetscInt    ii,jj;
17650c7d97c5SJed Brown           MPI_Request *requests;
17660c7d97c5SJed Brown 
17670c7d97c5SJed Brown           /* allocate auxiliary space */
17680c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
17690c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
17700c7d97c5SJed Brown           /* allocate stuffs for message massing */
17710c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
17720c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
17730c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
17740c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
17750c7d97c5SJed Brown           /* fill up quantities */
17760c7d97c5SJed Brown           j=0;
17770c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
17780c7d97c5SJed Brown             ii = ranks_recv[i];
17790c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
17800c7d97c5SJed Brown             localdispl2[i]=j;
17810c7d97c5SJed Brown             j+=localsizes2[i];
17820c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
17830c7d97c5SJed 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
17840c7d97c5SJed Brown           }
17850c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
17860c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
17870c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
17880c7d97c5SJed Brown           //printf("\n");
17890c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
17900c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
17910c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
17920c7d97c5SJed Brown           ins_local_primal_size=0;
17930c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
17940c7d97c5SJed Brown             if(aux_ins_indices[i])
17950c7d97c5SJed Brown               ins_local_primal_size++;
17960c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
17970c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
17980c7d97c5SJed Brown           j=0;
17990c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
18000c7d97c5SJed Brown             if(aux_ins_indices[i])
18010c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
18020c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
18030c7d97c5SJed Brown           j=0;
18040c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
18050c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
18060c7d97c5SJed Brown               aux_ins_indices[i]=-1;
18070c7d97c5SJed Brown             } else {
18080c7d97c5SJed Brown               aux_ins_indices[i]=j;
18090c7d97c5SJed Brown               j++;
18100c7d97c5SJed Brown             }
18110c7d97c5SJed Brown           }
18120c7d97c5SJed Brown 
18130c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
18140c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
18150c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
18160c7d97c5SJed Brown           //printf("\n");
18170c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
18180c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
18190c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
18200c7d97c5SJed Brown           //printf("\n");
18210c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
18220c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
18230c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
18240c7d97c5SJed Brown           //printf("\n");
18250c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
18260c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
18270c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
18280c7d97c5SJed 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]);
18290c7d97c5SJed Brown           //printf("\n");
18300c7d97c5SJed Brown 
18310c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
1832*53cdbc3dSStefano 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);
18330c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
18340c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
1835*53cdbc3dSStefano 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);
18360c7d97c5SJed Brown           }
1837*53cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
18380c7d97c5SJed Brown 
18390c7d97c5SJed Brown           //if(coarse_color == 0) {
18400c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
18410c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
18420c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
18430c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
18440c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
18450c7d97c5SJed 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]);
18460c7d97c5SJed Brown           //    printf("\n");
18470c7d97c5SJed Brown           //  }
18480c7d97c5SJed Brown           //}
18490c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
18500c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
18510c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
18520c7d97c5SJed Brown 
18530c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
18540c7d97c5SJed Brown           PetscInt row_ind,col_ind;
18550c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
18560c7d97c5SJed Brown             rr = ranks_recv[k];
18570c7d97c5SJed Brown             kk = localdispl2[k];
18580c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
18590c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
18600c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
18610c7d97c5SJed Brown             for(j=0;j<lps;j++){
18620c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
18630c7d97c5SJed Brown               for(i=0;i<lps;i++){
18640c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
18650c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
18660c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
18670c7d97c5SJed Brown               }
18680c7d97c5SJed Brown             }
18690c7d97c5SJed Brown           }
18700c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
18710c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
18720c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
18730c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
18740c7d97c5SJed Brown 
18750c7d97c5SJed Brown             /* create local to global mapping needed by coarse MATIS */
18760c7d97c5SJed Brown           {
18770c7d97c5SJed Brown             IS coarse_IS;
1878*53cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
18790c7d97c5SJed Brown             coarse_comm = prec_comm;
18800c7d97c5SJed Brown             active_rank=rank_prec_comm;
18810c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
18820c7d97c5SJed Brown             //ierr = ISSetBlockSize(coarse_IS,bs);CHKERRQ(ierr);
18830c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
18840c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
18850c7d97c5SJed Brown           }
18860c7d97c5SJed Brown         }
18870c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
18880c7d97c5SJed Brown           /* arrays for values insertion */
18890c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
18900c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
18910c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
18920c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
18930c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
18940c7d97c5SJed 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];
18950c7d97c5SJed Brown           }
18960c7d97c5SJed Brown         }
18970c7d97c5SJed Brown         break;
18980c7d97c5SJed Brown 
18990c7d97c5SJed Brown     }
19000c7d97c5SJed Brown 
19010c7d97c5SJed Brown     case(GATHERS_BDDC):
19020c7d97c5SJed Brown       {
19030c7d97c5SJed Brown 
19040c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
19050c7d97c5SJed Brown 
19060c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
19070c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
19080c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
19090c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
19100c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
19110c7d97c5SJed Brown           /* arrays for values insertion */
19120c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
19130c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
19140c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
19150c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
19160c7d97c5SJed Brown           localdispl2[0]=0;
19170c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
19180c7d97c5SJed Brown           j=0;
19190c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
19200c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
19210c7d97c5SJed Brown         }
19220c7d97c5SJed Brown 
19230c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
19240c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
19250c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
1926*53cdbc3dSStefano 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);
1927*53cdbc3dSStefano 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);
19280c7d97c5SJed Brown         } else {
1929*53cdbc3dSStefano 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);
1930*53cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
19310c7d97c5SJed Brown         }
19320c7d97c5SJed Brown 
19330c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
19340c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
19350c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
19360c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
19370c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
19380c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
19390c7d97c5SJed Brown           }
19400c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
19410c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
19420c7d97c5SJed Brown             offset2=localdispl2[k];
19430c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
19440c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
19450c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
19460c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
19470c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
19480c7d97c5SJed Brown               }
19490c7d97c5SJed Brown             }
19500c7d97c5SJed Brown           }
19510c7d97c5SJed Brown         }
19520c7d97c5SJed Brown         break;
19530c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
19540c7d97c5SJed Brown   }
19550c7d97c5SJed Brown 
19560c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
19570c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
19580c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
19590c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
19600c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
19610c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
19620c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
19630c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
19640c7d97c5SJed Brown     } else {
19650c7d97c5SJed Brown       Mat matis_coarse_local_mat;
19660c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
19670c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
19680c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
19690c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
19700c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr);
19710c7d97c5SJed Brown     }
19720c7d97c5SJed 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);
19730c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19740c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
19750c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
19760c7d97c5SJed Brown       Mat matis_coarse_local_mat;
19770c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
19780c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
19790c7d97c5SJed Brown     }
19800c7d97c5SJed Brown 
19810c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
19820c7d97c5SJed Brown     /* Preconditioner for coarse problem */
1983*53cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
1984*53cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
1985*53cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
1986*53cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
1987*53cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
1988*53cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
1989*53cdbc3dSStefano Zampini     //ierr = PCSetOptionsPrefix(pcbddc->coarse_pc,"pc_bddc_coarse_");CHKERRQ(ierr);
19900c7d97c5SJed Brown     /* Allow user's customization */
1991*53cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
19920c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
19930c7d97c5SJed Brown     //if(pcbddc->check_flag && pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1994*53cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1995*53cdbc3dSStefano Zampini       PetscPrintf(PETSC_COMM_WORLD,"----------------Setting up a new level---------------\n");
1996*53cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
1997*53cdbc3dSStefano Zampini     }
1998*53cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
19990c7d97c5SJed Brown   }
20000c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
20010c7d97c5SJed Brown      IS local_IS,global_IS;
20020c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
20030c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
20040c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
20050c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
20060c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
20070c7d97c5SJed Brown   }
20080c7d97c5SJed Brown 
20090c7d97c5SJed Brown 
20100c7d97c5SJed Brown   /* Check condition number of coarse problem */
2011*53cdbc3dSStefano Zampini   if( pcbddc->check_flag && rank_prec_comm == active_rank ) {
20120c7d97c5SJed Brown     PetscScalar m_one=-1.0;
20130c7d97c5SJed Brown     PetscReal infty_error,lambda_min,lambda_max;
20140c7d97c5SJed Brown 
2015*53cdbc3dSStefano Zampini     KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);
20160c7d97c5SJed Brown     VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);
20170c7d97c5SJed Brown     MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);
20180c7d97c5SJed Brown     MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);
2019*53cdbc3dSStefano Zampini     KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);
2020*53cdbc3dSStefano Zampini     KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);
20210c7d97c5SJed Brown     VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);
20220c7d97c5SJed Brown     VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);
20230c7d97c5SJed Brown     printf("eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);
20240c7d97c5SJed Brown     printf("Error on coarse ksp %1.14e\n",infty_error);
2025*53cdbc3dSStefano Zampini     KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);
2026*53cdbc3dSStefano Zampini   }
20270c7d97c5SJed Brown 
20280c7d97c5SJed Brown   /* free data structures no longer needed */
20290c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
20300c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
20310c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
20320c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
20330c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
20340c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
20350c7d97c5SJed Brown 
20360c7d97c5SJed Brown   PetscFunctionReturn(0);
20370c7d97c5SJed Brown }
20380c7d97c5SJed Brown 
20390c7d97c5SJed Brown #undef __FUNCT__
20400c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
2041*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
20420c7d97c5SJed Brown {
20430c7d97c5SJed Brown 
20440c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
20450c7d97c5SJed Brown   PC_IS      *pcis = (PC_IS*)pc->data;
20460c7d97c5SJed Brown   Mat_IS   *matis  = (Mat_IS*)pc->pmat->data;
20470c7d97c5SJed Brown   PetscInt *distinct_values;
2048*53cdbc3dSStefano Zampini   PetscInt **neighbours_set;
2049*53cdbc3dSStefano Zampini   PetscInt bs,ierr,i,j,s,k,iindex;
20500c7d97c5SJed Brown   PetscInt total_counts;
20510c7d97c5SJed Brown   PetscBool flg_row;
20520c7d97c5SJed Brown   PCBDDCGraph mat_graph;
2053*53cdbc3dSStefano Zampini   PetscInt   neumann_bsize;
2054*53cdbc3dSStefano Zampini   const PetscInt*  neumann_nodes;
20550c7d97c5SJed Brown   Mat        mat_adj;
20560c7d97c5SJed Brown 
20570c7d97c5SJed Brown   PetscFunctionBegin;
20580c7d97c5SJed Brown 
20590c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
20600c7d97c5SJed Brown   // allocate and initialize needed graph structure
20610c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
20620c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
20630c7d97c5SJed Brown   ierr = MatGetRowIJ(mat_adj,0,PETSC_FALSE,PETSC_FALSE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
20640c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
20650c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->where);CHKERRQ(ierr);
20660c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->count);CHKERRQ(ierr);
20670c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->which_dof);CHKERRQ(ierr);
20680c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->queue);CHKERRQ(ierr);
20690c7d97c5SJed Brown   ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->cptr);CHKERRQ(ierr);
20700c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscBool),&mat_graph->touched);CHKERRQ(ierr);
20710c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
20720c7d97c5SJed Brown     mat_graph->count[i]=0;
20730c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_FALSE;
20740c7d97c5SJed Brown   }
20750c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs/bs;i++) {
20760c7d97c5SJed Brown     for(s=0;s<bs;s++) {
20770c7d97c5SJed Brown       mat_graph->which_dof[i*bs+s]=s;
20780c7d97c5SJed Brown     }
20790c7d97c5SJed Brown   }
20800c7d97c5SJed Brown   //printf("nvtxs = %d\n",mat_graph->nvtxs);
20810c7d97c5SJed Brown   //printf("these are my IS data with n_neigh = %d\n",pcis->n_neigh);
20820c7d97c5SJed Brown   //for(i=0;i<pcis->n_neigh;i++){
20830c7d97c5SJed Brown   //  printf("number of shared nodes with rank %d is %d \n",pcis->neigh[i],pcis->n_shared[i]);
20840c7d97c5SJed Brown   // }
20850c7d97c5SJed Brown 
20860c7d97c5SJed Brown   total_counts=0;
20870c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
20880c7d97c5SJed Brown     s=pcis->n_shared[i];
20890c7d97c5SJed Brown     total_counts+=s;
20900c7d97c5SJed Brown     //printf("computing neigh %d (rank = %d, n_shared = %d)\n",i,pcis->neigh[i],s);
2091*53cdbc3dSStefano Zampini     for(j=0;j<s;j++){
20920c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
20930c7d97c5SJed Brown     }
20940c7d97c5SJed Brown   }
20950c7d97c5SJed Brown   /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */
2096*53cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
2097*53cdbc3dSStefano Zampini     ierr = ISGetLocalSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
2098*53cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
2099*53cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
2100*53cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
2101*53cdbc3dSStefano Zampini       if(mat_graph->count[iindex] > 2){
2102*53cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
21030c7d97c5SJed Brown         total_counts++;
21040c7d97c5SJed Brown       }
21050c7d97c5SJed Brown     }
21060c7d97c5SJed Brown   }
21070c7d97c5SJed Brown 
2108*53cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
2109*53cdbc3dSStefano Zampini   if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr);
2110*53cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
21110c7d97c5SJed Brown 
21120c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++) mat_graph->count[i]=0;
21130c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
21140c7d97c5SJed Brown     s=pcis->n_shared[i];
21150c7d97c5SJed Brown     for(j=0;j<s;j++) {
21160c7d97c5SJed Brown       k=pcis->shared[i][j];
2117*53cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
21180c7d97c5SJed Brown       mat_graph->count[k]+=1;
21190c7d97c5SJed Brown     }
21200c7d97c5SJed Brown   }
21210c7d97c5SJed Brown   /* set -1 fake neighbour */
2122*53cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
2123*53cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
2124*53cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
2125*53cdbc3dSStefano Zampini       if( mat_graph->count[iindex] > 2){
2126*53cdbc3dSStefano Zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1; //An additional fake neighbour (with rank -1)
2127*53cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
21280c7d97c5SJed Brown       }
21290c7d97c5SJed Brown     }
2130*53cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
21310c7d97c5SJed Brown   }
21320c7d97c5SJed Brown 
21330c7d97c5SJed Brown   /* sort sharing subdomains */
2134*53cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
21350c7d97c5SJed Brown 
2136*53cdbc3dSStefano Zampini   /* Prepare for FindConnectedComponents
2137*53cdbc3dSStefano Zampini      Vertices will be eliminated later (if needed) */
21380c7d97c5SJed Brown   PetscInt nodes_touched=0;
21390c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
21400c7d97c5SJed Brown     if(!mat_graph->count[i]){  //internal nodes
21410c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
21420c7d97c5SJed Brown       mat_graph->where[i]=0;
21430c7d97c5SJed Brown       nodes_touched++;
21440c7d97c5SJed Brown     }
21450c7d97c5SJed Brown     if(pcbddc->faces_flag){
21460c7d97c5SJed Brown       if(mat_graph->count[i]>2){  //all but faces
21470c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
21480c7d97c5SJed Brown         mat_graph->where[i]=0;
21490c7d97c5SJed Brown         nodes_touched++;
21500c7d97c5SJed Brown       }
21510c7d97c5SJed Brown     }
21520c7d97c5SJed Brown     if(pcbddc->edges_flag){
21530c7d97c5SJed Brown       if(mat_graph->count[i]==2){  //faces
21540c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
21550c7d97c5SJed Brown         mat_graph->where[i]=0;
21560c7d97c5SJed Brown         nodes_touched++;
21570c7d97c5SJed Brown       }
21580c7d97c5SJed Brown     }
21590c7d97c5SJed Brown   }
21600c7d97c5SJed Brown 
21610c7d97c5SJed Brown   PetscInt rvalue=1;
21620c7d97c5SJed Brown   PetscBool same_set;
21630c7d97c5SJed Brown   mat_graph->ncmps = 0;
21640c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
21650c7d97c5SJed Brown     // find first untouched node in local ordering
21660c7d97c5SJed Brown     i=0;
21670c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
21680c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
21690c7d97c5SJed Brown     mat_graph->where[i]=rvalue;
21700c7d97c5SJed Brown     nodes_touched++;
21710c7d97c5SJed Brown     // now find other connected nodes shared by the same set of subdomains
21720c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
21730c7d97c5SJed Brown       // check for same number of sharing subdomains and dof number
21740c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
21750c7d97c5SJed Brown         // check for same set of sharing subdomains
21760c7d97c5SJed Brown         same_set=PETSC_TRUE;
21770c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
2178*53cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
21790c7d97c5SJed Brown             same_set=PETSC_FALSE;
21800c7d97c5SJed Brown           }
21810c7d97c5SJed Brown         }
21820c7d97c5SJed Brown         // OK, I found a friend of mine
21830c7d97c5SJed Brown         if(same_set) {
21840c7d97c5SJed Brown           mat_graph->where[j]=rvalue;
21850c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
21860c7d97c5SJed Brown           nodes_touched++;
21870c7d97c5SJed Brown         }
21880c7d97c5SJed Brown       }
21890c7d97c5SJed Brown     }
21900c7d97c5SJed Brown     rvalue++;
21910c7d97c5SJed Brown   }
21920c7d97c5SJed Brown //  printf("where and count contains %d distinct values\n",rvalue);
21930c7d97c5SJed Brown //  for(j=0;j<mat_graph->nvtxs;j++)
21940c7d97c5SJed Brown //    printf("[%d %d %d]\n",j,mat_graph->where[j],mat_graph->count[j]);
21950c7d97c5SJed Brown 
21960c7d97c5SJed Brown   if(mat_graph->nvtxs) {
2197*53cdbc3dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
2198*53cdbc3dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
21990c7d97c5SJed Brown   }
22000c7d97c5SJed Brown 
22010c7d97c5SJed Brown   rvalue--;
22020c7d97c5SJed Brown   ierr  = PetscMalloc ( rvalue*sizeof(PetscInt),&distinct_values);CHKERRQ(ierr);
22030c7d97c5SJed Brown   for(i=0;i<rvalue;i++) distinct_values[i]=i+1;  //initializiation
22040c7d97c5SJed Brown   if(rvalue) ierr = PCBDDCFindConnectedComponents(mat_graph, rvalue, distinct_values);
22050c7d97c5SJed Brown   //printf("total number of connected components %d \n",mat_graph->ncmps);
22060c7d97c5SJed Brown   //for (i=0; i<mat_graph->ncmps; i++) {
22070c7d97c5SJed Brown   //  printf("[queue num %d] ptr %d, length %d, start index %d\n",i,mat_graph->cptr[i],mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->queue[mat_graph->cptr[i]]);
22080c7d97c5SJed Brown   //}
22090c7d97c5SJed Brown   PetscInt nfc=0;
22100c7d97c5SJed Brown   PetscInt nec=0;
22110c7d97c5SJed Brown   PetscInt nvc=0;
22120c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
22130c7d97c5SJed Brown     // sort each connected component (by local ordering)
22140c7d97c5SJed Brown     ierr = PetscSortInt(mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
22150c7d97c5SJed Brown     // count edge and faces
22160c7d97c5SJed Brown     if( !pcbddc->vertices_flag ) {
22170c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
22180c7d97c5SJed Brown         if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){
22190c7d97c5SJed Brown           nfc++;
22200c7d97c5SJed Brown         } else {
22210c7d97c5SJed Brown           nec++;
22220c7d97c5SJed Brown         }
22230c7d97c5SJed Brown       }
22240c7d97c5SJed Brown     }
22250c7d97c5SJed Brown     // count vertices
22260c7d97c5SJed Brown     if( !pcbddc->constraints_flag ){
22270c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
22280c7d97c5SJed Brown         nvc++;
22290c7d97c5SJed Brown       }
22300c7d97c5SJed Brown     }
22310c7d97c5SJed Brown   }
22320c7d97c5SJed Brown 
22330c7d97c5SJed Brown   pcbddc->n_constraints = nec+nfc;
22340c7d97c5SJed Brown   pcbddc->n_vertices    = nvc;
22350c7d97c5SJed Brown 
22360c7d97c5SJed Brown   if(pcbddc->n_constraints){
22370c7d97c5SJed Brown     /* allocate space for local constraints of BDDC */
22380c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr);
22390c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr);
22400c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr);
22410c7d97c5SJed Brown     k=0;
22420c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
22430c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
22440c7d97c5SJed Brown         pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i];
22450c7d97c5SJed Brown         k++;
22460c7d97c5SJed Brown       }
22470c7d97c5SJed Brown     }
22480c7d97c5SJed Brown //    printf("check constraints %d (should be %d)\n",k,pcbddc->n_constraints);
22490c7d97c5SJed Brown //    for(i=0;i<k;i++)
22500c7d97c5SJed Brown //      printf("%d ",pcbddc->sizes_of_constraint[i]);
22510c7d97c5SJed Brown //    printf("\n");
22520c7d97c5SJed Brown     k=0;
22530c7d97c5SJed Brown     for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i];
22540c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
22550c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
22560c7d97c5SJed Brown     for (i=1; i<pcbddc->n_constraints; i++) {
22570c7d97c5SJed Brown       pcbddc->indices_to_constraint[i]  = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
22580c7d97c5SJed Brown       pcbddc->quadrature_constraint[i]  = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
22590c7d97c5SJed Brown     }
22600c7d97c5SJed Brown     k=0;
22610c7d97c5SJed Brown     PetscScalar quad_value;
22620c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
22630c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
22640c7d97c5SJed Brown         quad_value=1.0/( (PetscScalar) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) );
22650c7d97c5SJed Brown         for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
22660c7d97c5SJed Brown           pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j];
22670c7d97c5SJed Brown           pcbddc->quadrature_constraint[k][j] = quad_value;
22680c7d97c5SJed Brown         }
22690c7d97c5SJed Brown         k++;
22700c7d97c5SJed Brown       }
22710c7d97c5SJed Brown     }
22720c7d97c5SJed Brown   }
22730c7d97c5SJed Brown   if(pcbddc->n_vertices){
22740c7d97c5SJed Brown     /* allocate space for local vertices of BDDC */
22750c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr);
22760c7d97c5SJed Brown     k=0;
22770c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
22780c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
22790c7d97c5SJed Brown         pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]];
22800c7d97c5SJed Brown         k++;
22810c7d97c5SJed Brown       }
22820c7d97c5SJed Brown     }
22830c7d97c5SJed Brown     // sort vertex set (by local ordering)
22840c7d97c5SJed Brown     ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr);
22850c7d97c5SJed Brown   }
22860c7d97c5SJed Brown 
22870c7d97c5SJed Brown   if(pcbddc->check_flag) {
22880c7d97c5SJed Brown     PetscViewer     viewer;
22890c7d97c5SJed Brown     PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);
22900c7d97c5SJed Brown     PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
22910c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
22920c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);
22930c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
22940c7d97c5SJed Brown //    PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");
22950c7d97c5SJed Brown //    PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
22960c7d97c5SJed Brown //    for(i=0;i<mat_graph->nvtxs;i++) {
22970c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);
22980c7d97c5SJed Brown //      for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
22990c7d97c5SJed Brown //        PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);
23000c7d97c5SJed Brown //      }
23010c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");
23020c7d97c5SJed Brown //    }
23030c7d97c5SJed Brown     // TODO: APPLY Local to Global Mapping from IS object?
23040c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);
23050c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
23060c7d97c5SJed Brown       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]]]);
23070c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
23080c7d97c5SJed Brown         PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->queue[j]);
23090c7d97c5SJed Brown       }
23100c7d97c5SJed Brown     }
23110c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");
23120c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);
23130c7d97c5SJed Brown     if( nfc )                PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);
23140c7d97c5SJed Brown     if( nec )                PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);
23150c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);
23160c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
23170c7d97c5SJed Brown                              PetscViewerASCIISynchronizedPrintf(viewer,"%d ",pcbddc->vertices[i]);
23180c7d97c5SJed Brown     }
23190c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"\n");
23200c7d97c5SJed Brown //    if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"Indices and quadrature constraints");
23210c7d97c5SJed Brown //    for(i=0;i<pcbddc->n_constraints;i++){
23220c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"\nConstraint number %d\n",i);
23230c7d97c5SJed Brown //      for(j=0;j<pcbddc->sizes_of_constraint[i];j++) {
23240c7d97c5SJed Brown //        PetscViewerASCIISynchronizedPrintf(viewer,"(%d, %f) ",pcbddc->indices_to_constraint[i][j],pcbddc->quadrature_constraint[i][j]);
23250c7d97c5SJed Brown //      }
23260c7d97c5SJed Brown //    }
23270c7d97c5SJed Brown //    if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"\n");
23280c7d97c5SJed Brown     PetscViewerFlush(viewer);
23290c7d97c5SJed Brown   }
23300c7d97c5SJed Brown 
23310c7d97c5SJed Brown   // Restore CSR structure into sequantial matrix and free memory space no longer needed
23320c7d97c5SJed Brown   ierr = MatRestoreRowIJ(mat_adj,0,PETSC_FALSE,PETSC_TRUE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
23330c7d97c5SJed Brown   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
23340c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
23350c7d97c5SJed Brown   ierr = PetscFree(distinct_values);CHKERRQ(ierr);
23360c7d97c5SJed Brown   // Free graph structure
23370c7d97c5SJed Brown   if(mat_graph->nvtxs){
23380c7d97c5SJed Brown     ierr = PetscFree(mat_graph->where);CHKERRQ(ierr);
23390c7d97c5SJed Brown     ierr = PetscFree(mat_graph->touched);CHKERRQ(ierr);
23400c7d97c5SJed Brown     ierr = PetscFree(mat_graph->which_dof);CHKERRQ(ierr);
23410c7d97c5SJed Brown     ierr = PetscFree(mat_graph->queue);CHKERRQ(ierr);
23420c7d97c5SJed Brown     ierr = PetscFree(mat_graph->cptr);CHKERRQ(ierr);
23430c7d97c5SJed Brown     ierr = PetscFree(mat_graph->count);CHKERRQ(ierr);
23440c7d97c5SJed Brown   }
23450c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
23460c7d97c5SJed Brown 
23470c7d97c5SJed Brown   PetscFunctionReturn(0);
23480c7d97c5SJed Brown 
23490c7d97c5SJed Brown }
23500c7d97c5SJed Brown 
23510c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
23520c7d97c5SJed Brown 
23530c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
23540c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
23550c7d97c5SJed Brown 
23560c7d97c5SJed Brown #undef __FUNCT__
23570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
2358*53cdbc3dSStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist, PetscInt *dist_vals)
23590c7d97c5SJed Brown {
23600c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
23610c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
23620c7d97c5SJed Brown   PetscInt *cptr;
23630c7d97c5SJed Brown   PetscBool *touched;
23640c7d97c5SJed Brown 
23650c7d97c5SJed Brown   PetscFunctionBegin;
23660c7d97c5SJed Brown 
23670c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
23680c7d97c5SJed Brown   xadj    = graph->xadj;
23690c7d97c5SJed Brown   adjncy  = graph->adjncy;
23700c7d97c5SJed Brown   where   = graph->where;
23710c7d97c5SJed Brown   touched = graph->touched;
23720c7d97c5SJed Brown   queue   = graph->queue;
23730c7d97c5SJed Brown   cptr    = graph->cptr;
23740c7d97c5SJed Brown 
23750c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
23760c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
23770c7d97c5SJed Brown 
23780c7d97c5SJed Brown   cum_queue=0;
23790c7d97c5SJed Brown   ncmps=0;
23800c7d97c5SJed Brown 
23810c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
23820c7d97c5SJed Brown     pid = dist_vals[n];
23830c7d97c5SJed Brown     nleft = 0;
23840c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
23850c7d97c5SJed Brown       if (where[i] == pid)
23860c7d97c5SJed Brown         nleft++;
23870c7d97c5SJed Brown     }
23880c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
23890c7d97c5SJed Brown       if (where[i] == pid)
23900c7d97c5SJed Brown         break;
23910c7d97c5SJed Brown     }
23920c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
23930c7d97c5SJed Brown     queue[cum_queue] = i;
23940c7d97c5SJed Brown     first = 0; last = 1;
23950c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
23960c7d97c5SJed Brown     ncmps_pid = 0;
23970c7d97c5SJed Brown     while (first != nleft) {
23980c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
23990c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
24000c7d97c5SJed Brown         ncmps_pid++;
24010c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
24020c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
24030c7d97c5SJed Brown             break;
24040c7d97c5SJed Brown         }
24050c7d97c5SJed Brown         queue[cum_queue+last] = i;
24060c7d97c5SJed Brown         last++;
24070c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
24080c7d97c5SJed Brown       }
24090c7d97c5SJed Brown       i = queue[cum_queue+first];
24100c7d97c5SJed Brown       first++;
24110c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
24120c7d97c5SJed Brown         k = adjncy[j];
24130c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
24140c7d97c5SJed Brown           queue[cum_queue+last] = k;
24150c7d97c5SJed Brown           last++;
24160c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
24170c7d97c5SJed Brown         }
24180c7d97c5SJed Brown       }
24190c7d97c5SJed Brown     }
24200c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
24210c7d97c5SJed Brown     ncmps_pid++;
24220c7d97c5SJed Brown     cum_queue=cptr[ncmps];
24230c7d97c5SJed Brown   }
24240c7d97c5SJed Brown   graph->ncmps = ncmps;
24250c7d97c5SJed Brown 
24260c7d97c5SJed Brown   PetscFunctionReturn(0);
24270c7d97c5SJed Brown }
24280c7d97c5SJed Brown 
2429