xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 11d8f4c266f2f7cba76c182cbc6d55893d277fca)
153cdbc3dSStefano Zampini /* TODOLIST
2da1bb401SStefano Zampini    DofSplitting and DM attached to pc?
3da1bb401SStefano Zampini    Change SetNeumannBoundaries to SetNeumannBoundariesLocal and provide new SetNeumannBoundaries (same Dirichlet)
4da1bb401SStefano Zampini    Exact solvers: Solve local saddle point directly
5831a100dSStefano Zampini      - change prec_type to switch_inexact_prec_type
6831a100dSStefano Zampini      - add bool solve_exact_saddle_point slot to pdbddc data
73b03a366Sstefano_zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
8a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
9a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
10a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
11a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
12a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
133b03a366Sstefano_zampini      - Add levels' slot to bddc data structure and associated Set/Get functions
14a0ba757dSStefano Zampini    code refactoring:
15a0ba757dSStefano Zampini      - pick up better names for static functions
16a0ba757dSStefano Zampini    change options structure:
17a0ba757dSStefano Zampini      - insert BDDC into MG framework?
18a0ba757dSStefano Zampini    provide other ops? Ask to developers
19a0ba757dSStefano Zampini    remove all unused printf
20a0ba757dSStefano Zampini    man pages
2153cdbc3dSStefano Zampini */
220c7d97c5SJed Brown 
2353cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
240c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
250c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2653cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2753cdbc3dSStefano Zampini 
2853cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
293b03a366Sstefano_zampini #include <petscblaslapack.h>
300c7d97c5SJed Brown 
310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
320c7d97c5SJed Brown #undef __FUNCT__
330c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
340c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
350c7d97c5SJed Brown {
360c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
370c7d97c5SJed Brown   PetscErrorCode ierr;
380c7d97c5SJed Brown 
390c7d97c5SJed Brown   PetscFunctionBegin;
400c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Verbose debugging of main data structures */
42e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
430c7d97c5SJed Brown   /* Some customization for default primal space */
44da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use only vertices in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
45da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use only constraints in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
46da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use only faces among constraints of coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
47da1bb401SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use only edges among constraints of coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
480c7d97c5SJed Brown   /* Coarse solver context */
49da1bb401SStefano Zampini   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; /*order of choiches depends on ENUM defined in bddc.h */
500c7d97c5SJed 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);
510c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
520c7d97c5SJed 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);
530c7d97c5SJed 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);
540c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
550c7d97c5SJed Brown   PetscFunctionReturn(0);
560c7d97c5SJed Brown }
570c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
580c7d97c5SJed Brown EXTERN_C_BEGIN
590c7d97c5SJed Brown #undef __FUNCT__
600c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
620c7d97c5SJed Brown {
630c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
640c7d97c5SJed Brown 
650c7d97c5SJed Brown   PetscFunctionBegin;
660c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
670c7d97c5SJed Brown   PetscFunctionReturn(0);
680c7d97c5SJed Brown }
690c7d97c5SJed Brown EXTERN_C_END
700c7d97c5SJed Brown #undef __FUNCT__
710c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7253cdbc3dSStefano Zampini /*@
739c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7453cdbc3dSStefano Zampini 
759c0446d6SStefano Zampini    Not collective
7653cdbc3dSStefano Zampini 
7753cdbc3dSStefano Zampini    Input Parameters:
7853cdbc3dSStefano Zampini +  pc - the preconditioning context
7953cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8053cdbc3dSStefano Zampini 
8153cdbc3dSStefano Zampini    Level: intermediate
8253cdbc3dSStefano Zampini 
8353cdbc3dSStefano Zampini    Notes:
84da1bb401SStefano Zampini    Not collective but all procs must call with same arguments.
8553cdbc3dSStefano Zampini 
8653cdbc3dSStefano Zampini .seealso: PCBDDC
8753cdbc3dSStefano Zampini @*/
880c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
890c7d97c5SJed Brown {
900c7d97c5SJed Brown   PetscErrorCode ierr;
910c7d97c5SJed Brown 
920c7d97c5SJed Brown   PetscFunctionBegin;
930c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
940c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
950c7d97c5SJed Brown   PetscFunctionReturn(0);
960c7d97c5SJed Brown }
970c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
980c7d97c5SJed Brown EXTERN_C_BEGIN
990c7d97c5SJed Brown #undef __FUNCT__
1003b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
1013b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
1023b03a366Sstefano_zampini {
1033b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1043b03a366Sstefano_zampini   PetscErrorCode ierr;
1053b03a366Sstefano_zampini 
1063b03a366Sstefano_zampini   PetscFunctionBegin;
1073b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
10836e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
10936e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
1103b03a366Sstefano_zampini   PetscFunctionReturn(0);
1113b03a366Sstefano_zampini }
1123b03a366Sstefano_zampini EXTERN_C_END
1133b03a366Sstefano_zampini #undef __FUNCT__
1143b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
1153b03a366Sstefano_zampini /*@
116da1bb401SStefano Zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part (in local ordering)
117da1bb401SStefano Zampini                               of Dirichlet boundaries for the global problem.
1183b03a366Sstefano_zampini 
1193b03a366Sstefano_zampini    Not collective
1203b03a366Sstefano_zampini 
1213b03a366Sstefano_zampini    Input Parameters:
1223b03a366Sstefano_zampini +  pc - the preconditioning context
1233b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
1243b03a366Sstefano_zampini 
1253b03a366Sstefano_zampini    Level: intermediate
1263b03a366Sstefano_zampini 
1273b03a366Sstefano_zampini    Notes:
1283b03a366Sstefano_zampini 
1293b03a366Sstefano_zampini .seealso: PCBDDC
1303b03a366Sstefano_zampini @*/
1313b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
1323b03a366Sstefano_zampini {
1333b03a366Sstefano_zampini   PetscErrorCode ierr;
1343b03a366Sstefano_zampini 
1353b03a366Sstefano_zampini   PetscFunctionBegin;
1363b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1373b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
1383b03a366Sstefano_zampini   PetscFunctionReturn(0);
1393b03a366Sstefano_zampini }
1403b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1413b03a366Sstefano_zampini EXTERN_C_BEGIN
1423b03a366Sstefano_zampini #undef __FUNCT__
1430c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
14453cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1450c7d97c5SJed Brown {
1460c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
14753cdbc3dSStefano Zampini   PetscErrorCode ierr;
1480c7d97c5SJed Brown 
1490c7d97c5SJed Brown   PetscFunctionBegin;
15053cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
15136e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
15236e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
1530c7d97c5SJed Brown   PetscFunctionReturn(0);
1540c7d97c5SJed Brown }
1550c7d97c5SJed Brown EXTERN_C_END
1560c7d97c5SJed Brown #undef __FUNCT__
1570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
15857527edcSJed Brown /*@
159da1bb401SStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part (in local ordering)
160da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
16157527edcSJed Brown 
1629c0446d6SStefano Zampini    Not collective
16357527edcSJed Brown 
16457527edcSJed Brown    Input Parameters:
16557527edcSJed Brown +  pc - the preconditioning context
1669c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
16757527edcSJed Brown 
16857527edcSJed Brown    Level: intermediate
16957527edcSJed Brown 
17057527edcSJed Brown    Notes:
17157527edcSJed Brown 
17257527edcSJed Brown .seealso: PCBDDC
17357527edcSJed Brown @*/
17453cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1750c7d97c5SJed Brown {
1760c7d97c5SJed Brown   PetscErrorCode ierr;
1770c7d97c5SJed Brown 
1780c7d97c5SJed Brown   PetscFunctionBegin;
1790c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18053cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
18153cdbc3dSStefano Zampini   PetscFunctionReturn(0);
18253cdbc3dSStefano Zampini }
18353cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
18453cdbc3dSStefano Zampini EXTERN_C_BEGIN
18553cdbc3dSStefano Zampini #undef __FUNCT__
186da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
187da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
188da1bb401SStefano Zampini {
189da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
190da1bb401SStefano Zampini 
191da1bb401SStefano Zampini   PetscFunctionBegin;
192da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
193da1bb401SStefano Zampini   PetscFunctionReturn(0);
194da1bb401SStefano Zampini }
195da1bb401SStefano Zampini EXTERN_C_END
196da1bb401SStefano Zampini #undef __FUNCT__
197da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
198da1bb401SStefano Zampini /*@
199da1bb401SStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part (in local ordering)
200da1bb401SStefano Zampini                                 of Dirichlet boundaries for the global problem.
201da1bb401SStefano Zampini 
202da1bb401SStefano Zampini    Not collective
203da1bb401SStefano Zampini 
204da1bb401SStefano Zampini    Input Parameters:
205da1bb401SStefano Zampini +  pc - the preconditioning context
206da1bb401SStefano Zampini 
207da1bb401SStefano Zampini    Output Parameters:
208da1bb401SStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
209da1bb401SStefano Zampini 
210da1bb401SStefano Zampini    Level: intermediate
211da1bb401SStefano Zampini 
212da1bb401SStefano Zampini    Notes:
213da1bb401SStefano Zampini 
214da1bb401SStefano Zampini .seealso: PCBDDC
215da1bb401SStefano Zampini @*/
216da1bb401SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
217da1bb401SStefano Zampini {
218da1bb401SStefano Zampini   PetscErrorCode ierr;
219da1bb401SStefano Zampini 
220da1bb401SStefano Zampini   PetscFunctionBegin;
221da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
222da1bb401SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
223da1bb401SStefano Zampini   PetscFunctionReturn(0);
224da1bb401SStefano Zampini }
225da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
226da1bb401SStefano Zampini EXTERN_C_BEGIN
227da1bb401SStefano Zampini #undef __FUNCT__
22853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
22953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
23053cdbc3dSStefano Zampini {
23153cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
23253cdbc3dSStefano Zampini 
23353cdbc3dSStefano Zampini   PetscFunctionBegin;
23453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
23553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
23653cdbc3dSStefano Zampini }
23753cdbc3dSStefano Zampini EXTERN_C_END
23853cdbc3dSStefano Zampini #undef __FUNCT__
23953cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
24053cdbc3dSStefano Zampini /*@
241da1bb401SStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part (in local ordering)
242da1bb401SStefano Zampini                               of Neumann boundaries for the global problem.
24353cdbc3dSStefano Zampini 
2449c0446d6SStefano Zampini    Not collective
24553cdbc3dSStefano Zampini 
24653cdbc3dSStefano Zampini    Input Parameters:
24753cdbc3dSStefano Zampini +  pc - the preconditioning context
24853cdbc3dSStefano Zampini 
24953cdbc3dSStefano Zampini    Output Parameters:
25053cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
25153cdbc3dSStefano Zampini 
25253cdbc3dSStefano Zampini    Level: intermediate
25353cdbc3dSStefano Zampini 
25453cdbc3dSStefano Zampini    Notes:
25553cdbc3dSStefano Zampini 
25653cdbc3dSStefano Zampini .seealso: PCBDDC
25753cdbc3dSStefano Zampini @*/
25853cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
25953cdbc3dSStefano Zampini {
26053cdbc3dSStefano Zampini   PetscErrorCode ierr;
26153cdbc3dSStefano Zampini 
26253cdbc3dSStefano Zampini   PetscFunctionBegin;
26353cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
26453cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
2650c7d97c5SJed Brown   PetscFunctionReturn(0);
2660c7d97c5SJed Brown }
26736e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
26836e030ebSStefano Zampini EXTERN_C_BEGIN
26936e030ebSStefano Zampini #undef __FUNCT__
270da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
271da1bb401SStefano Zampini static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs, PetscInt xadj[], PetscInt adjncy[], PetscCopyMode copymode)
27236e030ebSStefano Zampini {
27336e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
274da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
275da1bb401SStefano Zampini   PetscErrorCode ierr;
27636e030ebSStefano Zampini 
27736e030ebSStefano Zampini   PetscFunctionBegin;
278da1bb401SStefano Zampini   mat_graph->nvtxs=nvtxs;
279da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->xadj);CHKERRQ(ierr);
280da1bb401SStefano Zampini   ierr = PetscFree(mat_graph->adjncy);CHKERRQ(ierr);
281da1bb401SStefano Zampini   if(copymode == PETSC_COPY_VALUES) {
282da1bb401SStefano Zampini     ierr = PetscMalloc((mat_graph->nvtxs+1)*sizeof(PetscInt),&mat_graph->xadj);CHKERRQ(ierr);
283da1bb401SStefano Zampini     ierr = PetscMalloc(xadj[mat_graph->nvtxs]*sizeof(PetscInt),&mat_graph->adjncy);CHKERRQ(ierr);
284da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
285da1bb401SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[mat_graph->nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
286da1bb401SStefano Zampini   } else if(copymode == PETSC_OWN_POINTER) {
287da1bb401SStefano Zampini     mat_graph->xadj=xadj;
288da1bb401SStefano Zampini     mat_graph->adjncy=adjncy;
289da1bb401SStefano Zampini   } else {
290da1bb401SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
291da1bb401SStefano Zampini   }
29236e030ebSStefano Zampini   PetscFunctionReturn(0);
29336e030ebSStefano Zampini }
29436e030ebSStefano Zampini EXTERN_C_END
29536e030ebSStefano Zampini #undef __FUNCT__
296da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
29736e030ebSStefano Zampini /*@
298da1bb401SStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set CSR graph of local matrix for use of PCBDDC.
29936e030ebSStefano Zampini 
30036e030ebSStefano Zampini    Not collective
30136e030ebSStefano Zampini 
30236e030ebSStefano Zampini    Input Parameters:
30336e030ebSStefano Zampini +  pc - the preconditioning context
304da1bb401SStefano Zampini -  nvtxs - number of local vertices of the graph
305da1bb401SStefano Zampini -  xadj, adjncy - the CSR graph
306da1bb401SStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER. In the former case the user must free the array passed in;
307da1bb401SStefano Zampini                                                              in the latter case, memory must be obtained with PetscMalloc.
30836e030ebSStefano Zampini 
30936e030ebSStefano Zampini    Level: intermediate
31036e030ebSStefano Zampini 
31136e030ebSStefano Zampini    Notes:
31236e030ebSStefano Zampini 
31336e030ebSStefano Zampini .seealso: PCBDDC
31436e030ebSStefano Zampini @*/
315da1bb401SStefano Zampini PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,PetscInt xadj[],PetscInt adjncy[], PetscCopyMode copymode)
31636e030ebSStefano Zampini {
317da1bb401SStefano Zampini   PetscInt       nrows,ncols;
318da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
31936e030ebSStefano Zampini   PetscErrorCode ierr;
32036e030ebSStefano Zampini 
32136e030ebSStefano Zampini   PetscFunctionBegin;
32236e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
323da1bb401SStefano Zampini   ierr = MatGetSize(matis->A,&nrows,&ncols);CHKERRQ(ierr);
324da1bb401SStefano Zampini   if(nvtxs != nrows) {
325da1bb401SStefano Zampini     SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local adjacency size %d passed in %s differs from local problem size %d!\n",nvtxs,__FUNCT__,nrows);
326da1bb401SStefano Zampini   } else {
327da1bb401SStefano Zampini     ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,PetscInt[],PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
328da1bb401SStefano Zampini   }
32936e030ebSStefano Zampini   PetscFunctionReturn(0);
33036e030ebSStefano Zampini }
3319c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
3329c0446d6SStefano Zampini EXTERN_C_BEGIN
3339c0446d6SStefano Zampini #undef __FUNCT__
3349c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
3359c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
3369c0446d6SStefano Zampini {
3379c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3389c0446d6SStefano Zampini   PetscInt i;
3399c0446d6SStefano Zampini   PetscErrorCode ierr;
3409c0446d6SStefano Zampini 
3419c0446d6SStefano Zampini   PetscFunctionBegin;
342da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
3439c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
3449c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3459c0446d6SStefano Zampini   }
346d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
347da1bb401SStefano Zampini   /* allocate space then set */
3489c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
3499c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
350da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
351da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
3529c0446d6SStefano Zampini   }
3539c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
3549c0446d6SStefano Zampini   PetscFunctionReturn(0);
3559c0446d6SStefano Zampini }
3569c0446d6SStefano Zampini EXTERN_C_END
3579c0446d6SStefano Zampini #undef __FUNCT__
3589c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
3599c0446d6SStefano Zampini /*@
360da1bb401SStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of local mat.
3619c0446d6SStefano Zampini 
3629c0446d6SStefano Zampini    Not collective
3639c0446d6SStefano Zampini 
3649c0446d6SStefano Zampini    Input Parameters:
3659c0446d6SStefano Zampini +  pc - the preconditioning context
366da1bb401SStefano Zampini -  n - number of index sets defining the fields
367da1bb401SStefano Zampini -  IS[] - array of IS describing the fields
3689c0446d6SStefano Zampini 
3699c0446d6SStefano Zampini    Level: intermediate
3709c0446d6SStefano Zampini 
3719c0446d6SStefano Zampini    Notes:
3729c0446d6SStefano Zampini 
3739c0446d6SStefano Zampini .seealso: PCBDDC
3749c0446d6SStefano Zampini @*/
3759c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
3769c0446d6SStefano Zampini {
3779c0446d6SStefano Zampini   PetscErrorCode ierr;
3789c0446d6SStefano Zampini 
3799c0446d6SStefano Zampini   PetscFunctionBegin;
3809c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3819c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
3829c0446d6SStefano Zampini   PetscFunctionReturn(0);
3839c0446d6SStefano Zampini }
384da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
3859c0446d6SStefano Zampini 
38653cdbc3dSStefano Zampini #undef __FUNCT__
38753cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
3880c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3890c7d97c5SJed Brown /*
3900c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
3910c7d97c5SJed Brown                   by setting data structures and options.
3920c7d97c5SJed Brown 
3930c7d97c5SJed Brown    Input Parameter:
39453cdbc3dSStefano Zampini +  pc - the preconditioner context
3950c7d97c5SJed Brown 
3960c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
3970c7d97c5SJed Brown 
3980c7d97c5SJed Brown    Notes:
3990c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
4000c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
4010c7d97c5SJed Brown */
40253cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
4030c7d97c5SJed Brown {
4040c7d97c5SJed Brown   PetscErrorCode ierr;
4050c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
4060c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
4070c7d97c5SJed Brown 
4080c7d97c5SJed Brown   PetscFunctionBegin;
4090c7d97c5SJed Brown   if (!pc->setupcalled) {
4103b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
4119c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
4120c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
4130c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
4140c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
4150c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
4160c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
4173b03a366Sstefano_zampini     /* Get stdout for dbg */
418e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
419e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
420e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
421e269702eSStefano Zampini     }
4223b03a366Sstefano_zampini     /* TODO MOVE CODE FRAGMENT */
4230c7d97c5SJed Brown     PetscInt im_active=0;
4240c7d97c5SJed Brown     if(pcis->n) im_active = 1;
42553cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
4263b03a366Sstefano_zampini     /* Analyze local interface */
4270c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
4283b03a366Sstefano_zampini     /* Set up local constraint matrix */
4293b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
4300c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
4310c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
4323b03a366Sstefano_zampini     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
4333b03a366Sstefano_zampini     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
4340c7d97c5SJed Brown   }
4350c7d97c5SJed Brown   PetscFunctionReturn(0);
4360c7d97c5SJed Brown }
4370c7d97c5SJed Brown 
4380c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4390c7d97c5SJed Brown /*
4400c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
4410c7d97c5SJed Brown 
4420c7d97c5SJed Brown    Input Parameters:
4430c7d97c5SJed Brown .  pc - the preconditioner context
4440c7d97c5SJed Brown .  r - input vector (global)
4450c7d97c5SJed Brown 
4460c7d97c5SJed Brown    Output Parameter:
4470c7d97c5SJed Brown .  z - output vector (global)
4480c7d97c5SJed Brown 
4490c7d97c5SJed Brown    Application Interface Routine: PCApply()
4500c7d97c5SJed Brown  */
4510c7d97c5SJed Brown #undef __FUNCT__
4520c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
45353cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
4540c7d97c5SJed Brown {
4550c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
4560c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
4570c7d97c5SJed Brown   PetscErrorCode    ierr;
4583b03a366Sstefano_zampini   const PetscScalar one = 1.0;
4593b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
4602617d88aSStefano Zampini   const PetscScalar zero = 0.0;
4610c7d97c5SJed Brown 
4620c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
4630c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
4640c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
4650c7d97c5SJed Brown 
4660c7d97c5SJed Brown   PetscFunctionBegin;
4670c7d97c5SJed Brown   /* First Dirichlet solve */
4680c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4690c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
4710c7d97c5SJed Brown   /*
4720c7d97c5SJed Brown     Assembling right hand side for BDDC operator
4730c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
4740c7d97c5SJed Brown     - the interface part of the global vector z
4750c7d97c5SJed Brown   */
4760c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4770c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
4780c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4790c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4800c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
4810c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4820c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4830c7d97c5SJed Brown 
4842617d88aSStefano Zampini   /* Get Local boundary and apply partition of unity */
4852617d88aSStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4862617d88aSStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4872617d88aSStefano Zampini   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4882617d88aSStefano Zampini 
4892617d88aSStefano Zampini   /* Apply interface preconditioner
4902617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
4912617d88aSStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc);CHKERRQ(ierr);
4922617d88aSStefano Zampini 
4932617d88aSStefano Zampini   /* Apply partition of unity and sum boundary values */
4942617d88aSStefano Zampini   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4952617d88aSStefano Zampini   ierr = VecSet(z,zero);CHKERRQ(ierr);
4962617d88aSStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4972617d88aSStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4980c7d97c5SJed Brown 
4993b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
5000c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5010c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5020c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
5030c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
50453cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
5050c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
5060c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
5070c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
5080c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5090c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5100c7d97c5SJed Brown 
5110c7d97c5SJed Brown   PetscFunctionReturn(0);
5120c7d97c5SJed Brown 
5130c7d97c5SJed Brown }
514da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
515da1bb401SStefano Zampini #undef __FUNCT__
516da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
517da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
518da1bb401SStefano Zampini {
519da1bb401SStefano Zampini   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
520da1bb401SStefano Zampini   PetscErrorCode ierr;
521da1bb401SStefano Zampini 
522da1bb401SStefano Zampini   PetscFunctionBegin;
523da1bb401SStefano Zampini   /* free data created by PCIS */
524da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
525da1bb401SStefano Zampini   /* free BDDC data  */
526da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
527da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
528da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
529da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
530da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
531da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
532da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
533da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
534da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
535da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
536da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
537da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
538da1bb401SStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
539da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
540da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
541da1bb401SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
542da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
543da1bb401SStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
544da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
545da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
546da1bb401SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
547da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
548da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
549da1bb401SStefano Zampini   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
550da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
551da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
552da1bb401SStefano Zampini   PetscInt i;
553da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
554da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
555da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
556da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
557da1bb401SStefano Zampini   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
558da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
559da1bb401SStefano Zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
560da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->xadj);CHKERRQ(ierr);
561da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->adjncy);CHKERRQ(ierr);
562da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->neighbours_set[0]);CHKERRQ(ierr);
563da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph->neighbours_set);CHKERRQ(ierr);
564da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
565da1bb401SStefano Zampini   /* Free the private data structure that was hanging off the PC */
566da1bb401SStefano Zampini   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
567da1bb401SStefano Zampini   PetscFunctionReturn(0);
568da1bb401SStefano Zampini }
5690c7d97c5SJed Brown 
5700c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
571da1bb401SStefano Zampini /*MC
572da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
5730c7d97c5SJed Brown 
574da1bb401SStefano Zampini    Options Database Keys:
575da1bb401SStefano Zampini .    -pcbddc ??? -
576da1bb401SStefano Zampini 
577da1bb401SStefano Zampini    Level: intermediate
578da1bb401SStefano Zampini 
579da1bb401SStefano Zampini    Notes: The matrix used with this preconditioner must be of type MATIS
580da1bb401SStefano Zampini 
581da1bb401SStefano Zampini           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
582da1bb401SStefano Zampini           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
583da1bb401SStefano Zampini           on the subdomains).
584da1bb401SStefano Zampini 
585da1bb401SStefano Zampini           Options for the coarse grid preconditioner can be set with -
586da1bb401SStefano Zampini           Options for the Dirichlet subproblem can be set with -
587da1bb401SStefano Zampini           Options for the Neumann subproblem can be set with -
588da1bb401SStefano Zampini 
589da1bb401SStefano Zampini    Contributed by Stefano Zampini
590da1bb401SStefano Zampini 
591da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
592da1bb401SStefano Zampini M*/
593da1bb401SStefano Zampini EXTERN_C_BEGIN
594da1bb401SStefano Zampini #undef __FUNCT__
595da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
596da1bb401SStefano Zampini PetscErrorCode PCCreate_BDDC(PC pc)
597da1bb401SStefano Zampini {
598da1bb401SStefano Zampini   PetscErrorCode ierr;
599da1bb401SStefano Zampini   PC_BDDC        *pcbddc;
600da1bb401SStefano Zampini   PCBDDCGraph    mat_graph;
601da1bb401SStefano Zampini 
602da1bb401SStefano Zampini   PetscFunctionBegin;
603da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
604da1bb401SStefano Zampini   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
605da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
606da1bb401SStefano Zampini 
607da1bb401SStefano Zampini   /* create PCIS data structure */
608da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
609da1bb401SStefano Zampini 
610da1bb401SStefano Zampini   /* BDDC specific */
611da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
612da1bb401SStefano Zampini   pcbddc->coarse_rhs                 = 0;
613da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
614da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
615da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
616da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
617da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
618da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
619da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
620da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
621da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
622da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
623da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
624da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
625da1bb401SStefano Zampini   pcbddc->local_primal_indices       = 0;
626da1bb401SStefano Zampini   pcbddc->prec_type                  = PETSC_FALSE;
627da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
628da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
629da1bb401SStefano Zampini   pcbddc->ISForVertices              = 0;
630da1bb401SStefano Zampini   pcbddc->n_ISForFaces               = 0;
631da1bb401SStefano Zampini   pcbddc->n_ISForEdges               = 0;
632da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
633da1bb401SStefano Zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
634da1bb401SStefano Zampini   pcbddc->local_primal_sizes         = 0;
635da1bb401SStefano Zampini   pcbddc->local_primal_displacements = 0;
636da1bb401SStefano Zampini   pcbddc->replicated_local_primal_indices = 0;
637da1bb401SStefano Zampini   pcbddc->replicated_local_primal_values  = 0;
638da1bb401SStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
639da1bb401SStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
640da1bb401SStefano Zampini   pcbddc->coarsening_ratio           = 8;
641da1bb401SStefano Zampini 
642da1bb401SStefano Zampini   /* allocate and initialize needed graph structure */
643da1bb401SStefano Zampini   ierr = PetscMalloc(sizeof(*mat_graph),&pcbddc->mat_graph);CHKERRQ(ierr);
644da1bb401SStefano Zampini   pcbddc->mat_graph->xadj            = 0;
645da1bb401SStefano Zampini   pcbddc->mat_graph->adjncy          = 0;
646da1bb401SStefano Zampini 
647da1bb401SStefano Zampini   /* function pointers */
648da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
649da1bb401SStefano Zampini   pc->ops->applytranspose      = 0;
650da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
651da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
652da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
653da1bb401SStefano Zampini   pc->ops->view                = 0;
654da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
655da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
656da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
657da1bb401SStefano Zampini 
658da1bb401SStefano Zampini   /* composing function */
659da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
660da1bb401SStefano Zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
661da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
662da1bb401SStefano Zampini                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
663da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C","PCBDDCGetDirichletBoundaries_BDDC",
664da1bb401SStefano Zampini                     PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
665da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
666da1bb401SStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
667da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
668da1bb401SStefano Zampini                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
669da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
670da1bb401SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
671da1bb401SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C","PCBDDCSetLocalAdjacencyGraph_BDDC",
672da1bb401SStefano Zampini                     PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
673da1bb401SStefano Zampini   PetscFunctionReturn(0);
674da1bb401SStefano Zampini }
675da1bb401SStefano Zampini EXTERN_C_END
676da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
677da1bb401SStefano Zampini /* All static functions from now on                                           */
678da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
679da1bb401SStefano Zampini #undef __FUNCT__
680da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetupLocalAdjacencyGraph"
681da1bb401SStefano Zampini static PetscErrorCode PCBDDCSetupLocalAdjacencyGraph(PC pc)
682da1bb401SStefano Zampini {
683da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
684da1bb401SStefano Zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
685da1bb401SStefano Zampini   PetscInt       nvtxs,*xadj,*adjncy;
686da1bb401SStefano Zampini   Mat            mat_adj;
687da1bb401SStefano Zampini   PetscBool      symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE,flg_row=PETSC_TRUE;
688da1bb401SStefano Zampini   PCBDDCGraph    mat_graph=pcbddc->mat_graph;
689da1bb401SStefano Zampini   PetscErrorCode ierr;
690da1bb401SStefano Zampini 
691da1bb401SStefano Zampini   PetscFunctionBegin;
692da1bb401SStefano Zampini   /* get CSR adjacency from local matrix if user has not yet provided local graph using PCBDDCSetLocalAdjacencyGraph function */
693da1bb401SStefano Zampini   if(!mat_graph->xadj) {
694da1bb401SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
695da1bb401SStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
696da1bb401SStefano Zampini     if(!flg_row) {
697da1bb401SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
698da1bb401SStefano Zampini     }
699da1bb401SStefano Zampini     /* Get adjacency into BDDC workspace */
700da1bb401SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
701da1bb401SStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
702da1bb401SStefano Zampini     if(!flg_row) {
703da1bb401SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
704da1bb401SStefano Zampini     }
705da1bb401SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
706da1bb401SStefano Zampini   }
707da1bb401SStefano Zampini   PetscFunctionReturn(0);
708da1bb401SStefano Zampini }
709da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
7100c7d97c5SJed Brown #undef __FUNCT__
7110c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
7122617d88aSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc)
7130c7d97c5SJed Brown {
7140c7d97c5SJed Brown   PetscErrorCode ierr;
7150c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
7160c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
7173b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
7180c7d97c5SJed Brown 
7190c7d97c5SJed Brown   PetscFunctionBegin;
7200c7d97c5SJed Brown   /* Application of PHI^T  */
7210c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
7220c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
7230c7d97c5SJed Brown 
7240c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
7250c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
7260c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7270c7d97c5SJed Brown 
7280c7d97c5SJed Brown   /* Local solution on R nodes */
7290c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
7300c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7310c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7320c7d97c5SJed Brown   if(pcbddc->prec_type) {
7330c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7340c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7350c7d97c5SJed Brown   }
7360c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
7370c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
7380c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7390c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7400c7d97c5SJed Brown   if(pcbddc->prec_type) {
7410c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7420c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7430c7d97c5SJed Brown   }
7440c7d97c5SJed Brown 
7450c7d97c5SJed Brown   /* Coarse solution */
7460c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
74753cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
7480c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7490c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
7500c7d97c5SJed Brown 
7510c7d97c5SJed Brown   /* Sum contributions from two levels */
7520c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
7530c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
7540c7d97c5SJed Brown   PetscFunctionReturn(0);
7550c7d97c5SJed Brown }
7560c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7570c7d97c5SJed Brown #undef __FUNCT__
7580c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
75953cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
7600c7d97c5SJed Brown {
7610c7d97c5SJed Brown   PetscErrorCode ierr;
7620c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
7630c7d97c5SJed Brown 
7640c7d97c5SJed Brown   PetscFunctionBegin;
76553cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
7660c7d97c5SJed Brown   if(pcbddc->n_constraints) {
7670c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
7680c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
7690c7d97c5SJed Brown   }
7700c7d97c5SJed Brown   PetscFunctionReturn(0);
7710c7d97c5SJed Brown }
7720c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7730c7d97c5SJed Brown #undef __FUNCT__
7740c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
77553cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
7760c7d97c5SJed Brown {
7770c7d97c5SJed Brown   PetscErrorCode ierr;
7780c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
7790c7d97c5SJed Brown 
7800c7d97c5SJed Brown   PetscFunctionBegin;
7810c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
7820c7d97c5SJed Brown     case SCATTERS_BDDC:
7830c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
7840c7d97c5SJed Brown       break;
7850c7d97c5SJed Brown     case GATHERS_BDDC:
7860c7d97c5SJed Brown       break;
7870c7d97c5SJed Brown   }
7880c7d97c5SJed Brown   PetscFunctionReturn(0);
7890c7d97c5SJed Brown }
7900c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7910c7d97c5SJed Brown #undef __FUNCT__
7920c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
79353cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
7940c7d97c5SJed Brown {
7950c7d97c5SJed Brown   PetscErrorCode ierr;
7960c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
7970c7d97c5SJed Brown   PetscScalar*   array_to;
7980c7d97c5SJed Brown   PetscScalar*   array_from;
7990c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
8000c7d97c5SJed Brown   PetscInt i;
8010c7d97c5SJed Brown 
8020c7d97c5SJed Brown   PetscFunctionBegin;
8030c7d97c5SJed Brown 
8040c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
8050c7d97c5SJed Brown     case SCATTERS_BDDC:
8060c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
8070c7d97c5SJed Brown       break;
8080c7d97c5SJed Brown     case GATHERS_BDDC:
8090c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
8100c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
8110c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
8120c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
8130c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
81453cdbc3dSStefano Zampini             ierr = MPI_Gatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
8150c7d97c5SJed Brown             if(vec_to) {
8160c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
8170c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
8180c7d97c5SJed Brown             }
8190c7d97c5SJed Brown           } else {
8200c7d97c5SJed Brown             if(vec_from)
8210c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
8220c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
82353cdbc3dSStefano Zampini             ierr = MPI_Scatterv(&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,&array_to[0],pcbddc->local_primal_size,MPIU_SCALAR,0,comm);CHKERRQ(ierr);
8240c7d97c5SJed Brown           }
8250c7d97c5SJed Brown           break;
8260c7d97c5SJed Brown         case REPLICATED_BDDC:
8270c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
82853cdbc3dSStefano Zampini             ierr = MPI_Allgatherv(&array_from[0],pcbddc->local_primal_size,MPIU_SCALAR,&pcbddc->replicated_local_primal_values[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_SCALAR,comm);CHKERRQ(ierr);
8290c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
8300c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
8310c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
8320c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
8330c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
8340c7d97c5SJed Brown           }
8350c7d97c5SJed Brown           break;
83653cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
83753cdbc3dSStefano Zampini           break;
83853cdbc3dSStefano Zampini         case PARALLEL_BDDC:
83953cdbc3dSStefano Zampini           break;
8400c7d97c5SJed Brown       }
8410c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
8420c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
8430c7d97c5SJed Brown       break;
8440c7d97c5SJed Brown   }
8450c7d97c5SJed Brown   PetscFunctionReturn(0);
8460c7d97c5SJed Brown }
8470c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
848de534f79Sstefano_zampini #ifdef BDDC_USE_POD
849de534f79Sstefano_zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
8503b03a366Sstefano_zampini #define PETSC_MISSING_LAPACK_GESVD 1
851de534f79Sstefano_zampini #define UNDEF_PETSC_MISSING_LAPACK_GESVD 1
852de534f79Sstefano_zampini #endif
8533b03a366Sstefano_zampini #endif
8543b03a366Sstefano_zampini 
8553b03a366Sstefano_zampini #undef __FUNCT__
8563b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
8573b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
8583b03a366Sstefano_zampini {
8593b03a366Sstefano_zampini   PetscErrorCode ierr;
8603b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
8613b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8623b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
8633b03a366Sstefano_zampini   PetscInt       *nnz,*vertices,*is_indices;
8643b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
8653b03a366Sstefano_zampini   PetscInt       *temp_indices,*temp_indices_to_constraint;
8663b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
8673b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
8683b03a366Sstefano_zampini   PetscReal      quad_value;
8693b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
8703b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
8713b03a366Sstefano_zampini   IS             *used_IS;
8723b03a366Sstefano_zampini   const MatType  impMatType=MATSEQAIJ;
8733b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
8743b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
875fcda91b4SJed Brown   MatNullSpace   nearnullsp;
876fcda91b4SJed Brown   const Vec      *nearnullvecs;
8773b03a366Sstefano_zampini   Vec            *localnearnullsp;
8783b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
8793b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
880de534f79Sstefano_zampini   PetscBLASInt   Bone=1;
881de534f79Sstefano_zampini /* some ugly conditional declarations */
8823b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8833b03a366Sstefano_zampini   PetscScalar    dot_result;
8843b03a366Sstefano_zampini   PetscScalar    one=1.0,zero=0.0;
8853b03a366Sstefano_zampini   PetscInt       ii;
8863b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8873b03a366Sstefano_zampini   PetscScalar    val1,val2;
8883b03a366Sstefano_zampini #endif
8893b03a366Sstefano_zampini #else
8903b03a366Sstefano_zampini   PetscBLASInt   dummy_int;
8913b03a366Sstefano_zampini   PetscScalar    dummy_scalar;
8923b03a366Sstefano_zampini #endif
8933b03a366Sstefano_zampini 
8943b03a366Sstefano_zampini   PetscFunctionBegin;
8953b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
896fcda91b4SJed Brown   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
897fcda91b4SJed Brown   if (nearnullsp) {
898fcda91b4SJed Brown     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
8993b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
9003b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
9013b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
9023b03a366Sstefano_zampini   }
9033b03a366Sstefano_zampini   if(nnsp_has_cnst) {
9043b03a366Sstefano_zampini     nnsp_addone = 1;
9053b03a366Sstefano_zampini   }
9063b03a366Sstefano_zampini   /*
9073b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
9083b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
9093b03a366Sstefano_zampini        - temp_indices_to_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in local numbering) on which the constraint acts
9103b03a366Sstefano_zampini        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
9113b03a366Sstefano_zampini                                                                                                                                                          */
912da1bb401SStefano Zampini 
9133b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
9143b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
915da1bb401SStefano Zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
916da1bb401SStefano Zampini   total_counts += n_vertices;
9173b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
9183b03a366Sstefano_zampini   total_counts = 0;
9193b03a366Sstefano_zampini   max_size_of_constraint = 0;
9203b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
9213b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
9223b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
9233b03a366Sstefano_zampini     } else {
9243b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
9253b03a366Sstefano_zampini     }
9263b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
9273b03a366Sstefano_zampini     total_counts += j;
9283b03a366Sstefano_zampini     if(j>max_size_of_constraint) max_size_of_constraint=j;
9293b03a366Sstefano_zampini   }
9303b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
931da1bb401SStefano Zampini   total_counts += n_vertices;
9323b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
9333b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
9343b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
9353b03a366Sstefano_zampini   rwork = 0;
9363b03a366Sstefano_zampini   work = 0;
9373b03a366Sstefano_zampini   singular_vals = 0;
9383b03a366Sstefano_zampini   temp_basis = 0;
9393b03a366Sstefano_zampini   correlation_mat = 0;
9403b03a366Sstefano_zampini   if(!pcbddc->use_nnsp_true) {
9413b03a366Sstefano_zampini     PetscScalar temp_work;
9423b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
9433b03a366Sstefano_zampini     /* POD */
9443b03a366Sstefano_zampini     PetscInt max_n;
9453b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
9463b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
9473b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
9483b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
9493b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
9503b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9513b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
9523b03a366Sstefano_zampini #endif
9533b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
9543b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
9553b03a366Sstefano_zampini     lwork=-1;
9563b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9573b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
9583b03a366Sstefano_zampini #else
9593b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
9603b03a366Sstefano_zampini #endif
9613b03a366Sstefano_zampini #else /* on missing GESVD */
9623b03a366Sstefano_zampini     /* SVD */
9633b03a366Sstefano_zampini     PetscInt max_n,min_n;
9643b03a366Sstefano_zampini     max_n = max_size_of_constraint;
9653b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
9663b03a366Sstefano_zampini     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
9673b03a366Sstefano_zampini       min_n = max_size_of_constraint;
9683b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
9693b03a366Sstefano_zampini     }
9703b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
9713b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9723b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
9733b03a366Sstefano_zampini #endif
9743b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
9753b03a366Sstefano_zampini     lwork=-1;
9763b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
9773b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
9783b03a366Sstefano_zampini     dummy_int = Bs;
979670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
9803b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9813b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9823b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
9833b03a366Sstefano_zampini #else
9843b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9853b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
9863b03a366Sstefano_zampini #endif
9873b03a366Sstefano_zampini     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
988670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
9893b03a366Sstefano_zampini #endif
9903b03a366Sstefano_zampini     /* Allocate optimal workspace */
9913b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
9923b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
9933b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
9943b03a366Sstefano_zampini   }
9953b03a366Sstefano_zampini   /* get local part of global near null space vectors */
9963b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
9973b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) {
9983b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
999fcda91b4SJed Brown     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1000fcda91b4SJed Brown     ierr = VecScatterEnd  (matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10013b03a366Sstefano_zampini   }
10023b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
10033b03a366Sstefano_zampini   total_counts=0;
10043b03a366Sstefano_zampini   temp_indices[0]=0;
1005da1bb401SStefano Zampini   /* vertices */
1006da1bb401SStefano Zampini   PetscBool used_vertex;
1007da1bb401SStefano Zampini   ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
1008da1bb401SStefano Zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1009da1bb401SStefano Zampini   if(nnsp_has_cnst) { /* consider all vertices */
1010da1bb401SStefano Zampini     for(i=0;i<n_vertices;i++) {
1011da1bb401SStefano Zampini       temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1012da1bb401SStefano Zampini       temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1013da1bb401SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1014da1bb401SStefano Zampini       vertices[total_counts]=is_indices[i];
1015da1bb401SStefano Zampini       total_counts++;
1016da1bb401SStefano Zampini     }
1017da1bb401SStefano Zampini   } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1018da1bb401SStefano Zampini     for(i=0;i<n_vertices;i++) {
1019da1bb401SStefano Zampini       used_vertex=PETSC_FALSE;
1020da1bb401SStefano Zampini       k=0;
1021da1bb401SStefano Zampini       while(!used_vertex && k<nnsp_size) {
1022da1bb401SStefano Zampini         ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1023da1bb401SStefano Zampini         if(PetscAbsScalar(array_vector[is_indices[i]])>0.0) {
1024da1bb401SStefano Zampini           temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1025da1bb401SStefano Zampini           temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1026da1bb401SStefano Zampini           temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1027da1bb401SStefano Zampini           vertices[total_counts]=is_indices[i];
1028da1bb401SStefano Zampini           total_counts++;
1029da1bb401SStefano Zampini           used_vertex=PETSC_TRUE;
1030da1bb401SStefano Zampini         }
1031da1bb401SStefano Zampini         ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1032da1bb401SStefano Zampini         k++;
1033da1bb401SStefano Zampini       }
1034da1bb401SStefano Zampini     }
1035da1bb401SStefano Zampini   }
1036da1bb401SStefano Zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1037da1bb401SStefano Zampini   n_vertices=total_counts;
1038da1bb401SStefano Zampini   /* edges and faces */
10393b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
10403b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
10413b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
10423b03a366Sstefano_zampini     } else {
10433b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
10443b03a366Sstefano_zampini     }
10453b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
10463b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
10473b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
10483b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10493b03a366Sstefano_zampini     if(nnsp_has_cnst) {
10503b03a366Sstefano_zampini       temp_constraints++;
10513b03a366Sstefano_zampini       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
10523b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
10533b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
10543b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
10553b03a366Sstefano_zampini       }
10563b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
10573b03a366Sstefano_zampini       total_counts++;
10583b03a366Sstefano_zampini     }
10593b03a366Sstefano_zampini     for(k=0;k<nnsp_size;k++) {
10603b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
10613b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
10623b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
10633b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
10643b03a366Sstefano_zampini       }
10653b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
1066de534f79Sstefano_zampini       quad_value = 1.0;
1067de534f79Sstefano_zampini       if( use_nnsp_true ) { /* check if array is null on the connected component in case use_nnsp_true has been requested */
1068de534f79Sstefano_zampini         Bs = PetscBLASIntCast(size_of_constraint);
1069de534f79Sstefano_zampini         quad_value = BLASasum_(&Bs,&temp_quadrature_constraint[temp_indices[total_counts]],&Bone);
1070de534f79Sstefano_zampini       }
1071de534f79Sstefano_zampini       if ( quad_value > 0.0 ) { /* keep indices and values */
1072de534f79Sstefano_zampini         temp_constraints++;
10733b03a366Sstefano_zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
10743b03a366Sstefano_zampini         total_counts++;
10753b03a366Sstefano_zampini       }
1076de534f79Sstefano_zampini     }
10773b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1078de534f79Sstefano_zampini     /* perform SVD on the constraint if use_nnsp_true has not be requested by the user */
10793b03a366Sstefano_zampini     if(!use_nnsp_true) {
1080de534f79Sstefano_zampini 
10813b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
10823b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
1083de534f79Sstefano_zampini 
10843b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
10853b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
10863b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
10873b03a366Sstefano_zampini       for(j=0;j<temp_constraints;j++) {
10883b03a366Sstefano_zampini         for(k=0;k<j+1;k++) {
10893b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
10903b03a366Sstefano_zampini           /* hand made complex dot product */
10913b03a366Sstefano_zampini           dot_result = 0.0;
10923b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
10933b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
10943b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
10953b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
10963b03a366Sstefano_zampini           }
10973b03a366Sstefano_zampini #else
10983b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
10993b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
11003b03a366Sstefano_zampini #endif
11013b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
11023b03a366Sstefano_zampini         }
11033b03a366Sstefano_zampini       }
11043b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
11053b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
11063b03a366Sstefano_zampini #else
11073b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
11083b03a366Sstefano_zampini #endif
11093b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
11103b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
11113b03a366Sstefano_zampini       j=0;
11123b03a366Sstefano_zampini       while( j < Bt && singular_vals[j] < tol) j++;
11133b03a366Sstefano_zampini       total_counts=total_counts-j;
11143b03a366Sstefano_zampini       if(j<temp_constraints) {
11153b03a366Sstefano_zampini         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
11163b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
11173b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
11183b03a366Sstefano_zampini         for(k=0;k<Bt-j;k++) {
11193b03a366Sstefano_zampini           for(ii=0;ii<size_of_constraint;ii++) {
11203b03a366Sstefano_zampini             temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[Bt-1-k]*temp_basis[(Bt-1-k)*size_of_constraint+ii];
11213b03a366Sstefano_zampini           }
11223b03a366Sstefano_zampini         }
11233b03a366Sstefano_zampini       }
1124de534f79Sstefano_zampini 
11253b03a366Sstefano_zampini #else  /* on missing GESVD */
1126de534f79Sstefano_zampini 
11273b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
11283b03a366Sstefano_zampini       if(min_n > size_of_constraint) min_n = size_of_constraint;
11293b03a366Sstefano_zampini       dummy_int = Bs;
1130670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
11313b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
11323b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
11333b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
11343b03a366Sstefano_zampini #else
11353b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
11363b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
11373b03a366Sstefano_zampini #endif
11383b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
1139670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
11403b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
11413b03a366Sstefano_zampini       j=0;
11423b03a366Sstefano_zampini       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
11433b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
1144de534f79Sstefano_zampini 
11453b03a366Sstefano_zampini #endif
11463b03a366Sstefano_zampini     }
11473b03a366Sstefano_zampini   }
1148da1bb401SStefano Zampini   n_constraints=total_counts-n_vertices;
1149da1bb401SStefano Zampini   local_primal_size = total_counts;
11503b03a366Sstefano_zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
11513b03a366Sstefano_zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
11523b03a366Sstefano_zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
11533b03a366Sstefano_zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
1154da1bb401SStefano Zampini   for(i=0;i<local_primal_size;i++) {
1155da1bb401SStefano Zampini     nnz[i]=temp_indices[i+1]-temp_indices[i];
1156da1bb401SStefano Zampini   }
11573b03a366Sstefano_zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
1158da1bb401SStefano Zampini   for(i=0;i<local_primal_size;i++) {
11593b03a366Sstefano_zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1160da1bb401SStefano Zampini     ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&i,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
11613b03a366Sstefano_zampini   }
11623b03a366Sstefano_zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11633b03a366Sstefano_zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11643b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
11653b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
11663b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
1167da1bb401SStefano Zampini   pcbddc->local_primal_size = local_primal_size;
11683b03a366Sstefano_zampini   /* free workspace no longer needed */
11693b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
11703b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
11713b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
11723b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
11733b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
11743b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
11753b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
11763b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
11773b03a366Sstefano_zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
1178da1bb401SStefano Zampini   for(k=0;k<nnsp_size;k++) {
1179da1bb401SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1180da1bb401SStefano Zampini   }
11813b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
11823b03a366Sstefano_zampini   PetscFunctionReturn(0);
11833b03a366Sstefano_zampini }
1184de534f79Sstefano_zampini #ifdef UNDEF_PETSC_MISSING_LAPACK_GESVD
11853b03a366Sstefano_zampini #undef PETSC_MISSING_LAPACK_GESVD
11863b03a366Sstefano_zampini #endif
11873b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
11880c7d97c5SJed Brown #undef __FUNCT__
11890c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
119053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
11910c7d97c5SJed Brown {
11920c7d97c5SJed Brown   PetscErrorCode  ierr;
11930c7d97c5SJed Brown 
11940c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
11950c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
11960c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
11970c7d97c5SJed Brown   IS                is_R_local;
11980c7d97c5SJed Brown   IS                is_V_local;
11990c7d97c5SJed Brown   IS                is_C_local;
12000c7d97c5SJed Brown   IS                is_aux1;
12010c7d97c5SJed Brown   IS                is_aux2;
12020c7d97c5SJed Brown   const VecType     impVecType;
12030c7d97c5SJed Brown   const MatType     impMatType;
12040c7d97c5SJed Brown   PetscInt          n_R=0;
12050c7d97c5SJed Brown   PetscInt          n_D=0;
12060c7d97c5SJed Brown   PetscInt          n_B=0;
12070c7d97c5SJed Brown   PetscScalar       zero=0.0;
12080c7d97c5SJed Brown   PetscScalar       one=1.0;
12090c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
12100c7d97c5SJed Brown   PetscScalar*      array;
12110c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
12120c7d97c5SJed Brown   PetscInt          *idx_R_local;
12130c7d97c5SJed Brown   PetscInt          *idx_V_B;
12140c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
12150c7d97c5SJed Brown   PetscScalar       *constraints_errors;
12160c7d97c5SJed Brown   /* auxiliary indices */
1217da1bb401SStefano Zampini   PetscInt i,j;
1218e269702eSStefano Zampini   /* for verbose output of bddc */
1219e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1220e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1221a0ba757dSStefano Zampini   /* for counting coarse dofs */
12223b03a366Sstefano_zampini   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
12233b03a366Sstefano_zampini   PetscInt          size_of_constraint;
12243b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
12253b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
1226da1bb401SStefano Zampini   PetscInt          *vertices;
12270c7d97c5SJed Brown 
12280c7d97c5SJed Brown   PetscFunctionBegin;
12290c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
12300c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
12313b03a366Sstefano_zampini 
1232da1bb401SStefano Zampini   /* get vertex indices from constraint matrix */
1233da1bb401SStefano Zampini   ierr = PetscMalloc(pcbddc->n_vertices*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
1234da1bb401SStefano Zampini   j=0;
1235da1bb401SStefano Zampini   for(i=0;i<pcbddc->local_primal_size;i++) {
1236da1bb401SStefano Zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1237da1bb401SStefano Zampini     if(size_of_constraint == 1) {
1238da1bb401SStefano Zampini       vertices[j]=row_cmat_indices[0];
1239da1bb401SStefano Zampini       j++;
1240a0ba757dSStefano Zampini     }
1241da1bb401SStefano Zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1242a0ba757dSStefano Zampini   }
1243a0ba757dSStefano Zampini 
12440c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
12450c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
12460c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12473b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
12483b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
12490c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
12500c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1251e269702eSStefano Zampini   if(dbg_flag) {
12520c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12530c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12540c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
12550c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
12563b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,n_constraints,pcbddc->local_primal_size);CHKERRQ(ierr);
12570c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12580c7d97c5SJed Brown   }
12590c7d97c5SJed Brown   /* Allocate needed vectors */
12600c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
12610c7d97c5SJed Brown   impMatType = MATSEQDENSE;
12620c7d97c5SJed Brown   impVecType = VECSEQ;
12630c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
12640c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
12650c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
12660c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1267d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
12680c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
12690c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
12700c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
12710c7d97c5SJed Brown 
12720c7d97c5SJed Brown   /* Creating some index sets needed  */
12730c7d97c5SJed Brown   /* For submatrices */
1274da1bb401SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&is_R_local);CHKERRQ(ierr);
12753b03a366Sstefano_zampini   if(n_vertices)    {
1276da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_OWN_POINTER,&is_V_local);CHKERRQ(ierr);
12773b03a366Sstefano_zampini   }
1278da1bb401SStefano Zampini   if(n_constraints) {
1279da1bb401SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr);
1280da1bb401SStefano Zampini   }
1281da1bb401SStefano Zampini 
12820c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
12830c7d97c5SJed Brown   {
12840c7d97c5SJed Brown     PetscInt   *aux_array1;
12850c7d97c5SJed Brown     PetscInt   *aux_array2;
12860c7d97c5SJed Brown 
12873b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
12883b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
12890c7d97c5SJed Brown 
1290d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
12910c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12920c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12930c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12940c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12950c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12960c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12970c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1298da1bb401SStefano Zampini     for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[j] = i; j++; } }
12990c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1300da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
13010c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1302da1bb401SStefano Zampini     for (i=0, j=0; i<n_B; i++) { if (array[i] > one) { aux_array2[j] = i; j++; } }
13033828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1304da1bb401SStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
13050c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
13060c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
13070c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
13080c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
13090c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
13100c7d97c5SJed Brown 
1311e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
13120c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
13130c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1314da1bb401SStefano Zampini       for (i=0, j=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[j] = i; j++; } }
13150c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1316da1bb401SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
13170c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
13180c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
13190c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
13200c7d97c5SJed Brown     }
13210c7d97c5SJed Brown   }
13220c7d97c5SJed Brown 
13230c7d97c5SJed Brown   /* vertices in boundary numbering */
13243b03a366Sstefano_zampini   if(n_vertices) {
1325d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
13260c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13273b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
13280c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1329d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1330d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13313b03a366Sstefano_zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
13320c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13333b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) {
1334da1bb401SStefano Zampini       j=0;
1335da1bb401SStefano Zampini       while (array[j] != i ) {j++;}
1336da1bb401SStefano Zampini       idx_V_B[i]=j;
13370c7d97c5SJed Brown     }
13380c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13390c7d97c5SJed Brown   }
13400c7d97c5SJed Brown 
13410c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
13420c7d97c5SJed Brown   {
13430c7d97c5SJed Brown     Mat  A_RR;
134453cdbc3dSStefano Zampini     PC   pc_temp;
13450c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
134653cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
134753cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
134853cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
134953cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1350da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
13510c7d97c5SJed Brown     /* default */
135253cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
135353cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13540c7d97c5SJed Brown     /* Allow user's customization */
135553cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
135653cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
135753cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1358da1bb401SStefano Zampini     if(pcbddc->dbg_flag) ierr = KSPView(pcbddc->ksp_D,PETSC_VIEWER_STDOUT_SELF);
13590c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
13600c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
136153cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
136253cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
136353cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
136453cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1365da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
13660c7d97c5SJed Brown     /* default */
136753cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
136853cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13690c7d97c5SJed Brown     /* Allow user's customization */
137053cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
137153cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
137253cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1373da1bb401SStefano Zampini     if(pcbddc->dbg_flag) ierr = KSPView(pcbddc->ksp_R,PETSC_VIEWER_STDOUT_SELF);
1374a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1375e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
13760c7d97c5SJed Brown       Vec temp_vec;
13770c7d97c5SJed Brown       PetscScalar value;
13780c7d97c5SJed Brown 
1379a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1380a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1381a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1382a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1383a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1384a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1385a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1386a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1387a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1388a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1389a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1390d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1391d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1392d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1393d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1394d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1395d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1396e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
13970c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1398d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13990c7d97c5SJed Brown     }
14000c7d97c5SJed Brown     /* free Neumann problem's matrix */
14010c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
14020c7d97c5SJed Brown   }
14030c7d97c5SJed Brown 
14040c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
14050c7d97c5SJed Brown   {
14060c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
14070c7d97c5SJed Brown     Mat          M1,M2;
14080c7d97c5SJed Brown     Mat          C_CR;
14093b03a366Sstefano_zampini     Mat          AUXMAT;
14100c7d97c5SJed Brown     Vec          vec1_C;
14110c7d97c5SJed Brown     Vec          vec2_C;
14120c7d97c5SJed Brown     Vec          vec1_V;
14130c7d97c5SJed Brown     Vec          vec2_V;
14140c7d97c5SJed Brown     PetscInt     *nnz;
14150c7d97c5SJed Brown     PetscInt     *auxindices;
141653cdbc3dSStefano Zampini     PetscInt     index;
14170c7d97c5SJed Brown     PetscScalar* array2;
14180c7d97c5SJed Brown     MatFactorInfo matinfo;
14190c7d97c5SJed Brown 
14200c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
14210c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
14220c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
14230c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
14240c7d97c5SJed Brown 
14250c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
14263b03a366Sstefano_zampini     if(n_vertices) {
14270c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
14283b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
14290c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
14300c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
14310c7d97c5SJed Brown     }
14320c7d97c5SJed Brown     if(pcbddc->n_constraints) {
14330c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
14340c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
14350c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
14360c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
14370c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
14380c7d97c5SJed Brown     }
14390c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14403b03a366Sstefano_zampini     if(n_constraints) {
14410c7d97c5SJed Brown       /* some work vectors */
14420c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14433b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14440c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14453b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
14460c7d97c5SJed Brown 
14470c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14483b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
1449d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
14503b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
14513b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
14520c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14533b03a366Sstefano_zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14543b03a366Sstefano_zampini         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
14553b03a366Sstefano_zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14560c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14570c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
14580c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14590c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14603b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
146153cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14623b03a366Sstefano_zampini         /* Set values */
14630c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14643b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14650c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14660c7d97c5SJed Brown       }
14670c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14680c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14690c7d97c5SJed Brown 
14700c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
14713b03a366Sstefano_zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
14720c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
14730c7d97c5SJed Brown 
14740c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14750c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1476d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14773b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14780c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14790c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14800c7d97c5SJed Brown 
14813b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1482d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14833b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14840c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14853b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
14863b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
14870c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14880c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14890c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14900c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14910c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14920c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14930c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14943b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14950c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14960c7d97c5SJed Brown       }
14970c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14980c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14990c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
15000c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
15010c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
15020c7d97c5SJed Brown 
15030c7d97c5SJed Brown     }
15040c7d97c5SJed Brown 
15050c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
15063b03a366Sstefano_zampini     if(n_vertices){
15070c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
15080c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
15090c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
15100c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1511d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
15123b03a366Sstefano_zampini       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
15130c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
15143b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
15153b03a366Sstefano_zampini       for(i=0;i<n_vertices;i++) {
15160c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15170c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15180c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15190c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15200c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
152153cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
15220c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15233b03a366Sstefano_zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15240c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15250c7d97c5SJed Brown       }
15260c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15270c7d97c5SJed Brown       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15280c7d97c5SJed Brown     }
15290c7d97c5SJed Brown 
15300c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1531d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
15320c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
15330c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
15343b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1535e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1536d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
15370c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
15380c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
15393b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
15400c7d97c5SJed Brown     }
15410c7d97c5SJed Brown 
1542e269702eSStefano Zampini     if(dbg_flag) {
15430c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
15440c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
15450c7d97c5SJed Brown     }
15463b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15470c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15480c7d97c5SJed Brown 
15490c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15503b03a366Sstefano_zampini     for(i=0;i<n_vertices;i++){
15510c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15520c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15530c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15540c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15550c7d97c5SJed Brown       /* solution of saddle point problem */
15560c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15570c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15583b03a366Sstefano_zampini       if(n_constraints) {
15590c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15600c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15610c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15620c7d97c5SJed Brown       }
15630c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15640c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15650c7d97c5SJed Brown 
15660c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15670c7d97c5SJed Brown       /* coarse basis functions */
15680c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15690c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15700c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15710c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15723b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15730c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15740c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1575e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
15760c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15770c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15780c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15793b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15800c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15810c7d97c5SJed Brown       }
15820c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15830c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1584da1bb401SStefano Zampini       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } /* WARNING -> column major ordering */
15850c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15863b03a366Sstefano_zampini       if(n_constraints) {
15870c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1588da1bb401SStefano Zampini         for(j=0;j<n_constraints;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j+n_vertices] = array[j]; } /* WARNING -> column major ordering */
15890c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15900c7d97c5SJed Brown       }
15910c7d97c5SJed Brown 
1592e269702eSStefano Zampini       if( dbg_flag ) {
15930c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1594d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15950c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15960c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15970c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
15983b03a366Sstefano_zampini         array[ vertices[i] ] = one;
15990c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16000c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16010c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1602d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16030c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16040c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16053b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
16060c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16073b03a366Sstefano_zampini         if(n_constraints) {
16080c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16093b03a366Sstefano_zampini           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
16100c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16110c7d97c5SJed Brown         }
16120c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16130c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
16140c7d97c5SJed Brown         /* check saddle point solution */
16150c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16163b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
16173b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
16183b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16190c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16203b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
16210c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16223b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
16230c7d97c5SJed Brown       }
16240c7d97c5SJed Brown     }
16250c7d97c5SJed Brown 
16263b03a366Sstefano_zampini     for(i=0;i<n_constraints;i++){
1627d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
16280c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
16290c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
16300c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
16310c7d97c5SJed Brown       /* solution of saddle point problem */
16320c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
16330c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
16340c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
16353b03a366Sstefano_zampini       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
16360c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
16370c7d97c5SJed Brown       /* coarse basis functions */
16383b03a366Sstefano_zampini       index=i+n_vertices;
16390c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
16400c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16410c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16420c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
164353cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16440c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1645e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
16460c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16470c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16480c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
164953cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16500c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16510c7d97c5SJed Brown       }
16520c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16533b03a366Sstefano_zampini       if(n_vertices) {
16540c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
1655da1bb401SStefano Zampini         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} /* WARNING -> column major ordering */
16560c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16570c7d97c5SJed Brown       }
16580c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
1659da1bb401SStefano Zampini       for(j=0;j<n_constraints;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j+n_vertices]=array[j];} /* WARNING -> column major ordering */
16600c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16610c7d97c5SJed Brown 
1662e269702eSStefano Zampini       if( dbg_flag ) {
16630c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
166453cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16650c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16660c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16670c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
16680c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16690c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16700c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
167153cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16720c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16733b03a366Sstefano_zampini         if( n_vertices) {
16740c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16753b03a366Sstefano_zampini           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
16760c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16770c7d97c5SJed Brown         }
16780c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16793b03a366Sstefano_zampini         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16800c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16810c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16820c7d97c5SJed Brown         /* check saddle point solution */
16830c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16843b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
168553cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16863b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16870c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
168853cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16890c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
169053cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16910c7d97c5SJed Brown       }
16920c7d97c5SJed Brown     }
16930c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16940c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1695e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
16960c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16970c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16980c7d97c5SJed Brown     }
16990c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
17000c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
17019d2fce94SStefano Zampini     if(dbg_flag) {
17020c7d97c5SJed Brown 
17030c7d97c5SJed Brown       Mat coarse_sub_mat;
17040c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
17050c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1706a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
17070c7d97c5SJed Brown       PetscScalar      value;
17080c7d97c5SJed Brown 
1709c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1710c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1711c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1712c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1713c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1714c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1715c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1716c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
17170c7d97c5SJed Brown 
1718da1bb401SStefano Zampini       /*PetscViewer view_out;
1719da1bb401SStefano Zampini       PetscMPIInt myrank;
1720da1bb401SStefano Zampini       char filename[256];
1721da1bb401SStefano Zampini       MPI_Comm_rank(((PetscObject)pc)->comm,&myrank);
1722da1bb401SStefano Zampini       sprintf(filename,"coarsesubmat_%04d.m",myrank);
1723da1bb401SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&view_out);CHKERRQ(ierr);
1724da1bb401SStefano Zampini       ierr = PetscViewerSetFormat(view_out,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1725da1bb401SStefano Zampini       ierr = MatView(coarse_sub_mat,view_out);CHKERRQ(ierr);
1726da1bb401SStefano Zampini       ierr = PetscViewerDestroy(&view_out);CHKERRQ(ierr);*/
1727da1bb401SStefano Zampini 
17280c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
17290c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
17300c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
173153cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
173253cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
173353cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1734c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
173553cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173653cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1737c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
173853cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173953cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174053cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174153cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
174353cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
17440c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
17450c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
17460c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
17470c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
174853cdbc3dSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr); }
17490c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
175053cdbc3dSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) { ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr); }
17510c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
175253cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
175353cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
175453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
175553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
175653cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
175753cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
175853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
175953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
176053cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
176153cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
176253cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
17630c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
17640c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
17650c7d97c5SJed Brown     }
17660c7d97c5SJed Brown 
17670c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
17680c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
17690c7d97c5SJed Brown     /* free memory */
17700c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
17710c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
17720c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
17733b03a366Sstefano_zampini     if(n_vertices) {
17740c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
17750c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
17760c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
17770c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
17780c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
17790c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
17800c7d97c5SJed Brown     }
17810c7d97c5SJed Brown     if(pcbddc->n_constraints) {
17820c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
17830c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
17840c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
17850c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
17860c7d97c5SJed Brown     }
17870c7d97c5SJed Brown   }
17880c7d97c5SJed Brown   /* free memory */
17893b03a366Sstefano_zampini   if(n_vertices) {
17900c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17910c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17920c7d97c5SJed Brown   }
17930c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
17940c7d97c5SJed Brown 
17950c7d97c5SJed Brown   PetscFunctionReturn(0);
17960c7d97c5SJed Brown }
17970c7d97c5SJed Brown 
17980c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
17990c7d97c5SJed Brown 
18000c7d97c5SJed Brown #undef __FUNCT__
18010c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
180253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
18030c7d97c5SJed Brown {
18040c7d97c5SJed Brown 
18050c7d97c5SJed Brown 
18060c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
18070c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
18080c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
18090c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
18100c7d97c5SJed Brown   MPI_Comm  coarse_comm;
18110c7d97c5SJed Brown 
18120c7d97c5SJed Brown   /* common to all choiches */
18130c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
18140c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
18150c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
18160c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
18170c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
18180c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
18190c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
18200c7d97c5SJed Brown   PetscMPIInt master_proc=0;
18210c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
18220c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
18230c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
18240c7d97c5SJed Brown   PetscMPIInt count_recv=0;
18250c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
18260c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
18270c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
18280c7d97c5SJed Brown   /* some other variables */
18290c7d97c5SJed Brown   PetscErrorCode ierr;
18300c7d97c5SJed Brown   const MatType coarse_mat_type;
18310c7d97c5SJed Brown   const PCType  coarse_pc_type;
183253cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
183353cdbc3dSStefano Zampini   PC pc_temp;
18340c7d97c5SJed Brown   PetscInt i,j,k,bs;
18353b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1836e269702eSStefano Zampini   /* verbose output viewer */
1837e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1838e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
18390c7d97c5SJed Brown 
18400c7d97c5SJed Brown   PetscFunctionBegin;
18410c7d97c5SJed Brown 
18420c7d97c5SJed Brown   ins_local_primal_indices = 0;
18430c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
18440c7d97c5SJed Brown   localsizes2              = 0;
18450c7d97c5SJed Brown   localdispl2              = 0;
18460c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
18470c7d97c5SJed Brown   coarse_ISLG              = 0;
18480c7d97c5SJed Brown 
184953cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
185053cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
18510c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
18520c7d97c5SJed Brown 
1853beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1854beed3852SStefano Zampini   {
1855a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1856beed3852SStefano Zampini     PetscScalar    *array;
1857beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1858beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1859beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1860beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1861beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
1862da1bb401SStefano Zampini     PetscInt       *row_cmat_indices;
18633b03a366Sstefano_zampini     PetscInt       size_of_constraint;
1864da1bb401SStefano Zampini     PetscScalar    coarsesum;
1865beed3852SStefano Zampini 
1866beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1867beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1868beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1869beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1870beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
18715619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1872beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1873beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1874beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1875beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1876beed3852SStefano Zampini     }
18775619798eSStefano Zampini     if(rank_prec_comm == 0) {
1878beed3852SStefano Zampini       /* allocate some auxiliary space */
1879beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1880beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1881beed3852SStefano Zampini     }
1882beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1883beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1884beed3852SStefano Zampini 
1885da1bb401SStefano Zampini     /* First let's count coarse dofs.
1886beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1887beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1888beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
18893b03a366Sstefano_zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1890beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1891beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1892da1bb401SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1893da1bb401SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
18943b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
18953b03a366Sstefano_zampini         k = row_cmat_indices[j];
1896beed3852SStefano Zampini         if( array[k] == zero ) {
1897beed3852SStefano Zampini           array[k] = one;
1898da1bb401SStefano Zampini           auxlocal_primal[i] = k;
1899beed3852SStefano Zampini           break;
1900beed3852SStefano Zampini         }
1901beed3852SStefano Zampini       }
1902da1bb401SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1903beed3852SStefano Zampini     }
1904beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1905da1bb401SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1906da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1907da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1908da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1909da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1910da1bb401SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1911da1bb401SStefano Zampini     for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1912da1bb401SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1913da1bb401SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1914da1bb401SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1915da1bb401SStefano Zampini     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1916da1bb401SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1917da1bb401SStefano Zampini     pcbddc->coarse_size = (PetscInt) coarsesum;
1918a0ba757dSStefano Zampini 
1919beed3852SStefano Zampini     /* Now assign them a global numbering */
1920beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1921beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1922beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1923beed3852SStefano Zampini     ierr = MPI_Gatherv(&auxglobal_primal[0],pcbddc->local_primal_size,MPIU_INT,&all_auxglobal_primal[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1924beed3852SStefano Zampini 
1925beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1926beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1927beed3852SStefano Zampini     if(rank_prec_comm==0) {
1928beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1929beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1930beed3852SStefano Zampini       k=1;
1931beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1932beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1933beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1934beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1935beed3852SStefano Zampini           k++;
1936beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1937beed3852SStefano Zampini         }
1938beed3852SStefano Zampini       }
1939beed3852SStefano Zampini     } else {
1940beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1941beed3852SStefano Zampini     }
19425619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1943beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1944beed3852SStefano Zampini 
1945beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1946beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1947beed3852SStefano Zampini       k=0;
1948beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1949beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1950beed3852SStefano Zampini     }
1951e269702eSStefano Zampini     if(dbg_flag) {
1952e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1953da1bb401SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem %d\n",pcbddc->coarse_size);CHKERRQ(ierr);
1954e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1955e269702eSStefano Zampini     }
1956beed3852SStefano Zampini     /* free allocated memory */
1957beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1958beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1959beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1960e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1961beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1962beed3852SStefano Zampini     }
1963e269702eSStefano Zampini   }
1964beed3852SStefano Zampini 
19650c7d97c5SJed Brown   /* adapt coarse problem type */
19660c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
19670c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
19680c7d97c5SJed Brown 
19690c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
19700c7d97c5SJed Brown 
1971da1bb401SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
19720c7d97c5SJed Brown     {
19730c7d97c5SJed Brown       /* we need additional variables */
19740c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
19750c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
19760c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
19770c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
19780c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
19790c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
19800c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
19810c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
19820c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
19830c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
19840c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
19850c7d97c5SJed Brown       MetisInt    *faces_adjncy;
19860c7d97c5SJed Brown       MetisInt    *faces_xadj;
19870c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
19880c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
19890c7d97c5SJed Brown       PetscInt    *array_int;
19900c7d97c5SJed Brown       PetscMPIInt my_faces=0;
19910c7d97c5SJed Brown       PetscMPIInt total_faces=0;
19923828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
19930c7d97c5SJed Brown 
19940c7d97c5SJed Brown       /* define some quantities */
19950c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
19960c7d97c5SJed Brown       coarse_mat_type = MATIS;
19970c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
19986c9de887SHong Zhang       coarse_ksp_type  = KSPCHEBYSHEV;
19990c7d97c5SJed Brown 
20000c7d97c5SJed Brown       /* details of coarse decomposition */
20010c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
20020c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
20033828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
20043828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
20053828260eSStefano Zampini 
2006da1bb401SStefano Zampini       /*printf("Coarse algorithm details: \n");
2007da1bb401SStefano Zampini       printf("n_subdomains %d, n_parts %d\nstretch %d,jumps %d,coarse_ratio %d\nlevel should be log_%d(%d)\n",n_subdomains,n_parts,ranks_stretching_ratio,procs_jumps_coarse_comm,pcbddc->coarsening_ratio,pcbddc->coarsening_ratio,(ranks_stretching_ratio/pcbddc->coarsening_ratio+1));*/
20080c7d97c5SJed Brown 
20090c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
20100c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
20113828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
20120c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
20130c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20140c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
20150c7d97c5SJed Brown         }
20160c7d97c5SJed Brown       }
20170c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20180c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20190c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20200c7d97c5SJed Brown             my_faces++;
20210c7d97c5SJed Brown             break;
20220c7d97c5SJed Brown           }
20230c7d97c5SJed Brown         }
20240c7d97c5SJed Brown       }
20250c7d97c5SJed Brown 
202653cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
20270c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
20280c7d97c5SJed Brown       my_faces=0;
20290c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20300c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20310c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20320c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
20330c7d97c5SJed Brown             my_faces++;
20340c7d97c5SJed Brown             break;
20350c7d97c5SJed Brown           }
20360c7d97c5SJed Brown         }
20370c7d97c5SJed Brown       }
20380c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20390c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
20400c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
20410c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
20420c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
20430c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
20440c7d97c5SJed Brown       }
204553cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
20460c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20470c7d97c5SJed Brown         faces_xadj[0]=0;
20480c7d97c5SJed Brown         faces_displacements[0]=0;
20490c7d97c5SJed Brown         j=0;
20500c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
20510c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
20520c7d97c5SJed Brown           if(number_of_faces[i-1]) {
20530c7d97c5SJed Brown             j++;
20540c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
20550c7d97c5SJed Brown           }
20560c7d97c5SJed Brown         }
2057da1bb401SStefano Zampini         /*printf("The J I count is %d and should be %d\n",j,n_subdomains);
2058da1bb401SStefano Zampini         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);*/
20590c7d97c5SJed Brown       }
206053cdbc3dSStefano Zampini       ierr = MPI_Gatherv(&my_faces_connectivity[0],my_faces,MPIU_INT,&petsc_faces_adjncy[0],number_of_faces,faces_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
20610c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
20620c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
20630c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20643828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
2065da1bb401SStefano Zampini         /*printf("This is the face connectivity (actual ranks)\n");
20660c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
20670c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
20680c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
20690c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
20700c7d97c5SJed Brown           printf("\n");
2071da1bb401SStefano Zampini         }*/
20720c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
20730c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
20740c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
20750c7d97c5SJed Brown       }
20760c7d97c5SJed Brown 
20770c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
20780c7d97c5SJed Brown 
20793828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
20803828260eSStefano Zampini 
20810c7d97c5SJed Brown         ncon=1;
20820c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
20830c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
20840c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
20850c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
20860c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
20870c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
20880c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
20890c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
20903828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
20913828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
20923828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
20930c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20943828260eSStefano Zampini         } else {
20953828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20963828260eSStefano Zampini         }
20970c7d97c5SJed 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);
20980c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
20990c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
21000c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
21010c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
21023828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
21033828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
21040c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
21050c7d97c5SJed Brown       }
21060c7d97c5SJed Brown 
21070c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
21080c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2109da1bb401SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2110da1bb401SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
21110c7d97c5SJed Brown       }
2112da1bb401SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2113da1bb401SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
211453cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
21150c7d97c5SJed Brown 
21160c7d97c5SJed Brown       if( coarse_color == 0 ) {
211753cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
211853cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2119da1bb401SStefano Zampini         /*printf("Details of coarse comm\n");
21203828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
2121da1bb401SStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);*/
21220c7d97c5SJed Brown       } else {
21230c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
21240c7d97c5SJed Brown       }
21250c7d97c5SJed Brown 
21260c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
21270c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
21280c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
2129da1bb401SStefano Zampini         /*ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
2130da1bb401SStefano Zampini           ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);*/
21310c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
21320c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
21330c7d97c5SJed Brown         /* some initializations */
21340c7d97c5SJed Brown         displacements_recv[0]=0;
2135da1bb401SStefano Zampini         /* PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero */
21360c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
21370c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
21383828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
21390c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
21400c7d97c5SJed Brown               total_count_recv[j]++;
21410c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
21420c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
21430c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
21440c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
21450c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
21463828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
21470c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
21480c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
21493828260eSStefano Zampini               total_count_recv[j]+=1;
21500c7d97c5SJed Brown             }
21510c7d97c5SJed Brown           }
21520c7d97c5SJed Brown         }
2153da1bb401SStefano Zampini         /*for(j=0;j<size_coarse_comm;j++) {
21543828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
21553828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
21563828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
21573828260eSStefano Zampini           }
21583828260eSStefano Zampini           printf("\n");
2159da1bb401SStefano Zampini         }*/
21600c7d97c5SJed Brown 
21610c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
21623828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
2163da1bb401SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
21640c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
21653828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
21663828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
21673828260eSStefano Zampini           } else {
21683828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
21693828260eSStefano Zampini           }
2170da1bb401SStefano Zampini         printf("\n");*/
21710c7d97c5SJed Brown       }
21720c7d97c5SJed Brown 
21730c7d97c5SJed Brown       /* Scatter new decomposition for send details */
217453cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21750c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
21760c7d97c5SJed Brown       if( coarse_color == 0) {
217753cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21780c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
217953cdbc3dSStefano Zampini         ierr = MPI_Scatterv(&total_ranks_recv[0],total_count_recv,displacements_recv,MPIU_INT,&ranks_recv[0],count_recv,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21800c7d97c5SJed Brown       }
21810c7d97c5SJed Brown 
2182da1bb401SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2183da1bb401SStefano Zampini       if(coarse_color == 0) {
2184da1bb401SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2185da1bb401SStefano Zampini         for(i=0;i<count_recv;i++)
2186da1bb401SStefano Zampini           printf("%d ",ranks_recv[i]);
2187da1bb401SStefano Zampini         printf("\n");
2188da1bb401SStefano Zampini       }*/
21890c7d97c5SJed Brown 
21900c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
2191da1bb401SStefano Zampini         /*ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2192da1bb401SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
2193da1bb401SStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);*/
21940c7d97c5SJed Brown         free(coarse_subdivision);
21950c7d97c5SJed Brown         free(total_count_recv);
21960c7d97c5SJed Brown         free(total_ranks_recv);
21970c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
21980c7d97c5SJed Brown       }
21990c7d97c5SJed Brown       break;
22000c7d97c5SJed Brown     }
22010c7d97c5SJed Brown 
22020c7d97c5SJed Brown     case(REPLICATED_BDDC):
22030c7d97c5SJed Brown 
22040c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22050c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22060c7d97c5SJed Brown       coarse_pc_type  = PCLU;
220753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22080c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22090c7d97c5SJed Brown       active_rank = rank_prec_comm;
22100c7d97c5SJed Brown       break;
22110c7d97c5SJed Brown 
22120c7d97c5SJed Brown     case(PARALLEL_BDDC):
22130c7d97c5SJed Brown 
22140c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
22150c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
22160c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
221753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22180c7d97c5SJed Brown       coarse_comm = prec_comm;
22190c7d97c5SJed Brown       active_rank = rank_prec_comm;
22200c7d97c5SJed Brown       break;
22210c7d97c5SJed Brown 
22220c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
22230c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22240c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22250c7d97c5SJed Brown       coarse_pc_type = PCLU;
222653cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22270c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22280c7d97c5SJed Brown       active_rank = master_proc;
22290c7d97c5SJed Brown       break;
22300c7d97c5SJed Brown   }
22310c7d97c5SJed Brown 
22320c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
22330c7d97c5SJed Brown 
22340c7d97c5SJed Brown     case(SCATTERS_BDDC):
22350c7d97c5SJed Brown       {
22360c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
22370c7d97c5SJed Brown 
22380c7d97c5SJed Brown           PetscMPIInt send_size;
22390c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
22400c7d97c5SJed Brown           PetscInt    ii,jj;
22410c7d97c5SJed Brown           MPI_Request *requests;
22420c7d97c5SJed Brown 
22430c7d97c5SJed Brown           /* allocate auxiliary space */
22445619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
22455619798eSStefano Zampini           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],pcbddc->local_primal_size,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
22460c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
22470c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
22480c7d97c5SJed Brown           /* allocate stuffs for message massing */
22490c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
22500c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
22510c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
22520c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
22530c7d97c5SJed Brown           /* fill up quantities */
22540c7d97c5SJed Brown           j=0;
22550c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
22560c7d97c5SJed Brown             ii = ranks_recv[i];
22570c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
22580c7d97c5SJed Brown             localdispl2[i]=j;
22590c7d97c5SJed Brown             j+=localsizes2[i];
22600c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
2261da1bb401SStefano Zampini             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 */
22620c7d97c5SJed Brown           }
2263da1bb401SStefano Zampini           /*printf("aux_ins_indices 1\n");
2264da1bb401SStefano Zampini           for(i=0;i<pcbddc->coarse_size;i++)
2265da1bb401SStefano Zampini             printf("%d ",aux_ins_indices[i]);
2266da1bb401SStefano Zampini           printf("\n");*/
22670c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
22680c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
22690c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
22700c7d97c5SJed Brown           ins_local_primal_size=0;
22710c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22720c7d97c5SJed Brown             if(aux_ins_indices[i])
22730c7d97c5SJed Brown               ins_local_primal_size++;
22740c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
22750c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
22760c7d97c5SJed Brown           j=0;
22770c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22780c7d97c5SJed Brown             if(aux_ins_indices[i])
22790c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
22800c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
22810c7d97c5SJed Brown           j=0;
22820c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
22830c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
22840c7d97c5SJed Brown               aux_ins_indices[i]=-1;
22850c7d97c5SJed Brown             } else {
22860c7d97c5SJed Brown               aux_ins_indices[i]=j;
22870c7d97c5SJed Brown               j++;
22880c7d97c5SJed Brown             }
22890c7d97c5SJed Brown           }
22900c7d97c5SJed Brown 
2291da1bb401SStefano Zampini           /*printf("New details localsizes2 localdispl2\n");
2292da1bb401SStefano Zampini           for(i=0;i<count_recv;i++)
2293da1bb401SStefano Zampini             printf("(%d %d) ",localsizes2[i],localdispl2[i]);
2294da1bb401SStefano Zampini           printf("\n");
2295da1bb401SStefano Zampini           printf("aux_ins_indices 2\n");
2296da1bb401SStefano Zampini           for(i=0;i<pcbddc->coarse_size;i++)
2297da1bb401SStefano Zampini             printf("%d ",aux_ins_indices[i]);
2298da1bb401SStefano Zampini           printf("\n");
2299da1bb401SStefano Zampini           printf("ins_local_primal_indices\n");
2300da1bb401SStefano Zampini           for(i=0;i<ins_local_primal_size;i++)
2301da1bb401SStefano Zampini             printf("%d ",ins_local_primal_indices[i]);
2302da1bb401SStefano Zampini           printf("\n");
2303da1bb401SStefano Zampini           printf("coarse_submat_vals\n");
2304da1bb401SStefano Zampini           for(i=0;i<pcbddc->local_primal_size;i++)
2305da1bb401SStefano Zampini             for(j=0;j<pcbddc->local_primal_size;j++)
2306da1bb401SStefano Zampini               printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]);
2307da1bb401SStefano Zampini           printf("\n");*/
23080c7d97c5SJed Brown 
23090c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
231053cdbc3dSStefano Zampini           for(i=0;i<count_recv;i++) ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
23110c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
23120c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
231353cdbc3dSStefano Zampini             ierr = MPI_Isend(&coarse_submat_vals[0],send_size,MPIU_SCALAR,rank_coarse_proc_send_to,666,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
23140c7d97c5SJed Brown           }
231553cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
23160c7d97c5SJed Brown 
2317da1bb401SStefano Zampini           /*if(coarse_color == 0) {
2318da1bb401SStefano Zampini             printf("temp_coarse_mat_vals\n");
2319da1bb401SStefano Zampini             for(k=0;k<count_recv;k++){
2320da1bb401SStefano Zampini               printf("---- %d ----\n",ranks_recv[k]);
2321da1bb401SStefano Zampini               for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
2322da1bb401SStefano Zampini                 for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
2323da1bb401SStefano Zampini                   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]);
2324da1bb401SStefano Zampini               printf("\n");
2325da1bb401SStefano Zampini             }
2326da1bb401SStefano Zampini           }*/
23270c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
23280c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23290c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
23300c7d97c5SJed Brown 
23310c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
23320c7d97c5SJed Brown           PetscInt row_ind,col_ind;
23330c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
23340c7d97c5SJed Brown             rr = ranks_recv[k];
23350c7d97c5SJed Brown             kk = localdispl2[k];
23360c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
23370c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
2338da1bb401SStefano Zampini             /*printf("Inserting the following indices (received from %d)\n",rr);*/
23390c7d97c5SJed Brown             for(j=0;j<lps;j++){
23400c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
23410c7d97c5SJed Brown               for(i=0;i<lps;i++){
23420c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
2343da1bb401SStefano Zampini                 /*printf("%d %d\n",row_ind,col_ind);*/
23440c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
23450c7d97c5SJed Brown               }
23460c7d97c5SJed Brown             }
23470c7d97c5SJed Brown           }
23480c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
23490c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
23500c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
23510c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
23520c7d97c5SJed Brown 
23530c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
23540c7d97c5SJed Brown           {
23550c7d97c5SJed Brown             IS coarse_IS;
235653cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
23570c7d97c5SJed Brown             coarse_comm = prec_comm;
23580c7d97c5SJed Brown             active_rank=rank_prec_comm;
23590c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
23600c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
23610c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
23620c7d97c5SJed Brown           }
23630c7d97c5SJed Brown         }
23640c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
23650c7d97c5SJed Brown           /* arrays for values insertion */
23660c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
23670c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23680c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23690c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23700c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
23710c7d97c5SJed 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];
23720c7d97c5SJed Brown           }
23730c7d97c5SJed Brown         }
23740c7d97c5SJed Brown         break;
23750c7d97c5SJed Brown 
23760c7d97c5SJed Brown     }
23770c7d97c5SJed Brown 
23780c7d97c5SJed Brown     case(GATHERS_BDDC):
23790c7d97c5SJed Brown       {
23800c7d97c5SJed Brown 
23810c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
23820c7d97c5SJed Brown 
23830c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23840c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23850c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
23860c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23870c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
23880c7d97c5SJed Brown           /* arrays for values insertion */
23890c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
23900c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23910c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23920c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
23930c7d97c5SJed Brown           localdispl2[0]=0;
23940c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
23950c7d97c5SJed Brown           j=0;
23960c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
23970c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
23980c7d97c5SJed Brown         }
23990c7d97c5SJed Brown 
24000c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
24010c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
24020c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
240353cdbc3dSStefano Zampini           ierr = MPI_Gatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
240453cdbc3dSStefano Zampini           ierr = MPI_Gatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,master_proc,prec_comm);CHKERRQ(ierr);
24050c7d97c5SJed Brown         } else {
240653cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&pcbddc->local_primal_indices[0],mysize,MPIU_INT,&pcbddc->replicated_local_primal_indices[0],pcbddc->local_primal_sizes,pcbddc->local_primal_displacements,MPIU_INT,prec_comm);CHKERRQ(ierr);
240753cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
24080c7d97c5SJed Brown         }
24090c7d97c5SJed Brown 
24100c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
24110c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
24120c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
24130c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
24140c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
24150c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
24160c7d97c5SJed Brown           }
24170c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
24180c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
24190c7d97c5SJed Brown             offset2=localdispl2[k];
24200c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
24210c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
24220c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
24230c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
24240c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
24250c7d97c5SJed Brown               }
24260c7d97c5SJed Brown             }
24270c7d97c5SJed Brown           }
24280c7d97c5SJed Brown         }
24290c7d97c5SJed Brown         break;
2430da1bb401SStefano Zampini       }/* switch on coarse problem and communications associated with finished */
24310c7d97c5SJed Brown   }
24320c7d97c5SJed Brown 
24330c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
24340c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
24350c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
24360c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
24370c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
24380c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
24393b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
2440da1bb401SStefano Zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
24413b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24420c7d97c5SJed Brown     } else {
24430c7d97c5SJed Brown       Mat matis_coarse_local_mat;
2444d3ee2243SStefano Zampini       /* remind bs */
2445d3ee2243SStefano Zampini       ierr = MatCreateIS(coarse_comm,bs,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
24463b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24470c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
24483b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2449da1bb401SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2450a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24510c7d97c5SJed Brown     }
2452a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
24530c7d97c5SJed 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);
24540c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24550c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24560c7d97c5SJed Brown 
2457da1bb401SStefano Zampini     /*  PetscViewer view_out;
2458da1bb401SStefano Zampini       ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"coarsematfull.m",&view_out);CHKERRQ(ierr);
2459da1bb401SStefano Zampini       ierr = PetscViewerSetFormat(view_out,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2460da1bb401SStefano Zampini       ierr = MatView(pcbddc->coarse_mat,view_out);CHKERRQ(ierr);
2461da1bb401SStefano Zampini       ierr = PetscViewerDestroy(&view_out);CHKERRQ(ierr);*/
2462da1bb401SStefano Zampini 
24630c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
24640c7d97c5SJed Brown     /* Preconditioner for coarse problem */
246553cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
246653cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
246753cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
24683b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
246953cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
247053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
247153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
24720c7d97c5SJed Brown     /* Allow user's customization */
2473da1bb401SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
247453cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24750c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
247653cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2477e269702eSStefano Zampini       if(dbg_flag) {
2478e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2479e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2480e269702eSStefano Zampini       }
248153cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
248253cdbc3dSStefano Zampini     }
248353cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
24845619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
24855619798eSStefano Zampini       if(dbg_flag) {
24865619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
24875619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24885619798eSStefano Zampini       }
24895619798eSStefano Zampini     }
24900c7d97c5SJed Brown   }
24910c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
24920c7d97c5SJed Brown      IS local_IS,global_IS;
24930c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
24940c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
24950c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
24960c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
24970c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
24980c7d97c5SJed Brown   }
24990c7d97c5SJed Brown 
25000c7d97c5SJed Brown 
25013b03a366Sstefano_zampini   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
25023b03a366Sstefano_zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
25030c7d97c5SJed Brown     PetscScalar m_one=-1.0;
25045619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
25053b03a366Sstefano_zampini     const KSPType check_ksp_type=KSPGMRES;
25060c7d97c5SJed Brown 
25075619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
25083b03a366Sstefano_zampini     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2509d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
25105619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
25115619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2512d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2513d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2514d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2515d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2516d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
25173b03a366Sstefano_zampini     if(dbg_flag) {
25185619798eSStefano Zampini       kappa_2=lambda_max/lambda_min;
25195619798eSStefano Zampini       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2520d49ef151SStefano Zampini       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2521d49ef151SStefano Zampini       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
25223b03a366Sstefano_zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem condition number estimated with %d iterations of %s is: % 1.14e\n",k,check_ksp_type,kappa_2);CHKERRQ(ierr);
2523e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2524e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
25253b03a366Sstefano_zampini     }
25265619798eSStefano Zampini     /* restore coarse ksp to default values */
2527d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
25285619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
25296c9de887SHong Zhang     ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
25303b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
25315619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
25325619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
253353cdbc3dSStefano Zampini   }
25340c7d97c5SJed Brown 
25350c7d97c5SJed Brown   /* free data structures no longer needed */
25360c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
25370c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
25380c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
25390c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
25400c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
25410c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
25420c7d97c5SJed Brown 
25430c7d97c5SJed Brown   PetscFunctionReturn(0);
25440c7d97c5SJed Brown }
25450c7d97c5SJed Brown 
25460c7d97c5SJed Brown #undef __FUNCT__
25470c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
254853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
25490c7d97c5SJed Brown {
25500c7d97c5SJed Brown 
25510c7d97c5SJed Brown   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
25520c7d97c5SJed Brown   PC_IS         *pcis = (PC_IS*)pc->data;
25530c7d97c5SJed Brown   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
2554da1bb401SStefano Zampini   PCBDDCGraph mat_graph=pcbddc->mat_graph;
2555a0ba757dSStefano Zampini   PetscInt    *queue_in_global_numbering;
25563b03a366Sstefano_zampini   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
2557da1bb401SStefano Zampini   PetscInt    total_counts,nodes_touched,where_values=1,vertex_size;
25583b03a366Sstefano_zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
2559da1bb401SStefano Zampini   PetscBool   same_set;
2560a0ba757dSStefano Zampini   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
25613b03a366Sstefano_zampini   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
25623b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
25633b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
256436e030ebSStefano Zampini   IS          used_IS;
2565da1bb401SStefano Zampini   PetscScalar *array;
2566da1bb401SStefano Zampini   PetscScalar *array2;
2567da1bb401SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
25680c7d97c5SJed Brown 
25690c7d97c5SJed Brown   PetscFunctionBegin;
2570da1bb401SStefano Zampini   /* Setup local adjacency graph */
2571da1bb401SStefano Zampini   mat_graph->nvtxs=pcis->n;
2572da1bb401SStefano Zampini   ierr = PCBDDCSetupLocalAdjacencyGraph(pc);CHKERRQ(ierr);
2573a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2574a0ba757dSStefano Zampini   ierr = PetscMalloc4(i,PetscInt,&mat_graph->where,i,PetscInt,&mat_graph->count,i+1,PetscInt,&mat_graph->cptr,i,PetscInt,&mat_graph->queue);CHKERRQ(ierr);
2575a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2576a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2577a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2578a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2579a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25803828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2581a0ba757dSStefano Zampini 
25829c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
25839c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
25849c0446d6SStefano Zampini     PetscInt *is_indices;
25859c0446d6SStefano Zampini     PetscInt is_size;
25869c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
25879c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
25889c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25899c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
25909c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
25919c0446d6SStefano Zampini       }
25929c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25939c0446d6SStefano Zampini     }
25943b03a366Sstefano_zampini     /* use mat block size as vertex size */
25953b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
25963b03a366Sstefano_zampini   } else { /* otherwise it assumes a constant block size */
2597a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
25980c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
25990c7d97c5SJed Brown       for(s=0;s<bs;s++) {
26000c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
26010c7d97c5SJed Brown       }
26020c7d97c5SJed Brown     }
26033b03a366Sstefano_zampini     vertex_size=1;
26049c0446d6SStefano Zampini   }
26053b03a366Sstefano_zampini   /* count number of neigh per node */
26060c7d97c5SJed Brown   total_counts=0;
26073b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26080c7d97c5SJed Brown     s=pcis->n_shared[i];
26090c7d97c5SJed Brown     total_counts+=s;
261053cdbc3dSStefano Zampini     for(j=0;j<s;j++){
26110c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
26120c7d97c5SJed Brown     }
26130c7d97c5SJed Brown   }
26143b03a366Sstefano_zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
261536e030ebSStefano Zampini   ierr = PCBDDCGetNeumannBoundaries(pc,&used_IS);CHKERRQ(ierr);
2616da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
2617da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
261836e030ebSStefano Zampini   if(used_IS) {
261936e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&neumann_bsize);CHKERRQ(ierr);
262036e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
262153cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
262253cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
2623da1bb401SStefano Zampini       if(mat_graph->count[iindex] > 1 && array[iindex]==0.0){
262453cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26250c7d97c5SJed Brown         total_counts++;
2626da1bb401SStefano Zampini         array[iindex]=array[iindex]+1.0;
2627da1bb401SStefano Zampini       } else if(array[iindex]>0.0) {
2628da1bb401SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Error for neumann nodes provided to BDDC! They must be uniquely listed! Found duplicate node %d\n",iindex);
26290c7d97c5SJed Brown       }
26300c7d97c5SJed Brown     }
26310c7d97c5SJed Brown   }
2632da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2633da1bb401SStefano Zampini   /* allocate space for storing the set of neighbours for each node */
2634da1bb401SStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&mat_graph->neighbours_set);CHKERRQ(ierr);
2635da1bb401SStefano Zampini   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&mat_graph->neighbours_set[0]);CHKERRQ(ierr); }
2636da1bb401SStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) mat_graph->neighbours_set[i]=mat_graph->neighbours_set[i-1]+mat_graph->count[i-1];
2637a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
26383b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26390c7d97c5SJed Brown     s=pcis->n_shared[i];
26400c7d97c5SJed Brown     for(j=0;j<s;j++) {
26410c7d97c5SJed Brown       k=pcis->shared[i][j];
2642da1bb401SStefano Zampini       mat_graph->neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
26430c7d97c5SJed Brown       mat_graph->count[k]+=1;
26440c7d97c5SJed Brown     }
26450c7d97c5SJed Brown   }
2646da1bb401SStefano Zampini   /* Check consistency of Neumann nodes */
2647da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2648da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2649da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2650da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2651da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2652da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
26533b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
265436e030ebSStefano Zampini   if(used_IS) {
265553cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
265653cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
26573b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
2658da1bb401SStefano Zampini         if(mat_graph->count[iindex]+1 != (PetscInt)array[iindex]) {
2659da1bb401SStefano Zampini           SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Neumann nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,mat_graph->count[iindex]+1,(PetscInt)array[iindex]);
2660da1bb401SStefano Zampini         }
2661da1bb401SStefano Zampini         mat_graph->neighbours_set[iindex][mat_graph->count[iindex]] = -1;
266253cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26630c7d97c5SJed Brown       }
26640c7d97c5SJed Brown     }
266536e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
26660c7d97c5SJed Brown   }
2667da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2668da1bb401SStefano Zampini   /* sort set of sharing subdomains */
2669da1bb401SStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],mat_graph->neighbours_set[i]);CHKERRQ(ierr); }
26703b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
2671da1bb401SStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2672da1bb401SStefano Zampini   nodes_touched=0;
267336e030ebSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&used_IS);CHKERRQ(ierr);
2674da1bb401SStefano Zampini   ierr = VecSet(pcis->vec2_N,0.0);CHKERRQ(ierr);
2675da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2676da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2677da1bb401SStefano Zampini   if(used_IS) {
2678da1bb401SStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
2679da1bb401SStefano Zampini     if(dirichlet_bsize && matis->pure_neumann) {
2680da1bb401SStefano Zampini       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet boundaries are intended to be used with matrices with zeroed rows!\n");
2681da1bb401SStefano Zampini     }
2682da1bb401SStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
2683da1bb401SStefano Zampini     for(i=0;i<dirichlet_bsize;i++){
2684da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
2685da1bb401SStefano Zampini       if(mat_graph->count[iindex] && !mat_graph->touched[iindex]) {
2686da1bb401SStefano Zampini         if(array[iindex]>0.0) {
2687da1bb401SStefano Zampini           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"BDDC cannot have nodes which are marked as Neumann and Dirichlet at the same time! Wrong node %d\n",iindex);
2688da1bb401SStefano Zampini         }
2689da1bb401SStefano Zampini         mat_graph->touched[iindex]=PETSC_TRUE;
2690da1bb401SStefano Zampini         mat_graph->where[iindex]=0;
2691da1bb401SStefano Zampini         nodes_touched++;
2692da1bb401SStefano Zampini         array2[iindex]=array2[iindex]+1.0;
2693da1bb401SStefano Zampini       }
2694da1bb401SStefano Zampini     }
2695da1bb401SStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
2696da1bb401SStefano Zampini   }
2697da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2698da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2699da1bb401SStefano Zampini   /* Check consistency of Dirichlet nodes */
2700da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr);
2701da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2702da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2703da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2704da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2705da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2706da1bb401SStefano Zampini   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
2707da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2708da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec2_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2709da1bb401SStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2710da1bb401SStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2711da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2712da1bb401SStefano Zampini   ierr = VecGetArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
271336e030ebSStefano Zampini   if(used_IS) {
271436e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
271536e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
27163b03a366Sstefano_zampini     for(i=0;i<dirichlet_bsize;i++){
2717da1bb401SStefano Zampini       iindex=dirichlet_nodes[i];
2718da1bb401SStefano Zampini       if(array[iindex]>1.0 && array[iindex]!=array2[iindex] ) {
2719da1bb401SStefano Zampini          SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_USER,"Dirichlet nodes provided to BDDC must be consistent among neighbours!\nNode %d: number of sharing subdomains %d != number of subdomains for which it is a neumann node %d\n",iindex,(PetscInt)array[iindex],(PetscInt)array2[iindex]);
2720da1bb401SStefano Zampini       }
27213b03a366Sstefano_zampini     }
272236e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
27233b03a366Sstefano_zampini   }
2724da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
2725da1bb401SStefano Zampini   ierr = VecRestoreArray(pcis->vec2_N,&array2);CHKERRQ(ierr);
2726da1bb401SStefano Zampini 
27270c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
27283b03a366Sstefano_zampini     if(!mat_graph->count[i]){  /* interior nodes */
27290c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
27300c7d97c5SJed Brown       mat_graph->where[i]=0;
27310c7d97c5SJed Brown       nodes_touched++;
27320c7d97c5SJed Brown     }
27330c7d97c5SJed Brown   }
27340c7d97c5SJed Brown   mat_graph->ncmps = 0;
2735da1bb401SStefano Zampini   i=0;
27360c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2737a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
27380c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
27390c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2740a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
27410c7d97c5SJed Brown     nodes_touched++;
2742a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
27430c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2744a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
2745da1bb401SStefano Zampini       if(!mat_graph->touched[j] && mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2746a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
27470c7d97c5SJed Brown         same_set=PETSC_TRUE;
27480c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
2749da1bb401SStefano Zampini           if(mat_graph->neighbours_set[i][k]!=mat_graph->neighbours_set[j][k]) {
27500c7d97c5SJed Brown             same_set=PETSC_FALSE;
27510c7d97c5SJed Brown           }
27520c7d97c5SJed Brown         }
2753a0ba757dSStefano Zampini         /* I found a friend of mine */
27540c7d97c5SJed Brown         if(same_set) {
2755a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
27560c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
27570c7d97c5SJed Brown           nodes_touched++;
27580c7d97c5SJed Brown         }
27590c7d97c5SJed Brown       }
27600c7d97c5SJed Brown     }
2761a0ba757dSStefano Zampini     where_values++;
27620c7d97c5SJed Brown   }
2763a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2764a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2765a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2766a0ba757dSStefano Zampini   if(where_values) {
2767a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
27683b03a366Sstefano_zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2769a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2770a0ba757dSStefano Zampini       ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
2771a0ba757dSStefano Zampini       ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
2772a0ba757dSStefano Zampini     }
2773a0ba757dSStefano Zampini   }
2774a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2775a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
27763b03a366Sstefano_zampini     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
27773b03a366Sstefano_zampini     if(mat_graph->where_ncmps[i]>1) {
2778a0ba757dSStefano Zampini       adapt_interface=1;
2779a0ba757dSStefano Zampini       break;
2780a0ba757dSStefano Zampini     }
2781a0ba757dSStefano Zampini   }
2782a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2783da1bb401SStefano Zampini   if(pcbddc->dbg_flag && adapt_interface_reduced) {
2784da1bb401SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Interface adapted\n");CHKERRQ(ierr);
2785da1bb401SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2786da1bb401SStefano Zampini   }
2787a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
27880c7d97c5SJed Brown 
27893b03a366Sstefano_zampini 
2790a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2791a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2792a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2793a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2794a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2795a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2796a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2797a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2798a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2799a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2800a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2801a0ba757dSStefano Zampini     MPI_Request *send_requests;
2802a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2803a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2804a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2805a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2806a0ba757dSStefano Zampini     PetscInt *add_to_where;
2807a0ba757dSStefano Zampini 
2808a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2809a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2810a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2811a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2812a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2813a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2814a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2815a0ba757dSStefano Zampini       j=0;
2816a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2817a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
2818da1bb401SStefano Zampini       if(mat_graph->neighbours_set[j][0]!=-1) { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]; } /* We don't want sends/recvs_to/from_self -> here I don't count myself  */
28193b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2820a0ba757dSStefano Zampini     }
2821a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2822a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2823a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2824a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2825a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2826a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2827a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2828a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2829a0ba757dSStefano Zampini     }
2830a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2831a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2832a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2833da1bb401SStefano Zampini       k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2834a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2835da1bb401SStefano Zampini         ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2836da1bb401SStefano Zampini         ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2837a0ba757dSStefano Zampini         sum_requests++;
2838a0ba757dSStefano Zampini       }
2839a0ba757dSStefano Zampini     }
2840a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2841a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2842a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2843a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2844a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2845a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2846a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
28473b03a366Sstefano_zampini         /* The first condition is natural (i.e someone has a different number of cc than me), the second one is just to be safe */
28483b03a366Sstefano_zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2849a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2850a0ba757dSStefano Zampini           break;
2851a0ba757dSStefano Zampini         }
2852a0ba757dSStefano Zampini       }
2853a0ba757dSStefano Zampini     }
2854a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2855a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2856a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2857a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2858a0ba757dSStefano Zampini     sum_requests=0;
2859a0ba757dSStefano Zampini     start_of_send=0;
2860a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2861a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2862a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2863a0ba757dSStefano Zampini         size_of_send=0;
2864a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2865a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2866a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2867a0ba757dSStefano Zampini             size_of_send+=1;
2868a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2869a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2870a0ba757dSStefano Zampini             }
2871a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2872a0ba757dSStefano Zampini           }
2873a0ba757dSStefano Zampini         }
2874a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2875da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2876*11d8f4c2SStefano Zampini         sizes_of_sends[i]=size_of_send;
2877a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2878*11d8f4c2SStefano Zampini           ierr = MPI_Isend(&sizes_of_sends[i],1,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2879da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2880a0ba757dSStefano Zampini           sum_requests++;
2881a0ba757dSStefano Zampini         }
2882a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2883a0ba757dSStefano Zampini       }
2884a0ba757dSStefano Zampini     }
2885a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2886a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2887a0ba757dSStefano Zampini     buffer_size=0;
2888a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2889a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2890a0ba757dSStefano Zampini     /* now exchange the data */
2891a0ba757dSStefano Zampini     start_of_recv=0;
2892a0ba757dSStefano Zampini     start_of_send=0;
2893a0ba757dSStefano Zampini     sum_requests=0;
2894a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2895a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2896a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2897a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2898da1bb401SStefano Zampini         k = (mat_graph->neighbours_set[j][0] == -1 ?  1 : 0);
2899a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2900da1bb401SStefano Zampini           ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,mat_graph->neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2901a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2902da1bb401SStefano Zampini           ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,mat_graph->neighbours_set[j][k],(mat_graph->neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2903a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2904a0ba757dSStefano Zampini           sum_requests++;
2905a0ba757dSStefano Zampini         }
2906a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2907a0ba757dSStefano Zampini       }
2908a0ba757dSStefano Zampini     }
2909a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2910a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2911a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2912a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2913a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2914a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2915a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2916a0ba757dSStefano Zampini        j+=k;
2917a0ba757dSStefano Zampini     }
2918a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2919a0ba757dSStefano Zampini     start_of_recv=0;
2920a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2921a0ba757dSStefano Zampini     global_where_counter=0;
2922a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2923a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2924a0ba757dSStefano Zampini         temp_buffer_size=0;
2925a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2926a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2927a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2928a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2929a0ba757dSStefano Zampini             temp_buffer_size++;
2930a0ba757dSStefano Zampini           } else {
2931a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2932a0ba757dSStefano Zampini           }
2933a0ba757dSStefano Zampini         }
2934a0ba757dSStefano Zampini         /* allocate some temporary space */
2935a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2936a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2937a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2938a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2939a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2940a0ba757dSStefano Zampini         }
2941a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2942a0ba757dSStefano Zampini            temp buffer structure:
2943a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2944a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2945a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2946a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2947a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2948a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2949a0ba757dSStefano Zampini              [ 0, 0, 0;
2950a0ba757dSStefano Zampini                0, 0, 1;
2951a0ba757dSStefano Zampini                1, 1, 2;
2952a0ba757dSStefano Zampini                1, 1, 2;
2953a0ba757dSStefano Zampini                0, 1, 0; ];
2954a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2955a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2956a0ba757dSStefano Zampini                                                                                                                                    */
2957a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2958a0ba757dSStefano Zampini           ins_val=0;
2959a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2960a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2961a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2962a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2963a0ba757dSStefano Zampini             }
2964a0ba757dSStefano Zampini             buffer_size+=k;
2965a0ba757dSStefano Zampini             ins_val++;
2966a0ba757dSStefano Zampini           }
2967a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2968a0ba757dSStefano Zampini           sum_requests++;
2969a0ba757dSStefano Zampini         }
2970a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2971a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2972a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2973a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2974a0ba757dSStefano Zampini             global_where_counter++;
2975a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2976a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2977a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2978a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2979a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2980a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2981a0ba757dSStefano Zampini                   break;
2982a0ba757dSStefano Zampini                 }
2983a0ba757dSStefano Zampini               }
2984a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2985a0ba757dSStefano Zampini             }
2986a0ba757dSStefano Zampini           }
2987a0ba757dSStefano Zampini         }
2988a0ba757dSStefano Zampini         /* insert new data in where array */
2989a0ba757dSStefano Zampini         temp_buffer_size=0;
2990a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2991a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2992a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2993a0ba757dSStefano Zampini             temp_buffer_size++;
2994a0ba757dSStefano Zampini           }
2995a0ba757dSStefano Zampini         }
2996a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2997a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2998a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2999a0ba757dSStefano Zampini       }
3000a0ba757dSStefano Zampini     }
3001a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
3002a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
3003a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
3004a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
3005a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
3006a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
3007a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
3008a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
3009a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
3010a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
3011a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
3012a0ba757dSStefano Zampini     if(global_where_counter) {
3013a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
3014a0ba757dSStefano Zampini       global_where_counter=0;
3015a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
3016a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
3017a0ba757dSStefano Zampini           global_where_counter++;
3018a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
3019a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
3020a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
3021a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
3022a0ba757dSStefano Zampini             }
3023a0ba757dSStefano Zampini           }
3024a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
3025a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
3026a0ba757dSStefano Zampini         }
3027a0ba757dSStefano Zampini       }
3028a0ba757dSStefano Zampini       where_values=global_where_counter;
3029a0ba757dSStefano Zampini     }
3030a0ba757dSStefano Zampini     if(global_where_counter) {
3031a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
3032a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
3033a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
3034a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
3035a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
3036a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
3037a0ba757dSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,mat_graph->cptr[i+1]-mat_graph->cptr[i],&mat_graph->queue[mat_graph->cptr[i]],&queue_in_global_numbering[mat_graph->cptr[i]]);CHKERRQ(ierr);
3038a0ba757dSStefano Zampini         ierr = PetscSortIntWithArray(mat_graph->cptr[i+1]-mat_graph->cptr[i],&queue_in_global_numbering[mat_graph->cptr[i]],&mat_graph->queue[mat_graph->cptr[i]]);CHKERRQ(ierr);
3039a0ba757dSStefano Zampini       }
3040a0ba757dSStefano Zampini     }
30413b03a366Sstefano_zampini   } /* Finished adapting interface */
30420c7d97c5SJed Brown   PetscInt nfc=0;
30430c7d97c5SJed Brown   PetscInt nec=0;
30440c7d97c5SJed Brown   PetscInt nvc=0;
30453b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
30460c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
30473b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
30483b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
30490c7d97c5SJed Brown         nfc++;
30503b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
30513b03a366Sstefano_zampini         nec++;
30523b03a366Sstefano_zampini       }
30530c7d97c5SJed Brown     } else {
30543b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
30553b03a366Sstefano_zampini     }
30563b03a366Sstefano_zampini   }
30573b03a366Sstefano_zampini 
30583b03a366Sstefano_zampini   if(!nec) { /* we are in a 2d case -> no faces, only edges */
30593b03a366Sstefano_zampini     nec = nfc;
30603b03a366Sstefano_zampini     nfc = 0;
30613b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
30623b03a366Sstefano_zampini   }
30633b03a366Sstefano_zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set.
30643b03a366Sstefano_zampini      Reusing space allocated in mat_graph->where for creating IS objects */
30653b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
30663b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
30673b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
30683b03a366Sstefano_zampini   }
30693b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
30703b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
30713b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
30723b03a366Sstefano_zampini   }
30733b03a366Sstefano_zampini   nfc=0;
30743b03a366Sstefano_zampini   nec=0;
30753b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
30763b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
30773b03a366Sstefano_zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
30783b03a366Sstefano_zampini         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
30793b03a366Sstefano_zampini       }
30803b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
30813b03a366Sstefano_zampini         if(twodim_flag) {
30823b03a366Sstefano_zampini           if(use_edges) {
30833b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30843b03a366Sstefano_zampini             nec++;
30853b03a366Sstefano_zampini           }
30863b03a366Sstefano_zampini         } else {
30873b03a366Sstefano_zampini           if(use_faces) {
30883b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
30893b03a366Sstefano_zampini             nfc++;
30903b03a366Sstefano_zampini           }
30913b03a366Sstefano_zampini         }
30923b03a366Sstefano_zampini       } else {
30933b03a366Sstefano_zampini         if(use_edges) {
30943b03a366Sstefano_zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30950c7d97c5SJed Brown           nec++;
30960c7d97c5SJed Brown         }
30970c7d97c5SJed Brown       }
30980c7d97c5SJed Brown     }
30993b03a366Sstefano_zampini   }
31003b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
31013b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
31023b03a366Sstefano_zampini   nvc=0;
31030c7d97c5SJed Brown   if( !pcbddc->constraints_flag ) {
31043b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
31053b03a366Sstefano_zampini       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
31063b03a366Sstefano_zampini         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
31073b03a366Sstefano_zampini           mat_graph->where[nvc]=mat_graph->queue[j];
31080c7d97c5SJed Brown           nvc++;
31090c7d97c5SJed Brown         }
31100c7d97c5SJed Brown       }
31110c7d97c5SJed Brown     }
31120c7d97c5SJed Brown   }
3113a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
31143b03a366Sstefano_zampini   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
31153b03a366Sstefano_zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
31160c7d97c5SJed Brown 
3117e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
3118e269702eSStefano Zampini 
3119d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3120d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3121d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3122a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
3123a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3124e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
3125a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Nodes connected to node number %d are %d\n",i,mat_graph->xadj[i+1]-mat_graph->xadj[i]);CHKERRQ(ierr);
3126e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
3127a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
3128e269702eSStefano Zampini       }
3129a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
3130da1bb401SStefano Zampini     }*/
3131d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
31320c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
31333b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
31343b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
3135da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"subdomains: ");
3136da1bb401SStefano Zampini       for (j=0;j<mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]; j++) {
3137da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->neighbours_set[mat_graph->queue[mat_graph->cptr[i]]][j]);
3138da1bb401SStefano Zampini       }
3139da1bb401SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n");
31400c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
3141da1bb401SStefano Zampini         /* ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr); */
3142da1bb401SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d, ",mat_graph->queue[j]);CHKERRQ(ierr);
31430c7d97c5SJed Brown       }
31440c7d97c5SJed Brown     }
3145da1bb401SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
31463b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
31473b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
31483b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3149d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
31500c7d97c5SJed Brown   }
31510c7d97c5SJed Brown 
3152a0ba757dSStefano Zampini   /* Free graph structure */
31530c7d97c5SJed Brown   if(mat_graph->nvtxs){
3154a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3155a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3156a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
31570c7d97c5SJed Brown   }
31580c7d97c5SJed Brown 
31590c7d97c5SJed Brown   PetscFunctionReturn(0);
31600c7d97c5SJed Brown 
31610c7d97c5SJed Brown }
31620c7d97c5SJed Brown 
31630c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
31640c7d97c5SJed Brown 
31650c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
3166da1bb401SStefano Zampini    in source file contig.c of METIS library (version 5.0.1)
3167da1bb401SStefano Zampini    It finds connected components of each partition labeled from 1 to n_dist  */
31680c7d97c5SJed Brown 
31690c7d97c5SJed Brown #undef __FUNCT__
31700c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
31719c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
31720c7d97c5SJed Brown {
31730c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
31740c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
31750c7d97c5SJed Brown   PetscInt *cptr;
31760c7d97c5SJed Brown   PetscBool *touched;
31770c7d97c5SJed Brown 
31780c7d97c5SJed Brown   PetscFunctionBegin;
31790c7d97c5SJed Brown 
31800c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
31810c7d97c5SJed Brown   xadj    = graph->xadj;
31820c7d97c5SJed Brown   adjncy  = graph->adjncy;
31830c7d97c5SJed Brown   where   = graph->where;
31840c7d97c5SJed Brown   touched = graph->touched;
31850c7d97c5SJed Brown   queue   = graph->queue;
31860c7d97c5SJed Brown   cptr    = graph->cptr;
31870c7d97c5SJed Brown 
31880c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
31890c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
31900c7d97c5SJed Brown 
31910c7d97c5SJed Brown   cum_queue=0;
31920c7d97c5SJed Brown   ncmps=0;
31930c7d97c5SJed Brown 
31940c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
3195da1bb401SStefano Zampini     pid = n+1;  /* partition labeled by 0 is discarded */
31960c7d97c5SJed Brown     nleft = 0;
31970c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
31980c7d97c5SJed Brown       if (where[i] == pid)
31990c7d97c5SJed Brown         nleft++;
32000c7d97c5SJed Brown     }
32010c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
32020c7d97c5SJed Brown       if (where[i] == pid)
32030c7d97c5SJed Brown         break;
32040c7d97c5SJed Brown     }
32050c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
32060c7d97c5SJed Brown     queue[cum_queue] = i;
32070c7d97c5SJed Brown     first = 0; last = 1;
32080c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
32090c7d97c5SJed Brown     ncmps_pid = 0;
32100c7d97c5SJed Brown     while (first != nleft) {
32110c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
32120c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
32130c7d97c5SJed Brown         ncmps_pid++;
32140c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
32150c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
32160c7d97c5SJed Brown             break;
32170c7d97c5SJed Brown         }
32180c7d97c5SJed Brown         queue[cum_queue+last] = i;
32190c7d97c5SJed Brown         last++;
32200c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
32210c7d97c5SJed Brown       }
32220c7d97c5SJed Brown       i = queue[cum_queue+first];
32230c7d97c5SJed Brown       first++;
32240c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
32250c7d97c5SJed Brown         k = adjncy[j];
32260c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
32270c7d97c5SJed Brown           queue[cum_queue+last] = k;
32280c7d97c5SJed Brown           last++;
32290c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
32300c7d97c5SJed Brown         }
32310c7d97c5SJed Brown       }
32320c7d97c5SJed Brown     }
32330c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
32340c7d97c5SJed Brown     ncmps_pid++;
32350c7d97c5SJed Brown     cum_queue=cptr[ncmps];
3236a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
32370c7d97c5SJed Brown   }
32380c7d97c5SJed Brown   graph->ncmps = ncmps;
32390c7d97c5SJed Brown 
32400c7d97c5SJed Brown   PetscFunctionReturn(0);
32410c7d97c5SJed Brown }
32420c7d97c5SJed Brown 
3243