xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 36e030eb8e58b038c8a980256364da8f785d22b6)
153cdbc3dSStefano Zampini /* TODOLIST
2d11ae9bbSstefano_zampini    DofSplitting and DM attached to pc.
33b03a366Sstefano_zampini    Exact solvers: Solve local saddle point directly for very hard problems
4831a100dSStefano Zampini      - change prec_type to switch_inexact_prec_type
5831a100dSStefano Zampini      - add bool solve_exact_saddle_point slot to pdbddc data
63b03a366Sstefano_zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
7a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
8a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
9a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
10a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
11a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
123b03a366Sstefano_zampini      - Add levels' slot to bddc data structure and associated Set/Get functions
13a0ba757dSStefano Zampini    code refactoring:
14a0ba757dSStefano Zampini      - pick up better names for static functions
153b03a366Sstefano_zampini    check log_summary for leaking (actually: 1 Vector per level )
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    remove // commments and adhere to PETSc code requirements
21a0ba757dSStefano Zampini    man pages
2253cdbc3dSStefano Zampini */
230c7d97c5SJed Brown 
2453cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
250c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
260c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2753cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2853cdbc3dSStefano Zampini 
2953cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
303b03a366Sstefano_zampini #include <petscblaslapack.h>
310c7d97c5SJed Brown 
320c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
330c7d97c5SJed Brown #undef __FUNCT__
340c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
350c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
360c7d97c5SJed Brown {
370c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
380c7d97c5SJed Brown   PetscErrorCode ierr;
390c7d97c5SJed Brown 
400c7d97c5SJed Brown   PetscFunctionBegin;
410c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
420c7d97c5SJed Brown   /* Verbose debugging of main data structures */
43e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
440c7d97c5SJed Brown   /* Some customization for default primal space */
450c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
460c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
470c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use faces only in coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
480c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use edges only in coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
490c7d97c5SJed Brown   /* Coarse solver context */
500c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
510c7d97c5SJed 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);
520c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
530c7d97c5SJed 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);
540c7d97c5SJed 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);
550c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
560c7d97c5SJed Brown   PetscFunctionReturn(0);
570c7d97c5SJed Brown }
580c7d97c5SJed Brown 
590c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
600c7d97c5SJed Brown EXTERN_C_BEGIN
610c7d97c5SJed Brown #undef __FUNCT__
620c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
640c7d97c5SJed Brown {
650c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
660c7d97c5SJed Brown 
670c7d97c5SJed Brown   PetscFunctionBegin;
680c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
690c7d97c5SJed Brown   PetscFunctionReturn(0);
700c7d97c5SJed Brown }
710c7d97c5SJed Brown EXTERN_C_END
720c7d97c5SJed Brown 
730c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
740c7d97c5SJed Brown #undef __FUNCT__
750c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7653cdbc3dSStefano Zampini /*@
779c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7853cdbc3dSStefano Zampini 
799c0446d6SStefano Zampini    Not collective
8053cdbc3dSStefano Zampini 
8153cdbc3dSStefano Zampini    Input Parameters:
8253cdbc3dSStefano Zampini +  pc - the preconditioning context
8353cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8453cdbc3dSStefano Zampini 
8553cdbc3dSStefano Zampini    Level: intermediate
8653cdbc3dSStefano Zampini 
8753cdbc3dSStefano Zampini    Notes:
889c0446d6SStefano Zampini    Not collective but all procs must call this.
8953cdbc3dSStefano Zampini 
9053cdbc3dSStefano Zampini .seealso: PCBDDC
9153cdbc3dSStefano Zampini @*/
920c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
930c7d97c5SJed Brown {
940c7d97c5SJed Brown   PetscErrorCode ierr;
950c7d97c5SJed Brown 
960c7d97c5SJed Brown   PetscFunctionBegin;
970c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
980c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
990c7d97c5SJed Brown   PetscFunctionReturn(0);
1000c7d97c5SJed Brown }
1010c7d97c5SJed Brown 
1020c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1030c7d97c5SJed Brown EXTERN_C_BEGIN
1040c7d97c5SJed Brown #undef __FUNCT__
1053b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
1063b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
1073b03a366Sstefano_zampini {
1083b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1093b03a366Sstefano_zampini   PetscErrorCode ierr;
1103b03a366Sstefano_zampini 
1113b03a366Sstefano_zampini   PetscFunctionBegin;
1123b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
113*36e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
114*36e030ebSStefano Zampini   pcbddc->DirichletBoundaries=DirichletBoundaries;
1153b03a366Sstefano_zampini   PetscFunctionReturn(0);
1163b03a366Sstefano_zampini }
1173b03a366Sstefano_zampini EXTERN_C_END
1183b03a366Sstefano_zampini 
1193b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1203b03a366Sstefano_zampini #undef __FUNCT__
1213b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
1223b03a366Sstefano_zampini /*@
1233b03a366Sstefano_zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part of
1243b03a366Sstefano_zampini                               Dirichlet boundaries for the global problem.
1253b03a366Sstefano_zampini 
1263b03a366Sstefano_zampini    Not collective
1273b03a366Sstefano_zampini 
1283b03a366Sstefano_zampini    Input Parameters:
1293b03a366Sstefano_zampini +  pc - the preconditioning context
1303b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
1313b03a366Sstefano_zampini 
1323b03a366Sstefano_zampini    Level: intermediate
1333b03a366Sstefano_zampini 
1343b03a366Sstefano_zampini    Notes:
1353b03a366Sstefano_zampini 
1363b03a366Sstefano_zampini .seealso: PCBDDC
1373b03a366Sstefano_zampini @*/
1383b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
1393b03a366Sstefano_zampini {
1403b03a366Sstefano_zampini   PetscErrorCode ierr;
1413b03a366Sstefano_zampini 
1423b03a366Sstefano_zampini   PetscFunctionBegin;
1433b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1443b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
1453b03a366Sstefano_zampini   PetscFunctionReturn(0);
1463b03a366Sstefano_zampini }
1473b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1483b03a366Sstefano_zampini EXTERN_C_BEGIN
1493b03a366Sstefano_zampini #undef __FUNCT__
1500c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
15153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1520c7d97c5SJed Brown {
1530c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15453cdbc3dSStefano Zampini   PetscErrorCode ierr;
1550c7d97c5SJed Brown 
1560c7d97c5SJed Brown   PetscFunctionBegin;
15753cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
158*36e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
159*36e030ebSStefano Zampini   pcbddc->NeumannBoundaries=NeumannBoundaries;
1600c7d97c5SJed Brown   PetscFunctionReturn(0);
1610c7d97c5SJed Brown }
1620c7d97c5SJed Brown EXTERN_C_END
1630c7d97c5SJed Brown 
1640c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1650c7d97c5SJed Brown #undef __FUNCT__
1660c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
16757527edcSJed Brown /*@
16853cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
16953cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
17057527edcSJed Brown 
1719c0446d6SStefano Zampini    Not collective
17257527edcSJed Brown 
17357527edcSJed Brown    Input Parameters:
17457527edcSJed Brown +  pc - the preconditioning context
1759c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
17657527edcSJed Brown 
17757527edcSJed Brown    Level: intermediate
17857527edcSJed Brown 
17957527edcSJed Brown    Notes:
18057527edcSJed Brown 
18157527edcSJed Brown .seealso: PCBDDC
18257527edcSJed Brown @*/
18353cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1840c7d97c5SJed Brown {
1850c7d97c5SJed Brown   PetscErrorCode ierr;
1860c7d97c5SJed Brown 
1870c7d97c5SJed Brown   PetscFunctionBegin;
1880c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18953cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
19053cdbc3dSStefano Zampini   PetscFunctionReturn(0);
19153cdbc3dSStefano Zampini }
19253cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
19353cdbc3dSStefano Zampini EXTERN_C_BEGIN
19453cdbc3dSStefano Zampini #undef __FUNCT__
19553cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
19653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
19753cdbc3dSStefano Zampini {
19853cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
19953cdbc3dSStefano Zampini 
20053cdbc3dSStefano Zampini   PetscFunctionBegin;
20153cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
20253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
20353cdbc3dSStefano Zampini }
20453cdbc3dSStefano Zampini EXTERN_C_END
20553cdbc3dSStefano Zampini 
20653cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
20753cdbc3dSStefano Zampini #undef __FUNCT__
20853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
20953cdbc3dSStefano Zampini /*@
21053cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
21153cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
21253cdbc3dSStefano Zampini 
2139c0446d6SStefano Zampini    Not collective
21453cdbc3dSStefano Zampini 
21553cdbc3dSStefano Zampini    Input Parameters:
21653cdbc3dSStefano Zampini +  pc - the preconditioning context
21753cdbc3dSStefano Zampini 
21853cdbc3dSStefano Zampini    Output Parameters:
21953cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
22053cdbc3dSStefano Zampini 
22153cdbc3dSStefano Zampini    Level: intermediate
22253cdbc3dSStefano Zampini 
22353cdbc3dSStefano Zampini    Notes:
22453cdbc3dSStefano Zampini 
22553cdbc3dSStefano Zampini .seealso: PCBDDC
22653cdbc3dSStefano Zampini @*/
22753cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
22853cdbc3dSStefano Zampini {
22953cdbc3dSStefano Zampini   PetscErrorCode ierr;
23053cdbc3dSStefano Zampini 
23153cdbc3dSStefano Zampini   PetscFunctionBegin;
23253cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
23353cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
2340c7d97c5SJed Brown   PetscFunctionReturn(0);
2350c7d97c5SJed Brown }
236*36e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
237*36e030ebSStefano Zampini EXTERN_C_BEGIN
238*36e030ebSStefano Zampini #undef __FUNCT__
239*36e030ebSStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
240*36e030ebSStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
241*36e030ebSStefano Zampini {
242*36e030ebSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
243*36e030ebSStefano Zampini 
244*36e030ebSStefano Zampini   PetscFunctionBegin;
245*36e030ebSStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
246*36e030ebSStefano Zampini   PetscFunctionReturn(0);
247*36e030ebSStefano Zampini }
248*36e030ebSStefano Zampini EXTERN_C_END
249*36e030ebSStefano Zampini 
250*36e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
251*36e030ebSStefano Zampini #undef __FUNCT__
252*36e030ebSStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
253*36e030ebSStefano Zampini /*@
254*36e030ebSStefano Zampini  PCBDDCGetDirichletBoundaries - Get index set defining subdomain part of
255*36e030ebSStefano Zampini                               Dirichlet boundaries for the global problem.
256*36e030ebSStefano Zampini 
257*36e030ebSStefano Zampini    Not collective
258*36e030ebSStefano Zampini 
259*36e030ebSStefano Zampini    Input Parameters:
260*36e030ebSStefano Zampini +  pc - the preconditioning context
261*36e030ebSStefano Zampini 
262*36e030ebSStefano Zampini    Output Parameters:
263*36e030ebSStefano Zampini +  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
264*36e030ebSStefano Zampini 
265*36e030ebSStefano Zampini    Level: intermediate
266*36e030ebSStefano Zampini 
267*36e030ebSStefano Zampini    Notes:
268*36e030ebSStefano Zampini 
269*36e030ebSStefano Zampini .seealso: PCBDDC
270*36e030ebSStefano Zampini @*/
271*36e030ebSStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
272*36e030ebSStefano Zampini {
273*36e030ebSStefano Zampini   PetscErrorCode ierr;
274*36e030ebSStefano Zampini 
275*36e030ebSStefano Zampini   PetscFunctionBegin;
276*36e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
277*36e030ebSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
278*36e030ebSStefano Zampini   PetscFunctionReturn(0);
279*36e030ebSStefano Zampini }
2800c7d97c5SJed Brown 
2819c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
2829c0446d6SStefano Zampini EXTERN_C_BEGIN
2839c0446d6SStefano Zampini #undef __FUNCT__
2849c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
2859c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
2869c0446d6SStefano Zampini {
2879c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2889c0446d6SStefano Zampini   PetscInt i;
2899c0446d6SStefano Zampini   PetscErrorCode ierr;
2909c0446d6SStefano Zampini 
2919c0446d6SStefano Zampini   PetscFunctionBegin;
292d11ae9bbSstefano_zampini   /* Destroy ISs if they were already set */
2939c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
2949c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2959c0446d6SStefano Zampini   }
296d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
297d11ae9bbSstefano_zampini 
2989c0446d6SStefano Zampini   /* allocate space then copy ISs */
2999c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
3009c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
3019c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3029c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
3039c0446d6SStefano Zampini   }
3049c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
305d11ae9bbSstefano_zampini 
3069c0446d6SStefano Zampini   PetscFunctionReturn(0);
3079c0446d6SStefano Zampini }
3089c0446d6SStefano Zampini EXTERN_C_END
3099c0446d6SStefano Zampini 
3109c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
3119c0446d6SStefano Zampini #undef __FUNCT__
3129c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
3139c0446d6SStefano Zampini /*@
3149c0446d6SStefano Zampini  PCBDDCSetDofsSplitting - Set index set defining how dofs are splitted.
3159c0446d6SStefano Zampini 
3169c0446d6SStefano Zampini    Not collective
3179c0446d6SStefano Zampini 
3189c0446d6SStefano Zampini    Input Parameters:
3199c0446d6SStefano Zampini +  pc - the preconditioning context
3209c0446d6SStefano Zampini -  n - number of index sets defining dofs spltting
3219c0446d6SStefano Zampini -  IS[] - array of IS describing dofs splitting
3229c0446d6SStefano Zampini 
3239c0446d6SStefano Zampini    Level: intermediate
3249c0446d6SStefano Zampini 
3259c0446d6SStefano Zampini    Notes:
3269c0446d6SStefano Zampini    Sequential ISs are copied, the user must destroy the array of IS passed in.
3279c0446d6SStefano Zampini 
3289c0446d6SStefano Zampini .seealso: PCBDDC
3299c0446d6SStefano Zampini @*/
3309c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
3319c0446d6SStefano Zampini {
3329c0446d6SStefano Zampini   PetscErrorCode ierr;
3339c0446d6SStefano Zampini 
3349c0446d6SStefano Zampini   PetscFunctionBegin;
3359c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3369c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
3379c0446d6SStefano Zampini   PetscFunctionReturn(0);
3389c0446d6SStefano Zampini }
3399c0446d6SStefano Zampini 
34053cdbc3dSStefano Zampini #undef __FUNCT__
34153cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
3420c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3430c7d97c5SJed Brown /*
3440c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
3450c7d97c5SJed Brown                   by setting data structures and options.
3460c7d97c5SJed Brown 
3470c7d97c5SJed Brown    Input Parameter:
34853cdbc3dSStefano Zampini +  pc - the preconditioner context
3490c7d97c5SJed Brown 
3500c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
3510c7d97c5SJed Brown 
3520c7d97c5SJed Brown    Notes:
3530c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
3540c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
3550c7d97c5SJed Brown */
35653cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
3570c7d97c5SJed Brown {
3580c7d97c5SJed Brown   PetscErrorCode ierr;
3590c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
3600c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
3610c7d97c5SJed Brown 
3620c7d97c5SJed Brown   PetscFunctionBegin;
3630c7d97c5SJed Brown   if (!pc->setupcalled) {
3643b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
3659c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
3660c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
3670c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
3680c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
3690c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
3700c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
3713b03a366Sstefano_zampini     /* Get stdout for dbg */
372e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
373e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
374e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
375e269702eSStefano Zampini     }
3763b03a366Sstefano_zampini     /* TODO MOVE CODE FRAGMENT */
3770c7d97c5SJed Brown     PetscInt im_active=0;
3780c7d97c5SJed Brown     if(pcis->n) im_active = 1;
37953cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
3803b03a366Sstefano_zampini     /* Analyze local interface */
3810c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
3823b03a366Sstefano_zampini     /* Set up local constraint matrix */
3833b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
3840c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
3850c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
3863b03a366Sstefano_zampini     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
3873b03a366Sstefano_zampini     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
3880c7d97c5SJed Brown   }
3890c7d97c5SJed Brown   PetscFunctionReturn(0);
3900c7d97c5SJed Brown }
3910c7d97c5SJed Brown 
3920c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3930c7d97c5SJed Brown /*
3940c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
3950c7d97c5SJed Brown 
3960c7d97c5SJed Brown    Input Parameters:
3970c7d97c5SJed Brown .  pc - the preconditioner context
3980c7d97c5SJed Brown .  r - input vector (global)
3990c7d97c5SJed Brown 
4000c7d97c5SJed Brown    Output Parameter:
4010c7d97c5SJed Brown .  z - output vector (global)
4020c7d97c5SJed Brown 
4030c7d97c5SJed Brown    Application Interface Routine: PCApply()
4040c7d97c5SJed Brown  */
4050c7d97c5SJed Brown #undef __FUNCT__
4060c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
40753cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
4080c7d97c5SJed Brown {
4090c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
4100c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
4110c7d97c5SJed Brown   PetscErrorCode    ierr;
4123b03a366Sstefano_zampini   const PetscScalar one = 1.0;
4133b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
4140c7d97c5SJed Brown 
4150c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
4160c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
4170c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
4180c7d97c5SJed Brown 
4190c7d97c5SJed Brown   PetscFunctionBegin;
4200c7d97c5SJed Brown   /* First Dirichlet solve */
4210c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4220c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
42353cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
4240c7d97c5SJed Brown   /*
4250c7d97c5SJed Brown     Assembling right hand side for BDDC operator
4260c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
4270c7d97c5SJed Brown     - the interface part of the global vector z
4280c7d97c5SJed Brown   */
4290c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4300c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
4310c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4320c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
4330c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
4340c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4350c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4360c7d97c5SJed Brown 
4370c7d97c5SJed Brown   /*
4380c7d97c5SJed Brown     Apply interface preconditioner
4390c7d97c5SJed Brown     Results are stored in:
4400c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
4410c7d97c5SJed Brown     -  the interface part of the global vector z
4420c7d97c5SJed Brown   */
4430c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
4440c7d97c5SJed Brown 
4453b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
4460c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4470c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4480c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
4490c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
45053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
4510c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
4520c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
4530c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
4540c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4550c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4560c7d97c5SJed Brown 
4570c7d97c5SJed Brown   PetscFunctionReturn(0);
4580c7d97c5SJed Brown 
4590c7d97c5SJed Brown }
4600c7d97c5SJed Brown 
4610c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4620c7d97c5SJed Brown /*
4630c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
4640c7d97c5SJed Brown 
4650c7d97c5SJed Brown */
4660c7d97c5SJed Brown #undef __FUNCT__
4670c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
46853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
4690c7d97c5SJed Brown {
4700c7d97c5SJed Brown   PetscErrorCode ierr;
4710c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4720c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
4733b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
4740c7d97c5SJed Brown 
4750c7d97c5SJed Brown   PetscFunctionBegin;
4760c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
4770c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4780c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4790c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4800c7d97c5SJed Brown 
4810c7d97c5SJed Brown   /* Application of PHI^T  */
4820c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4830c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4840c7d97c5SJed Brown 
4850c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
4860c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
4870c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4880c7d97c5SJed Brown 
4890c7d97c5SJed Brown   /* Local solution on R nodes */
4900c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
4910c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4920c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4930c7d97c5SJed Brown   if(pcbddc->prec_type) {
4940c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4950c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4960c7d97c5SJed Brown   }
4970c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
4980c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
4990c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5000c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5010c7d97c5SJed Brown   if(pcbddc->prec_type) {
5020c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5030c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5040c7d97c5SJed Brown   }
5050c7d97c5SJed Brown 
5060c7d97c5SJed Brown   /* Coarse solution */
5070c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
50853cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
5090c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5100c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5110c7d97c5SJed Brown 
5120c7d97c5SJed Brown   /* Sum contributions from two levels */
5130c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
5140c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
5150c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
5160c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
5170c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
5180c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5190c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5200c7d97c5SJed Brown 
5210c7d97c5SJed Brown   PetscFunctionReturn(0);
5220c7d97c5SJed Brown }
5230c7d97c5SJed Brown 
5240c7d97c5SJed Brown 
5250c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5260c7d97c5SJed Brown /*
5270c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
5280c7d97c5SJed Brown 
5290c7d97c5SJed Brown */
5300c7d97c5SJed Brown #undef __FUNCT__
5310c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
53253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
5330c7d97c5SJed Brown {
5340c7d97c5SJed Brown   PetscErrorCode ierr;
5350c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5360c7d97c5SJed Brown 
5370c7d97c5SJed Brown   PetscFunctionBegin;
5380c7d97c5SJed Brown 
53953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
5400c7d97c5SJed Brown   if(pcbddc->n_constraints) {
5410c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
5420c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5430c7d97c5SJed Brown   }
5440c7d97c5SJed Brown 
5450c7d97c5SJed Brown   PetscFunctionReturn(0);
5460c7d97c5SJed Brown }
5470c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5480c7d97c5SJed Brown /*
5490c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
5500c7d97c5SJed Brown 
5510c7d97c5SJed Brown */
5520c7d97c5SJed Brown #undef __FUNCT__
5530c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
55453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5550c7d97c5SJed Brown {
5560c7d97c5SJed Brown   PetscErrorCode ierr;
5570c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5580c7d97c5SJed Brown 
5590c7d97c5SJed Brown   PetscFunctionBegin;
5600c7d97c5SJed Brown 
5610c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5620c7d97c5SJed Brown     case SCATTERS_BDDC:
5630c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5640c7d97c5SJed Brown       break;
5650c7d97c5SJed Brown     case GATHERS_BDDC:
5660c7d97c5SJed Brown       break;
5670c7d97c5SJed Brown   }
5680c7d97c5SJed Brown   PetscFunctionReturn(0);
5690c7d97c5SJed Brown 
5700c7d97c5SJed Brown }
5710c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5720c7d97c5SJed Brown /*
5730c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
5740c7d97c5SJed Brown 
5750c7d97c5SJed Brown */
5760c7d97c5SJed Brown #undef __FUNCT__
5770c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
57853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5790c7d97c5SJed Brown {
5800c7d97c5SJed Brown   PetscErrorCode ierr;
5810c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5820c7d97c5SJed Brown   PetscScalar*   array_to;
5830c7d97c5SJed Brown   PetscScalar*   array_from;
5840c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
5850c7d97c5SJed Brown   PetscInt i;
5860c7d97c5SJed Brown 
5870c7d97c5SJed Brown   PetscFunctionBegin;
5880c7d97c5SJed Brown 
5890c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5900c7d97c5SJed Brown     case SCATTERS_BDDC:
5910c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5920c7d97c5SJed Brown       break;
5930c7d97c5SJed Brown     case GATHERS_BDDC:
5940c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
5950c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
5960c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
5970c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
5980c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
59953cdbc3dSStefano 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);
6000c7d97c5SJed Brown             if(vec_to) {
6010c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
6020c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
6030c7d97c5SJed Brown             }
6040c7d97c5SJed Brown           } else {
6050c7d97c5SJed Brown             if(vec_from)
6060c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
6070c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
60853cdbc3dSStefano 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);
6090c7d97c5SJed Brown           }
6100c7d97c5SJed Brown           break;
6110c7d97c5SJed Brown         case REPLICATED_BDDC:
6120c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
61353cdbc3dSStefano 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);
6140c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
6150c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
6160c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
6170c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
6180c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
6190c7d97c5SJed Brown           }
6200c7d97c5SJed Brown           break;
62153cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
62253cdbc3dSStefano Zampini           break;
62353cdbc3dSStefano Zampini         case PARALLEL_BDDC:
62453cdbc3dSStefano Zampini           break;
6250c7d97c5SJed Brown       }
6260c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
6270c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
6280c7d97c5SJed Brown       break;
6290c7d97c5SJed Brown   }
6300c7d97c5SJed Brown   PetscFunctionReturn(0);
6310c7d97c5SJed Brown 
6320c7d97c5SJed Brown }
6330c7d97c5SJed Brown 
6340c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6350c7d97c5SJed Brown /*
6360c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
6370c7d97c5SJed Brown    that was created with PCCreate_BDDC().
6380c7d97c5SJed Brown 
6390c7d97c5SJed Brown    Input Parameter:
6400c7d97c5SJed Brown .  pc - the preconditioner context
6410c7d97c5SJed Brown 
6420c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
6430c7d97c5SJed Brown */
6440c7d97c5SJed Brown #undef __FUNCT__
6450c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
64653cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
6470c7d97c5SJed Brown {
6480c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
6490c7d97c5SJed Brown   PetscErrorCode ierr;
6500c7d97c5SJed Brown 
6510c7d97c5SJed Brown   PetscFunctionBegin;
6520c7d97c5SJed Brown   /* free data created by PCIS */
6530c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
6540c7d97c5SJed Brown   /* free BDDC data  */
65553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
65653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
65753cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
65853cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
65953cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
66053cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
66153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
66253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
66353cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
66453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
66553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
66653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
66753cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
66853cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
66953cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
67053cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
67153cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
67253cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
67353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
6743b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
6753b03a366Sstefano_zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
67653cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
67753cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
6780c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
67953cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
68053cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
6819c0446d6SStefano Zampini   PetscInt i;
6823b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
6833b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
6843b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
6853b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
6863b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
6873b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
6883b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
6890c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
6900c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
6910c7d97c5SJed Brown   PetscFunctionReturn(0);
6920c7d97c5SJed Brown }
6930c7d97c5SJed Brown 
6940c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6950c7d97c5SJed Brown /*MC
6960c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
6970c7d97c5SJed Brown 
6980c7d97c5SJed Brown    Options Database Keys:
699a0ba757dSStefano Zampini .    -pcbddc ??? -
7000c7d97c5SJed Brown 
7010c7d97c5SJed Brown    Level: intermediate
7020c7d97c5SJed Brown 
7030c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
7040c7d97c5SJed Brown 
7050c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
7060c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
7070c7d97c5SJed Brown           on the subdomains).
7080c7d97c5SJed Brown 
709a0ba757dSStefano Zampini           Options for the coarse grid preconditioner can be set with -
710a0ba757dSStefano Zampini           Options for the Dirichlet subproblem can be set with -
711a0ba757dSStefano Zampini           Options for the Neumann subproblem can be set with -
7120c7d97c5SJed Brown 
7130c7d97c5SJed Brown    Contributed by Stefano Zampini
7140c7d97c5SJed Brown 
7150c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
7160c7d97c5SJed Brown M*/
7170c7d97c5SJed Brown EXTERN_C_BEGIN
7180c7d97c5SJed Brown #undef __FUNCT__
7190c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
7200c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
7210c7d97c5SJed Brown {
7220c7d97c5SJed Brown   PetscErrorCode ierr;
7230c7d97c5SJed Brown   PC_BDDC          *pcbddc;
7240c7d97c5SJed Brown 
7250c7d97c5SJed Brown   PetscFunctionBegin;
7260c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
7270c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
7280c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
7290c7d97c5SJed Brown   /* create PCIS data structure */
7300c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
7310c7d97c5SJed Brown   /* BDDC specific */
7320c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
7330c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
73453cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
7350c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
7360c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
7370c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
7380c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
7390c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
7400c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
7410c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
7420c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
7430c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
74453cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
74553cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
7460c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
7470c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
74853cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
7493b03a366Sstefano_zampini   pcbddc->ISForDofs                  = 0;
7503b03a366Sstefano_zampini   pcbddc->ISForVertices              = 0;
7513b03a366Sstefano_zampini   pcbddc->n_ISForFaces               = 0;
7523b03a366Sstefano_zampini   pcbddc->n_ISForEdges               = 0;
7533b03a366Sstefano_zampini   pcbddc->ConstraintMatrix           = 0;
7543b03a366Sstefano_zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
7550c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
7560c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
7570c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
7580c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
7590c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
760e269702eSStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
7610c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
7620c7d97c5SJed Brown   /* function pointers */
7630c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
7640c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
7650c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
7660c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
7670c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
7680c7d97c5SJed Brown   pc->ops->view                = 0;
7690c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
7700c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
7710c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
7720c7d97c5SJed Brown   /* composing function */
7733b03a366Sstefano_zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
7743b03a366Sstefano_zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
7750c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
7760c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
777*36e030ebSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C","PCBDDCGetDirichletBoundaries_BDDC",
778*36e030ebSStefano Zampini                     PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
77953cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
78053cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
7810c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
7820c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
7839c0446d6SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
7849c0446d6SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
7850c7d97c5SJed Brown   PetscFunctionReturn(0);
7860c7d97c5SJed Brown }
7870c7d97c5SJed Brown EXTERN_C_END
7880c7d97c5SJed Brown 
7890c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7900c7d97c5SJed Brown /*
7913b03a366Sstefano_zampini    Create C matrix [I 0; 0 const]
7923b03a366Sstefano_zampini */
793de534f79Sstefano_zampini #ifdef BDDC_USE_POD
794de534f79Sstefano_zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
7953b03a366Sstefano_zampini #define PETSC_MISSING_LAPACK_GESVD 1
796de534f79Sstefano_zampini #define UNDEF_PETSC_MISSING_LAPACK_GESVD 1
797de534f79Sstefano_zampini #endif
7983b03a366Sstefano_zampini #endif
7993b03a366Sstefano_zampini 
8003b03a366Sstefano_zampini #undef __FUNCT__
8013b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
8023b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
8033b03a366Sstefano_zampini {
8043b03a366Sstefano_zampini   PetscErrorCode ierr;
8053b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
8063b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8073b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
8083b03a366Sstefano_zampini   PetscInt       *nnz,*vertices,*is_indices;
8093b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
8103b03a366Sstefano_zampini   PetscInt       *temp_indices,*temp_indices_to_constraint;
8113b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
8123b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
8133b03a366Sstefano_zampini   PetscReal      quad_value;
8143b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
8153b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
8163b03a366Sstefano_zampini   IS             *used_IS;
8173b03a366Sstefano_zampini   const MatType  impMatType=MATSEQAIJ;
8183b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
8193b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
820fcda91b4SJed Brown   MatNullSpace   nearnullsp;
821fcda91b4SJed Brown   const Vec      *nearnullvecs;
8223b03a366Sstefano_zampini   Vec            *localnearnullsp;
8233b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
8243b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
825de534f79Sstefano_zampini   PetscBLASInt   Bone=1;
826de534f79Sstefano_zampini /* some ugly conditional declarations */
8273b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8283b03a366Sstefano_zampini   PetscScalar    dot_result;
8293b03a366Sstefano_zampini   PetscScalar    one=1.0,zero=0.0;
8303b03a366Sstefano_zampini   PetscInt       ii;
8313b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8323b03a366Sstefano_zampini   PetscScalar    val1,val2;
8333b03a366Sstefano_zampini #endif
8343b03a366Sstefano_zampini #else
8353b03a366Sstefano_zampini   PetscBLASInt   dummy_int;
8363b03a366Sstefano_zampini   PetscScalar    dummy_scalar;
8373b03a366Sstefano_zampini #endif
8383b03a366Sstefano_zampini 
8393b03a366Sstefano_zampini   PetscFunctionBegin;
8403b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
841fcda91b4SJed Brown   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
842fcda91b4SJed Brown   if (nearnullsp) {
843fcda91b4SJed Brown     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
8443b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
8453b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
8463b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
8473b03a366Sstefano_zampini   }
8483b03a366Sstefano_zampini   if(nnsp_has_cnst) {
8493b03a366Sstefano_zampini     nnsp_addone = 1;
8503b03a366Sstefano_zampini   }
8513b03a366Sstefano_zampini   /*
8523b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
8533b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
8543b03a366Sstefano_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
8553b03a366Sstefano_zampini        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
8563b03a366Sstefano_zampini                                                                                                                                                          */
8573b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
8583b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8593b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
8603b03a366Sstefano_zampini   total_counts = 0;
8613b03a366Sstefano_zampini   max_size_of_constraint = 0;
8623b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
8633b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
8643b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
8653b03a366Sstefano_zampini     } else {
8663b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
8673b03a366Sstefano_zampini     }
8683b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
8693b03a366Sstefano_zampini     total_counts += j;
8703b03a366Sstefano_zampini     if(j>max_size_of_constraint) max_size_of_constraint=j;
8713b03a366Sstefano_zampini   }
8723b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8733b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
8743b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
8753b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
8763b03a366Sstefano_zampini   rwork = 0;
8773b03a366Sstefano_zampini   work = 0;
8783b03a366Sstefano_zampini   singular_vals = 0;
8793b03a366Sstefano_zampini   temp_basis = 0;
8803b03a366Sstefano_zampini   correlation_mat = 0;
8813b03a366Sstefano_zampini   if(!pcbddc->use_nnsp_true) {
8823b03a366Sstefano_zampini     PetscScalar temp_work;
8833b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8843b03a366Sstefano_zampini     /* POD */
8853b03a366Sstefano_zampini     PetscInt max_n;
8863b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
8873b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
8883b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
8893b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
8903b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
8913b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8923b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
8933b03a366Sstefano_zampini #endif
8943b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
8953b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
8963b03a366Sstefano_zampini     lwork=-1;
8973b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
8983b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
8993b03a366Sstefano_zampini #else
9003b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
9013b03a366Sstefano_zampini #endif
9023b03a366Sstefano_zampini #else /* on missing GESVD */
9033b03a366Sstefano_zampini     /* SVD */
9043b03a366Sstefano_zampini     PetscInt max_n,min_n;
9053b03a366Sstefano_zampini     max_n = max_size_of_constraint;
9063b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
9073b03a366Sstefano_zampini     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
9083b03a366Sstefano_zampini       min_n = max_size_of_constraint;
9093b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
9103b03a366Sstefano_zampini     }
9113b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
9123b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9133b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
9143b03a366Sstefano_zampini #endif
9153b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
9163b03a366Sstefano_zampini     lwork=-1;
9173b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
9183b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
9193b03a366Sstefano_zampini     dummy_int = Bs;
920670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
9213b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9223b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9233b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
9243b03a366Sstefano_zampini #else
9253b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
9263b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
9273b03a366Sstefano_zampini #endif
9283b03a366Sstefano_zampini     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
929670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
9303b03a366Sstefano_zampini #endif
9313b03a366Sstefano_zampini     /* Allocate optimal workspace */
9323b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
9333b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
9343b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
9353b03a366Sstefano_zampini   }
9363b03a366Sstefano_zampini   /* get local part of global near null space vectors */
9373b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
9383b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) {
9393b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
940fcda91b4SJed Brown     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
941fcda91b4SJed Brown     ierr = VecScatterEnd  (matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9423b03a366Sstefano_zampini   }
9433b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
9443b03a366Sstefano_zampini   total_counts=0;
9453b03a366Sstefano_zampini   temp_indices[0]=0;
9463b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
9473b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
9483b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
9493b03a366Sstefano_zampini     } else {
9503b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
9513b03a366Sstefano_zampini     }
9523b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
9533b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
9543b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
9553b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
9563b03a366Sstefano_zampini     if(nnsp_has_cnst) {
9573b03a366Sstefano_zampini       temp_constraints++;
9583b03a366Sstefano_zampini       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
9593b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9603b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9613b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
9623b03a366Sstefano_zampini       }
9633b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9643b03a366Sstefano_zampini       total_counts++;
9653b03a366Sstefano_zampini     }
9663b03a366Sstefano_zampini     for(k=0;k<nnsp_size;k++) {
9673b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
9683b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9693b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9703b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
9713b03a366Sstefano_zampini       }
9723b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
973de534f79Sstefano_zampini       quad_value = 1.0;
974de534f79Sstefano_zampini       if( use_nnsp_true ) { /* check if array is null on the connected component in case use_nnsp_true has been requested */
975de534f79Sstefano_zampini         Bs = PetscBLASIntCast(size_of_constraint);
976de534f79Sstefano_zampini         quad_value = BLASasum_(&Bs,&temp_quadrature_constraint[temp_indices[total_counts]],&Bone);
977de534f79Sstefano_zampini       }
978de534f79Sstefano_zampini       if ( quad_value > 0.0 ) { /* keep indices and values */
979de534f79Sstefano_zampini         temp_constraints++;
9803b03a366Sstefano_zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9813b03a366Sstefano_zampini         total_counts++;
9823b03a366Sstefano_zampini       }
983de534f79Sstefano_zampini     }
9843b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
985de534f79Sstefano_zampini     /* perform SVD on the constraint if use_nnsp_true has not be requested by the user */
9863b03a366Sstefano_zampini     if(!use_nnsp_true) {
987de534f79Sstefano_zampini 
9883b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
9893b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
990de534f79Sstefano_zampini 
9913b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
9923b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
9933b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
9943b03a366Sstefano_zampini       for(j=0;j<temp_constraints;j++) {
9953b03a366Sstefano_zampini         for(k=0;k<j+1;k++) {
9963b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9973b03a366Sstefano_zampini           /* hand made complex dot product */
9983b03a366Sstefano_zampini           dot_result = 0.0;
9993b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
10003b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
10013b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
10023b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
10033b03a366Sstefano_zampini           }
10043b03a366Sstefano_zampini #else
10053b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
10063b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
10073b03a366Sstefano_zampini #endif
10083b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
10093b03a366Sstefano_zampini         }
10103b03a366Sstefano_zampini       }
10113b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
10123b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
10133b03a366Sstefano_zampini #else
10143b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
10153b03a366Sstefano_zampini #endif
10163b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
10173b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
10183b03a366Sstefano_zampini       j=0;
10193b03a366Sstefano_zampini       while( j < Bt && singular_vals[j] < tol) j++;
10203b03a366Sstefano_zampini       total_counts=total_counts-j;
10213b03a366Sstefano_zampini       if(j<temp_constraints) {
10223b03a366Sstefano_zampini         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
10233b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
10243b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
10253b03a366Sstefano_zampini         for(k=0;k<Bt-j;k++) {
10263b03a366Sstefano_zampini           for(ii=0;ii<size_of_constraint;ii++) {
10273b03a366Sstefano_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];
10283b03a366Sstefano_zampini           }
10293b03a366Sstefano_zampini         }
10303b03a366Sstefano_zampini       }
1031de534f79Sstefano_zampini 
10323b03a366Sstefano_zampini #else  /* on missing GESVD */
1033de534f79Sstefano_zampini 
10343b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
10353b03a366Sstefano_zampini       if(min_n > size_of_constraint) min_n = size_of_constraint;
10363b03a366Sstefano_zampini       dummy_int = Bs;
1037670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
10383b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
10393b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
10403b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
10413b03a366Sstefano_zampini #else
10423b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
10433b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
10443b03a366Sstefano_zampini #endif
10453b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
1046670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
10473b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
10483b03a366Sstefano_zampini       j=0;
10493b03a366Sstefano_zampini       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
10503b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
1051de534f79Sstefano_zampini 
10523b03a366Sstefano_zampini #endif
10533b03a366Sstefano_zampini     }
10543b03a366Sstefano_zampini   }
10553b03a366Sstefano_zampini   n_constraints=total_counts;
10563b03a366Sstefano_zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
10573b03a366Sstefano_zampini   local_primal_size = n_vertices+n_constraints;
10583b03a366Sstefano_zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
10593b03a366Sstefano_zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
10603b03a366Sstefano_zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
10613b03a366Sstefano_zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
10623b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { nnz[i]= 1; }
10633b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) { nnz[i+n_vertices]=temp_indices[i+1]-temp_indices[i]; }
10643b03a366Sstefano_zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
10653b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10663b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { ierr = MatSetValue(pcbddc->ConstraintMatrix,i,vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr); }
10673b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10683b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
10693b03a366Sstefano_zampini     j=i+n_vertices;
10703b03a366Sstefano_zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
10713b03a366Sstefano_zampini     ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&j,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
10723b03a366Sstefano_zampini   }
10733b03a366Sstefano_zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10743b03a366Sstefano_zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10753b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
10763b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
10773b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
10783b03a366Sstefano_zampini   pcbddc->local_primal_size = n_vertices+n_constraints;
10793b03a366Sstefano_zampini   /* free workspace no longer needed */
10803b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
10813b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
10823b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
10833b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
10843b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
10853b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
10863b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
10873b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
10883b03a366Sstefano_zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
10893b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) { ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr); }
10903b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
10913b03a366Sstefano_zampini   PetscFunctionReturn(0);
10923b03a366Sstefano_zampini }
1093de534f79Sstefano_zampini #ifdef UNDEF_PETSC_MISSING_LAPACK_GESVD
10943b03a366Sstefano_zampini #undef PETSC_MISSING_LAPACK_GESVD
10953b03a366Sstefano_zampini #endif
1096de534f79Sstefano_zampini 
10973b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
10983b03a366Sstefano_zampini /*
10990c7d97c5SJed Brown    PCBDDCCoarseSetUp -
11000c7d97c5SJed Brown */
11010c7d97c5SJed Brown #undef __FUNCT__
11020c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
110353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
11040c7d97c5SJed Brown {
11050c7d97c5SJed Brown   PetscErrorCode  ierr;
11060c7d97c5SJed Brown 
11070c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
11080c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
11090c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
11100c7d97c5SJed Brown   IS                is_R_local;
11110c7d97c5SJed Brown   IS                is_V_local;
11120c7d97c5SJed Brown   IS                is_C_local;
11130c7d97c5SJed Brown   IS                is_aux1;
11140c7d97c5SJed Brown   IS                is_aux2;
11150c7d97c5SJed Brown   const VecType     impVecType;
11160c7d97c5SJed Brown   const MatType     impMatType;
11170c7d97c5SJed Brown   PetscInt          n_R=0;
11180c7d97c5SJed Brown   PetscInt          n_D=0;
11190c7d97c5SJed Brown   PetscInt          n_B=0;
11200c7d97c5SJed Brown   PetscScalar       zero=0.0;
11210c7d97c5SJed Brown   PetscScalar       one=1.0;
11220c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
11230c7d97c5SJed Brown   PetscScalar*      array;
11240c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
11250c7d97c5SJed Brown   PetscInt          *idx_R_local;
11260c7d97c5SJed Brown   PetscInt          *idx_V_B;
11270c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
11280c7d97c5SJed Brown   PetscScalar       *constraints_errors;
11290c7d97c5SJed Brown   /* auxiliary indices */
11300c7d97c5SJed Brown   PetscInt s,i,j,k;
1131e269702eSStefano Zampini   /* for verbose output of bddc */
1132e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1133e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1134a0ba757dSStefano Zampini   /* for counting coarse dofs */
1135a0ba757dSStefano Zampini   PetscScalar       coarsesum;
11363b03a366Sstefano_zampini   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
11373b03a366Sstefano_zampini   PetscInt          size_of_constraint;
11383b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
11393b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
11403b03a366Sstefano_zampini   const PetscInt    *vertices;
11410c7d97c5SJed Brown 
11420c7d97c5SJed Brown   PetscFunctionBegin;
11430c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
11440c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
11453b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,&vertices);CHKERRQ(ierr);
1146a0ba757dSStefano Zampini   /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants) */
1147a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1148a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11493b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { array[ vertices[i] ] = one; }
11503b03a366Sstefano_zampini 
11513b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
11523b03a366Sstefano_zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
11533b03a366Sstefano_zampini     for (j=0; j<size_of_constraint; j++) {
11543b03a366Sstefano_zampini       k = row_cmat_indices[j];
1155a0ba757dSStefano Zampini       if( array[k] == zero ) {
1156a0ba757dSStefano Zampini         array[k] = one;
1157a0ba757dSStefano Zampini         break;
1158a0ba757dSStefano Zampini       }
1159a0ba757dSStefano Zampini     }
11603b03a366Sstefano_zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1161a0ba757dSStefano Zampini   }
1162a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1163a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1164a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1166a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1167a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1168a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1169a0ba757dSStefano Zampini   for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1170a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1171a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1172a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1173a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1174a0ba757dSStefano Zampini   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1175a0ba757dSStefano Zampini   pcbddc->coarse_size = (PetscInt) coarsesum;
1176a0ba757dSStefano Zampini 
11770c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
11780c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
11790c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11803b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
11813b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
11820c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
11830c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1184e269702eSStefano Zampini   if(dbg_flag) {
11850c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
11860c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11870c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
11880c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
11893b03a366Sstefano_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);
11900c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1191a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1192a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1193a0ba757dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11940c7d97c5SJed Brown   }
11950c7d97c5SJed Brown   /* Allocate needed vectors */
11960c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
11970c7d97c5SJed Brown   impMatType = MATSEQDENSE;
11980c7d97c5SJed Brown   impVecType = VECSEQ;
11990c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
12000c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
12010c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
12020c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
12030c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1204d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
12050c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
12060c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
12070c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
12080c7d97c5SJed Brown 
12090c7d97c5SJed Brown   /* Creating some index sets needed  */
12100c7d97c5SJed Brown   /* For submatrices */
12110c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
12123b03a366Sstefano_zampini   if(n_vertices)    {
12133b03a366Sstefano_zampini     ierr = ISDuplicate(pcbddc->ISForVertices,&is_V_local);CHKERRQ(ierr);
12143b03a366Sstefano_zampini     ierr = ISCopy(pcbddc->ISForVertices,is_V_local);CHKERRQ(ierr);
12153b03a366Sstefano_zampini   }
12163b03a366Sstefano_zampini   if(n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr); }
12170c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
12180c7d97c5SJed Brown   {
12190c7d97c5SJed Brown     PetscInt   *aux_array1;
12200c7d97c5SJed Brown     PetscInt   *aux_array2;
12210c7d97c5SJed Brown     PetscScalar      value;
12220c7d97c5SJed Brown 
12233b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
12243b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
12250c7d97c5SJed Brown 
1226d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
12270c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12280c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12290c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12300c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12310c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12320c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12330c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12340c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
12350c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12360c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
12370c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12380c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
12393828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12400c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
12410c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
12420c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
12430c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
12440c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
12450c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
12460c7d97c5SJed Brown 
1247e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
12480c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
12490c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12500c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
12510c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12520c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
12530c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
12540c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
12550c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
12560c7d97c5SJed Brown     }
12570c7d97c5SJed Brown 
12580c7d97c5SJed Brown     /* Check scatters */
1259e269702eSStefano Zampini     if(dbg_flag) {
12600c7d97c5SJed Brown 
12610c7d97c5SJed Brown       Vec            vec_aux;
12620c7d97c5SJed Brown 
12630c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12640c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
12650c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1266d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1267d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1268d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1269d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1270d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1271d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1272d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1273d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1274d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1275d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12760c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1277d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12780c7d97c5SJed Brown 
1279d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1280d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1281d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
1282d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
1283d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1284d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1285d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1286d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1287d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
1288d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12890c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1290d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12910c7d97c5SJed Brown 
12920c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12930c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
12940c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12950c7d97c5SJed Brown 
1296d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1297d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1298d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1299d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1300d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1301d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1302d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1303d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1304d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1305d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
13060c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1307d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
13080c7d97c5SJed Brown 
1309d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1310d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1311d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
1312d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
1313d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1314d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1315d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1316d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1317d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
1318d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
13190c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1320d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
13210c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13220c7d97c5SJed Brown 
13230c7d97c5SJed Brown     }
13240c7d97c5SJed Brown   }
13250c7d97c5SJed Brown 
13260c7d97c5SJed Brown   /* vertices in boundary numbering */
13273b03a366Sstefano_zampini   if(n_vertices) {
1328d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
13290c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13303b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
13310c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1332d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1333d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13343b03a366Sstefano_zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
13350c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13363b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) {
13370c7d97c5SJed Brown       s=0;
13380c7d97c5SJed Brown       while (array[s] != i ) {s++;}
13390c7d97c5SJed Brown       idx_V_B[i]=s;
13400c7d97c5SJed Brown     }
13410c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13420c7d97c5SJed Brown   }
13430c7d97c5SJed Brown 
13440c7d97c5SJed Brown 
13450c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
13460c7d97c5SJed Brown   {
13470c7d97c5SJed Brown     Mat  A_RR;
134853cdbc3dSStefano Zampini     PC   pc_temp;
13490c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
135053cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
135153cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
135253cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
135353cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1354a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
13550c7d97c5SJed Brown     /* default */
135653cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
135753cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13580c7d97c5SJed Brown     /* Allow user's customization */
135953cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
136053cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
136153cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
13620c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
13630c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
136453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
136553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
136653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
136753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1368a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
13690c7d97c5SJed Brown     /* default */
137053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
137153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13720c7d97c5SJed Brown     /* Allow user's customization */
137353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
137453cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
137553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1376a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1377e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
13780c7d97c5SJed Brown       Vec temp_vec;
13790c7d97c5SJed Brown       PetscScalar value;
13800c7d97c5SJed Brown 
1381a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1382a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1383a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1384a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1385a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1386a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1387a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1388a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1389a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1390a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1391a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1392d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1393d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1394d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1395d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1396d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1397d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1398e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
13990c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1400d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
14010c7d97c5SJed Brown     }
14020c7d97c5SJed Brown     /* free Neumann problem's matrix */
14030c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
14040c7d97c5SJed Brown   }
14050c7d97c5SJed Brown 
14060c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
14070c7d97c5SJed Brown   {
14080c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
14090c7d97c5SJed Brown     Mat          M1,M2;
14100c7d97c5SJed Brown     Mat          C_CR;
14113b03a366Sstefano_zampini     Mat          AUXMAT;
14120c7d97c5SJed Brown     Vec          vec1_C;
14130c7d97c5SJed Brown     Vec          vec2_C;
14140c7d97c5SJed Brown     Vec          vec1_V;
14150c7d97c5SJed Brown     Vec          vec2_V;
14160c7d97c5SJed Brown     PetscInt     *nnz;
14170c7d97c5SJed Brown     PetscInt     *auxindices;
141853cdbc3dSStefano Zampini     PetscInt     index;
14190c7d97c5SJed Brown     PetscScalar* array2;
14200c7d97c5SJed Brown     MatFactorInfo matinfo;
14210c7d97c5SJed Brown 
14220c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
14230c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
14240c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
14250c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
14260c7d97c5SJed Brown 
14270c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
14283b03a366Sstefano_zampini     if(n_vertices) {
14290c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
14303b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
14310c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
14320c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
14330c7d97c5SJed Brown     }
14340c7d97c5SJed Brown     if(pcbddc->n_constraints) {
14350c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
14360c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
14370c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
14380c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
14390c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
14400c7d97c5SJed Brown     }
14410c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14423b03a366Sstefano_zampini     if(n_constraints) {
14430c7d97c5SJed Brown       /* some work vectors */
14440c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14453b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14460c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14473b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
14480c7d97c5SJed Brown 
14490c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14503b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
1451d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
14523b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
14533b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
14540c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14553b03a366Sstefano_zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14563b03a366Sstefano_zampini         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
14573b03a366Sstefano_zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14580c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14590c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
14600c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14610c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14623b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
146353cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14643b03a366Sstefano_zampini         /* Set values */
14650c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14663b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14670c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14680c7d97c5SJed Brown       }
14690c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14700c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14710c7d97c5SJed Brown 
14720c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
14733b03a366Sstefano_zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
14740c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
14750c7d97c5SJed Brown 
14760c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14770c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1478d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14793b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14800c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14810c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14820c7d97c5SJed Brown 
14833b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1484d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14853b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14860c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14873b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
14883b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
14890c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14900c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14910c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14920c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14930c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14940c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14950c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14963b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14970c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14980c7d97c5SJed Brown       }
14990c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15000c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15010c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
15020c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
15030c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
15040c7d97c5SJed Brown 
15050c7d97c5SJed Brown     }
15060c7d97c5SJed Brown 
15070c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
15083b03a366Sstefano_zampini     if(n_vertices){
15090c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
15100c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
15110c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
15120c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1513d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
15143b03a366Sstefano_zampini       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
15150c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
15163b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
15173b03a366Sstefano_zampini       for(i=0;i<n_vertices;i++) {
15180c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15190c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15200c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15210c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15220c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
152353cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
15240c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15253b03a366Sstefano_zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15260c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
15270c7d97c5SJed Brown       }
15280c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15290c7d97c5SJed Brown       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
15300c7d97c5SJed Brown     }
15310c7d97c5SJed Brown 
15320c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1533d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
15340c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
15350c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
15363b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1537e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1538d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
15390c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
15400c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
15413b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
15420c7d97c5SJed Brown     }
15430c7d97c5SJed Brown 
1544e269702eSStefano Zampini     if(dbg_flag) {
15450c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
15460c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
15470c7d97c5SJed Brown     }
15483b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15490c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15500c7d97c5SJed Brown 
15510c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15523b03a366Sstefano_zampini     for(i=0;i<n_vertices;i++){
15530c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15540c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15550c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15560c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15570c7d97c5SJed Brown       /* solution of saddle point problem */
15580c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15590c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15603b03a366Sstefano_zampini       if(n_constraints) {
15610c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15620c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15630c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15640c7d97c5SJed Brown       }
15650c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15660c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15670c7d97c5SJed Brown 
15680c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15690c7d97c5SJed Brown       /* coarse basis functions */
15700c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15710c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15720c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15730c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15743b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15750c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15760c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1577e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
15780c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15790c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15800c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15813b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15820c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15830c7d97c5SJed Brown       }
15840c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15850c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15863b03a366Sstefano_zampini       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } //WARNING -> column major ordering
15870c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15883b03a366Sstefano_zampini       if(n_constraints) {
15890c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15903b03a366Sstefano_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
15910c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15920c7d97c5SJed Brown       }
15930c7d97c5SJed Brown 
1594e269702eSStefano Zampini       if( dbg_flag ) {
15950c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1596d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15970c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15980c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15990c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
16003b03a366Sstefano_zampini         array[ vertices[i] ] = one;
16010c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16020c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16030c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1604d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16050c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16060c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16073b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
16080c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16093b03a366Sstefano_zampini         if(n_constraints) {
16100c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16113b03a366Sstefano_zampini           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
16120c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16130c7d97c5SJed Brown         }
16140c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16150c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
16160c7d97c5SJed Brown         /* check saddle point solution */
16170c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16183b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
16193b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
16203b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16210c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16223b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
16230c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
16243b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
16250c7d97c5SJed Brown       }
16260c7d97c5SJed Brown     }
16270c7d97c5SJed Brown 
16283b03a366Sstefano_zampini     for(i=0;i<n_constraints;i++){
1629d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
16300c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
16310c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
16320c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
16330c7d97c5SJed Brown       /* solution of saddle point problem */
16340c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
16350c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
16360c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
16373b03a366Sstefano_zampini       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
16380c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
16390c7d97c5SJed Brown       /* coarse basis functions */
16403b03a366Sstefano_zampini       index=i+n_vertices;
16410c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
16420c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16430c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16440c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
164553cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16460c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1647e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
16480c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16490c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16500c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
165153cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16520c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16530c7d97c5SJed Brown       }
16540c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16553b03a366Sstefano_zampini       if(n_vertices) {
16560c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16573b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
16580c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16590c7d97c5SJed Brown       }
16600c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16613b03a366Sstefano_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
16620c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16630c7d97c5SJed Brown 
1664e269702eSStefano Zampini       if( dbg_flag ) {
16650c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
166653cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16670c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16680c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16690c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
16700c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16710c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16720c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
167353cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16740c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16753b03a366Sstefano_zampini         if( n_vertices) {
16760c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16773b03a366Sstefano_zampini           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
16780c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16790c7d97c5SJed Brown         }
16800c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16813b03a366Sstefano_zampini         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16820c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16830c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16840c7d97c5SJed Brown         /* check saddle point solution */
16850c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16863b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
168753cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16883b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16890c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
169053cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16910c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
169253cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16930c7d97c5SJed Brown       }
16940c7d97c5SJed Brown     }
16950c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16960c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1697e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
16980c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16990c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
17000c7d97c5SJed Brown     }
17010c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
17020c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
17039d2fce94SStefano Zampini     if(dbg_flag) {
17040c7d97c5SJed Brown 
17050c7d97c5SJed Brown       Mat coarse_sub_mat;
17060c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
17070c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1708a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
17090c7d97c5SJed Brown       PetscScalar      value;
17100c7d97c5SJed Brown 
1711c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1712c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1713c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1714c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1715c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1716c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1717c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1718c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
17190c7d97c5SJed Brown 
17200c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
17210c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
17220c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
172353cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
172453cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
172553cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1726c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
172753cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
172853cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1729c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
173053cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
173153cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
173253cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
173353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
173453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
173553cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
17360c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
17370c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
17380c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
17390c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
174053cdbc3dSStefano 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); }
17410c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
174253cdbc3dSStefano 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); }
17430c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
174453cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
174553cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
174653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
174753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
174853cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
174953cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
175053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
175153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
175253cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
175353cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
175453cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
17550c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
17560c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
17570c7d97c5SJed Brown     }
17580c7d97c5SJed Brown 
17590c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
17600c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
17610c7d97c5SJed Brown     /* free memory */
17620c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
17630c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
17640c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
17653b03a366Sstefano_zampini     if(n_vertices) {
17660c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
17670c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
17680c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
17690c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
17700c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
17710c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
17720c7d97c5SJed Brown     }
17730c7d97c5SJed Brown     if(pcbddc->n_constraints) {
17740c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
17750c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
17760c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
17770c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
17780c7d97c5SJed Brown     }
17790c7d97c5SJed Brown   }
17800c7d97c5SJed Brown   /* free memory */
17813b03a366Sstefano_zampini   if(n_vertices) {
17820c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17830c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17840c7d97c5SJed Brown   }
17850c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
17860c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
17873b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
17880c7d97c5SJed Brown 
17890c7d97c5SJed Brown   PetscFunctionReturn(0);
17900c7d97c5SJed Brown }
17910c7d97c5SJed Brown 
17920c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
17930c7d97c5SJed Brown 
17940c7d97c5SJed Brown #undef __FUNCT__
17950c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
179653cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
17970c7d97c5SJed Brown {
17980c7d97c5SJed Brown 
17990c7d97c5SJed Brown 
18000c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
18010c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
18020c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
18030c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
18040c7d97c5SJed Brown   MPI_Comm  coarse_comm;
18050c7d97c5SJed Brown 
18060c7d97c5SJed Brown   /* common to all choiches */
18070c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
18080c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
18090c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
18100c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
18110c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
18120c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
18130c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
18140c7d97c5SJed Brown   PetscMPIInt master_proc=0;
18150c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
18160c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
18170c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
18180c7d97c5SJed Brown   PetscMPIInt count_recv=0;
18190c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
18200c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
18210c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
18220c7d97c5SJed Brown   /* some other variables */
18230c7d97c5SJed Brown   PetscErrorCode ierr;
18240c7d97c5SJed Brown   const MatType coarse_mat_type;
18250c7d97c5SJed Brown   const PCType  coarse_pc_type;
182653cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
182753cdbc3dSStefano Zampini   PC pc_temp;
18280c7d97c5SJed Brown   PetscInt i,j,k,bs;
18293b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1830e269702eSStefano Zampini   /* verbose output viewer */
1831e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1832e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
18330c7d97c5SJed Brown 
18340c7d97c5SJed Brown   PetscFunctionBegin;
18350c7d97c5SJed Brown 
18360c7d97c5SJed Brown   ins_local_primal_indices = 0;
18370c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
18380c7d97c5SJed Brown   localsizes2              = 0;
18390c7d97c5SJed Brown   localdispl2              = 0;
18400c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
18410c7d97c5SJed Brown   coarse_ISLG              = 0;
18420c7d97c5SJed Brown 
184353cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
184453cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
18450c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
18460c7d97c5SJed Brown 
1847beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1848beed3852SStefano Zampini   {
1849a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1850beed3852SStefano Zampini     PetscScalar    *array;
1851beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1852beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1853beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1854beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1855beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
18563b03a366Sstefano_zampini     PetscInt       *vertices,*row_cmat_indices;
18573b03a366Sstefano_zampini     PetscInt       size_of_constraint;
1858beed3852SStefano Zampini 
1859beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1860beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1861beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1862beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1863beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
18645619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1865beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1866beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1867beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1868beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1869beed3852SStefano Zampini     }
18705619798eSStefano Zampini     if(rank_prec_comm == 0) {
1871beed3852SStefano Zampini       /* allocate some auxiliary space */
1872beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1873beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1874beed3852SStefano Zampini     }
1875beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1876beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1877beed3852SStefano Zampini 
1878beed3852SStefano Zampini     /* First let's count coarse dofs: note that we allow to have a constraint on a subdomain and not its counterpart on the neighbour subdomain (if user wants)
1879beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1880beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1881beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
18823b03a366Sstefano_zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1883beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18843b03a366Sstefano_zampini     ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1885beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18863b03a366Sstefano_zampini     for(i=0;i<pcbddc->n_vertices;i++) {  /* note that  pcbddc->n_vertices can be different from size of ISForVertices */
18873b03a366Sstefano_zampini       array[ vertices[i] ] = one;
18883b03a366Sstefano_zampini       auxlocal_primal[i] = vertices[i];
1889beed3852SStefano Zampini     }
18903b03a366Sstefano_zampini     ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1891beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
18923b03a366Sstefano_zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
18933b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
18943b03a366Sstefano_zampini         k = row_cmat_indices[j];
1895beed3852SStefano Zampini         if( array[k] == zero ) {
1896beed3852SStefano Zampini           array[k] = one;
1897beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1898beed3852SStefano Zampini           break;
1899beed3852SStefano Zampini         }
1900beed3852SStefano Zampini       }
19013b03a366Sstefano_zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1902beed3852SStefano Zampini     }
1903beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1904a0ba757dSStefano Zampini 
1905beed3852SStefano Zampini     /* Now assign them a global numbering */
1906beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1907beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1908beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1909beed3852SStefano 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);
1910beed3852SStefano Zampini 
1911beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1912beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1913beed3852SStefano Zampini     if(rank_prec_comm==0) {
1914beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1915beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1916beed3852SStefano Zampini       k=1;
1917beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1918beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1919beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1920beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1921beed3852SStefano Zampini           k++;
1922beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1923beed3852SStefano Zampini         }
1924beed3852SStefano Zampini       }
1925beed3852SStefano Zampini     } else {
1926beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1927beed3852SStefano Zampini     }
19285619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1929beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1930beed3852SStefano Zampini 
1931beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1932beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1933beed3852SStefano Zampini       k=0;
1934beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1935beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1936beed3852SStefano Zampini     }
1937e269702eSStefano Zampini     if(dbg_flag) {
1938e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1939e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1940e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1941e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1942e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1943e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1944e269702eSStefano Zampini       }
1945e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1946e269702eSStefano Zampini     }
1947beed3852SStefano Zampini     /* free allocated memory */
1948beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1949beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1950beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1951e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1952beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1953beed3852SStefano Zampini     }
1954e269702eSStefano Zampini   }
1955beed3852SStefano Zampini 
19560c7d97c5SJed Brown   /* adapt coarse problem type */
19570c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
19580c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
19590c7d97c5SJed Brown 
19600c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
19610c7d97c5SJed Brown 
19620c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
19630c7d97c5SJed Brown     {
19640c7d97c5SJed Brown       /* we need additional variables */
19650c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
19660c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
19670c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
19680c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
19690c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
19700c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
19710c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
19720c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
19730c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
19740c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
19750c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
19760c7d97c5SJed Brown       MetisInt    *faces_adjncy;
19770c7d97c5SJed Brown       MetisInt    *faces_xadj;
19780c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
19790c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
19800c7d97c5SJed Brown       PetscInt    *array_int;
19810c7d97c5SJed Brown       PetscMPIInt my_faces=0;
19820c7d97c5SJed Brown       PetscMPIInt total_faces=0;
19833828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
19840c7d97c5SJed Brown 
19850c7d97c5SJed Brown       /* define some quantities */
19860c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
19870c7d97c5SJed Brown       coarse_mat_type = MATIS;
19880c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
19893b03a366Sstefano_zampini       coarse_ksp_type  = KSPCHEBYCHEV;
19900c7d97c5SJed Brown 
19910c7d97c5SJed Brown       /* details of coarse decomposition */
19920c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
19930c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
19943828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
19953828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
19963828260eSStefano Zampini 
19973828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1998a0ba757dSStefano 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));
19990c7d97c5SJed Brown 
20000c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
20010c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
20023828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
20030c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
20040c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20050c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
20060c7d97c5SJed Brown         }
20070c7d97c5SJed Brown       }
20080c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20090c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20100c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20110c7d97c5SJed Brown             my_faces++;
20120c7d97c5SJed Brown             break;
20130c7d97c5SJed Brown           }
20140c7d97c5SJed Brown         }
20150c7d97c5SJed Brown       }
20160c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
20170c7d97c5SJed Brown 
201853cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
20190c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
20200c7d97c5SJed Brown       my_faces=0;
20210c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
20220c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
20230c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
20240c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
20250c7d97c5SJed Brown             my_faces++;
20260c7d97c5SJed Brown             break;
20270c7d97c5SJed Brown           }
20280c7d97c5SJed Brown         }
20290c7d97c5SJed Brown       }
20300c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20310c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
20320c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
20330c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
20340c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
20350c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
20360c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
20370c7d97c5SJed Brown       }
203853cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
20390c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20400c7d97c5SJed Brown         faces_xadj[0]=0;
20410c7d97c5SJed Brown         faces_displacements[0]=0;
20420c7d97c5SJed Brown         j=0;
20430c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
20440c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
20450c7d97c5SJed Brown           if(number_of_faces[i-1]) {
20460c7d97c5SJed Brown             j++;
20470c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
20480c7d97c5SJed Brown           }
20490c7d97c5SJed Brown         }
20500c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
20510c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
20520c7d97c5SJed Brown       }
205353cdbc3dSStefano 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);
20540c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
20550c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
20560c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20573828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
20583828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
20590c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
20600c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
20610c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
20620c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
20630c7d97c5SJed Brown           printf("\n");
20640c7d97c5SJed Brown         }
20650c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
20660c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
20670c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
20680c7d97c5SJed Brown       }
20690c7d97c5SJed Brown 
20700c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
20710c7d97c5SJed Brown 
20723828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
20733828260eSStefano Zampini 
20740c7d97c5SJed Brown         ncon=1;
20750c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
20760c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
20770c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
20780c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
20790c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
20800c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
20810c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
20820c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
20830c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
20843828260eSStefano Zampini         printf("METIS PART GRAPH\n");
20853828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
20863828260eSStefano Zampini           printf("Using Kway\n");
20873828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
20883828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
20890c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20903828260eSStefano Zampini         } else {
20913828260eSStefano Zampini           printf("Using Recursive\n");
20923828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20933828260eSStefano Zampini         }
20940c7d97c5SJed 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);
20953828260eSStefano Zampini         printf("Partition done!\n");
20960c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
20970c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
20980c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
20990c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
21003828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
21013828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
21020c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
21030c7d97c5SJed Brown       }
21040c7d97c5SJed Brown 
21050c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
21060c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
21070c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
21080c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
21090c7d97c5SJed Brown       }
21100c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
21110c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
211253cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
21130c7d97c5SJed Brown 
21140c7d97c5SJed Brown       if( coarse_color == 0 ) {
211553cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
211653cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
21173828260eSStefano Zampini         printf("Details of coarse comm\n");
21183828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
21193828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
21200c7d97c5SJed Brown       } else {
21210c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
21220c7d97c5SJed Brown       }
21230c7d97c5SJed Brown 
21240c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
21250c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
21260c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
21270c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
21280c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
21290c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
21300c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
21310c7d97c5SJed Brown         /* some initializations */
21320c7d97c5SJed Brown         displacements_recv[0]=0;
21330c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
21340c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
21350c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
21363828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
21370c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
21380c7d97c5SJed Brown               total_count_recv[j]++;
21390c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
21400c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
21410c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
21420c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
21430c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
21443828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
21450c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
21460c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
21473828260eSStefano Zampini               total_count_recv[j]+=1;
21480c7d97c5SJed Brown             }
21490c7d97c5SJed Brown           }
21500c7d97c5SJed Brown         }
21513828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
21523828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
21533828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
21543828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
21553828260eSStefano Zampini           }
21563828260eSStefano Zampini           printf("\n");
21573828260eSStefano Zampini         }
21580c7d97c5SJed Brown 
21590c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
21603828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
21610c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
21620c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
21633828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
21643828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
21653828260eSStefano Zampini           } else {
21663828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
21673828260eSStefano Zampini           }
21680c7d97c5SJed Brown         printf("\n");
21690c7d97c5SJed Brown       }
21700c7d97c5SJed Brown 
21710c7d97c5SJed Brown       /* Scatter new decomposition for send details */
217253cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21730c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
21740c7d97c5SJed Brown       if( coarse_color == 0) {
217553cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21760c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
217753cdbc3dSStefano 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);
21780c7d97c5SJed Brown       }
21790c7d97c5SJed Brown 
21800c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
21810c7d97c5SJed Brown       //if(coarse_color == 0) {
21820c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
21830c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
21840c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
21850c7d97c5SJed Brown       //  printf("\n");
21860c7d97c5SJed Brown       //}
21870c7d97c5SJed Brown 
21880c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
21890c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
21900c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
21910c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
21920c7d97c5SJed Brown         free(coarse_subdivision);
21930c7d97c5SJed Brown         free(total_count_recv);
21940c7d97c5SJed Brown         free(total_ranks_recv);
21950c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
21960c7d97c5SJed Brown       }
21970c7d97c5SJed Brown       break;
21980c7d97c5SJed Brown     }
21990c7d97c5SJed Brown 
22000c7d97c5SJed Brown     case(REPLICATED_BDDC):
22010c7d97c5SJed Brown 
22020c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22030c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22040c7d97c5SJed Brown       coarse_pc_type  = PCLU;
220553cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22060c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22070c7d97c5SJed Brown       active_rank = rank_prec_comm;
22080c7d97c5SJed Brown       break;
22090c7d97c5SJed Brown 
22100c7d97c5SJed Brown     case(PARALLEL_BDDC):
22110c7d97c5SJed Brown 
22120c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
22130c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
22140c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
221553cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22160c7d97c5SJed Brown       coarse_comm = prec_comm;
22170c7d97c5SJed Brown       active_rank = rank_prec_comm;
22180c7d97c5SJed Brown       break;
22190c7d97c5SJed Brown 
22200c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
22210c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
22220c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
22230c7d97c5SJed Brown       coarse_pc_type = PCLU;
222453cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
22250c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
22260c7d97c5SJed Brown       active_rank = master_proc;
22270c7d97c5SJed Brown       break;
22280c7d97c5SJed Brown   }
22290c7d97c5SJed Brown 
22300c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
22310c7d97c5SJed Brown 
22320c7d97c5SJed Brown     case(SCATTERS_BDDC):
22330c7d97c5SJed Brown       {
22340c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
22350c7d97c5SJed Brown 
22360c7d97c5SJed Brown           PetscMPIInt send_size;
22370c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
22380c7d97c5SJed Brown           PetscInt    ii,jj;
22390c7d97c5SJed Brown           MPI_Request *requests;
22400c7d97c5SJed Brown 
22410c7d97c5SJed Brown           /* allocate auxiliary space */
22425619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
22435619798eSStefano 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);
22440c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
22450c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
22460c7d97c5SJed Brown           /* allocate stuffs for message massing */
22470c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
22480c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
22490c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
22500c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
22510c7d97c5SJed Brown           /* fill up quantities */
22520c7d97c5SJed Brown           j=0;
22530c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
22540c7d97c5SJed Brown             ii = ranks_recv[i];
22550c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
22560c7d97c5SJed Brown             localdispl2[i]=j;
22570c7d97c5SJed Brown             j+=localsizes2[i];
22580c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
22590c7d97c5SJed Brown             for(k=0;k<pcbddc->local_primal_sizes[ii];k++) aux_ins_indices[pcbddc->replicated_local_primal_indices[jj+k]]+=1;  // it counts the coarse subdomains sharing the coarse node
22600c7d97c5SJed Brown           }
22610c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
22620c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22630c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22640c7d97c5SJed Brown           //printf("\n");
22650c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
22660c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
22670c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
22680c7d97c5SJed Brown           ins_local_primal_size=0;
22690c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22700c7d97c5SJed Brown             if(aux_ins_indices[i])
22710c7d97c5SJed Brown               ins_local_primal_size++;
22720c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
22730c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
22740c7d97c5SJed Brown           j=0;
22750c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22760c7d97c5SJed Brown             if(aux_ins_indices[i])
22770c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
22780c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
22790c7d97c5SJed Brown           j=0;
22800c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
22810c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
22820c7d97c5SJed Brown               aux_ins_indices[i]=-1;
22830c7d97c5SJed Brown             } else {
22840c7d97c5SJed Brown               aux_ins_indices[i]=j;
22850c7d97c5SJed Brown               j++;
22860c7d97c5SJed Brown             }
22870c7d97c5SJed Brown           }
22880c7d97c5SJed Brown 
22890c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
22900c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
22910c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
22920c7d97c5SJed Brown           //printf("\n");
22930c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
22940c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22950c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22960c7d97c5SJed Brown           //printf("\n");
22970c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
22980c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
22990c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
23000c7d97c5SJed Brown           //printf("\n");
23010c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
23020c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
23030c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
23040c7d97c5SJed Brown           //    printf("(%lf %d %d)\n",coarse_submat_vals[j*pcbddc->local_primal_size+i],pcbddc->local_primal_indices[i],pcbddc->local_primal_indices[j]);
23050c7d97c5SJed Brown           //printf("\n");
23060c7d97c5SJed Brown 
23070c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
230853cdbc3dSStefano 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);
23090c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
23100c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
231153cdbc3dSStefano 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);
23120c7d97c5SJed Brown           }
231353cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
23140c7d97c5SJed Brown 
23150c7d97c5SJed Brown           //if(coarse_color == 0) {
23160c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
23170c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
23180c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
23190c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
23200c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
23210c7d97c5SJed Brown           //        printf("(%lf %d %d)\n",temp_coarse_mat_vals[localdispl2[k]+j*pcbddc->local_primal_sizes[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+i],pcbddc->replicated_local_primal_indices[pcbddc->local_primal_displacements[ranks_recv[k]]+j]);
23220c7d97c5SJed Brown           //    printf("\n");
23230c7d97c5SJed Brown           //  }
23240c7d97c5SJed Brown           //}
23250c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
23260c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23270c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
23280c7d97c5SJed Brown 
23290c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
23300c7d97c5SJed Brown           PetscInt row_ind,col_ind;
23310c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
23320c7d97c5SJed Brown             rr = ranks_recv[k];
23330c7d97c5SJed Brown             kk = localdispl2[k];
23340c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
23350c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
23360c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
23370c7d97c5SJed Brown             for(j=0;j<lps;j++){
23380c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
23390c7d97c5SJed Brown               for(i=0;i<lps;i++){
23400c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
23410c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
23420c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
23430c7d97c5SJed Brown               }
23440c7d97c5SJed Brown             }
23450c7d97c5SJed Brown           }
23460c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
23470c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
23480c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
23490c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
23500c7d97c5SJed Brown 
23510c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
23520c7d97c5SJed Brown           {
23530c7d97c5SJed Brown             IS coarse_IS;
235453cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
23550c7d97c5SJed Brown             coarse_comm = prec_comm;
23560c7d97c5SJed Brown             active_rank=rank_prec_comm;
23570c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
23580c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
23590c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
23600c7d97c5SJed Brown           }
23610c7d97c5SJed Brown         }
23620c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
23630c7d97c5SJed Brown           /* arrays for values insertion */
23640c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
23650c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23660c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23670c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23680c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
23690c7d97c5SJed 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];
23700c7d97c5SJed Brown           }
23710c7d97c5SJed Brown         }
23720c7d97c5SJed Brown         break;
23730c7d97c5SJed Brown 
23740c7d97c5SJed Brown     }
23750c7d97c5SJed Brown 
23760c7d97c5SJed Brown     case(GATHERS_BDDC):
23770c7d97c5SJed Brown       {
23780c7d97c5SJed Brown 
23790c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
23800c7d97c5SJed Brown 
23810c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23820c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23830c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
23840c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23850c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
23860c7d97c5SJed Brown           /* arrays for values insertion */
23870c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
23880c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23890c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23900c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
23910c7d97c5SJed Brown           localdispl2[0]=0;
23920c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
23930c7d97c5SJed Brown           j=0;
23940c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
23950c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
23960c7d97c5SJed Brown         }
23970c7d97c5SJed Brown 
23980c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
23990c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
24000c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
240153cdbc3dSStefano 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);
240253cdbc3dSStefano 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);
24030c7d97c5SJed Brown         } else {
240453cdbc3dSStefano 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);
240553cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
24060c7d97c5SJed Brown         }
24070c7d97c5SJed Brown 
24080c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
24090c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
24100c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
24110c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
24120c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
24130c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
24140c7d97c5SJed Brown           }
24150c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
24160c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
24170c7d97c5SJed Brown             offset2=localdispl2[k];
24180c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
24190c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
24200c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
24210c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
24220c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
24230c7d97c5SJed Brown               }
24240c7d97c5SJed Brown             }
24250c7d97c5SJed Brown           }
24260c7d97c5SJed Brown         }
24270c7d97c5SJed Brown         break;
24280c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
24290c7d97c5SJed Brown   }
24300c7d97c5SJed Brown 
24310c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
24320c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
24330c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
24340c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
24350c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
24360c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
24373b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24380c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
24393b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24400c7d97c5SJed Brown     } else {
24410c7d97c5SJed Brown       Mat matis_coarse_local_mat;
2442d3ee2243SStefano Zampini       /* remind bs */
2443d3ee2243SStefano Zampini       ierr = MatCreateIS(coarse_comm,bs,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
24443b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24450c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
24463b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
24470c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2448a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24490c7d97c5SJed Brown     }
2450a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
24510c7d97c5SJed 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);
24520c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24530c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24540c7d97c5SJed Brown 
24550c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
24560c7d97c5SJed Brown     /* Preconditioner for coarse problem */
245753cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
245853cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
245953cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
24603b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
246153cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
246253cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
246353cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
24640c7d97c5SJed Brown     /* Allow user's customization */
246553cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24660c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
246753cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2468e269702eSStefano Zampini       if(dbg_flag) {
2469e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2470e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2471e269702eSStefano Zampini       }
247253cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
247353cdbc3dSStefano Zampini     }
247453cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
24755619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
24765619798eSStefano Zampini       if(dbg_flag) {
24775619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
24785619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24795619798eSStefano Zampini       }
24805619798eSStefano Zampini     }
24810c7d97c5SJed Brown   }
24820c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
24830c7d97c5SJed Brown      IS local_IS,global_IS;
24840c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
24850c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
24860c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
24870c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
24880c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
24890c7d97c5SJed Brown   }
24900c7d97c5SJed Brown 
24910c7d97c5SJed Brown 
24923b03a366Sstefano_zampini   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
24933b03a366Sstefano_zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
24940c7d97c5SJed Brown     PetscScalar m_one=-1.0;
24955619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
24963b03a366Sstefano_zampini     const KSPType check_ksp_type=KSPGMRES;
24970c7d97c5SJed Brown 
24985619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
24993b03a366Sstefano_zampini     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2500d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
25015619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
25025619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2503d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2504d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2505d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2506d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2507d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
25083b03a366Sstefano_zampini     if(dbg_flag) {
25095619798eSStefano Zampini       kappa_2=lambda_max/lambda_min;
25105619798eSStefano Zampini       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2511d49ef151SStefano Zampini       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2512d49ef151SStefano Zampini       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
25133b03a366Sstefano_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);
2514e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2515e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
25163b03a366Sstefano_zampini     }
25175619798eSStefano Zampini     /* restore coarse ksp to default values */
2518d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
25195619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
25203b03a366Sstefano_zampini     ierr = KSPChebychevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
25213b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
25225619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
25235619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
252453cdbc3dSStefano Zampini   }
25250c7d97c5SJed Brown 
25260c7d97c5SJed Brown   /* free data structures no longer needed */
25270c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
25280c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
25290c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
25300c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
25310c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
25320c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
25330c7d97c5SJed Brown 
25340c7d97c5SJed Brown   PetscFunctionReturn(0);
25350c7d97c5SJed Brown }
25360c7d97c5SJed Brown 
25370c7d97c5SJed Brown #undef __FUNCT__
25380c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
253953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
25400c7d97c5SJed Brown {
25410c7d97c5SJed Brown 
25420c7d97c5SJed Brown   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
25430c7d97c5SJed Brown   PC_IS         *pcis = (PC_IS*)pc->data;
25440c7d97c5SJed Brown   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
25450c7d97c5SJed Brown   PCBDDCGraph mat_graph;
25460c7d97c5SJed Brown   Mat         mat_adj;
25473b03a366Sstefano_zampini   PetscInt    **neighbours_set;
2548a0ba757dSStefano Zampini   PetscInt    *queue_in_global_numbering;
25493b03a366Sstefano_zampini   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
25503b03a366Sstefano_zampini   PetscInt    total_counts,nodes_touched=0,where_values=1,vertex_size;
25513b03a366Sstefano_zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
25523b03a366Sstefano_zampini   PetscBool   same_set,flg_row;
25533b03a366Sstefano_zampini   PetscBool   symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2554a0ba757dSStefano Zampini   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
25553b03a366Sstefano_zampini   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
25563b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
25573b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
2558*36e030ebSStefano Zampini   IS          used_IS;
25590c7d97c5SJed Brown 
25600c7d97c5SJed Brown   PetscFunctionBegin;
2561a0ba757dSStefano Zampini   /* allocate and initialize needed graph structure */
25620c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
25630c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2564a0ba757dSStefano Zampini   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2565a0ba757dSStefano Zampini   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
25660c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2567a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2568a0ba757dSStefano 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);
2569a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2570a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2571a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2572a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2573a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25743828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
25753828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2576a0ba757dSStefano Zampini 
25779c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
25789c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
25799c0446d6SStefano Zampini     PetscInt *is_indices;
25809c0446d6SStefano Zampini     PetscInt is_size;
25819c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
25829c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
25839c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25849c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
25859c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
25869c0446d6SStefano Zampini       }
25879c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25889c0446d6SStefano Zampini     }
25893b03a366Sstefano_zampini     /* use mat block size as vertex size */
25903b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
25913b03a366Sstefano_zampini   } else { /* otherwise it assumes a constant block size */
2592a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
25930c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
25940c7d97c5SJed Brown       for(s=0;s<bs;s++) {
25950c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
25960c7d97c5SJed Brown       }
25970c7d97c5SJed Brown     }
25983b03a366Sstefano_zampini     vertex_size=1;
25999c0446d6SStefano Zampini   }
26003b03a366Sstefano_zampini   /* count number of neigh per node */
26010c7d97c5SJed Brown   total_counts=0;
26023b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26030c7d97c5SJed Brown     s=pcis->n_shared[i];
26040c7d97c5SJed Brown     total_counts+=s;
260553cdbc3dSStefano Zampini     for(j=0;j<s;j++){
26060c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
26070c7d97c5SJed Brown     }
26080c7d97c5SJed Brown   }
26093b03a366Sstefano_zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
2610*36e030ebSStefano Zampini   ierr = PCBDDCGetNeumannBoundaries(pc,&used_IS);CHKERRQ(ierr);
2611*36e030ebSStefano Zampini   if(used_IS) {
2612*36e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&neumann_bsize);CHKERRQ(ierr);
2613*36e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
261453cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
261553cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
26163b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
261753cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26180c7d97c5SJed Brown         total_counts++;
26190c7d97c5SJed Brown       }
26200c7d97c5SJed Brown     }
26210c7d97c5SJed Brown   }
26223b03a366Sstefano_zampini   /* allocate space for storing the set of neighbours of each node */
262353cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
26243b03a366Sstefano_zampini   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr); }
262553cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2626a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
26273b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
26280c7d97c5SJed Brown     s=pcis->n_shared[i];
26290c7d97c5SJed Brown     for(j=0;j<s;j++) {
26300c7d97c5SJed Brown       k=pcis->shared[i][j];
263153cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
26320c7d97c5SJed Brown       mat_graph->count[k]+=1;
26330c7d97c5SJed Brown     }
26340c7d97c5SJed Brown   }
26353b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
2636*36e030ebSStefano Zampini   if(used_IS) {
263753cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
263853cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
26393b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
26403b03a366Sstefano_zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1;
264153cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26420c7d97c5SJed Brown       }
26430c7d97c5SJed Brown     }
2644*36e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&neumann_nodes);CHKERRQ(ierr);
26450c7d97c5SJed Brown   }
26463b03a366Sstefano_zampini   /* sort set of sharing subdomains (needed for comparison below) */
264753cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
26483b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
2649*36e030ebSStefano Zampini   ierr = PCBDDCGetDirichletBoundaries(pc,&used_IS);CHKERRQ(ierr);
2650*36e030ebSStefano Zampini   if(used_IS) {
2651*36e030ebSStefano Zampini     ierr = ISGetSize(used_IS,&dirichlet_bsize);CHKERRQ(ierr);
2652*36e030ebSStefano Zampini     ierr = ISGetIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
26533b03a366Sstefano_zampini     for(i=0;i<dirichlet_bsize;i++){
26543b03a366Sstefano_zampini       mat_graph->count[dirichlet_nodes[i]]=0;
26553b03a366Sstefano_zampini     }
2656*36e030ebSStefano Zampini     ierr = ISRestoreIndices(used_IS,&dirichlet_nodes);CHKERRQ(ierr);
26573b03a366Sstefano_zampini   }
26580c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
26593b03a366Sstefano_zampini     if(!mat_graph->count[i]){  /* interior nodes */
26600c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
26610c7d97c5SJed Brown       mat_graph->where[i]=0;
26620c7d97c5SJed Brown       nodes_touched++;
26630c7d97c5SJed Brown     }
26640c7d97c5SJed Brown   }
26650c7d97c5SJed Brown   mat_graph->ncmps = 0;
26660c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2667a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
26680c7d97c5SJed Brown     i=0;
26690c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
26700c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2671a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
26720c7d97c5SJed Brown     nodes_touched++;
2673a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
26740c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2675a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
26760c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2677a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
26780c7d97c5SJed Brown         same_set=PETSC_TRUE;
26790c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
268053cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
26810c7d97c5SJed Brown             same_set=PETSC_FALSE;
26820c7d97c5SJed Brown           }
26830c7d97c5SJed Brown         }
2684a0ba757dSStefano Zampini         /* I found a friend of mine */
26850c7d97c5SJed Brown         if(same_set) {
2686a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
26870c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
26880c7d97c5SJed Brown           nodes_touched++;
26890c7d97c5SJed Brown         }
26900c7d97c5SJed Brown       }
26910c7d97c5SJed Brown     }
2692a0ba757dSStefano Zampini     where_values++;
26930c7d97c5SJed Brown   }
2694a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2695a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2696a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2697a0ba757dSStefano Zampini   if(where_values) {
2698a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
26993b03a366Sstefano_zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2700a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2701a0ba757dSStefano 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);
2702a0ba757dSStefano 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);
2703a0ba757dSStefano Zampini     }
2704a0ba757dSStefano Zampini   }
2705a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2706a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
27073b03a366Sstefano_zampini     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
27083b03a366Sstefano_zampini     if(mat_graph->where_ncmps[i]>1) {
2709a0ba757dSStefano Zampini       adapt_interface=1;
2710a0ba757dSStefano Zampini       break;
2711a0ba757dSStefano Zampini     }
2712a0ba757dSStefano Zampini   }
2713a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2714a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
27150c7d97c5SJed Brown 
27163b03a366Sstefano_zampini     printf("Adapting Interface\n");
27173b03a366Sstefano_zampini 
2718a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2719a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2720a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2721a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2722a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2723a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2724a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2725a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2726a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2727a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2728a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2729a0ba757dSStefano Zampini     MPI_Request *send_requests;
2730a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2731a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2732a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2733a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2734a0ba757dSStefano Zampini     PetscInt *add_to_where;
2735a0ba757dSStefano Zampini 
2736a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2737a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2738a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2739a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2740a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2741a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2742a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2743a0ba757dSStefano Zampini       j=0;
2744a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2745a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
27463b03a366Sstefano_zampini       if(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  */
27473b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2748a0ba757dSStefano Zampini     }
2749a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2750a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2751a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2752a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2753a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2754a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2755a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2756a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2757a0ba757dSStefano Zampini     }
2758a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2759a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2760a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2761a0ba757dSStefano Zampini       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2762a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2763a0ba757dSStefano Zampini         ierr = MPI_Isend(&mat_graph->where_ncmps[i],1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2764a0ba757dSStefano Zampini         ierr = MPI_Irecv(&recv_buffer_where[sum_requests],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2765a0ba757dSStefano Zampini         sum_requests++;
2766a0ba757dSStefano Zampini       }
2767a0ba757dSStefano Zampini     }
2768a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2769a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2770a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2771a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2772a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2773a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2774a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
27753b03a366Sstefano_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 */
27763b03a366Sstefano_zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2777a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2778a0ba757dSStefano Zampini           break;
2779a0ba757dSStefano Zampini         }
2780a0ba757dSStefano Zampini       }
2781a0ba757dSStefano Zampini     }
2782a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2783a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2784a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2785a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2786a0ba757dSStefano Zampini     sum_requests=0;
2787a0ba757dSStefano Zampini     start_of_send=0;
2788a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2789a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2790a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2791a0ba757dSStefano Zampini         size_of_send=0;
2792a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2793a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2794a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2795a0ba757dSStefano Zampini             size_of_send+=1;
2796a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2797a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2798a0ba757dSStefano Zampini             }
2799a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2800a0ba757dSStefano Zampini           }
2801a0ba757dSStefano Zampini         }
2802a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2803a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2804a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2805a0ba757dSStefano Zampini           ierr = MPI_Isend(&size_of_send,1,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2806a0ba757dSStefano Zampini           ierr = MPI_Irecv(&recv_buffer_where[sum_requests+start_of_recv],1,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2807a0ba757dSStefano Zampini           sum_requests++;
2808a0ba757dSStefano Zampini         }
2809a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2810a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2811a0ba757dSStefano Zampini       }
2812a0ba757dSStefano Zampini     }
2813a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2814a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2815a0ba757dSStefano Zampini     buffer_size=0;
2816a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2817a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2818a0ba757dSStefano Zampini     /* now exchange the data */
2819a0ba757dSStefano Zampini     start_of_recv=0;
2820a0ba757dSStefano Zampini     start_of_send=0;
2821a0ba757dSStefano Zampini     sum_requests=0;
2822a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2823a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2824a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2825a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2826a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2827a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2828a0ba757dSStefano Zampini           ierr = MPI_Isend(&send_buffer[start_of_send],size_of_send,MPIU_INT,neighbours_set[j][k],(my_rank+1)*mat_graph->count[j],interface_comm,&send_requests[sum_requests]);CHKERRQ(ierr);
2829a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2830a0ba757dSStefano Zampini           ierr = MPI_Irecv(&recv_buffer[start_of_recv],size_of_recv,MPIU_INT,neighbours_set[j][k],(neighbours_set[j][k]+1)*mat_graph->count[j],interface_comm,&recv_requests[sum_requests]);CHKERRQ(ierr);
2831a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2832a0ba757dSStefano Zampini           sum_requests++;
2833a0ba757dSStefano Zampini         }
2834a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2835a0ba757dSStefano Zampini       }
2836a0ba757dSStefano Zampini     }
2837a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2838a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2839a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2840a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2841a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2842a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2843a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2844a0ba757dSStefano Zampini        j+=k;
2845a0ba757dSStefano Zampini     }
2846a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2847a0ba757dSStefano Zampini     start_of_recv=0;
2848a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2849a0ba757dSStefano Zampini     global_where_counter=0;
2850a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2851a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2852a0ba757dSStefano Zampini         temp_buffer_size=0;
2853a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2854a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2855a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2856a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2857a0ba757dSStefano Zampini             temp_buffer_size++;
2858a0ba757dSStefano Zampini           } else {
2859a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2860a0ba757dSStefano Zampini           }
2861a0ba757dSStefano Zampini         }
2862a0ba757dSStefano Zampini         /* allocate some temporary space */
2863a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2864a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2865a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2866a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2867a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2868a0ba757dSStefano Zampini         }
2869a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2870a0ba757dSStefano Zampini            temp buffer structure:
2871a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2872a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2873a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2874a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2875a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2876a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2877a0ba757dSStefano Zampini              [ 0, 0, 0;
2878a0ba757dSStefano Zampini                0, 0, 1;
2879a0ba757dSStefano Zampini                1, 1, 2;
2880a0ba757dSStefano Zampini                1, 1, 2;
2881a0ba757dSStefano Zampini                0, 1, 0; ];
2882a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2883a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2884a0ba757dSStefano Zampini                                                                                                                                    */
2885a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2886a0ba757dSStefano Zampini           ins_val=0;
2887a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2888a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2889a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2890a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2891a0ba757dSStefano Zampini             }
2892a0ba757dSStefano Zampini             buffer_size+=k;
2893a0ba757dSStefano Zampini             ins_val++;
2894a0ba757dSStefano Zampini           }
2895a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2896a0ba757dSStefano Zampini           sum_requests++;
2897a0ba757dSStefano Zampini         }
2898a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2899a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2900a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2901a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2902a0ba757dSStefano Zampini             global_where_counter++;
2903a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2904a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2905a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2906a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2907a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2908a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2909a0ba757dSStefano Zampini                   break;
2910a0ba757dSStefano Zampini                 }
2911a0ba757dSStefano Zampini               }
2912a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2913a0ba757dSStefano Zampini             }
2914a0ba757dSStefano Zampini           }
2915a0ba757dSStefano Zampini         }
2916a0ba757dSStefano Zampini         /* insert new data in where array */
2917a0ba757dSStefano Zampini         temp_buffer_size=0;
2918a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2919a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2920a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2921a0ba757dSStefano Zampini             temp_buffer_size++;
2922a0ba757dSStefano Zampini           }
2923a0ba757dSStefano Zampini         }
2924a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2925a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2926a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2927a0ba757dSStefano Zampini       }
2928a0ba757dSStefano Zampini     }
2929a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2930a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2931a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2932a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2933a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2934a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2935a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2936a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2937a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2938a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2939a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2940a0ba757dSStefano Zampini     if(global_where_counter) {
2941a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2942a0ba757dSStefano Zampini       global_where_counter=0;
2943a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
2944a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2945a0ba757dSStefano Zampini           global_where_counter++;
2946a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
2947a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2948a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
2949a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
2950a0ba757dSStefano Zampini             }
2951a0ba757dSStefano Zampini           }
2952a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
2953a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
2954a0ba757dSStefano Zampini         }
2955a0ba757dSStefano Zampini       }
2956a0ba757dSStefano Zampini       where_values=global_where_counter;
2957a0ba757dSStefano Zampini     }
2958a0ba757dSStefano Zampini     if(global_where_counter) {
2959a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2960a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2961a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2962a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2963a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2964a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
2965a0ba757dSStefano 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);
2966a0ba757dSStefano 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);
2967a0ba757dSStefano Zampini       }
2968a0ba757dSStefano Zampini     }
29693b03a366Sstefano_zampini   } /* Finished adapting interface */
29700c7d97c5SJed Brown   PetscInt nfc=0;
29710c7d97c5SJed Brown   PetscInt nec=0;
29720c7d97c5SJed Brown   PetscInt nvc=0;
29733b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
29740c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
29753b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
29763b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
29770c7d97c5SJed Brown         nfc++;
29783b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
29793b03a366Sstefano_zampini         nec++;
29803b03a366Sstefano_zampini       }
29810c7d97c5SJed Brown     } else {
29823b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
29833b03a366Sstefano_zampini     }
29843b03a366Sstefano_zampini   }
29853b03a366Sstefano_zampini 
29863b03a366Sstefano_zampini   if(!nec) { /* we are in a 2d case -> no faces, only edges */
29873b03a366Sstefano_zampini     nec = nfc;
29883b03a366Sstefano_zampini     nfc = 0;
29893b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
29903b03a366Sstefano_zampini   }
29913b03a366Sstefano_zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set.
29923b03a366Sstefano_zampini      Reusing space allocated in mat_graph->where for creating IS objects */
29933b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
29943b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
29953b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
29963b03a366Sstefano_zampini   }
29973b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
29983b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
29993b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
30003b03a366Sstefano_zampini   }
30013b03a366Sstefano_zampini   nfc=0;
30023b03a366Sstefano_zampini   nec=0;
30033b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
30043b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
30053b03a366Sstefano_zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
30063b03a366Sstefano_zampini         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
30073b03a366Sstefano_zampini       }
30083b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
30093b03a366Sstefano_zampini         if(twodim_flag) {
30103b03a366Sstefano_zampini           if(use_edges) {
30113b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30123b03a366Sstefano_zampini             nec++;
30133b03a366Sstefano_zampini           }
30143b03a366Sstefano_zampini         } else {
30153b03a366Sstefano_zampini           if(use_faces) {
30163b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
30173b03a366Sstefano_zampini             nfc++;
30183b03a366Sstefano_zampini           }
30193b03a366Sstefano_zampini         }
30203b03a366Sstefano_zampini       } else {
30213b03a366Sstefano_zampini         if(use_edges) {
30223b03a366Sstefano_zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
30230c7d97c5SJed Brown           nec++;
30240c7d97c5SJed Brown         }
30250c7d97c5SJed Brown       }
30260c7d97c5SJed Brown     }
30273b03a366Sstefano_zampini   }
30283b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
30293b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
30303b03a366Sstefano_zampini   nvc=0;
30310c7d97c5SJed Brown   if( !pcbddc->constraints_flag ) {
30323b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
30333b03a366Sstefano_zampini       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
30343b03a366Sstefano_zampini         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
30353b03a366Sstefano_zampini           mat_graph->where[nvc]=mat_graph->queue[j];
30360c7d97c5SJed Brown           nvc++;
30370c7d97c5SJed Brown         }
30380c7d97c5SJed Brown       }
30390c7d97c5SJed Brown     }
30400c7d97c5SJed Brown   }
3041a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
30423b03a366Sstefano_zampini   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
30433b03a366Sstefano_zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
30440c7d97c5SJed Brown 
3045e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
3046e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
3047e269702eSStefano Zampini 
3048d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3049d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3050d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3051a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
3052a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3053e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
3054a0ba757dSStefano 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);
3055e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
3056a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
3057e269702eSStefano Zampini       }
3058a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
30593b03a366Sstefano_zampini     }
3060d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
30610c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
30623b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
30633b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
30640c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
30653828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
30660c7d97c5SJed Brown       }
30670c7d97c5SJed Brown     }
30683b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);*/
30693b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
30703b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
30713b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3072d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
30730c7d97c5SJed Brown   }
30740c7d97c5SJed Brown 
3075a0ba757dSStefano Zampini   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
3076a0ba757dSStefano Zampini   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
30770c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
3078a0ba757dSStefano Zampini   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
3079a0ba757dSStefano Zampini   /* Free graph structure */
30800c7d97c5SJed Brown   if(mat_graph->nvtxs){
3081a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
3082a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
3083a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3084a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3085a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
30860c7d97c5SJed Brown   }
30870c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
30880c7d97c5SJed Brown 
30890c7d97c5SJed Brown   PetscFunctionReturn(0);
30900c7d97c5SJed Brown 
30910c7d97c5SJed Brown }
30920c7d97c5SJed Brown 
30930c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
30940c7d97c5SJed Brown 
30950c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
30960c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
30970c7d97c5SJed Brown 
30980c7d97c5SJed Brown #undef __FUNCT__
30990c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
31009c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
31010c7d97c5SJed Brown {
31020c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
31030c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
31040c7d97c5SJed Brown   PetscInt *cptr;
31050c7d97c5SJed Brown   PetscBool *touched;
31060c7d97c5SJed Brown 
31070c7d97c5SJed Brown   PetscFunctionBegin;
31080c7d97c5SJed Brown 
31090c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
31100c7d97c5SJed Brown   xadj    = graph->xadj;
31110c7d97c5SJed Brown   adjncy  = graph->adjncy;
31120c7d97c5SJed Brown   where   = graph->where;
31130c7d97c5SJed Brown   touched = graph->touched;
31140c7d97c5SJed Brown   queue   = graph->queue;
31150c7d97c5SJed Brown   cptr    = graph->cptr;
31160c7d97c5SJed Brown 
31170c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
31180c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
31190c7d97c5SJed Brown 
31200c7d97c5SJed Brown   cum_queue=0;
31210c7d97c5SJed Brown   ncmps=0;
31220c7d97c5SJed Brown 
31230c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
3124a0ba757dSStefano Zampini     pid = n+1;
31250c7d97c5SJed Brown     nleft = 0;
31260c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
31270c7d97c5SJed Brown       if (where[i] == pid)
31280c7d97c5SJed Brown         nleft++;
31290c7d97c5SJed Brown     }
31300c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
31310c7d97c5SJed Brown       if (where[i] == pid)
31320c7d97c5SJed Brown         break;
31330c7d97c5SJed Brown     }
31340c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
31350c7d97c5SJed Brown     queue[cum_queue] = i;
31360c7d97c5SJed Brown     first = 0; last = 1;
31370c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
31380c7d97c5SJed Brown     ncmps_pid = 0;
31390c7d97c5SJed Brown     while (first != nleft) {
31400c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
31410c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
31420c7d97c5SJed Brown         ncmps_pid++;
31430c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
31440c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
31450c7d97c5SJed Brown             break;
31460c7d97c5SJed Brown         }
31470c7d97c5SJed Brown         queue[cum_queue+last] = i;
31480c7d97c5SJed Brown         last++;
31490c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
31500c7d97c5SJed Brown       }
31510c7d97c5SJed Brown       i = queue[cum_queue+first];
31520c7d97c5SJed Brown       first++;
31530c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
31540c7d97c5SJed Brown         k = adjncy[j];
31550c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
31560c7d97c5SJed Brown           queue[cum_queue+last] = k;
31570c7d97c5SJed Brown           last++;
31580c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
31590c7d97c5SJed Brown         }
31600c7d97c5SJed Brown       }
31610c7d97c5SJed Brown     }
31620c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
31630c7d97c5SJed Brown     ncmps_pid++;
31640c7d97c5SJed Brown     cum_queue=cptr[ncmps];
3165a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
31660c7d97c5SJed Brown   }
31670c7d97c5SJed Brown   graph->ncmps = ncmps;
31680c7d97c5SJed Brown 
31690c7d97c5SJed Brown   PetscFunctionReturn(0);
31700c7d97c5SJed Brown }
31710c7d97c5SJed Brown 
3172