xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 0c7d97c552af63b52c0a7c542d03dbdd9c18957c)
1*0c7d97c5SJed Brown 
2*0c7d97c5SJed Brown #include "bddc.h"
3*0c7d97c5SJed Brown 
4*0c7d97c5SJed Brown /*
5*0c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
6*0c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
7*0c7d97c5SJed Brown */
8*0c7d97c5SJed Brown 
9*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
10*0c7d97c5SJed Brown #undef __FUNCT__
11*0c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
12*0c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
13*0c7d97c5SJed Brown {
14*0c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
15*0c7d97c5SJed Brown   PetscErrorCode ierr;
16*0c7d97c5SJed Brown 
17*0c7d97c5SJed Brown   PetscFunctionBegin;
18*0c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
19*0c7d97c5SJed Brown   /* Verbose debugging of main data structures */
20*0c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                            ,"none",pcbddc->check_flag      ,&pcbddc->check_flag      ,PETSC_NULL);CHKERRQ(ierr);
21*0c7d97c5SJed Brown   /* Some customization for default primal space */
22*0c7d97c5SJed 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);
23*0c7d97c5SJed 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);
24*0c7d97c5SJed 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);
25*0c7d97c5SJed 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);
26*0c7d97c5SJed Brown   /* Coarse solver context */
27*0c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
28*0c7d97c5SJed 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);
29*0c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
30*0c7d97c5SJed 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);
31*0c7d97c5SJed 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);
32*0c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
33*0c7d97c5SJed Brown   PetscFunctionReturn(0);
34*0c7d97c5SJed Brown }
35*0c7d97c5SJed Brown 
36*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
37*0c7d97c5SJed Brown EXTERN_C_BEGIN
38*0c7d97c5SJed Brown #undef __FUNCT__
39*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
40*0c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
41*0c7d97c5SJed Brown {
42*0c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
43*0c7d97c5SJed Brown 
44*0c7d97c5SJed Brown   PetscFunctionBegin;
45*0c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
46*0c7d97c5SJed Brown   PetscFunctionReturn(0);
47*0c7d97c5SJed Brown }
48*0c7d97c5SJed Brown EXTERN_C_END
49*0c7d97c5SJed Brown 
50*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
51*0c7d97c5SJed Brown #undef __FUNCT__
52*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
53*0c7d97c5SJed Brown /*
54*0c7d97c5SJed Brown SZ INSERT COMMENT HERE
55*0c7d97c5SJed Brown */
56*0c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
57*0c7d97c5SJed Brown {
58*0c7d97c5SJed Brown   PetscErrorCode ierr;
59*0c7d97c5SJed Brown 
60*0c7d97c5SJed Brown   PetscFunctionBegin;
61*0c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
62*0c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
63*0c7d97c5SJed Brown   PetscFunctionReturn(0);
64*0c7d97c5SJed Brown }
65*0c7d97c5SJed Brown 
66*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
67*0c7d97c5SJed Brown EXTERN_C_BEGIN
68*0c7d97c5SJed Brown #undef __FUNCT__
69*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
70*0c7d97c5SJed Brown PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,Vec input_vec)
71*0c7d97c5SJed Brown {
72*0c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
73*0c7d97c5SJed Brown 
74*0c7d97c5SJed Brown   PetscFunctionBegin;
75*0c7d97c5SJed Brown   VecDuplicate(input_vec,&pcbddc->Vec_Neumann);
76*0c7d97c5SJed Brown   VecCopy(input_vec,pcbddc->Vec_Neumann);
77*0c7d97c5SJed Brown   PetscFunctionReturn(0);
78*0c7d97c5SJed Brown }
79*0c7d97c5SJed Brown EXTERN_C_END
80*0c7d97c5SJed Brown 
81*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
82*0c7d97c5SJed Brown #undef __FUNCT__
83*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
84*0c7d97c5SJed Brown /*
85*0c7d97c5SJed Brown SZ INSERT COMMENT HERE
86*0c7d97c5SJed Brown */
87*0c7d97c5SJed Brown PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,Vec input_vec)
88*0c7d97c5SJed Brown {
89*0c7d97c5SJed Brown   PetscErrorCode ierr;
90*0c7d97c5SJed Brown 
91*0c7d97c5SJed Brown   PetscFunctionBegin;
92*0c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
93*0c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,Vec),(pc,input_vec));CHKERRQ(ierr);
94*0c7d97c5SJed Brown   PetscFunctionReturn(0);
95*0c7d97c5SJed Brown }
96*0c7d97c5SJed Brown 
97*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
98*0c7d97c5SJed Brown /*
99*0c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
100*0c7d97c5SJed Brown                     by setting data structures and options.
101*0c7d97c5SJed Brown 
102*0c7d97c5SJed Brown    Input Parameter:
103*0c7d97c5SJed Brown .  pc - the preconditioner context
104*0c7d97c5SJed Brown 
105*0c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
106*0c7d97c5SJed Brown 
107*0c7d97c5SJed Brown    Notes:
108*0c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
109*0c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
110*0c7d97c5SJed Brown */
111*0c7d97c5SJed Brown #undef __FUNCT__
112*0c7d97c5SJed Brown #define __FUNCT__ "PCSetUp_BDDC"
113*0c7d97c5SJed Brown static PetscErrorCode PCSetUp_BDDC(PC pc)
114*0c7d97c5SJed Brown {
115*0c7d97c5SJed Brown   PetscErrorCode ierr;
116*0c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
117*0c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
118*0c7d97c5SJed Brown 
119*0c7d97c5SJed Brown   PetscFunctionBegin;
120*0c7d97c5SJed Brown   if (!pc->setupcalled) {
121*0c7d97c5SJed Brown 
122*0c7d97c5SJed Brown     /* For BDDC we need to define a local "Neumann" to that defined in PCISSetup
123*0c7d97c5SJed Brown        So, we set to pcnone the Neumann problem of pcid in order to avoid unneeded computation
124*0c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
125*0c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
126*0c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
127*0c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
128*0c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
129*0c7d97c5SJed Brown     /* Destroy some PC_IS data which is not needed by BDDC */
130*0c7d97c5SJed Brown     //if (pcis->ksp_D)  {ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);}
131*0c7d97c5SJed Brown     //if (pcis->ksp_N)  {ierr = KSPDestroy(&pcis->ksp_N);CHKERRQ(ierr);}
132*0c7d97c5SJed Brown     //if (pcis->vec2_B) {ierr = VecDestroy(&pcis->vec2_B);CHKERRQ(ierr);}
133*0c7d97c5SJed Brown     //if (pcis->vec3_B) {ierr = VecDestroy(&pcis->vec3_B);CHKERRQ(ierr);}
134*0c7d97c5SJed Brown     //pcis->ksp_D  = 0;
135*0c7d97c5SJed Brown     //pcis->ksp_N  = 0;
136*0c7d97c5SJed Brown     //pcis->vec2_B = 0;
137*0c7d97c5SJed Brown     //pcis->vec3_B = 0;
138*0c7d97c5SJed Brown 
139*0c7d97c5SJed Brown     //TODO MOVE CODE FRAGMENT
140*0c7d97c5SJed Brown     PetscInt im_active=0;
141*0c7d97c5SJed Brown     if(pcis->n) im_active = 1;
142*0c7d97c5SJed Brown     MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);
143*0c7d97c5SJed Brown     //printf("Calling PCBDDC MANAGE with active procs %d (im_active = %d)\n",pcbddc->active_procs,im_active);
144*0c7d97c5SJed Brown     /* Set up grid quantities for BDDC */
145*0c7d97c5SJed Brown     //TODO only active procs must call this -> remove synchronized print inside (the only point of sync)
146*0c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
147*0c7d97c5SJed Brown 
148*0c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
149*0c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
150*0c7d97c5SJed Brown 
151*0c7d97c5SJed Brown     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE; //processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo
152*0c7d97c5SJed Brown     /* We no more need this matrix */
153*0c7d97c5SJed Brown     //if (pcis->A_BB)  {ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);}
154*0c7d97c5SJed Brown     //pcis->A_BB   = 0;
155*0c7d97c5SJed Brown 
156*0c7d97c5SJed Brown     //printf("Using coarse problem type %d\n",pcbddc->coarse_problem_type);
157*0c7d97c5SJed Brown     //printf("Using coarse communications type %d\n",pcbddc->coarse_communications_type);
158*0c7d97c5SJed Brown     //printf("Using coarsening ratio %d\n",pcbddc->coarsening_ratio);
159*0c7d97c5SJed Brown   }
160*0c7d97c5SJed Brown 
161*0c7d97c5SJed Brown   PetscFunctionReturn(0);
162*0c7d97c5SJed Brown }
163*0c7d97c5SJed Brown 
164*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
165*0c7d97c5SJed Brown /*
166*0c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
167*0c7d97c5SJed Brown 
168*0c7d97c5SJed Brown    Input Parameters:
169*0c7d97c5SJed Brown .  pc - the preconditioner context
170*0c7d97c5SJed Brown .  r - input vector (global)
171*0c7d97c5SJed Brown 
172*0c7d97c5SJed Brown    Output Parameter:
173*0c7d97c5SJed Brown .  z - output vector (global)
174*0c7d97c5SJed Brown 
175*0c7d97c5SJed Brown    Application Interface Routine: PCApply()
176*0c7d97c5SJed Brown  */
177*0c7d97c5SJed Brown #undef __FUNCT__
178*0c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
179*0c7d97c5SJed Brown static PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
180*0c7d97c5SJed Brown {
181*0c7d97c5SJed Brown   PC_IS          *pcis = (PC_IS*)(pc->data);
182*0c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
183*0c7d97c5SJed Brown   PetscErrorCode ierr;
184*0c7d97c5SJed Brown   PetscScalar    one = 1.0;
185*0c7d97c5SJed Brown   PetscScalar    m_one = -1.0;
186*0c7d97c5SJed Brown 
187*0c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
188*0c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
189*0c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
190*0c7d97c5SJed Brown 
191*0c7d97c5SJed Brown   PetscFunctionBegin;
192*0c7d97c5SJed Brown   /* First Dirichlet solve */
193*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
194*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195*0c7d97c5SJed Brown   ierr = PCApply(pcbddc->pc_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
196*0c7d97c5SJed Brown   /*
197*0c7d97c5SJed Brown     Assembling right hand side for BDDC operator
198*0c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
199*0c7d97c5SJed Brown     - the interface part of the global vector z
200*0c7d97c5SJed Brown   */
201*0c7d97c5SJed Brown   //ierr = VecScatterBegin(pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
202*0c7d97c5SJed Brown   //ierr = VecScatterEnd  (pcis->global_to_B,r,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
203*0c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
204*0c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
205*0c7d97c5SJed Brown   //ierr = MatMultAdd(pcis->A_BI,pcis->vec2_D,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
206*0c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
207*0c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
208*0c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
209*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
211*0c7d97c5SJed Brown 
212*0c7d97c5SJed Brown   /*
213*0c7d97c5SJed Brown     Apply interface preconditioner
214*0c7d97c5SJed Brown     Results are stored in:
215*0c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
216*0c7d97c5SJed Brown     -  the interface part of the global vector z
217*0c7d97c5SJed Brown   */
218*0c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z); CHKERRQ(ierr);
219*0c7d97c5SJed Brown 
220*0c7d97c5SJed Brown   /* Second Dirichlet solves and assembling of output */
221*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
222*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
223*0c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
224*0c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
225*0c7d97c5SJed Brown   ierr = PCApply(pcbddc->pc_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
226*0c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
227*0c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
228*0c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
229*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
230*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
231*0c7d97c5SJed Brown 
232*0c7d97c5SJed Brown   PetscFunctionReturn(0);
233*0c7d97c5SJed Brown 
234*0c7d97c5SJed Brown }
235*0c7d97c5SJed Brown 
236*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
237*0c7d97c5SJed Brown /*
238*0c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
239*0c7d97c5SJed Brown 
240*0c7d97c5SJed Brown */
241*0c7d97c5SJed Brown #undef __FUNCT__
242*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
243*0c7d97c5SJed Brown PetscErrorCode  PCBDDCApplyInterfacePreconditioner (PC pc, Vec z)
244*0c7d97c5SJed Brown {
245*0c7d97c5SJed Brown   PetscErrorCode ierr;
246*0c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
247*0c7d97c5SJed Brown   PC_IS*         pcis =   (PC_IS*)  (pc->data);
248*0c7d97c5SJed Brown   PetscScalar    zero = 0.0;
249*0c7d97c5SJed Brown 
250*0c7d97c5SJed Brown   PetscFunctionBegin;
251*0c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
252*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
253*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
254*0c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
255*0c7d97c5SJed Brown 
256*0c7d97c5SJed Brown   /* Application of PHI^T  */
257*0c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
258*0c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
259*0c7d97c5SJed Brown 
260*0c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
261*0c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
262*0c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
263*0c7d97c5SJed Brown 
264*0c7d97c5SJed Brown   /* Local solution on R nodes */
265*0c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
266*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
267*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
268*0c7d97c5SJed Brown   if(pcbddc->prec_type) {
269*0c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
270*0c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
271*0c7d97c5SJed Brown   }
272*0c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
273*0c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
274*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
275*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
276*0c7d97c5SJed Brown   if(pcbddc->prec_type) {
277*0c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
278*0c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
279*0c7d97c5SJed Brown   }
280*0c7d97c5SJed Brown 
281*0c7d97c5SJed Brown   /* Coarse solution */
282*0c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
283*0c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = PCApply(pcbddc->coarse_pc,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
284*0c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
285*0c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
286*0c7d97c5SJed Brown 
287*0c7d97c5SJed Brown   /* Sum contributions from two levels */
288*0c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
289*0c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
290*0c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
291*0c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
292*0c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
293*0c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
294*0c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
295*0c7d97c5SJed Brown 
296*0c7d97c5SJed Brown   PetscFunctionReturn(0);
297*0c7d97c5SJed Brown }
298*0c7d97c5SJed Brown 
299*0c7d97c5SJed Brown 
300*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
301*0c7d97c5SJed Brown /*
302*0c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
303*0c7d97c5SJed Brown 
304*0c7d97c5SJed Brown */
305*0c7d97c5SJed Brown #undef __FUNCT__
306*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
307*0c7d97c5SJed Brown PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
308*0c7d97c5SJed Brown 
309*0c7d97c5SJed Brown {
310*0c7d97c5SJed Brown   PetscErrorCode ierr;
311*0c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
312*0c7d97c5SJed Brown 
313*0c7d97c5SJed Brown   PetscFunctionBegin;
314*0c7d97c5SJed Brown 
315*0c7d97c5SJed Brown   ierr = PCApply(pcbddc->pc_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
316*0c7d97c5SJed Brown   if(pcbddc->n_constraints) {
317*0c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
318*0c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
319*0c7d97c5SJed Brown   }
320*0c7d97c5SJed Brown 
321*0c7d97c5SJed Brown   PetscFunctionReturn(0);
322*0c7d97c5SJed Brown 
323*0c7d97c5SJed Brown }
324*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
325*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
326*0c7d97c5SJed Brown /*
327*0c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
328*0c7d97c5SJed Brown 
329*0c7d97c5SJed Brown */
330*0c7d97c5SJed Brown #undef __FUNCT__
331*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
332*0c7d97c5SJed Brown PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
333*0c7d97c5SJed Brown {
334*0c7d97c5SJed Brown   PetscErrorCode ierr;
335*0c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
336*0c7d97c5SJed Brown 
337*0c7d97c5SJed Brown   PetscFunctionBegin;
338*0c7d97c5SJed Brown 
339*0c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
340*0c7d97c5SJed Brown     case SCATTERS_BDDC:
341*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
342*0c7d97c5SJed Brown       break;
343*0c7d97c5SJed Brown     case GATHERS_BDDC:
344*0c7d97c5SJed Brown       break;
345*0c7d97c5SJed Brown   }
346*0c7d97c5SJed Brown   PetscFunctionReturn(0);
347*0c7d97c5SJed Brown 
348*0c7d97c5SJed Brown }
349*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
350*0c7d97c5SJed Brown /*
351*0c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
352*0c7d97c5SJed Brown 
353*0c7d97c5SJed Brown */
354*0c7d97c5SJed Brown #undef __FUNCT__
355*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
356*0c7d97c5SJed Brown PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
357*0c7d97c5SJed Brown {
358*0c7d97c5SJed Brown   PetscErrorCode ierr;
359*0c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
360*0c7d97c5SJed Brown   PetscScalar*   array_to;
361*0c7d97c5SJed Brown   PetscScalar*   array_from;
362*0c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
363*0c7d97c5SJed Brown   PetscInt i;
364*0c7d97c5SJed Brown 
365*0c7d97c5SJed Brown   PetscFunctionBegin;
366*0c7d97c5SJed Brown 
367*0c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
368*0c7d97c5SJed Brown     case SCATTERS_BDDC:
369*0c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
370*0c7d97c5SJed Brown       break;
371*0c7d97c5SJed Brown     case GATHERS_BDDC:
372*0c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
373*0c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
374*0c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
375*0c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
376*0c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
377*0c7d97c5SJed 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);
378*0c7d97c5SJed Brown             if(vec_to) {
379*0c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
380*0c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
381*0c7d97c5SJed Brown             }
382*0c7d97c5SJed Brown           } else {
383*0c7d97c5SJed Brown             if(vec_from)
384*0c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
385*0c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
386*0c7d97c5SJed 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);
387*0c7d97c5SJed Brown           }
388*0c7d97c5SJed Brown           break;
389*0c7d97c5SJed Brown         case REPLICATED_BDDC:
390*0c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
391*0c7d97c5SJed 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);
392*0c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
393*0c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
394*0c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
395*0c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
396*0c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
397*0c7d97c5SJed Brown           }
398*0c7d97c5SJed Brown           break;
399*0c7d97c5SJed Brown       }
400*0c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
401*0c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
402*0c7d97c5SJed Brown       break;
403*0c7d97c5SJed Brown   }
404*0c7d97c5SJed Brown   PetscFunctionReturn(0);
405*0c7d97c5SJed Brown 
406*0c7d97c5SJed Brown }
407*0c7d97c5SJed Brown 
408*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
409*0c7d97c5SJed Brown /*
410*0c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
411*0c7d97c5SJed Brown    that was created with PCCreate_BDDC().
412*0c7d97c5SJed Brown 
413*0c7d97c5SJed Brown    Input Parameter:
414*0c7d97c5SJed Brown .  pc - the preconditioner context
415*0c7d97c5SJed Brown 
416*0c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
417*0c7d97c5SJed Brown */
418*0c7d97c5SJed Brown #undef __FUNCT__
419*0c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
420*0c7d97c5SJed Brown static PetscErrorCode PCDestroy_BDDC(PC pc)
421*0c7d97c5SJed Brown {
422*0c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
423*0c7d97c5SJed Brown   PetscErrorCode ierr;
424*0c7d97c5SJed Brown 
425*0c7d97c5SJed Brown   PetscFunctionBegin;
426*0c7d97c5SJed Brown   /* free data created by PCIS */
427*0c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
428*0c7d97c5SJed Brown   /* free BDDC data  */
429*0c7d97c5SJed Brown   if (pcbddc->coarse_vec)         {ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);}
430*0c7d97c5SJed Brown   if (pcbddc->coarse_rhs)         {ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);}
431*0c7d97c5SJed Brown   if (pcbddc->coarse_pc)          {ierr = PCDestroy(&pcbddc->coarse_pc);CHKERRQ(ierr);}
432*0c7d97c5SJed Brown   if (pcbddc->coarse_mat)         {ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);}
433*0c7d97c5SJed Brown   if (pcbddc->coarse_phi_B)       {ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);}
434*0c7d97c5SJed Brown   if (pcbddc->coarse_phi_D)       {ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);}
435*0c7d97c5SJed Brown   if (pcbddc->vec1_P)             {ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);}
436*0c7d97c5SJed Brown   if (pcbddc->vec1_C)             {ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);}
437*0c7d97c5SJed Brown   if (pcbddc->local_auxmat1)      {ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);}
438*0c7d97c5SJed Brown   if (pcbddc->local_auxmat2)      {ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);}
439*0c7d97c5SJed Brown   if (pcbddc->vec1_R)             {ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);}
440*0c7d97c5SJed Brown   if (pcbddc->vec2_R)             {ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);}
441*0c7d97c5SJed Brown   if (pcbddc->vec4_D)             {ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);}
442*0c7d97c5SJed Brown   if (pcbddc->R_to_B)             {ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);}
443*0c7d97c5SJed Brown   if (pcbddc->R_to_D)             {ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);}
444*0c7d97c5SJed Brown   if (pcbddc->coarse_loc_to_glob) {ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);}
445*0c7d97c5SJed Brown   if (pcbddc->pc_D)               {ierr = PCDestroy(&pcbddc->pc_D);CHKERRQ(ierr);}
446*0c7d97c5SJed Brown   if (pcbddc->pc_R)               {ierr = PCDestroy(&pcbddc->pc_R);CHKERRQ(ierr);}
447*0c7d97c5SJed Brown   if (pcbddc->Vec_Neumann)        {ierr = VecDestroy(&pcbddc->Vec_Neumann);CHKERRQ(ierr);}
448*0c7d97c5SJed Brown   if (pcbddc->vertices)           {ierr = PetscFree(pcbddc->vertices);CHKERRQ(ierr);}
449*0c7d97c5SJed Brown   if (pcbddc->local_primal_indices)              { ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);}
450*0c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_indices)   { ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);}
451*0c7d97c5SJed Brown   //if (pcbddc->replicated_local_primal_values)    { ierr = PetscFree(pcbddc->replicated_local_primal_values);CHKERRQ(ierr);}
452*0c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
453*0c7d97c5SJed Brown   if (pcbddc->local_primal_displacements)        { ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);}
454*0c7d97c5SJed Brown   if (pcbddc->local_primal_sizes)                { ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);}
455*0c7d97c5SJed Brown   if (pcbddc->n_constraints) {
456*0c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
457*0c7d97c5SJed Brown     ierr = PetscFree(pcbddc->indices_to_constraint);CHKERRQ(ierr);
458*0c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
459*0c7d97c5SJed Brown     ierr = PetscFree(pcbddc->quadrature_constraint);CHKERRQ(ierr);
460*0c7d97c5SJed Brown     ierr = PetscFree(pcbddc->sizes_of_constraint);CHKERRQ(ierr);
461*0c7d97c5SJed Brown   }
462*0c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
463*0c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
464*0c7d97c5SJed Brown   PetscFunctionReturn(0);
465*0c7d97c5SJed Brown }
466*0c7d97c5SJed Brown 
467*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
468*0c7d97c5SJed Brown /*MC
469*0c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
470*0c7d97c5SJed Brown 
471*0c7d97c5SJed Brown    Options Database Keys:
472*0c7d97c5SJed Brown .    -pc_is_damp_fixed <fact> -
473*0c7d97c5SJed Brown .    -pc_is_remove_nullspace_fixed -
474*0c7d97c5SJed Brown .    -pc_is_set_damping_factor_floating <fact> -
475*0c7d97c5SJed Brown .    -pc_is_not_damp_floating -
476*0c7d97c5SJed Brown 
477*0c7d97c5SJed Brown    Level: intermediate
478*0c7d97c5SJed Brown 
479*0c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
480*0c7d97c5SJed Brown 
481*0c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
482*0c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
483*0c7d97c5SJed Brown           on the subdomains).
484*0c7d97c5SJed Brown 
485*0c7d97c5SJed Brown           Options for the coarse grid preconditioner can be set with -pc_bddc_coarse_pc_xxx
486*0c7d97c5SJed Brown           Options for the Dirichlet subproblem can be set with -pc_bddc_localD_xxx
487*0c7d97c5SJed Brown           Options for the Neumann subproblem can be set with -pc_bddc_localN_xxx
488*0c7d97c5SJed Brown 
489*0c7d97c5SJed Brown    Contributed by Stefano Zampini
490*0c7d97c5SJed Brown 
491*0c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
492*0c7d97c5SJed Brown M*/
493*0c7d97c5SJed Brown EXTERN_C_BEGIN
494*0c7d97c5SJed Brown #undef __FUNCT__
495*0c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
496*0c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
497*0c7d97c5SJed Brown {
498*0c7d97c5SJed Brown   PetscErrorCode ierr;
499*0c7d97c5SJed Brown   PC_BDDC          *pcbddc;
500*0c7d97c5SJed Brown 
501*0c7d97c5SJed Brown   PetscFunctionBegin;
502*0c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
503*0c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
504*0c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
505*0c7d97c5SJed Brown   /* create PCIS data structure */
506*0c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
507*0c7d97c5SJed Brown   /* BDDC specific */
508*0c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
509*0c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
510*0c7d97c5SJed Brown   pcbddc->coarse_pc                  = 0;
511*0c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
512*0c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
513*0c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
514*0c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
515*0c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
516*0c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
517*0c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
518*0c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
519*0c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
520*0c7d97c5SJed Brown   pcbddc->pc_D                       = 0;
521*0c7d97c5SJed Brown   pcbddc->pc_R                       = 0;
522*0c7d97c5SJed Brown   pcbddc->n_constraints              = 0;
523*0c7d97c5SJed Brown   pcbddc->n_vertices                 = 0;
524*0c7d97c5SJed Brown   pcbddc->vertices                   = 0;
525*0c7d97c5SJed Brown   pcbddc->indices_to_constraint      = 0;
526*0c7d97c5SJed Brown   pcbddc->quadrature_constraint      = 0;
527*0c7d97c5SJed Brown   pcbddc->sizes_of_constraint        = 0;
528*0c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
529*0c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
530*0c7d97c5SJed Brown   pcbddc->Vec_Neumann                = 0;
531*0c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
532*0c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
533*0c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
534*0c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
535*0c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
536*0c7d97c5SJed Brown   pcbddc->check_flag                 = PETSC_FALSE;
537*0c7d97c5SJed Brown   pcbddc->vertices_flag              = PETSC_FALSE;
538*0c7d97c5SJed Brown   pcbddc->constraints_flag           = PETSC_FALSE;
539*0c7d97c5SJed Brown   pcbddc->faces_flag                 = PETSC_FALSE;
540*0c7d97c5SJed Brown   pcbddc->edges_flag                 = PETSC_FALSE;
541*0c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
542*0c7d97c5SJed Brown   /* function pointers */
543*0c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
544*0c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
545*0c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
546*0c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
547*0c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
548*0c7d97c5SJed Brown   pc->ops->view                = 0;
549*0c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
550*0c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
551*0c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
552*0c7d97c5SJed Brown   /* composing function */
553*0c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
554*0c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
555*0c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
556*0c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
557*0c7d97c5SJed Brown   PetscFunctionReturn(0);
558*0c7d97c5SJed Brown }
559*0c7d97c5SJed Brown EXTERN_C_END
560*0c7d97c5SJed Brown 
561*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
562*0c7d97c5SJed Brown /*
563*0c7d97c5SJed Brown    PCBDDCCoarseSetUp -
564*0c7d97c5SJed Brown */
565*0c7d97c5SJed Brown #undef __FUNCT__
566*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
567*0c7d97c5SJed Brown PetscErrorCode PCBDDCCoarseSetUp(PC pc)
568*0c7d97c5SJed Brown {
569*0c7d97c5SJed Brown   PetscErrorCode  ierr;
570*0c7d97c5SJed Brown 
571*0c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
572*0c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
573*0c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
574*0c7d97c5SJed Brown   IS                is_R_local;
575*0c7d97c5SJed Brown   IS                is_V_local;
576*0c7d97c5SJed Brown   IS                is_C_local;
577*0c7d97c5SJed Brown   IS                is_aux1;
578*0c7d97c5SJed Brown   IS                is_aux2;
579*0c7d97c5SJed Brown   PetscViewer       viewer;
580*0c7d97c5SJed Brown   PetscBool         check_flag=pcbddc->check_flag;
581*0c7d97c5SJed Brown   const VecType     impVecType;
582*0c7d97c5SJed Brown   const MatType     impMatType;
583*0c7d97c5SJed Brown   PetscInt          n_R=0;
584*0c7d97c5SJed Brown   PetscInt          n_D=0;
585*0c7d97c5SJed Brown   PetscInt          n_B=0;
586*0c7d97c5SJed Brown   PetscMPIInt       totprocs;
587*0c7d97c5SJed Brown   PetscScalar       zero=0.0;
588*0c7d97c5SJed Brown   PetscScalar       one=1.0;
589*0c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
590*0c7d97c5SJed Brown   PetscScalar*      array;
591*0c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
592*0c7d97c5SJed Brown   PetscInt          *idx_R_local;
593*0c7d97c5SJed Brown   PetscInt          *idx_V_B;
594*0c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
595*0c7d97c5SJed Brown   PetscScalar       *constraints_errors;
596*0c7d97c5SJed Brown   /* auxiliary indices */
597*0c7d97c5SJed Brown   PetscInt s,i,j,k;
598*0c7d97c5SJed Brown 
599*0c7d97c5SJed Brown   PetscFunctionBegin;
600*0c7d97c5SJed Brown //  if ( !pcbddc->n_vertices && !pcbddc->n_constraints ) {
601*0c7d97c5SJed Brown //    SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"BDDC preconditioner needs vertices and/or constraints!");
602*0c7d97c5SJed Brown //  }
603*0c7d97c5SJed Brown   if(pcbddc->check_flag) {
604*0c7d97c5SJed Brown     ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr);
605*0c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
606*0c7d97c5SJed Brown   }
607*0c7d97c5SJed Brown 
608*0c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
609*0c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
610*0c7d97c5SJed Brown   /* Set local primal size */
611*0c7d97c5SJed Brown   pcbddc->local_primal_size = pcbddc->n_vertices + pcbddc->n_constraints;
612*0c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
613*0c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
614*0c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
615*0c7d97c5SJed Brown   for (i=0;i<pcbddc->n_vertices;i++) { array[ pcbddc->vertices[i] ] = zero; }
616*0c7d97c5SJed Brown   ierr = PetscMalloc(( pcis->n - pcbddc->n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
617*0c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
618*0c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
619*0c7d97c5SJed Brown   if(check_flag) {
620*0c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
621*0c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
622*0c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
623*0c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
624*0c7d97c5SJed 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);
625*0c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
626*0c7d97c5SJed Brown   }
627*0c7d97c5SJed Brown   /* Allocate needed vectors */
628*0c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
629*0c7d97c5SJed Brown //  ierr = MatGetType(matis->A,&impMatType);CHKERRQ(ierr);
630*0c7d97c5SJed Brown   //ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
631*0c7d97c5SJed Brown   impMatType = MATSEQDENSE;
632*0c7d97c5SJed Brown   impVecType = VECSEQ;
633*0c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
634*0c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
635*0c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
636*0c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
637*0c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
638*0c7d97c5SJed Brown   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);
639*0c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
640*0c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
641*0c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
642*0c7d97c5SJed Brown 
643*0c7d97c5SJed Brown   /* Creating some index sets needed  */
644*0c7d97c5SJed Brown   /* For submatrices */
645*0c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
646*0c7d97c5SJed Brown   if(pcbddc->n_vertices)    { ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->n_vertices,pcbddc->vertices,PETSC_COPY_VALUES,&is_V_local);CHKERRQ(ierr); }
647*0c7d97c5SJed Brown   if(pcbddc->n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,pcbddc->n_vertices,1,&is_C_local);CHKERRQ(ierr); }
648*0c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
649*0c7d97c5SJed Brown   {
650*0c7d97c5SJed Brown     PetscInt   *aux_array1;
651*0c7d97c5SJed Brown     PetscInt   *aux_array2;
652*0c7d97c5SJed Brown     PetscScalar      value;
653*0c7d97c5SJed Brown 
654*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
655*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcis->n_B-pcbddc->n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
656*0c7d97c5SJed Brown 
657*0c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);
658*0c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
659*0c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
660*0c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
661*0c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
662*0c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
663*0c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
664*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
665*0c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
666*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
667*0c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
668*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
669*0c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
670*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
671*0c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
672*0c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
673*0c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
674*0c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
675*0c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
676*0c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
677*0c7d97c5SJed Brown 
678*0c7d97c5SJed Brown     if(pcbddc->prec_type || check_flag ) {
679*0c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
680*0c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
681*0c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
682*0c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
683*0c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
684*0c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
685*0c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
686*0c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
687*0c7d97c5SJed Brown     }
688*0c7d97c5SJed Brown 
689*0c7d97c5SJed Brown     /* Check scatters */
690*0c7d97c5SJed Brown     if(check_flag) {
691*0c7d97c5SJed Brown 
692*0c7d97c5SJed Brown       Vec            vec_aux;
693*0c7d97c5SJed Brown 
694*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
695*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
696*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
697*0c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
698*0c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);
699*0c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);
700*0c7d97c5SJed Brown       ierr = VecCopy(pcbddc->vec1_R,vec_aux);
701*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
702*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
703*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
704*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
705*0c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);
706*0c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
707*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
708*0c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
709*0c7d97c5SJed Brown 
710*0c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
711*0c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);
712*0c7d97c5SJed Brown       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);
713*0c7d97c5SJed Brown       ierr = VecCopy(pcis->vec1_B,vec_aux);
714*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
715*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
716*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
717*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
718*0c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);
719*0c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
720*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
721*0c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
722*0c7d97c5SJed Brown 
723*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
724*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
725*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
726*0c7d97c5SJed Brown 
727*0c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
728*0c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);
729*0c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);
730*0c7d97c5SJed Brown       ierr = VecCopy(pcbddc->vec1_R,vec_aux);
731*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);
732*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);
733*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
734*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);
735*0c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);
736*0c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
737*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
738*0c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
739*0c7d97c5SJed Brown 
740*0c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
741*0c7d97c5SJed Brown       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);
742*0c7d97c5SJed Brown       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);
743*0c7d97c5SJed Brown       ierr = VecCopy(pcis->vec1_D,vec_aux);
744*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
745*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);
746*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
747*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);
748*0c7d97c5SJed Brown       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);
749*0c7d97c5SJed Brown       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);
750*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
751*0c7d97c5SJed Brown       ierr = VecDestroy(&vec_aux);
752*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
753*0c7d97c5SJed Brown 
754*0c7d97c5SJed Brown     }
755*0c7d97c5SJed Brown   }
756*0c7d97c5SJed Brown 
757*0c7d97c5SJed Brown   /* vertices in boundary numbering */
758*0c7d97c5SJed Brown   if(pcbddc->n_vertices) {
759*0c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_N,m_one);
760*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
761*0c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) { array[ pcbddc->vertices[i] ] = i; }
762*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
763*0c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
764*0c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);
765*0c7d97c5SJed Brown     ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
766*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
767*0c7d97c5SJed Brown     //printf("vertices in boundary numbering\n");
768*0c7d97c5SJed Brown     for (i=0; i<pcbddc->n_vertices; i++) {
769*0c7d97c5SJed Brown       s=0;
770*0c7d97c5SJed Brown       while (array[s] != i ) {s++;}
771*0c7d97c5SJed Brown       idx_V_B[i]=s;
772*0c7d97c5SJed Brown       //printf("idx_V_B[%d]=%d\n",i,s);
773*0c7d97c5SJed Brown     }
774*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
775*0c7d97c5SJed Brown   }
776*0c7d97c5SJed Brown 
777*0c7d97c5SJed Brown 
778*0c7d97c5SJed Brown   /* Assign global numbering to coarse dofs */
779*0c7d97c5SJed Brown   // TODO move this block before calling SetupCoarseEnvironment
780*0c7d97c5SJed Brown   {
781*0c7d97c5SJed Brown     PetscScalar    coarsesum;
782*0c7d97c5SJed Brown     PetscMPIInt    *auxlocal_primal;
783*0c7d97c5SJed Brown     PetscMPIInt    *auxglobal_primal;
784*0c7d97c5SJed Brown     PetscMPIInt    *all_auxglobal_primal;
785*0c7d97c5SJed Brown     PetscMPIInt    *all_auxglobal_primal_type;  /* dummy */
786*0c7d97c5SJed Brown 
787*0c7d97c5SJed Brown     ierr = MPI_Comm_size(((PetscObject)pc)->comm,&totprocs);CHKERRQ(ierr);
788*0c7d97c5SJed Brown     /* Construct needed data structures for message passing */
789*0c7d97c5SJed Brown     ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
790*0c7d97c5SJed Brown     ierr = PetscMalloc(          totprocs*sizeof(PetscMPIInt),          &pcbddc->local_primal_sizes);CHKERRQ(ierr);
791*0c7d97c5SJed Brown     ierr = PetscMalloc(          totprocs*sizeof(PetscMPIInt),  &pcbddc->local_primal_displacements);CHKERRQ(ierr);
792*0c7d97c5SJed Brown     /* Gather local_primal_size information to all processes  */
793*0c7d97c5SJed Brown     ierr = MPI_Allgather(&pcbddc->local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT, ((PetscObject)pc)->comm );CHKERRQ(ierr);
794*0c7d97c5SJed Brown     pcbddc->replicated_primal_size = 0;
795*0c7d97c5SJed Brown     for (i=0; i<totprocs; i++) {
796*0c7d97c5SJed Brown       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
797*0c7d97c5SJed Brown       pcbddc->replicated_primal_size  += pcbddc->local_primal_sizes[i];
798*0c7d97c5SJed Brown     }
799*0c7d97c5SJed Brown     /* allocate some auxiliary space */
800*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->local_primal_size)*sizeof(PetscMPIInt),          &auxlocal_primal);CHKERRQ(ierr);
801*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->local_primal_size)*sizeof(PetscMPIInt),         &auxglobal_primal);CHKERRQ(ierr);
802*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->replicated_primal_size)*sizeof(PetscMPIInt),     &all_auxglobal_primal);CHKERRQ(ierr);
803*0c7d97c5SJed Brown     ierr = PetscMalloc( (pcbddc->replicated_primal_size)*sizeof(PetscMPIInt),&all_auxglobal_primal_type);CHKERRQ(ierr);
804*0c7d97c5SJed Brown 
805*0c7d97c5SJed 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)
806*0c7d97c5SJed Brown        This code fragment assumes that the number of local constraints per connected component
807*0c7d97c5SJed Brown        is not greater than the number of nodes on the connected component (for each dof)
808*0c7d97c5SJed Brown        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
809*0c7d97c5SJed Brown     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) */
810*0c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_N,zero);
811*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
812*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
813*0c7d97c5SJed Brown       array[ pcbddc->vertices[i] ] = one;
814*0c7d97c5SJed Brown       auxlocal_primal[i] = pcbddc->vertices[i];
815*0c7d97c5SJed Brown     }
816*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
817*0c7d97c5SJed Brown       for (s=0; s<pcbddc->sizes_of_constraint[i]; s++) {
818*0c7d97c5SJed Brown         k = pcbddc->indices_to_constraint[i][s];
819*0c7d97c5SJed Brown         if( array[k] == zero ) {
820*0c7d97c5SJed Brown           array[k] = one;
821*0c7d97c5SJed Brown           auxlocal_primal[i+pcbddc->n_vertices] = k;
822*0c7d97c5SJed Brown           break;
823*0c7d97c5SJed Brown         }
824*0c7d97c5SJed Brown       }
825*0c7d97c5SJed Brown     }
826*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
827*0c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
828*0c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
829*0c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
830*0c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
831*0c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
832*0c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
833*0c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {
834*0c7d97c5SJed Brown       if(array[i]) { array[i] = one/array[i]; }
835*0c7d97c5SJed Brown     }
836*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
837*0c7d97c5SJed Brown     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
838*0c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
839*0c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
840*0c7d97c5SJed Brown 
841*0c7d97c5SJed Brown     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
842*0c7d97c5SJed Brown     pcbddc->coarse_size = (PetscInt) coarsesum;
843*0c7d97c5SJed Brown     if(check_flag) {
844*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
845*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
846*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
847*0c7d97c5SJed Brown     }
848*0c7d97c5SJed Brown     /* Now assign them a global numbering */
849*0c7d97c5SJed Brown     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
850*0c7d97c5SJed Brown     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
851*0c7d97c5SJed Brown     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
852*0c7d97c5SJed 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);
853*0c7d97c5SJed Brown     /* aux_global_type is a dummy argument (PetscSortMPIInt doesn't exist!) */
854*0c7d97c5SJed Brown     ierr = PetscSortMPIIntWithArray( pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_type);CHKERRQ(ierr);
855*0c7d97c5SJed Brown     k=1;
856*0c7d97c5SJed Brown     j=all_auxglobal_primal[0];  /* first dof in global numbering */
857*0c7d97c5SJed Brown     for(i=1;i< pcbddc->replicated_primal_size ;i++) {
858*0c7d97c5SJed Brown       if(j != all_auxglobal_primal[i] ) {
859*0c7d97c5SJed Brown         all_auxglobal_primal[k]=all_auxglobal_primal[i];
860*0c7d97c5SJed Brown         k++;
861*0c7d97c5SJed Brown         j=all_auxglobal_primal[i];
862*0c7d97c5SJed Brown       }
863*0c7d97c5SJed Brown     }
864*0c7d97c5SJed Brown     /* At this point all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
865*0c7d97c5SJed Brown     /* We need only the indices from 0 to pcbddc->coarse_size. Remaning elements of array are garbage. */
866*0c7d97c5SJed Brown     /* Now get global coarse numbering of local primal nodes */
867*0c7d97c5SJed Brown     for(i=0;i<pcbddc->local_primal_size;i++) {
868*0c7d97c5SJed Brown       k=0;
869*0c7d97c5SJed Brown       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
870*0c7d97c5SJed Brown       pcbddc->local_primal_indices[i]=k;
871*0c7d97c5SJed Brown     }
872*0c7d97c5SJed Brown     if(check_flag) {
873*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
874*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
875*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
876*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
877*0c7d97c5SJed Brown       for(i=0;i<pcbddc->local_primal_size;i++) {
878*0c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
879*0c7d97c5SJed Brown       }
880*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
881*0c7d97c5SJed Brown     }
882*0c7d97c5SJed Brown     /* free allocated memory */
883*0c7d97c5SJed Brown     ierr = PetscFree(          auxlocal_primal);CHKERRQ(ierr);
884*0c7d97c5SJed Brown     ierr = PetscFree(         auxglobal_primal);CHKERRQ(ierr);
885*0c7d97c5SJed Brown     ierr = PetscFree(     all_auxglobal_primal);CHKERRQ(ierr);
886*0c7d97c5SJed Brown     ierr = PetscFree(all_auxglobal_primal_type);CHKERRQ(ierr);
887*0c7d97c5SJed Brown 
888*0c7d97c5SJed Brown   }
889*0c7d97c5SJed Brown 
890*0c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
891*0c7d97c5SJed Brown   {
892*0c7d97c5SJed Brown     Mat  A_RR;
893*0c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
894*0c7d97c5SJed Brown     ierr = PCCreate(PETSC_COMM_SELF,&pcbddc->pc_D);CHKERRQ(ierr);
895*0c7d97c5SJed Brown     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->pc_D,(PetscObject)pc,1);CHKERRQ(ierr);
896*0c7d97c5SJed Brown     ierr = PCSetOperators(pcbddc->pc_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
897*0c7d97c5SJed Brown     ierr = PCSetOptionsPrefix(pcbddc->pc_D,"pc_bddc_localD_");CHKERRQ(ierr);
898*0c7d97c5SJed Brown     /* default */
899*0c7d97c5SJed Brown     ierr = PCSetType(pcbddc->pc_D,PCLU);CHKERRQ(ierr);
900*0c7d97c5SJed Brown     /* Allow user's customization */
901*0c7d97c5SJed Brown     ierr = PCSetFromOptions(pcbddc->pc_D);CHKERRQ(ierr);
902*0c7d97c5SJed Brown     /* Set Up PC for Dirichlet problem of BDDC */
903*0c7d97c5SJed Brown     ierr = PCSetUp(pcbddc->pc_D);CHKERRQ(ierr);
904*0c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
905*0c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
906*0c7d97c5SJed Brown     ierr = PCCreate(PETSC_COMM_SELF,&pcbddc->pc_R);CHKERRQ(ierr);
907*0c7d97c5SJed Brown     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->pc_R,(PetscObject)pc,1);CHKERRQ(ierr);
908*0c7d97c5SJed Brown     ierr = PCSetOperators(pcbddc->pc_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
909*0c7d97c5SJed Brown     ierr = PCSetOptionsPrefix(pcbddc->pc_R,"pc_bddc_localN_");CHKERRQ(ierr);
910*0c7d97c5SJed Brown     /* default */
911*0c7d97c5SJed Brown     ierr = PCSetType(pcbddc->pc_R,PCLU);CHKERRQ(ierr);
912*0c7d97c5SJed Brown     /* Allow user's customization */
913*0c7d97c5SJed Brown     ierr = PCSetFromOptions(pcbddc->pc_R);CHKERRQ(ierr);
914*0c7d97c5SJed Brown     /* Set Up PC for Neumann problem of BDDC */
915*0c7d97c5SJed Brown     ierr = PCSetUp(pcbddc->pc_R);CHKERRQ(ierr);
916*0c7d97c5SJed Brown     /* check Neumann solve */
917*0c7d97c5SJed Brown     if(pcbddc->check_flag) {
918*0c7d97c5SJed Brown       Vec temp_vec;
919*0c7d97c5SJed Brown       PetscScalar value;
920*0c7d97c5SJed Brown 
921*0c7d97c5SJed Brown       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);
922*0c7d97c5SJed Brown       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);
923*0c7d97c5SJed Brown       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);
924*0c7d97c5SJed Brown       ierr = PCApply(pcbddc->pc_R,pcbddc->vec2_R,temp_vec);
925*0c7d97c5SJed Brown       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);
926*0c7d97c5SJed Brown       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);
927*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);
928*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
929*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Neumann problem\n");CHKERRQ(ierr);
930*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Neumann solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
931*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);
932*0c7d97c5SJed Brown       ierr = VecDestroy(&temp_vec);
933*0c7d97c5SJed Brown     }
934*0c7d97c5SJed Brown     /* free Neumann problem's matrix */
935*0c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
936*0c7d97c5SJed Brown   }
937*0c7d97c5SJed Brown 
938*0c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
939*0c7d97c5SJed Brown   {
940*0c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
941*0c7d97c5SJed Brown     Mat          M1,M2;
942*0c7d97c5SJed Brown     Mat          C_CR;
943*0c7d97c5SJed Brown     Mat          CMAT,AUXMAT;
944*0c7d97c5SJed Brown     Vec          vec1_C;
945*0c7d97c5SJed Brown     Vec          vec2_C;
946*0c7d97c5SJed Brown     Vec          vec1_V;
947*0c7d97c5SJed Brown     Vec          vec2_V;
948*0c7d97c5SJed Brown     PetscInt     *nnz;
949*0c7d97c5SJed Brown     PetscInt     *auxindices;
950*0c7d97c5SJed Brown     PetscInt     index[0];
951*0c7d97c5SJed Brown     PetscScalar* array2;
952*0c7d97c5SJed Brown     MatFactorInfo matinfo;
953*0c7d97c5SJed Brown 
954*0c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
955*0c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
956*0c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
957*0c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
958*0c7d97c5SJed Brown 
959*0c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
960*0c7d97c5SJed Brown     if(pcbddc->n_vertices) {
961*0c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
962*0c7d97c5SJed Brown       ierr = VecSetSizes(vec1_V,pcbddc->n_vertices,pcbddc->n_vertices);CHKERRQ(ierr);
963*0c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
964*0c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
965*0c7d97c5SJed Brown     }
966*0c7d97c5SJed Brown     if(pcbddc->n_constraints) {
967*0c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
968*0c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
969*0c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
970*0c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C); CHKERRQ(ierr);
971*0c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C); CHKERRQ(ierr);
972*0c7d97c5SJed Brown     }
973*0c7d97c5SJed Brown     /* Create C matrix [I 0; 0 const] */
974*0c7d97c5SJed Brown     ierr = MatCreate(PETSC_COMM_SELF,&CMAT);
975*0c7d97c5SJed Brown     ierr = MatSetType(CMAT,MATSEQAIJ);CHKERRQ(ierr);
976*0c7d97c5SJed Brown     ierr = MatSetSizes(CMAT,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
977*0c7d97c5SJed Brown     /* nonzeros */
978*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) { nnz[i]= 1; }
979*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) { nnz[i+pcbddc->n_vertices]=pcbddc->sizes_of_constraint[i];}
980*0c7d97c5SJed Brown     ierr = MatSeqAIJSetPreallocation(CMAT,0,nnz);CHKERRQ(ierr);
981*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++) {
982*0c7d97c5SJed Brown       ierr = MatSetValue(CMAT,i,pcbddc->vertices[i],1.0,INSERT_VALUES); CHKERRQ(ierr);
983*0c7d97c5SJed Brown     }
984*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++) {
985*0c7d97c5SJed Brown       index[0]=i+pcbddc->n_vertices;
986*0c7d97c5SJed Brown       ierr = MatSetValues(CMAT,1,index,pcbddc->sizes_of_constraint[i],pcbddc->indices_to_constraint[i],pcbddc->quadrature_constraint[i],INSERT_VALUES); CHKERRQ(ierr);
987*0c7d97c5SJed Brown     }
988*0c7d97c5SJed Brown     //if(check_flag) printf("CMAT assembling\n");
989*0c7d97c5SJed Brown     ierr = MatAssemblyBegin(CMAT,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
990*0c7d97c5SJed Brown     ierr = MatAssemblyEnd(CMAT,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
991*0c7d97c5SJed Brown     //ierr = MatView(CMAT,PETSC_VIEWER_STDOUT_SELF);
992*0c7d97c5SJed Brown 
993*0c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
994*0c7d97c5SJed Brown 
995*0c7d97c5SJed Brown     if(pcbddc->n_constraints) {
996*0c7d97c5SJed Brown       /* some work vectors */
997*0c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
998*0c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,pcbddc->n_constraints,n_R,pcbddc->n_constraints);CHKERRQ(ierr);
999*0c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
1000*0c7d97c5SJed Brown 
1001*0c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
1002*0c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
1003*0c7d97c5SJed Brown         ierr = VecSet(pcis->vec1_N,zero);
1004*0c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1005*0c7d97c5SJed Brown         for(j=0;j<pcbddc->sizes_of_constraint[i];j++) { array[ pcbddc->indices_to_constraint[i][j] ] = - pcbddc->quadrature_constraint[i][j]; }
1006*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1007*0c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
1008*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1009*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1010*0c7d97c5SJed Brown         ierr = PCApply(pcbddc->pc_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1011*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1012*0c7d97c5SJed Brown         index[0]=i;
1013*0c7d97c5SJed Brown         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,index,array,INSERT_VALUES); CHKERRQ(ierr);
1014*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1015*0c7d97c5SJed Brown       }
1016*0c7d97c5SJed Brown       //if(check_flag) printf("pcbddc->local_auxmat2 assembling\n");
1017*0c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1018*0c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1019*0c7d97c5SJed Brown 
1020*0c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
1021*0c7d97c5SJed Brown       ierr = MatGetSubMatrix(CMAT,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
1022*0c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local); CHKERRQ(ierr);
1023*0c7d97c5SJed Brown 
1024*0c7d97c5SJed Brown         /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
1025*0c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT); CHKERRQ(ierr);
1026*0c7d97c5SJed Brown       ierr = MatFactorInfoInitialize(&matinfo);
1027*0c7d97c5SJed Brown       ierr = ISCreateStride (PETSC_COMM_SELF,pcbddc->n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
1028*0c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
1029*0c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1); CHKERRQ(ierr);
1030*0c7d97c5SJed Brown 
1031*0c7d97c5SJed Brown         /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc (should be dense) */
1032*0c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&M1);
1033*0c7d97c5SJed Brown       ierr = MatSetSizes(M1,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
1034*0c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
1035*0c7d97c5SJed Brown       for(i=0;i<pcbddc->n_constraints;i++) {
1036*0c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
1037*0c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
1038*0c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
1039*0c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
1040*0c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
1041*0c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
1042*0c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
1043*0c7d97c5SJed Brown         index[0]=i;
1044*0c7d97c5SJed Brown         ierr = MatSetValues(M1,pcbddc->n_constraints,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1045*0c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
1046*0c7d97c5SJed Brown       }
1047*0c7d97c5SJed Brown       //if(check_flag) printf("M1 assembling\n");
1048*0c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1049*0c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M1,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1050*0c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
1051*0c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
1052*0c7d97c5SJed Brown       //if(check_flag) printf("pcbddc->local_auxmat1 computing and assembling\n");
1053*0c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1); CHKERRQ(ierr);
1054*0c7d97c5SJed Brown 
1055*0c7d97c5SJed Brown     }
1056*0c7d97c5SJed Brown 
1057*0c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
1058*0c7d97c5SJed Brown     if(pcbddc->n_vertices){
1059*0c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
1060*0c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
1061*0c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
1062*0c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1063*0c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&M2);
1064*0c7d97c5SJed Brown       ierr = MatSetSizes(M2,n_R,pcbddc->n_vertices,n_R,pcbddc->n_vertices);CHKERRQ(ierr);
1065*0c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
1066*0c7d97c5SJed Brown       for(i=0;i<pcbddc->n_vertices;i++) {
1067*0c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
1068*0c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
1069*0c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
1070*0c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
1071*0c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
1072*0c7d97c5SJed Brown         ierr = PCApply(pcbddc->pc_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1073*0c7d97c5SJed Brown         index[0]=i;
1074*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1075*0c7d97c5SJed Brown         ierr = MatSetValues(M2,n_R,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1076*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
1077*0c7d97c5SJed Brown       }
1078*0c7d97c5SJed Brown       //if(check_flag) printf("M2 assembling\n");
1079*0c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1080*0c7d97c5SJed Brown       ierr = MatAssemblyEnd  (M2,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1081*0c7d97c5SJed Brown     }
1082*0c7d97c5SJed Brown 
1083*0c7d97c5SJed Brown /* Matrix of coarse basis functions (local) */
1084*0c7d97c5SJed Brown     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);
1085*0c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
1086*0c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
1087*0c7d97c5SJed Brown     if(pcbddc->prec_type || check_flag ) {
1088*0c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);
1089*0c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
1090*0c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
1091*0c7d97c5SJed Brown     }
1092*0c7d97c5SJed Brown 
1093*0c7d97c5SJed Brown /* Subdomain contribution (Non-overlapping) to coarse matrix  */
1094*0c7d97c5SJed Brown     if(check_flag) {
1095*0c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
1096*0c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
1097*0c7d97c5SJed Brown     }
1098*0c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
1099*0c7d97c5SJed Brown 
1100*0c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
1101*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
1102*0c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
1103*0c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
1104*0c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
1105*0c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
1106*0c7d97c5SJed Brown       /* solution of saddle point problem */
1107*0c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
1108*0c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
1109*0c7d97c5SJed Brown       if(pcbddc->n_constraints) {
1110*0c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
1111*0c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
1112*0c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
1113*0c7d97c5SJed Brown       }
1114*0c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
1115*0c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
1116*0c7d97c5SJed Brown 
1117*0c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
1118*0c7d97c5SJed Brown       /* coarse basis functions */
1119*0c7d97c5SJed Brown       index[0]=i;
1120*0c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1121*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1122*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1123*0c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1124*0c7d97c5SJed Brown       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1125*0c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1126*0c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1127*0c7d97c5SJed Brown       if( pcbddc->prec_type || check_flag  ) {
1128*0c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1129*0c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1130*0c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1131*0c7d97c5SJed Brown         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1132*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1133*0c7d97c5SJed Brown       }
1134*0c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
1135*0c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1136*0c7d97c5SJed Brown       for(j=0;j<pcbddc->n_vertices;j++) {coarse_submat_vals[i*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
1137*0c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1138*0c7d97c5SJed Brown       if( pcbddc->n_constraints) {
1139*0c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1140*0c7d97c5SJed 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
1141*0c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1142*0c7d97c5SJed Brown       }
1143*0c7d97c5SJed Brown 
1144*0c7d97c5SJed Brown       if( check_flag ) {
1145*0c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1146*0c7d97c5SJed Brown         ierr = VecSet(pcis->vec1_N,zero);
1147*0c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1148*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1149*0c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
1150*0c7d97c5SJed Brown         array[ pcbddc->vertices[i] ] = one;
1151*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1152*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1153*0c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1154*0c7d97c5SJed Brown         ierr = VecSet(pcbddc->vec1_P,zero);
1155*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1156*0c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1157*0c7d97c5SJed Brown         for(j=0;j<pcbddc->n_vertices;j++) { array2[j]=array[j]; }
1158*0c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1159*0c7d97c5SJed Brown         if(pcbddc->n_constraints) {
1160*0c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1161*0c7d97c5SJed Brown           for(j=0;j<pcbddc->n_constraints;j++) { array2[j+pcbddc->n_vertices]=array[j]; }
1162*0c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1163*0c7d97c5SJed Brown         }
1164*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1165*0c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
1166*0c7d97c5SJed Brown         /* check saddle point solution */
1167*0c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N); CHKERRQ(ierr);
1168*0c7d97c5SJed Brown         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);
1169*0c7d97c5SJed Brown         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index[0]]); CHKERRQ(ierr);
1170*0c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P); CHKERRQ(ierr);
1171*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1172*0c7d97c5SJed Brown         array[index[0]]=array[index[0]]+m_one;  /* shift by the identity matrix */
1173*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1174*0c7d97c5SJed Brown         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index[0]]); CHKERRQ(ierr);
1175*0c7d97c5SJed Brown       }
1176*0c7d97c5SJed Brown     }
1177*0c7d97c5SJed Brown 
1178*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_constraints;i++){
1179*0c7d97c5SJed Brown       ierr = VecSet(vec2_C,zero);
1180*0c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
1181*0c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
1182*0c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
1183*0c7d97c5SJed Brown       /* solution of saddle point problem */
1184*0c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
1185*0c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
1186*0c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
1187*0c7d97c5SJed Brown       if(pcbddc->n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
1188*0c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
1189*0c7d97c5SJed Brown       /* coarse basis functions */
1190*0c7d97c5SJed Brown       index[0]=i+pcbddc->n_vertices;
1191*0c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1192*0c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1193*0c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1194*0c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1195*0c7d97c5SJed Brown       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1196*0c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1197*0c7d97c5SJed Brown       if( pcbddc->prec_type || check_flag ) {
1198*0c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1199*0c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1200*0c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1201*0c7d97c5SJed Brown         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,index,array,INSERT_VALUES);CHKERRQ(ierr);
1202*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
1203*0c7d97c5SJed Brown       }
1204*0c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
1205*0c7d97c5SJed Brown       if(pcbddc->n_vertices) {
1206*0c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1207*0c7d97c5SJed 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
1208*0c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1209*0c7d97c5SJed Brown       }
1210*0c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1211*0c7d97c5SJed 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
1212*0c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1213*0c7d97c5SJed Brown 
1214*0c7d97c5SJed Brown       if( check_flag ) {
1215*0c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1216*0c7d97c5SJed Brown         ierr = VecSet(pcis->vec1_N,zero);
1217*0c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1218*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1219*0c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
1220*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
1221*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1222*0c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
1223*0c7d97c5SJed Brown         ierr = VecSet(pcbddc->vec1_P,zero);
1224*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1225*0c7d97c5SJed Brown         if( pcbddc->n_vertices) {
1226*0c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1227*0c7d97c5SJed Brown           for(j=0;j<pcbddc->n_vertices;j++) {array2[j]=-array[j];}
1228*0c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
1229*0c7d97c5SJed Brown         }
1230*0c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1231*0c7d97c5SJed Brown         for(j=0;j<pcbddc->n_constraints;j++) {array2[j+pcbddc->n_vertices]=-array[j];}
1232*0c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
1233*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
1234*0c7d97c5SJed Brown         /* check saddle point solution */
1235*0c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N); CHKERRQ(ierr);
1236*0c7d97c5SJed Brown         ierr = MatMultTransposeAdd(CMAT,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);
1237*0c7d97c5SJed Brown         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index[0]]); CHKERRQ(ierr);
1238*0c7d97c5SJed Brown         ierr = MatMult(CMAT,pcis->vec1_N,pcbddc->vec1_P); CHKERRQ(ierr);
1239*0c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1240*0c7d97c5SJed Brown         array[index[0]]=array[index[0]]+m_one; /* shift by the identity matrix */
1241*0c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
1242*0c7d97c5SJed Brown         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index[0]]); CHKERRQ(ierr);
1243*0c7d97c5SJed Brown       }
1244*0c7d97c5SJed Brown     }
1245*0c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1246*0c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1247*0c7d97c5SJed Brown     if( pcbddc->prec_type || check_flag ) {
1248*0c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1249*0c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1250*0c7d97c5SJed Brown     }
1251*0c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
1252*0c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
1253*0c7d97c5SJed Brown     if(check_flag) {
1254*0c7d97c5SJed Brown 
1255*0c7d97c5SJed Brown       Mat coarse_sub_mat;
1256*0c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
1257*0c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1258*0c7d97c5SJed Brown       const MatType checkmattype;
1259*0c7d97c5SJed Brown       PetscScalar      value;
1260*0c7d97c5SJed Brown       PetscInt bs;
1261*0c7d97c5SJed Brown 
1262*0c7d97c5SJed Brown       ierr = MatGetType(matis->A,&checkmattype);CHKERRQ(ierr);
1263*0c7d97c5SJed Brown       ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1264*0c7d97c5SJed Brown       //printf("Mat type local ismat: %s\n",checkmattype);
1265*0c7d97c5SJed Brown       //printf("Mat bs   local ismat: %d\n",bs);
1266*0c7d97c5SJed Brown       ierr = MatGetType(pcis->A_II,&checkmattype);CHKERRQ(ierr);
1267*0c7d97c5SJed Brown       ierr = MatGetBlockSize(pcis->A_II,&bs);CHKERRQ(ierr);
1268*0c7d97c5SJed Brown       //printf("Mat type local is D : %s\n",checkmattype);
1269*0c7d97c5SJed Brown       //printf("Mat bs   local is D : %d\n",bs);
1270*0c7d97c5SJed Brown       checkmattype = MATSEQAIJ;
1271*0c7d97c5SJed Brown       MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);
1272*0c7d97c5SJed Brown       MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);
1273*0c7d97c5SJed Brown       MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);
1274*0c7d97c5SJed Brown       MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);
1275*0c7d97c5SJed Brown       MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);
1276*0c7d97c5SJed Brown       MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);
1277*0c7d97c5SJed Brown       MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1278*0c7d97c5SJed Brown       MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);
1279*0c7d97c5SJed Brown 
1280*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1281*0c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
1282*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1283*0c7d97c5SJed Brown       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);
1284*0c7d97c5SJed Brown       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);
1285*0c7d97c5SJed Brown       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);
1286*0c7d97c5SJed Brown       ierr = MatMatTransposeMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);
1287*0c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);
1288*0c7d97c5SJed Brown       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);
1289*0c7d97c5SJed Brown       ierr = MatMatTransposeMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);
1290*0c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);
1291*0c7d97c5SJed Brown       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);
1292*0c7d97c5SJed Brown       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);
1293*0c7d97c5SJed Brown       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);
1294*0c7d97c5SJed Brown       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);
1295*0c7d97c5SJed Brown       ierr = MatNorm(TM1,NORM_INFINITY,&value);
1296*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
1297*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
1298*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
1299*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
1300*0c7d97c5SJed Brown       for(i=0;i<pcbddc->local_primal_size;i++) {
1301*0c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
1302*0c7d97c5SJed Brown       }
1303*0c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
1304*0c7d97c5SJed Brown       for(i=0;i<pcbddc->local_primal_size;i++) {
1305*0c7d97c5SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
1306*0c7d97c5SJed Brown       }
1307*0c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1308*0c7d97c5SJed Brown       ierr = MatDestroy(&A_II);
1309*0c7d97c5SJed Brown       ierr = MatDestroy(&A_BB);
1310*0c7d97c5SJed Brown       ierr = MatDestroy(&A_IB);
1311*0c7d97c5SJed Brown       ierr = MatDestroy(&A_BI);
1312*0c7d97c5SJed Brown       ierr = MatDestroy(&TM1);
1313*0c7d97c5SJed Brown       ierr = MatDestroy(&TM2);
1314*0c7d97c5SJed Brown       ierr = MatDestroy(&TM3);
1315*0c7d97c5SJed Brown       ierr = MatDestroy(&TM4);
1316*0c7d97c5SJed Brown       ierr = MatDestroy(&coarse_phi_D);
1317*0c7d97c5SJed Brown       ierr = MatDestroy(&coarse_sub_mat);
1318*0c7d97c5SJed Brown       ierr = MatDestroy(&coarse_phi_B);
1319*0c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
1320*0c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
1321*0c7d97c5SJed Brown     }
1322*0c7d97c5SJed Brown 
1323*0c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
1324*0c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
1325*0c7d97c5SJed Brown     /* free memory */
1326*0c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
1327*0c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
1328*0c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
1329*0c7d97c5SJed Brown     if(pcbddc->n_vertices) {
1330*0c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
1331*0c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
1332*0c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
1333*0c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
1334*0c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
1335*0c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
1336*0c7d97c5SJed Brown     }
1337*0c7d97c5SJed Brown     if(pcbddc->n_constraints) {
1338*0c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
1339*0c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
1340*0c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
1341*0c7d97c5SJed Brown       ierr = MatDestroy(&C_CR); CHKERRQ(ierr);
1342*0c7d97c5SJed Brown     }
1343*0c7d97c5SJed Brown     ierr = MatDestroy(&CMAT); CHKERRQ(ierr);
1344*0c7d97c5SJed Brown   }
1345*0c7d97c5SJed Brown   /* free memory */
1346*0c7d97c5SJed Brown   if(pcbddc->n_vertices) {
1347*0c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
1348*0c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
1349*0c7d97c5SJed Brown   }
1350*0c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1351*0c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
1352*0c7d97c5SJed Brown   //ierr = VecDestroy(&pcis->vec2_N);CHKERRQ(ierr);
1353*0c7d97c5SJed Brown   //pcis->vec2_N = 0;
1354*0c7d97c5SJed Brown 
1355*0c7d97c5SJed Brown   PetscFunctionReturn(0);
1356*0c7d97c5SJed Brown 
1357*0c7d97c5SJed Brown }
1358*0c7d97c5SJed Brown 
1359*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1360*0c7d97c5SJed Brown 
1361*0c7d97c5SJed Brown #undef __FUNCT__
1362*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
1363*0c7d97c5SJed Brown PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
1364*0c7d97c5SJed Brown {
1365*0c7d97c5SJed Brown 
1366*0c7d97c5SJed Brown 
1367*0c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
1368*0c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
1369*0c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
1370*0c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
1371*0c7d97c5SJed Brown   MPI_Comm  coarse_comm;
1372*0c7d97c5SJed Brown 
1373*0c7d97c5SJed Brown   /* common to all choiches */
1374*0c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
1375*0c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
1376*0c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
1377*0c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
1378*0c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
1379*0c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
1380*0c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
1381*0c7d97c5SJed Brown   PetscMPIInt master_proc=0;
1382*0c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
1383*0c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
1384*0c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
1385*0c7d97c5SJed Brown   PetscMPIInt count_recv=0;
1386*0c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
1387*0c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
1388*0c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
1389*0c7d97c5SJed Brown   /* some other variables */
1390*0c7d97c5SJed Brown   PetscErrorCode ierr;
1391*0c7d97c5SJed Brown   const MatType coarse_mat_type;
1392*0c7d97c5SJed Brown   const PCType  coarse_pc_type;
1393*0c7d97c5SJed Brown   PetscInt i,j,k,bs;
1394*0c7d97c5SJed Brown 
1395*0c7d97c5SJed Brown   PetscFunctionBegin;
1396*0c7d97c5SJed Brown 
1397*0c7d97c5SJed Brown   ins_local_primal_indices = 0;
1398*0c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
1399*0c7d97c5SJed Brown   localsizes2              = 0;
1400*0c7d97c5SJed Brown   localdispl2              = 0;
1401*0c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
1402*0c7d97c5SJed Brown   coarse_ISLG              = 0;
1403*0c7d97c5SJed Brown 
1404*0c7d97c5SJed Brown   MPI_Comm_size(prec_comm,&size_prec_comm);
1405*0c7d97c5SJed Brown   MPI_Comm_rank(prec_comm,&rank_prec_comm);
1406*0c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1407*0c7d97c5SJed Brown 
1408*0c7d97c5SJed Brown   /* adapt coarse problem type */
1409*0c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
1410*0c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
1411*0c7d97c5SJed Brown 
1412*0c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
1413*0c7d97c5SJed Brown 
1414*0c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
1415*0c7d97c5SJed Brown     {
1416*0c7d97c5SJed Brown       /* we need additional variables */
1417*0c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
1418*0c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
1419*0c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
1420*0c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
1421*0c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
1422*0c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
1423*0c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
1424*0c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
1425*0c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
1426*0c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
1427*0c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
1428*0c7d97c5SJed Brown       MetisInt    *faces_adjncy;
1429*0c7d97c5SJed Brown       MetisInt    *faces_xadj;
1430*0c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
1431*0c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
1432*0c7d97c5SJed Brown       PetscInt    *array_int;
1433*0c7d97c5SJed Brown       PetscMPIInt my_faces=0;
1434*0c7d97c5SJed Brown       PetscMPIInt total_faces=0;
1435*0c7d97c5SJed Brown 
1436*0c7d97c5SJed Brown       /* this code has a bug (see below) for more then three levels -> I can solve it quickly */
1437*0c7d97c5SJed Brown 
1438*0c7d97c5SJed Brown       /* define some quantities */
1439*0c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1440*0c7d97c5SJed Brown       coarse_mat_type = MATIS;
1441*0c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
1442*0c7d97c5SJed Brown 
1443*0c7d97c5SJed Brown       /* details of coarse decomposition */
1444*0c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
1445*0c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
1446*0c7d97c5SJed Brown       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*(size_prec_comm/pcbddc->active_procs);
1447*0c7d97c5SJed Brown 
1448*0c7d97c5SJed Brown       ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
1449*0c7d97c5SJed 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);
1450*0c7d97c5SJed Brown 
1451*0c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
1452*0c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
1453*0c7d97c5SJed Brown       PetscMemzero(array_int,pcis->n*sizeof(PetscInt));
1454*0c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
1455*0c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
1456*0c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
1457*0c7d97c5SJed Brown         }
1458*0c7d97c5SJed Brown       }
1459*0c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
1460*0c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
1461*0c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
1462*0c7d97c5SJed Brown             my_faces++;
1463*0c7d97c5SJed Brown             break;
1464*0c7d97c5SJed Brown           }
1465*0c7d97c5SJed Brown         }
1466*0c7d97c5SJed Brown       }
1467*0c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
1468*0c7d97c5SJed Brown 
1469*0c7d97c5SJed Brown       MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);
1470*0c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
1471*0c7d97c5SJed Brown       my_faces=0;
1472*0c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
1473*0c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
1474*0c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
1475*0c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
1476*0c7d97c5SJed Brown             my_faces++;
1477*0c7d97c5SJed Brown             break;
1478*0c7d97c5SJed Brown           }
1479*0c7d97c5SJed Brown         }
1480*0c7d97c5SJed Brown       }
1481*0c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
1482*0c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
1483*0c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
1484*0c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
1485*0c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
1486*0c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
1487*0c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
1488*0c7d97c5SJed Brown       }
1489*0c7d97c5SJed Brown       MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);
1490*0c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
1491*0c7d97c5SJed Brown         faces_xadj[0]=0;
1492*0c7d97c5SJed Brown         faces_displacements[0]=0;
1493*0c7d97c5SJed Brown         j=0;
1494*0c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
1495*0c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
1496*0c7d97c5SJed Brown           if(number_of_faces[i-1]) {
1497*0c7d97c5SJed Brown             j++;
1498*0c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
1499*0c7d97c5SJed Brown           }
1500*0c7d97c5SJed Brown         }
1501*0c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
1502*0c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
1503*0c7d97c5SJed Brown       }
1504*0c7d97c5SJed 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);
1505*0c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
1506*0c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
1507*0c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
1508*0c7d97c5SJed Brown         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]); ///procs_jumps_coarse_comm); // cast to MetisInt
1509*0c7d97c5SJed Brown         printf("This is the face connectivity (%d)\n",procs_jumps_coarse_comm);
1510*0c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
1511*0c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
1512*0c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
1513*0c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
1514*0c7d97c5SJed Brown           printf("\n");
1515*0c7d97c5SJed Brown         }
1516*0c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
1517*0c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
1518*0c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
1519*0c7d97c5SJed Brown       }
1520*0c7d97c5SJed Brown 
1521*0c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
1522*0c7d97c5SJed Brown 
1523*0c7d97c5SJed Brown         ncon=1;
1524*0c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
1525*0c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
1526*0c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
1527*0c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
1528*0c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
1529*0c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
1530*0c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
1531*0c7d97c5SJed Brown         options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
1532*0c7d97c5SJed Brown         options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
1533*0c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
1534*0c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
1535*0c7d97c5SJed Brown         //printf("METIS PART GRAPH\n");
1536*0c7d97c5SJed Brown         /* BUG: faces_xadj and faces_adjncy content must be adapted using the coarsening factor*/
1537*0c7d97c5SJed Brown         ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
1538*0c7d97c5SJed Brown         //printf("OKOKOKOKOKOKOKOK\n");
1539*0c7d97c5SJed 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);
1540*0c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
1541*0c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
1542*0c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
1543*0c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
1544*0c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;;
1545*0c7d97c5SJed Brown         k=size_prec_comm/pcbddc->active_procs;
1546*0c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=(PetscInt)(metis_coarse_subdivision[i]);
1547*0c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
1548*0c7d97c5SJed Brown 
1549*0c7d97c5SJed Brown       }
1550*0c7d97c5SJed Brown 
1551*0c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
1552*0c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
1553*0c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
1554*0c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
1555*0c7d97c5SJed Brown       }
1556*0c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
1557*0c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
1558*0c7d97c5SJed Brown       MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);
1559*0c7d97c5SJed Brown 
1560*0c7d97c5SJed Brown       if( coarse_color == 0 ) {
1561*0c7d97c5SJed Brown         MPI_Comm_size(coarse_comm,&size_coarse_comm);
1562*0c7d97c5SJed Brown         MPI_Comm_rank(coarse_comm,&rank_coarse_comm);
1563*0c7d97c5SJed Brown         //printf("Details of coarse comm\n");
1564*0c7d97c5SJed Brown         //printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
1565*0c7d97c5SJed Brown         //printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
1566*0c7d97c5SJed Brown       } else {
1567*0c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
1568*0c7d97c5SJed Brown       }
1569*0c7d97c5SJed Brown 
1570*0c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
1571*0c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
1572*0c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
1573*0c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
1574*0c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
1575*0c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
1576*0c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
1577*0c7d97c5SJed Brown         /* some initializations */
1578*0c7d97c5SJed Brown         displacements_recv[0]=0;
1579*0c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
1580*0c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
1581*0c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
1582*0c7d97c5SJed Brown           for(i=0;i<n_subdomains;i++)
1583*0c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
1584*0c7d97c5SJed Brown               total_count_recv[j]++;
1585*0c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
1586*0c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
1587*0c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
1588*0c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
1589*0c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
1590*0c7d97c5SJed Brown           for(i=0;i<n_subdomains;i++) {
1591*0c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
1592*0c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
1593*0c7d97c5SJed Brown               total_count_recv[j]=total_count_recv[j]+1;
1594*0c7d97c5SJed Brown             }
1595*0c7d97c5SJed Brown           }
1596*0c7d97c5SJed Brown         }
1597*0c7d97c5SJed Brown         //for(j=0;j<size_coarse_comm;j++) {
1598*0c7d97c5SJed Brown         //  printf("process %d in new rank will receive from %d processes (ranks follows)\n",j,total_count_recv[j]);
1599*0c7d97c5SJed Brown         //  for(i=0;i<total_count_recv[j];i++) {
1600*0c7d97c5SJed Brown         //    printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
1601*0c7d97c5SJed Brown         //  }
1602*0c7d97c5SJed Brown         //  printf("\n");
1603*0c7d97c5SJed Brown        // }
1604*0c7d97c5SJed Brown 
1605*0c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
1606*0c7d97c5SJed Brown         k=size_prec_comm/pcbddc->active_procs;
1607*0c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++) coarse_subdivision[k*i]=coarse_subdivision[k*i]*procs_jumps_coarse_comm;
1608*0c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
1609*0c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
1610*0c7d97c5SJed Brown           printf("(%d %d) ",coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
1611*0c7d97c5SJed Brown         printf("\n");
1612*0c7d97c5SJed Brown       }
1613*0c7d97c5SJed Brown 
1614*0c7d97c5SJed Brown       /* Scatter new decomposition for send details */
1615*0c7d97c5SJed Brown       MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);
1616*0c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
1617*0c7d97c5SJed Brown       if( coarse_color == 0) {
1618*0c7d97c5SJed Brown         MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);
1619*0c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
1620*0c7d97c5SJed 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);
1621*0c7d97c5SJed Brown       }
1622*0c7d97c5SJed Brown 
1623*0c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
1624*0c7d97c5SJed Brown       //if(coarse_color == 0) {
1625*0c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
1626*0c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
1627*0c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
1628*0c7d97c5SJed Brown       //  printf("\n");
1629*0c7d97c5SJed Brown       //}
1630*0c7d97c5SJed Brown 
1631*0c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
1632*0c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
1633*0c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
1634*0c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
1635*0c7d97c5SJed Brown         free(coarse_subdivision);
1636*0c7d97c5SJed Brown         free(total_count_recv);
1637*0c7d97c5SJed Brown         free(total_ranks_recv);
1638*0c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
1639*0c7d97c5SJed Brown       }
1640*0c7d97c5SJed Brown       break;
1641*0c7d97c5SJed Brown     }
1642*0c7d97c5SJed Brown 
1643*0c7d97c5SJed Brown     case(REPLICATED_BDDC):
1644*0c7d97c5SJed Brown 
1645*0c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
1646*0c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
1647*0c7d97c5SJed Brown       coarse_pc_type  = PCLU;
1648*0c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
1649*0c7d97c5SJed Brown       active_rank = rank_prec_comm;
1650*0c7d97c5SJed Brown       break;
1651*0c7d97c5SJed Brown 
1652*0c7d97c5SJed Brown     case(PARALLEL_BDDC):
1653*0c7d97c5SJed Brown 
1654*0c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
1655*0c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
1656*0c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
1657*0c7d97c5SJed Brown       coarse_comm = prec_comm;
1658*0c7d97c5SJed Brown       active_rank = rank_prec_comm;
1659*0c7d97c5SJed Brown       break;
1660*0c7d97c5SJed Brown 
1661*0c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
1662*0c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
1663*0c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
1664*0c7d97c5SJed Brown       coarse_pc_type = PCLU;
1665*0c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
1666*0c7d97c5SJed Brown       active_rank = master_proc;
1667*0c7d97c5SJed Brown       break;
1668*0c7d97c5SJed Brown   }
1669*0c7d97c5SJed Brown 
1670*0c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
1671*0c7d97c5SJed Brown 
1672*0c7d97c5SJed Brown     case(SCATTERS_BDDC):
1673*0c7d97c5SJed Brown       {
1674*0c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
1675*0c7d97c5SJed Brown 
1676*0c7d97c5SJed Brown           PetscMPIInt send_size;
1677*0c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
1678*0c7d97c5SJed Brown           PetscInt    ii,jj;
1679*0c7d97c5SJed Brown           MPI_Request *requests;
1680*0c7d97c5SJed Brown 
1681*0c7d97c5SJed Brown           /* allocate auxiliary space */
1682*0c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
1683*0c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
1684*0c7d97c5SJed Brown           /* allocate stuffs for message massing */
1685*0c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
1686*0c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
1687*0c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
1688*0c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
1689*0c7d97c5SJed Brown           /* fill up quantities */
1690*0c7d97c5SJed Brown           j=0;
1691*0c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
1692*0c7d97c5SJed Brown             ii = ranks_recv[i];
1693*0c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
1694*0c7d97c5SJed Brown             localdispl2[i]=j;
1695*0c7d97c5SJed Brown             j+=localsizes2[i];
1696*0c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
1697*0c7d97c5SJed 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
1698*0c7d97c5SJed Brown           }
1699*0c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
1700*0c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
1701*0c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
1702*0c7d97c5SJed Brown           //printf("\n");
1703*0c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
1704*0c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
1705*0c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
1706*0c7d97c5SJed Brown           ins_local_primal_size=0;
1707*0c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
1708*0c7d97c5SJed Brown             if(aux_ins_indices[i])
1709*0c7d97c5SJed Brown               ins_local_primal_size++;
1710*0c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
1711*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
1712*0c7d97c5SJed Brown           j=0;
1713*0c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
1714*0c7d97c5SJed Brown             if(aux_ins_indices[i])
1715*0c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
1716*0c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
1717*0c7d97c5SJed Brown           j=0;
1718*0c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
1719*0c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
1720*0c7d97c5SJed Brown               aux_ins_indices[i]=-1;
1721*0c7d97c5SJed Brown             } else {
1722*0c7d97c5SJed Brown               aux_ins_indices[i]=j;
1723*0c7d97c5SJed Brown               j++;
1724*0c7d97c5SJed Brown             }
1725*0c7d97c5SJed Brown           }
1726*0c7d97c5SJed Brown 
1727*0c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
1728*0c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
1729*0c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
1730*0c7d97c5SJed Brown           //printf("\n");
1731*0c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
1732*0c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
1733*0c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
1734*0c7d97c5SJed Brown           //printf("\n");
1735*0c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
1736*0c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
1737*0c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
1738*0c7d97c5SJed Brown           //printf("\n");
1739*0c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
1740*0c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
1741*0c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
1742*0c7d97c5SJed 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]);
1743*0c7d97c5SJed Brown           //printf("\n");
1744*0c7d97c5SJed Brown 
1745*0c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
1746*0c7d97c5SJed 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]);
1747*0c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
1748*0c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
1749*0c7d97c5SJed Brown             MPI_Isend(&coarse_submat_vals[0],send_size,MPIU_SCALAR,rank_coarse_proc_send_to,666,prec_comm,&requests[count_recv]);
1750*0c7d97c5SJed Brown           }
1751*0c7d97c5SJed Brown           MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);
1752*0c7d97c5SJed Brown 
1753*0c7d97c5SJed Brown           //if(coarse_color == 0) {
1754*0c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
1755*0c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
1756*0c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
1757*0c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
1758*0c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
1759*0c7d97c5SJed 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]);
1760*0c7d97c5SJed Brown           //    printf("\n");
1761*0c7d97c5SJed Brown           //  }
1762*0c7d97c5SJed Brown           //}
1763*0c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
1764*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
1765*0c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
1766*0c7d97c5SJed Brown 
1767*0c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
1768*0c7d97c5SJed Brown           PetscInt row_ind,col_ind;
1769*0c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
1770*0c7d97c5SJed Brown             rr = ranks_recv[k];
1771*0c7d97c5SJed Brown             kk = localdispl2[k];
1772*0c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
1773*0c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
1774*0c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
1775*0c7d97c5SJed Brown             for(j=0;j<lps;j++){
1776*0c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
1777*0c7d97c5SJed Brown               for(i=0;i<lps;i++){
1778*0c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
1779*0c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
1780*0c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
1781*0c7d97c5SJed Brown               }
1782*0c7d97c5SJed Brown             }
1783*0c7d97c5SJed Brown           }
1784*0c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
1785*0c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
1786*0c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
1787*0c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
1788*0c7d97c5SJed Brown 
1789*0c7d97c5SJed Brown             /* create local to global mapping needed by coarse MATIS */
1790*0c7d97c5SJed Brown           {
1791*0c7d97c5SJed Brown             IS coarse_IS;
1792*0c7d97c5SJed Brown             if(coarse_comm != MPI_COMM_NULL ) MPI_Comm_free(&coarse_comm);
1793*0c7d97c5SJed Brown             coarse_comm = prec_comm;
1794*0c7d97c5SJed Brown             active_rank=rank_prec_comm;
1795*0c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
1796*0c7d97c5SJed Brown             //ierr = ISSetBlockSize(coarse_IS,bs);CHKERRQ(ierr);
1797*0c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
1798*0c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
1799*0c7d97c5SJed Brown           }
1800*0c7d97c5SJed Brown         }
1801*0c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
1802*0c7d97c5SJed Brown           /* arrays for values insertion */
1803*0c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
1804*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
1805*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
1806*0c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
1807*0c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
1808*0c7d97c5SJed 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];
1809*0c7d97c5SJed Brown           }
1810*0c7d97c5SJed Brown         }
1811*0c7d97c5SJed Brown         break;
1812*0c7d97c5SJed Brown 
1813*0c7d97c5SJed Brown     }
1814*0c7d97c5SJed Brown 
1815*0c7d97c5SJed Brown     case(GATHERS_BDDC):
1816*0c7d97c5SJed Brown       {
1817*0c7d97c5SJed Brown 
1818*0c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
1819*0c7d97c5SJed Brown 
1820*0c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
1821*0c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
1822*0c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
1823*0c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
1824*0c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
1825*0c7d97c5SJed Brown           /* arrays for values insertion */
1826*0c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
1827*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
1828*0c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
1829*0c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
1830*0c7d97c5SJed Brown           localdispl2[0]=0;
1831*0c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
1832*0c7d97c5SJed Brown           j=0;
1833*0c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
1834*0c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
1835*0c7d97c5SJed Brown         }
1836*0c7d97c5SJed Brown 
1837*0c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
1838*0c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
1839*0c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
1840*0c7d97c5SJed 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);
1841*0c7d97c5SJed Brown           MPI_Gatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,master_proc,prec_comm);
1842*0c7d97c5SJed Brown         } else {
1843*0c7d97c5SJed 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);
1844*0c7d97c5SJed Brown           MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);
1845*0c7d97c5SJed Brown         }
1846*0c7d97c5SJed Brown 
1847*0c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
1848*0c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
1849*0c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
1850*0c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
1851*0c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
1852*0c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
1853*0c7d97c5SJed Brown           }
1854*0c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
1855*0c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
1856*0c7d97c5SJed Brown             offset2=localdispl2[k];
1857*0c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
1858*0c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
1859*0c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
1860*0c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
1861*0c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
1862*0c7d97c5SJed Brown               }
1863*0c7d97c5SJed Brown             }
1864*0c7d97c5SJed Brown           }
1865*0c7d97c5SJed Brown         }
1866*0c7d97c5SJed Brown         break;
1867*0c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
1868*0c7d97c5SJed Brown   }
1869*0c7d97c5SJed Brown 
1870*0c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
1871*0c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
1872*0c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
1873*0c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
1874*0c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
1875*0c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
1876*0c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
1877*0c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
1878*0c7d97c5SJed Brown     } else {
1879*0c7d97c5SJed Brown       Mat matis_coarse_local_mat;
1880*0c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
1881*0c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
1882*0c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
1883*0c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
1884*0c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr);
1885*0c7d97c5SJed Brown     }
1886*0c7d97c5SJed 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);
1887*0c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1888*0c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1889*0c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1890*0c7d97c5SJed Brown       Mat matis_coarse_local_mat;
1891*0c7d97c5SJed Brown       printf("Setting bs %d\n",bs);
1892*0c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
1893*0c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
1894*0c7d97c5SJed Brown     }
1895*0c7d97c5SJed Brown 
1896*0c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
1897*0c7d97c5SJed Brown     /* Preconditioner for coarse problem */
1898*0c7d97c5SJed Brown     ierr = PCCreate(coarse_comm,&pcbddc->coarse_pc);CHKERRQ(ierr);
1899*0c7d97c5SJed Brown     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_pc,(PetscObject)pc,1);CHKERRQ(ierr);
1900*0c7d97c5SJed Brown     ierr = PCSetOperators(pcbddc->coarse_pc,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
1901*0c7d97c5SJed Brown     ierr = PCSetType(pcbddc->coarse_pc,coarse_pc_type);CHKERRQ(ierr);
1902*0c7d97c5SJed Brown     ierr = PCSetOptionsPrefix(pcbddc->coarse_pc,"pc_bddc_coarse_");CHKERRQ(ierr);
1903*0c7d97c5SJed Brown     /* Allow user's customization */
1904*0c7d97c5SJed Brown     ierr = PCSetFromOptions(pcbddc->coarse_pc);CHKERRQ(ierr);
1905*0c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
1906*0c7d97c5SJed Brown     //if(pcbddc->check_flag && pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
1907*0c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) PetscPrintf(PETSC_COMM_WORLD,"----------------Setting up a new level---------------\n");
1908*0c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) PCBDDCSetCoarseProblemType(pcbddc->coarse_pc,MULTILEVEL_BDDC);
1909*0c7d97c5SJed Brown     ierr = PCSetUp(pcbddc->coarse_pc);CHKERRQ(ierr);
1910*0c7d97c5SJed Brown   }
1911*0c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
1912*0c7d97c5SJed Brown      IS local_IS,global_IS;
1913*0c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
1914*0c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
1915*0c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
1916*0c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
1917*0c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
1918*0c7d97c5SJed Brown   }
1919*0c7d97c5SJed Brown 
1920*0c7d97c5SJed Brown 
1921*0c7d97c5SJed Brown   /* Check condition number of coarse problem */
1922*0c7d97c5SJed Brown   /* How to destroy KSP without destroying PC associated with? */
1923*0c7d97c5SJed Brown /*  if( rank_prec_comm == active_rank ) {
1924*0c7d97c5SJed Brown     KSP coarseksp;
1925*0c7d97c5SJed Brown     PetscScalar m_one=-1.0;
1926*0c7d97c5SJed Brown     PetscReal infty_error,lambda_min,lambda_max;
1927*0c7d97c5SJed Brown 
1928*0c7d97c5SJed Brown     KSPCreate(coarse_comm,&coarseksp);
1929*0c7d97c5SJed Brown     KSPSetType(coarseksp,KSPCG);
1930*0c7d97c5SJed Brown     KSPSetOperators(coarseksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);
1931*0c7d97c5SJed Brown     KSPSetPC(coarseksp,pcbddc->coarse_pc);
1932*0c7d97c5SJed Brown     KSPSetComputeSingularValues(coarseksp,PETSC_TRUE);
1933*0c7d97c5SJed Brown     VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);
1934*0c7d97c5SJed Brown     MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);
1935*0c7d97c5SJed Brown     MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);
1936*0c7d97c5SJed Brown     KSPSolve(coarseksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);
1937*0c7d97c5SJed Brown     KSPComputeExtremeSingularValues(coarseksp,&lambda_max,&lambda_min);
1938*0c7d97c5SJed Brown     VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);
1939*0c7d97c5SJed Brown     VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);
1940*0c7d97c5SJed Brown     printf("eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);
1941*0c7d97c5SJed Brown     printf("Error on coarse ksp %1.14e\n",infty_error);
1942*0c7d97c5SJed Brown 
1943*0c7d97c5SJed Brown   }*/
1944*0c7d97c5SJed Brown 
1945*0c7d97c5SJed Brown   /* free data structures no longer needed */
1946*0c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
1947*0c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
1948*0c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
1949*0c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
1950*0c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
1951*0c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
1952*0c7d97c5SJed Brown 
1953*0c7d97c5SJed Brown   PetscFunctionReturn(0);
1954*0c7d97c5SJed Brown 
1955*0c7d97c5SJed Brown }
1956*0c7d97c5SJed Brown 
1957*0c7d97c5SJed Brown #undef __FUNCT__
1958*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
1959*0c7d97c5SJed Brown PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
1960*0c7d97c5SJed Brown {
1961*0c7d97c5SJed Brown 
1962*0c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1963*0c7d97c5SJed Brown   PC_IS      *pcis = (PC_IS*)pc->data;
1964*0c7d97c5SJed Brown   Mat_IS   *matis  = (Mat_IS*)pc->pmat->data;
1965*0c7d97c5SJed Brown   PetscInt *distinct_values;
1966*0c7d97c5SJed Brown   PetscInt **array_int;
1967*0c7d97c5SJed Brown   PetscInt bs,ierr,i,j,s,k;
1968*0c7d97c5SJed Brown   PetscInt total_counts;
1969*0c7d97c5SJed Brown   PetscBool flg_row;
1970*0c7d97c5SJed Brown   PCBDDCGraph mat_graph;
1971*0c7d97c5SJed Brown   PetscScalar *array;
1972*0c7d97c5SJed Brown   Mat        mat_adj;
1973*0c7d97c5SJed Brown 
1974*0c7d97c5SJed Brown   PetscFunctionBegin;
1975*0c7d97c5SJed Brown 
1976*0c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1977*0c7d97c5SJed Brown   // allocate and initialize needed graph structure
1978*0c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
1979*0c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
1980*0c7d97c5SJed Brown   ierr = MatGetRowIJ(mat_adj,0,PETSC_FALSE,PETSC_FALSE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
1981*0c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
1982*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->where);CHKERRQ(ierr);
1983*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->count);CHKERRQ(ierr);
1984*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->which_dof);CHKERRQ(ierr);
1985*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&mat_graph->queue);CHKERRQ(ierr);
1986*0c7d97c5SJed Brown   ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->cptr);CHKERRQ(ierr);
1987*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscBool),&mat_graph->touched);CHKERRQ(ierr);
1988*0c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
1989*0c7d97c5SJed Brown     mat_graph->count[i]=0;
1990*0c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_FALSE;
1991*0c7d97c5SJed Brown   }
1992*0c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs/bs;i++) {
1993*0c7d97c5SJed Brown     for(s=0;s<bs;s++) {
1994*0c7d97c5SJed Brown       mat_graph->which_dof[i*bs+s]=s;
1995*0c7d97c5SJed Brown     }
1996*0c7d97c5SJed Brown   }
1997*0c7d97c5SJed Brown   //printf("nvtxs = %d\n",mat_graph->nvtxs);
1998*0c7d97c5SJed Brown   //printf("these are my IS data with n_neigh = %d\n",pcis->n_neigh);
1999*0c7d97c5SJed Brown   //for(i=0;i<pcis->n_neigh;i++){
2000*0c7d97c5SJed Brown   //  printf("number of shared nodes with rank %d is %d \n",pcis->neigh[i],pcis->n_shared[i]);
2001*0c7d97c5SJed Brown   // }
2002*0c7d97c5SJed Brown 
2003*0c7d97c5SJed Brown   total_counts=0;
2004*0c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
2005*0c7d97c5SJed Brown     s=pcis->n_shared[i];
2006*0c7d97c5SJed Brown     total_counts+=s;
2007*0c7d97c5SJed Brown     //printf("computing neigh %d (rank = %d, n_shared = %d)\n",i,pcis->neigh[i],s);
2008*0c7d97c5SJed Brown     for(j=0;j<s;j=j++){
2009*0c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
2010*0c7d97c5SJed Brown     }
2011*0c7d97c5SJed Brown   }
2012*0c7d97c5SJed Brown   /* Take into account Neumann data incrementing number of sharing subdomains for all but faces nodes lying on the interface */
2013*0c7d97c5SJed Brown   if(pcbddc->Vec_Neumann) {
2014*0c7d97c5SJed Brown     ierr = VecGetArray(pcbddc->Vec_Neumann,&array);CHKERRQ(ierr);
2015*0c7d97c5SJed Brown     for(i=0;i<pcis->n;i++){
2016*0c7d97c5SJed Brown       if(array[i] > 0.0  && mat_graph->count[i] > 2){
2017*0c7d97c5SJed Brown         mat_graph->count[i]=mat_graph->count[i]+1;
2018*0c7d97c5SJed Brown         total_counts++;
2019*0c7d97c5SJed Brown       }
2020*0c7d97c5SJed Brown     }
2021*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcbddc->Vec_Neumann,&array);CHKERRQ(ierr);
2022*0c7d97c5SJed Brown   }
2023*0c7d97c5SJed Brown 
2024*0c7d97c5SJed Brown   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&array_int);CHKERRQ(ierr);
2025*0c7d97c5SJed Brown   if(mat_graph->nvtxs) ierr = PetscMalloc(total_counts*sizeof(PetscInt),&array_int[0]);CHKERRQ(ierr);
2026*0c7d97c5SJed Brown   for(i=1;i<mat_graph->nvtxs;i++) array_int[i]=array_int[i-1]+mat_graph->count[i-1];
2027*0c7d97c5SJed Brown 
2028*0c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++) mat_graph->count[i]=0;
2029*0c7d97c5SJed Brown   for(i=0;i<pcis->n_neigh;i++){
2030*0c7d97c5SJed Brown     s=pcis->n_shared[i];
2031*0c7d97c5SJed Brown     for(j=0;j<s;j++) {
2032*0c7d97c5SJed Brown       k=pcis->shared[i][j];
2033*0c7d97c5SJed Brown       array_int[k][mat_graph->count[k]] = pcis->neigh[i];
2034*0c7d97c5SJed Brown       mat_graph->count[k]+=1;
2035*0c7d97c5SJed Brown     }
2036*0c7d97c5SJed Brown   }
2037*0c7d97c5SJed Brown   /* set -1 fake neighbour */
2038*0c7d97c5SJed Brown   if(pcbddc->Vec_Neumann) {
2039*0c7d97c5SJed Brown     ierr = VecGetArray(pcbddc->Vec_Neumann,&array);CHKERRQ(ierr);
2040*0c7d97c5SJed Brown     for(i=0;i<pcis->n;i++){
2041*0c7d97c5SJed Brown       if( array[i] > 0.0 && mat_graph->count[i] > 2){
2042*0c7d97c5SJed Brown         array_int[i][mat_graph->count[i]] = -1; //An additional fake neighbour (with rank -1)
2043*0c7d97c5SJed Brown         mat_graph->count[i]+=1;
2044*0c7d97c5SJed Brown       }
2045*0c7d97c5SJed Brown     }
2046*0c7d97c5SJed Brown     ierr = VecRestoreArray(pcbddc->Vec_Neumann,&array);CHKERRQ(ierr);
2047*0c7d97c5SJed Brown   }
2048*0c7d97c5SJed Brown 
2049*0c7d97c5SJed Brown   /* sort sharing subdomains */
2050*0c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],array_int[i]);CHKERRQ(ierr); }
2051*0c7d97c5SJed Brown 
2052*0c7d97c5SJed Brown   // Prepare for FindConnectedComponents
2053*0c7d97c5SJed Brown   // Vertices will be eliminated later (if needed)
2054*0c7d97c5SJed Brown   PetscInt nodes_touched=0;
2055*0c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
2056*0c7d97c5SJed Brown     if(!mat_graph->count[i]){  //internal nodes
2057*0c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
2058*0c7d97c5SJed Brown       mat_graph->where[i]=0;
2059*0c7d97c5SJed Brown       nodes_touched++;
2060*0c7d97c5SJed Brown     }
2061*0c7d97c5SJed Brown     if(pcbddc->faces_flag){
2062*0c7d97c5SJed Brown       if(mat_graph->count[i]>2){  //all but faces
2063*0c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
2064*0c7d97c5SJed Brown         mat_graph->where[i]=0;
2065*0c7d97c5SJed Brown         nodes_touched++;
2066*0c7d97c5SJed Brown       }
2067*0c7d97c5SJed Brown     }
2068*0c7d97c5SJed Brown     if(pcbddc->edges_flag){
2069*0c7d97c5SJed Brown       if(mat_graph->count[i]==2){  //faces
2070*0c7d97c5SJed Brown         mat_graph->touched[i]=PETSC_TRUE;
2071*0c7d97c5SJed Brown         mat_graph->where[i]=0;
2072*0c7d97c5SJed Brown         nodes_touched++;
2073*0c7d97c5SJed Brown       }
2074*0c7d97c5SJed Brown     }
2075*0c7d97c5SJed Brown   }
2076*0c7d97c5SJed Brown 
2077*0c7d97c5SJed Brown   PetscInt rvalue=1;
2078*0c7d97c5SJed Brown   PetscBool same_set;
2079*0c7d97c5SJed Brown   mat_graph->ncmps = 0;
2080*0c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2081*0c7d97c5SJed Brown     // find first untouched node in local ordering
2082*0c7d97c5SJed Brown     i=0;
2083*0c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
2084*0c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2085*0c7d97c5SJed Brown     mat_graph->where[i]=rvalue;
2086*0c7d97c5SJed Brown     nodes_touched++;
2087*0c7d97c5SJed Brown     // now find other connected nodes shared by the same set of subdomains
2088*0c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2089*0c7d97c5SJed Brown       // check for same number of sharing subdomains and dof number
2090*0c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2091*0c7d97c5SJed Brown         // check for same set of sharing subdomains
2092*0c7d97c5SJed Brown         same_set=PETSC_TRUE;
2093*0c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
2094*0c7d97c5SJed Brown           if(array_int[i][k]!=array_int[j][k]) {
2095*0c7d97c5SJed Brown             same_set=PETSC_FALSE;
2096*0c7d97c5SJed Brown           }
2097*0c7d97c5SJed Brown         }
2098*0c7d97c5SJed Brown         // OK, I found a friend of mine
2099*0c7d97c5SJed Brown         if(same_set) {
2100*0c7d97c5SJed Brown           mat_graph->where[j]=rvalue;
2101*0c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
2102*0c7d97c5SJed Brown           nodes_touched++;
2103*0c7d97c5SJed Brown         }
2104*0c7d97c5SJed Brown       }
2105*0c7d97c5SJed Brown     }
2106*0c7d97c5SJed Brown     rvalue++;
2107*0c7d97c5SJed Brown   }
2108*0c7d97c5SJed Brown //  printf("where and count contains %d distinct values\n",rvalue);
2109*0c7d97c5SJed Brown //  for(j=0;j<mat_graph->nvtxs;j++)
2110*0c7d97c5SJed Brown //    printf("[%d %d %d]\n",j,mat_graph->where[j],mat_graph->count[j]);
2111*0c7d97c5SJed Brown 
2112*0c7d97c5SJed Brown   if(mat_graph->nvtxs) {
2113*0c7d97c5SJed Brown     ierr = PetscFree(array_int[0]);CHKERRQ(ierr);
2114*0c7d97c5SJed Brown     ierr = PetscFree(array_int);CHKERRQ(ierr);
2115*0c7d97c5SJed Brown   }
2116*0c7d97c5SJed Brown 
2117*0c7d97c5SJed Brown   rvalue--;
2118*0c7d97c5SJed Brown   ierr  = PetscMalloc ( rvalue*sizeof(PetscInt),&distinct_values);CHKERRQ(ierr);
2119*0c7d97c5SJed Brown   for(i=0;i<rvalue;i++) distinct_values[i]=i+1;  //initializiation
2120*0c7d97c5SJed Brown   if(rvalue) ierr = PCBDDCFindConnectedComponents(mat_graph, rvalue, distinct_values);
2121*0c7d97c5SJed Brown   //printf("total number of connected components %d \n",mat_graph->ncmps);
2122*0c7d97c5SJed Brown   //for (i=0; i<mat_graph->ncmps; i++) {
2123*0c7d97c5SJed 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]]);
2124*0c7d97c5SJed Brown   //}
2125*0c7d97c5SJed Brown   PetscInt nfc=0;
2126*0c7d97c5SJed Brown   PetscInt nec=0;
2127*0c7d97c5SJed Brown   PetscInt nvc=0;
2128*0c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
2129*0c7d97c5SJed Brown     // sort each connected component (by local ordering)
2130*0c7d97c5SJed Brown     ierr = PetscSortInt(mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2131*0c7d97c5SJed Brown     // count edge and faces
2132*0c7d97c5SJed Brown     if( !pcbddc->vertices_flag ) {
2133*0c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
2134*0c7d97c5SJed Brown         if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==2){
2135*0c7d97c5SJed Brown           nfc++;
2136*0c7d97c5SJed Brown         } else {
2137*0c7d97c5SJed Brown           nec++;
2138*0c7d97c5SJed Brown         }
2139*0c7d97c5SJed Brown       }
2140*0c7d97c5SJed Brown     }
2141*0c7d97c5SJed Brown     // count vertices
2142*0c7d97c5SJed Brown     if( !pcbddc->constraints_flag ){
2143*0c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
2144*0c7d97c5SJed Brown         nvc++;
2145*0c7d97c5SJed Brown       }
2146*0c7d97c5SJed Brown     }
2147*0c7d97c5SJed Brown   }
2148*0c7d97c5SJed Brown 
2149*0c7d97c5SJed Brown   pcbddc->n_constraints = nec+nfc;
2150*0c7d97c5SJed Brown   pcbddc->n_vertices    = nvc;
2151*0c7d97c5SJed Brown 
2152*0c7d97c5SJed Brown   if(pcbddc->n_constraints){
2153*0c7d97c5SJed Brown     /* allocate space for local constraints of BDDC */
2154*0c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt*),&pcbddc->indices_to_constraint);CHKERRQ(ierr);
2155*0c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscScalar*),&pcbddc->quadrature_constraint);CHKERRQ(ierr);
2156*0c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_constraints*sizeof(PetscInt),&pcbddc->sizes_of_constraint);CHKERRQ(ierr);
2157*0c7d97c5SJed Brown     k=0;
2158*0c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
2159*0c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
2160*0c7d97c5SJed Brown         pcbddc->sizes_of_constraint[k] = mat_graph->cptr[i+1]-mat_graph->cptr[i];
2161*0c7d97c5SJed Brown         k++;
2162*0c7d97c5SJed Brown       }
2163*0c7d97c5SJed Brown     }
2164*0c7d97c5SJed Brown //    printf("check constraints %d (should be %d)\n",k,pcbddc->n_constraints);
2165*0c7d97c5SJed Brown //    for(i=0;i<k;i++)
2166*0c7d97c5SJed Brown //      printf("%d ",pcbddc->sizes_of_constraint[i]);
2167*0c7d97c5SJed Brown //    printf("\n");
2168*0c7d97c5SJed Brown     k=0;
2169*0c7d97c5SJed Brown     for (i=0; i<pcbddc->n_constraints; i++) k+=pcbddc->sizes_of_constraint[i];
2170*0c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscInt),&pcbddc->indices_to_constraint[0]);CHKERRQ(ierr);
2171*0c7d97c5SJed Brown     ierr = PetscMalloc (k*sizeof(PetscScalar),&pcbddc->quadrature_constraint[0]);CHKERRQ(ierr);
2172*0c7d97c5SJed Brown     for (i=1; i<pcbddc->n_constraints; i++) {
2173*0c7d97c5SJed Brown       pcbddc->indices_to_constraint[i]  = pcbddc->indices_to_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
2174*0c7d97c5SJed Brown       pcbddc->quadrature_constraint[i]  = pcbddc->quadrature_constraint[i-1] + pcbddc->sizes_of_constraint[i-1];
2175*0c7d97c5SJed Brown     }
2176*0c7d97c5SJed Brown     k=0;
2177*0c7d97c5SJed Brown     PetscScalar quad_value;
2178*0c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
2179*0c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > 1 ){
2180*0c7d97c5SJed Brown         quad_value=1.0/( (PetscScalar) (mat_graph->cptr[i+1]-mat_graph->cptr[i]) );
2181*0c7d97c5SJed Brown         for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
2182*0c7d97c5SJed Brown           pcbddc->indices_to_constraint[k][j] = mat_graph->queue[mat_graph->cptr[i]+j];
2183*0c7d97c5SJed Brown           pcbddc->quadrature_constraint[k][j] = quad_value;
2184*0c7d97c5SJed Brown         }
2185*0c7d97c5SJed Brown         k++;
2186*0c7d97c5SJed Brown       }
2187*0c7d97c5SJed Brown     }
2188*0c7d97c5SJed Brown   }
2189*0c7d97c5SJed Brown   if(pcbddc->n_vertices){
2190*0c7d97c5SJed Brown     /* allocate space for local vertices of BDDC */
2191*0c7d97c5SJed Brown     ierr  = PetscMalloc (pcbddc->n_vertices*sizeof(PetscInt),&pcbddc->vertices);CHKERRQ(ierr);
2192*0c7d97c5SJed Brown     k=0;
2193*0c7d97c5SJed Brown     for (i=0; i<mat_graph->ncmps; i++) {
2194*0c7d97c5SJed Brown       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] == 1 ){
2195*0c7d97c5SJed Brown         pcbddc->vertices[k] = mat_graph->queue[mat_graph->cptr[i]];
2196*0c7d97c5SJed Brown         k++;
2197*0c7d97c5SJed Brown       }
2198*0c7d97c5SJed Brown     }
2199*0c7d97c5SJed Brown     // sort vertex set (by local ordering)
2200*0c7d97c5SJed Brown     ierr = PetscSortInt(pcbddc->n_vertices,pcbddc->vertices);CHKERRQ(ierr);
2201*0c7d97c5SJed Brown   }
2202*0c7d97c5SJed Brown 
2203*0c7d97c5SJed Brown   if(pcbddc->check_flag) {
2204*0c7d97c5SJed Brown     PetscViewer     viewer;
2205*0c7d97c5SJed Brown     PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);
2206*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
2207*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
2208*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);
2209*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
2210*0c7d97c5SJed Brown //    PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");
2211*0c7d97c5SJed Brown //    PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");
2212*0c7d97c5SJed Brown //    for(i=0;i<mat_graph->nvtxs;i++) {
2213*0c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);
2214*0c7d97c5SJed Brown //      for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
2215*0c7d97c5SJed Brown //        PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);
2216*0c7d97c5SJed Brown //      }
2217*0c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");
2218*0c7d97c5SJed Brown //    }
2219*0c7d97c5SJed Brown     // TODO: APPLY Local to Global Mapping from IS object?
2220*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);
2221*0c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
2222*0c7d97c5SJed 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]]]);
2223*0c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
2224*0c7d97c5SJed Brown         PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->queue[j]);
2225*0c7d97c5SJed Brown       }
2226*0c7d97c5SJed Brown     }
2227*0c7d97c5SJed Brown     PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");
2228*0c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,pcbddc->n_vertices);
2229*0c7d97c5SJed Brown     if( nfc )                PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);
2230*0c7d97c5SJed Brown     if( nec )                PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);
2231*0c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain vertices follows\n",PetscGlobalRank,pcbddc->n_vertices);
2232*0c7d97c5SJed Brown     for(i=0;i<pcbddc->n_vertices;i++){
2233*0c7d97c5SJed Brown                              PetscViewerASCIISynchronizedPrintf(viewer,"%d ",pcbddc->vertices[i]);
2234*0c7d97c5SJed Brown     }
2235*0c7d97c5SJed Brown     if( pcbddc->n_vertices ) PetscViewerASCIISynchronizedPrintf(viewer,"\n");
2236*0c7d97c5SJed Brown //    if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"Indices and quadrature constraints");
2237*0c7d97c5SJed Brown //    for(i=0;i<pcbddc->n_constraints;i++){
2238*0c7d97c5SJed Brown //      PetscViewerASCIISynchronizedPrintf(viewer,"\nConstraint number %d\n",i);
2239*0c7d97c5SJed Brown //      for(j=0;j<pcbddc->sizes_of_constraint[i];j++) {
2240*0c7d97c5SJed Brown //        PetscViewerASCIISynchronizedPrintf(viewer,"(%d, %f) ",pcbddc->indices_to_constraint[i][j],pcbddc->quadrature_constraint[i][j]);
2241*0c7d97c5SJed Brown //      }
2242*0c7d97c5SJed Brown //    }
2243*0c7d97c5SJed Brown //    if( pcbddc->n_constraints ) PetscViewerASCIISynchronizedPrintf(viewer,"\n");
2244*0c7d97c5SJed Brown     PetscViewerFlush(viewer);
2245*0c7d97c5SJed Brown   }
2246*0c7d97c5SJed Brown 
2247*0c7d97c5SJed Brown   // Restore CSR structure into sequantial matrix and free memory space no longer needed
2248*0c7d97c5SJed Brown   ierr = MatRestoreRowIJ(mat_adj,0,PETSC_FALSE,PETSC_TRUE,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
2249*0c7d97c5SJed Brown   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2250*0c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
2251*0c7d97c5SJed Brown   ierr = PetscFree(distinct_values);CHKERRQ(ierr);
2252*0c7d97c5SJed Brown   // Free graph structure
2253*0c7d97c5SJed Brown   if(mat_graph->nvtxs){
2254*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->where);CHKERRQ(ierr);
2255*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->touched);CHKERRQ(ierr);
2256*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->which_dof);CHKERRQ(ierr);
2257*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->queue);CHKERRQ(ierr);
2258*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->cptr);CHKERRQ(ierr);
2259*0c7d97c5SJed Brown     ierr = PetscFree(mat_graph->count);CHKERRQ(ierr);
2260*0c7d97c5SJed Brown   }
2261*0c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
2262*0c7d97c5SJed Brown 
2263*0c7d97c5SJed Brown   PetscFunctionReturn(0);
2264*0c7d97c5SJed Brown 
2265*0c7d97c5SJed Brown }
2266*0c7d97c5SJed Brown 
2267*0c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2268*0c7d97c5SJed Brown 
2269*0c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
2270*0c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
2271*0c7d97c5SJed Brown 
2272*0c7d97c5SJed Brown #undef __FUNCT__
2273*0c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
2274*0c7d97c5SJed Brown PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist, PetscInt *dist_vals)
2275*0c7d97c5SJed Brown {
2276*0c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
2277*0c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
2278*0c7d97c5SJed Brown   PetscInt *cptr;
2279*0c7d97c5SJed Brown   PetscBool *touched;
2280*0c7d97c5SJed Brown 
2281*0c7d97c5SJed Brown   PetscFunctionBegin;
2282*0c7d97c5SJed Brown 
2283*0c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
2284*0c7d97c5SJed Brown   xadj    = graph->xadj;
2285*0c7d97c5SJed Brown   adjncy  = graph->adjncy;
2286*0c7d97c5SJed Brown   where   = graph->where;
2287*0c7d97c5SJed Brown   touched = graph->touched;
2288*0c7d97c5SJed Brown   queue   = graph->queue;
2289*0c7d97c5SJed Brown   cptr    = graph->cptr;
2290*0c7d97c5SJed Brown 
2291*0c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
2292*0c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
2293*0c7d97c5SJed Brown 
2294*0c7d97c5SJed Brown   cum_queue=0;
2295*0c7d97c5SJed Brown   ncmps=0;
2296*0c7d97c5SJed Brown 
2297*0c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
2298*0c7d97c5SJed Brown 
2299*0c7d97c5SJed Brown     pid = dist_vals[n];
2300*0c7d97c5SJed Brown     nleft = 0;
2301*0c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
2302*0c7d97c5SJed Brown       if (where[i] == pid)
2303*0c7d97c5SJed Brown         nleft++;
2304*0c7d97c5SJed Brown     }
2305*0c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
2306*0c7d97c5SJed Brown       if (where[i] == pid)
2307*0c7d97c5SJed Brown         break;
2308*0c7d97c5SJed Brown     }
2309*0c7d97c5SJed Brown 
2310*0c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
2311*0c7d97c5SJed Brown     queue[cum_queue] = i;
2312*0c7d97c5SJed Brown     first = 0; last = 1;
2313*0c7d97c5SJed Brown 
2314*0c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
2315*0c7d97c5SJed Brown     ncmps_pid = 0;
2316*0c7d97c5SJed Brown     while (first != nleft) {
2317*0c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
2318*0c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
2319*0c7d97c5SJed Brown         ncmps_pid++;
2320*0c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
2321*0c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
2322*0c7d97c5SJed Brown             break;
2323*0c7d97c5SJed Brown         }
2324*0c7d97c5SJed Brown         queue[cum_queue+last] = i;
2325*0c7d97c5SJed Brown         last++;
2326*0c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
2327*0c7d97c5SJed Brown       }
2328*0c7d97c5SJed Brown 
2329*0c7d97c5SJed Brown       i = queue[cum_queue+first];
2330*0c7d97c5SJed Brown       first++;
2331*0c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
2332*0c7d97c5SJed Brown         k = adjncy[j];
2333*0c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
2334*0c7d97c5SJed Brown           queue[cum_queue+last] = k;
2335*0c7d97c5SJed Brown           last++;
2336*0c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
2337*0c7d97c5SJed Brown         }
2338*0c7d97c5SJed Brown       }
2339*0c7d97c5SJed Brown     }
2340*0c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
2341*0c7d97c5SJed Brown     ncmps_pid++;
2342*0c7d97c5SJed Brown     cum_queue=cptr[ncmps];
2343*0c7d97c5SJed Brown 
2344*0c7d97c5SJed Brown     //printf("The graph has %d connected components in partition %d\n", ncmps_pid, pid);
2345*0c7d97c5SJed Brown   }
2346*0c7d97c5SJed Brown   graph->ncmps = ncmps;
2347*0c7d97c5SJed Brown 
2348*0c7d97c5SJed Brown   PetscFunctionReturn(0);
2349*0c7d97c5SJed Brown }
2350*0c7d97c5SJed Brown 
2351