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