xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 670f3ff9a12f3667ff7d4cebfc50ebc8579c9e33)
153cdbc3dSStefano Zampini /* TODOLIST
23b03a366Sstefano_zampini    Exact solvers: Solve local saddle point directly for very hard problems
33b03a366Sstefano_zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
4a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
5a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
6a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
7a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
8a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
93b03a366Sstefano_zampini      - Add levels' slot to bddc data structure and associated Set/Get functions
10a0ba757dSStefano Zampini    code refactoring:
11a0ba757dSStefano Zampini      - pick up better names for static functions
123b03a366Sstefano_zampini    check log_summary for leaking (actually: 1 Vector per level )
13a0ba757dSStefano Zampini    change options structure:
14a0ba757dSStefano Zampini      - insert BDDC into MG framework?
15a0ba757dSStefano Zampini    provide other ops? Ask to developers
16a0ba757dSStefano Zampini    remove all unused printf
17a0ba757dSStefano Zampini    remove // commments and adhere to PETSc code requirements
18a0ba757dSStefano Zampini    man pages
1953cdbc3dSStefano Zampini */
200c7d97c5SJed Brown 
2153cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
220c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
230c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2453cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2553cdbc3dSStefano Zampini 
2653cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
273b03a366Sstefano_zampini #include <petscblaslapack.h>
280c7d97c5SJed Brown 
290c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
300c7d97c5SJed Brown #undef __FUNCT__
310c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
320c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
330c7d97c5SJed Brown {
340c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
350c7d97c5SJed Brown   PetscErrorCode ierr;
360c7d97c5SJed Brown 
370c7d97c5SJed Brown   PetscFunctionBegin;
380c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
390c7d97c5SJed Brown   /* Verbose debugging of main data structures */
40e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
410c7d97c5SJed Brown   /* Some customization for default primal space */
420c7d97c5SJed 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);
430c7d97c5SJed 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);
440c7d97c5SJed 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);
450c7d97c5SJed 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);
460c7d97c5SJed Brown   /* Coarse solver context */
470c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
480c7d97c5SJed 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);
490c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
500c7d97c5SJed 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);
510c7d97c5SJed 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);
520c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
530c7d97c5SJed Brown   PetscFunctionReturn(0);
540c7d97c5SJed Brown }
550c7d97c5SJed Brown 
560c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
570c7d97c5SJed Brown EXTERN_C_BEGIN
580c7d97c5SJed Brown #undef __FUNCT__
590c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
610c7d97c5SJed Brown {
620c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
630c7d97c5SJed Brown 
640c7d97c5SJed Brown   PetscFunctionBegin;
650c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
660c7d97c5SJed Brown   PetscFunctionReturn(0);
670c7d97c5SJed Brown }
680c7d97c5SJed Brown EXTERN_C_END
690c7d97c5SJed Brown 
700c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
710c7d97c5SJed Brown #undef __FUNCT__
720c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7353cdbc3dSStefano Zampini /*@
749c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7553cdbc3dSStefano Zampini 
769c0446d6SStefano Zampini    Not collective
7753cdbc3dSStefano Zampini 
7853cdbc3dSStefano Zampini    Input Parameters:
7953cdbc3dSStefano Zampini +  pc - the preconditioning context
8053cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8153cdbc3dSStefano Zampini 
8253cdbc3dSStefano Zampini    Level: intermediate
8353cdbc3dSStefano Zampini 
8453cdbc3dSStefano Zampini    Notes:
859c0446d6SStefano Zampini    Not collective but all procs must call this.
8653cdbc3dSStefano Zampini 
8753cdbc3dSStefano Zampini .seealso: PCBDDC
8853cdbc3dSStefano Zampini @*/
890c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
900c7d97c5SJed Brown {
910c7d97c5SJed Brown   PetscErrorCode ierr;
920c7d97c5SJed Brown 
930c7d97c5SJed Brown   PetscFunctionBegin;
940c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
950c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
960c7d97c5SJed Brown   PetscFunctionReturn(0);
970c7d97c5SJed Brown }
980c7d97c5SJed Brown 
990c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1000c7d97c5SJed Brown EXTERN_C_BEGIN
1010c7d97c5SJed Brown #undef __FUNCT__
1023b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
1033b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
1043b03a366Sstefano_zampini {
1053b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1063b03a366Sstefano_zampini   PetscErrorCode ierr;
1073b03a366Sstefano_zampini 
1083b03a366Sstefano_zampini   PetscFunctionBegin;
1093b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1103b03a366Sstefano_zampini   ierr = ISDuplicate(DirichletBoundaries,&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1113b03a366Sstefano_zampini   ierr = ISCopy(DirichletBoundaries,pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1123b03a366Sstefano_zampini   PetscFunctionReturn(0);
1133b03a366Sstefano_zampini }
1143b03a366Sstefano_zampini EXTERN_C_END
1153b03a366Sstefano_zampini 
1163b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1173b03a366Sstefano_zampini #undef __FUNCT__
1183b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
1193b03a366Sstefano_zampini /*@
1203b03a366Sstefano_zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part of
1213b03a366Sstefano_zampini                               Dirichlet boundaries for the global problem.
1223b03a366Sstefano_zampini 
1233b03a366Sstefano_zampini    Not collective
1243b03a366Sstefano_zampini 
1253b03a366Sstefano_zampini    Input Parameters:
1263b03a366Sstefano_zampini +  pc - the preconditioning context
1273b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
1283b03a366Sstefano_zampini 
1293b03a366Sstefano_zampini    Level: intermediate
1303b03a366Sstefano_zampini 
1313b03a366Sstefano_zampini    Notes:
1323b03a366Sstefano_zampini    The sequential IS is copied; the user must destroy the IS object passed in.
1333b03a366Sstefano_zampini 
1343b03a366Sstefano_zampini .seealso: PCBDDC
1353b03a366Sstefano_zampini @*/
1363b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
1373b03a366Sstefano_zampini {
1383b03a366Sstefano_zampini   PetscErrorCode ierr;
1393b03a366Sstefano_zampini 
1403b03a366Sstefano_zampini   PetscFunctionBegin;
1413b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1423b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
1433b03a366Sstefano_zampini   PetscFunctionReturn(0);
1443b03a366Sstefano_zampini }
1453b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1463b03a366Sstefano_zampini EXTERN_C_BEGIN
1473b03a366Sstefano_zampini #undef __FUNCT__
1480c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
14953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1500c7d97c5SJed Brown {
1510c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15253cdbc3dSStefano Zampini   PetscErrorCode ierr;
1530c7d97c5SJed Brown 
1540c7d97c5SJed Brown   PetscFunctionBegin;
15553cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
15653cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
15753cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1580c7d97c5SJed Brown   PetscFunctionReturn(0);
1590c7d97c5SJed Brown }
1600c7d97c5SJed Brown EXTERN_C_END
1610c7d97c5SJed Brown 
1620c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1630c7d97c5SJed Brown #undef __FUNCT__
1640c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
16557527edcSJed Brown /*@
16653cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
16753cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
16857527edcSJed Brown 
1699c0446d6SStefano Zampini    Not collective
17057527edcSJed Brown 
17157527edcSJed Brown    Input Parameters:
17257527edcSJed Brown +  pc - the preconditioning context
1739c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
17457527edcSJed Brown 
17557527edcSJed Brown    Level: intermediate
17657527edcSJed Brown 
17757527edcSJed Brown    Notes:
1789c0446d6SStefano Zampini    The sequential IS is copied; the user must destroy the IS object passed in.
17957527edcSJed Brown 
18057527edcSJed Brown .seealso: PCBDDC
18157527edcSJed Brown @*/
18253cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1830c7d97c5SJed Brown {
1840c7d97c5SJed Brown   PetscErrorCode ierr;
1850c7d97c5SJed Brown 
1860c7d97c5SJed Brown   PetscFunctionBegin;
1870c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18853cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
18953cdbc3dSStefano Zampini   PetscFunctionReturn(0);
19053cdbc3dSStefano Zampini }
19153cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
19253cdbc3dSStefano Zampini EXTERN_C_BEGIN
19353cdbc3dSStefano Zampini #undef __FUNCT__
19453cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
19553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
19653cdbc3dSStefano Zampini {
19753cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
19853cdbc3dSStefano Zampini 
19953cdbc3dSStefano Zampini   PetscFunctionBegin;
20053cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
20153cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
20253cdbc3dSStefano Zampini   } else {
2039c0446d6SStefano Zampini     *NeumannBoundaries = PETSC_NULL;
2049c0446d6SStefano Zampini     //SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
20553cdbc3dSStefano Zampini   }
20653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
20753cdbc3dSStefano Zampini }
20853cdbc3dSStefano Zampini EXTERN_C_END
20953cdbc3dSStefano Zampini 
21053cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
21153cdbc3dSStefano Zampini #undef __FUNCT__
21253cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
21353cdbc3dSStefano Zampini /*@
21453cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
21553cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
21653cdbc3dSStefano Zampini 
2179c0446d6SStefano Zampini    Not collective
21853cdbc3dSStefano Zampini 
21953cdbc3dSStefano Zampini    Input Parameters:
22053cdbc3dSStefano Zampini +  pc - the preconditioning context
22153cdbc3dSStefano Zampini 
22253cdbc3dSStefano Zampini    Output Parameters:
22353cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
22453cdbc3dSStefano Zampini 
22553cdbc3dSStefano Zampini    Level: intermediate
22653cdbc3dSStefano Zampini 
22753cdbc3dSStefano Zampini    Notes:
2289c0446d6SStefano Zampini    If the user has not yet provided such information, PETSC_NULL is returned.
22953cdbc3dSStefano Zampini 
23053cdbc3dSStefano Zampini .seealso: PCBDDC
23153cdbc3dSStefano Zampini @*/
23253cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
23353cdbc3dSStefano Zampini {
23453cdbc3dSStefano Zampini   PetscErrorCode ierr;
23553cdbc3dSStefano Zampini 
23653cdbc3dSStefano Zampini   PetscFunctionBegin;
23753cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
23853cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
2390c7d97c5SJed Brown   PetscFunctionReturn(0);
2400c7d97c5SJed Brown }
2410c7d97c5SJed Brown 
2429c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
2439c0446d6SStefano Zampini EXTERN_C_BEGIN
2449c0446d6SStefano Zampini #undef __FUNCT__
2459c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
2469c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
2479c0446d6SStefano Zampini {
2489c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2499c0446d6SStefano Zampini   PetscInt i;
2509c0446d6SStefano Zampini   PetscErrorCode ierr;
2519c0446d6SStefano Zampini 
2529c0446d6SStefano Zampini   PetscFunctionBegin;
2539c0446d6SStefano Zampini   /* Destroy IS if already set */
2549c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
2559c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2569c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2579c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2589c0446d6SStefano Zampini   }
2599c0446d6SStefano Zampini   /* allocate space then copy ISs */
2609c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
2619c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
2629c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2639c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2649c0446d6SStefano Zampini   }
2659c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
2669c0446d6SStefano Zampini   PetscFunctionReturn(0);
2679c0446d6SStefano Zampini }
2689c0446d6SStefano Zampini EXTERN_C_END
2699c0446d6SStefano Zampini 
2709c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
2719c0446d6SStefano Zampini #undef __FUNCT__
2729c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
2739c0446d6SStefano Zampini /*@
2749c0446d6SStefano Zampini  PCBDDCSetDofsSplitting - Set index set defining how dofs are splitted.
2759c0446d6SStefano Zampini 
2769c0446d6SStefano Zampini    Not collective
2779c0446d6SStefano Zampini 
2789c0446d6SStefano Zampini    Input Parameters:
2799c0446d6SStefano Zampini +  pc - the preconditioning context
2809c0446d6SStefano Zampini -  n - number of index sets defining dofs spltting
2819c0446d6SStefano Zampini -  IS[] - array of IS describing dofs splitting
2829c0446d6SStefano Zampini 
2839c0446d6SStefano Zampini    Level: intermediate
2849c0446d6SStefano Zampini 
2859c0446d6SStefano Zampini    Notes:
2869c0446d6SStefano Zampini    Sequential ISs are copied, the user must destroy the array of IS passed in.
2879c0446d6SStefano Zampini 
2889c0446d6SStefano Zampini .seealso: PCBDDC
2899c0446d6SStefano Zampini @*/
2909c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
2919c0446d6SStefano Zampini {
2929c0446d6SStefano Zampini   PetscErrorCode ierr;
2939c0446d6SStefano Zampini 
2949c0446d6SStefano Zampini   PetscFunctionBegin;
2959c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2969c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
2979c0446d6SStefano Zampini   PetscFunctionReturn(0);
2989c0446d6SStefano Zampini }
2999c0446d6SStefano Zampini 
30053cdbc3dSStefano Zampini #undef __FUNCT__
30153cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
3020c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3030c7d97c5SJed Brown /*
3040c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
3050c7d97c5SJed Brown                   by setting data structures and options.
3060c7d97c5SJed Brown 
3070c7d97c5SJed Brown    Input Parameter:
30853cdbc3dSStefano Zampini +  pc - the preconditioner context
3090c7d97c5SJed Brown 
3100c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
3110c7d97c5SJed Brown 
3120c7d97c5SJed Brown    Notes:
3130c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
3140c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
3150c7d97c5SJed Brown */
31653cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
3170c7d97c5SJed Brown {
3180c7d97c5SJed Brown   PetscErrorCode ierr;
3190c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
3200c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
3210c7d97c5SJed Brown 
3220c7d97c5SJed Brown   PetscFunctionBegin;
3230c7d97c5SJed Brown   if (!pc->setupcalled) {
3243b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
3259c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
3260c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
3270c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
3280c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
3290c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
3300c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
3313b03a366Sstefano_zampini     /* Get stdout for dbg */
332e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
333e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
334e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
335e269702eSStefano Zampini     }
3363b03a366Sstefano_zampini     /* TODO MOVE CODE FRAGMENT */
3370c7d97c5SJed Brown     PetscInt im_active=0;
3380c7d97c5SJed Brown     if(pcis->n) im_active = 1;
33953cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
3403b03a366Sstefano_zampini     /* Analyze local interface */
3410c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
3423b03a366Sstefano_zampini     /* Set up local constraint matrix */
3433b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
3440c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
3450c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
3463b03a366Sstefano_zampini     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
3473b03a366Sstefano_zampini     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
3480c7d97c5SJed Brown   }
3490c7d97c5SJed Brown   PetscFunctionReturn(0);
3500c7d97c5SJed Brown }
3510c7d97c5SJed Brown 
3520c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3530c7d97c5SJed Brown /*
3540c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
3550c7d97c5SJed Brown 
3560c7d97c5SJed Brown    Input Parameters:
3570c7d97c5SJed Brown .  pc - the preconditioner context
3580c7d97c5SJed Brown .  r - input vector (global)
3590c7d97c5SJed Brown 
3600c7d97c5SJed Brown    Output Parameter:
3610c7d97c5SJed Brown .  z - output vector (global)
3620c7d97c5SJed Brown 
3630c7d97c5SJed Brown    Application Interface Routine: PCApply()
3640c7d97c5SJed Brown  */
3650c7d97c5SJed Brown #undef __FUNCT__
3660c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
36753cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
3680c7d97c5SJed Brown {
3690c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
3700c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
3710c7d97c5SJed Brown   PetscErrorCode    ierr;
3723b03a366Sstefano_zampini   const PetscScalar one = 1.0;
3733b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
3740c7d97c5SJed Brown 
3750c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
3760c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
3770c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
3780c7d97c5SJed Brown 
3790c7d97c5SJed Brown   PetscFunctionBegin;
3800c7d97c5SJed Brown   /* First Dirichlet solve */
3810c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3820c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
38353cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3840c7d97c5SJed Brown   /*
3850c7d97c5SJed Brown     Assembling right hand side for BDDC operator
3860c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
3870c7d97c5SJed Brown     - the interface part of the global vector z
3880c7d97c5SJed Brown   */
3890c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3900c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
3910c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3920c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3930c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
3940c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3950c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3960c7d97c5SJed Brown 
3970c7d97c5SJed Brown   /*
3980c7d97c5SJed Brown     Apply interface preconditioner
3990c7d97c5SJed Brown     Results are stored in:
4000c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
4010c7d97c5SJed Brown     -  the interface part of the global vector z
4020c7d97c5SJed Brown   */
4030c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
4040c7d97c5SJed Brown 
4053b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
4060c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4070c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4080c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
4090c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
41053cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
4110c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
4120c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
4130c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
4140c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4150c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4160c7d97c5SJed Brown 
4170c7d97c5SJed Brown   PetscFunctionReturn(0);
4180c7d97c5SJed Brown 
4190c7d97c5SJed Brown }
4200c7d97c5SJed Brown 
4210c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4220c7d97c5SJed Brown /*
4230c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
4240c7d97c5SJed Brown 
4250c7d97c5SJed Brown */
4260c7d97c5SJed Brown #undef __FUNCT__
4270c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
42853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
4290c7d97c5SJed Brown {
4300c7d97c5SJed Brown   PetscErrorCode ierr;
4310c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4320c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
4333b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
4340c7d97c5SJed Brown 
4350c7d97c5SJed Brown   PetscFunctionBegin;
4360c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
4370c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4380c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4390c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4400c7d97c5SJed Brown 
4410c7d97c5SJed Brown   /* Application of PHI^T  */
4420c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4430c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4440c7d97c5SJed Brown 
4450c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
4460c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
4470c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4480c7d97c5SJed Brown 
4490c7d97c5SJed Brown   /* Local solution on R nodes */
4500c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
4510c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4520c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4530c7d97c5SJed Brown   if(pcbddc->prec_type) {
4540c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4550c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4560c7d97c5SJed Brown   }
4570c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
4580c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
4590c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4600c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4610c7d97c5SJed Brown   if(pcbddc->prec_type) {
4620c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4630c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4640c7d97c5SJed Brown   }
4650c7d97c5SJed Brown 
4660c7d97c5SJed Brown   /* Coarse solution */
4670c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
46853cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
4690c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4700c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4710c7d97c5SJed Brown 
4720c7d97c5SJed Brown   /* Sum contributions from two levels */
4730c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
4740c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4750c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4760c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4770c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
4780c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4790c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4800c7d97c5SJed Brown 
4810c7d97c5SJed Brown   PetscFunctionReturn(0);
4820c7d97c5SJed Brown }
4830c7d97c5SJed Brown 
4840c7d97c5SJed Brown 
4850c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4860c7d97c5SJed Brown /*
4870c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
4880c7d97c5SJed Brown 
4890c7d97c5SJed Brown */
4900c7d97c5SJed Brown #undef __FUNCT__
4910c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
49253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
4930c7d97c5SJed Brown {
4940c7d97c5SJed Brown   PetscErrorCode ierr;
4950c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
4960c7d97c5SJed Brown 
4970c7d97c5SJed Brown   PetscFunctionBegin;
4980c7d97c5SJed Brown 
49953cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
5000c7d97c5SJed Brown   if(pcbddc->n_constraints) {
5010c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
5020c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5030c7d97c5SJed Brown   }
5040c7d97c5SJed Brown 
5050c7d97c5SJed Brown   PetscFunctionReturn(0);
5060c7d97c5SJed Brown }
5070c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5080c7d97c5SJed Brown /*
5090c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
5100c7d97c5SJed Brown 
5110c7d97c5SJed Brown */
5120c7d97c5SJed Brown #undef __FUNCT__
5130c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
51453cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5150c7d97c5SJed Brown {
5160c7d97c5SJed Brown   PetscErrorCode ierr;
5170c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5180c7d97c5SJed Brown 
5190c7d97c5SJed Brown   PetscFunctionBegin;
5200c7d97c5SJed Brown 
5210c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5220c7d97c5SJed Brown     case SCATTERS_BDDC:
5230c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5240c7d97c5SJed Brown       break;
5250c7d97c5SJed Brown     case GATHERS_BDDC:
5260c7d97c5SJed Brown       break;
5270c7d97c5SJed Brown   }
5280c7d97c5SJed Brown   PetscFunctionReturn(0);
5290c7d97c5SJed Brown 
5300c7d97c5SJed Brown }
5310c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5320c7d97c5SJed Brown /*
5330c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
5340c7d97c5SJed Brown 
5350c7d97c5SJed Brown */
5360c7d97c5SJed Brown #undef __FUNCT__
5370c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
53853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5390c7d97c5SJed Brown {
5400c7d97c5SJed Brown   PetscErrorCode ierr;
5410c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5420c7d97c5SJed Brown   PetscScalar*   array_to;
5430c7d97c5SJed Brown   PetscScalar*   array_from;
5440c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
5450c7d97c5SJed Brown   PetscInt i;
5460c7d97c5SJed Brown 
5470c7d97c5SJed Brown   PetscFunctionBegin;
5480c7d97c5SJed Brown 
5490c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5500c7d97c5SJed Brown     case SCATTERS_BDDC:
5510c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5520c7d97c5SJed Brown       break;
5530c7d97c5SJed Brown     case GATHERS_BDDC:
5540c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
5550c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
5560c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
5570c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
5580c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
55953cdbc3dSStefano 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);
5600c7d97c5SJed Brown             if(vec_to) {
5610c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5620c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5630c7d97c5SJed Brown             }
5640c7d97c5SJed Brown           } else {
5650c7d97c5SJed Brown             if(vec_from)
5660c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5670c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
56853cdbc3dSStefano 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);
5690c7d97c5SJed Brown           }
5700c7d97c5SJed Brown           break;
5710c7d97c5SJed Brown         case REPLICATED_BDDC:
5720c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
57353cdbc3dSStefano 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);
5740c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
5750c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5760c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
5770c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
5780c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
5790c7d97c5SJed Brown           }
5800c7d97c5SJed Brown           break;
58153cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
58253cdbc3dSStefano Zampini           break;
58353cdbc3dSStefano Zampini         case PARALLEL_BDDC:
58453cdbc3dSStefano Zampini           break;
5850c7d97c5SJed Brown       }
5860c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
5870c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
5880c7d97c5SJed Brown       break;
5890c7d97c5SJed Brown   }
5900c7d97c5SJed Brown   PetscFunctionReturn(0);
5910c7d97c5SJed Brown 
5920c7d97c5SJed Brown }
5930c7d97c5SJed Brown 
5940c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5950c7d97c5SJed Brown /*
5960c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
5970c7d97c5SJed Brown    that was created with PCCreate_BDDC().
5980c7d97c5SJed Brown 
5990c7d97c5SJed Brown    Input Parameter:
6000c7d97c5SJed Brown .  pc - the preconditioner context
6010c7d97c5SJed Brown 
6020c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
6030c7d97c5SJed Brown */
6040c7d97c5SJed Brown #undef __FUNCT__
6050c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
60653cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
6070c7d97c5SJed Brown {
6080c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
6090c7d97c5SJed Brown   PetscErrorCode ierr;
6100c7d97c5SJed Brown 
6110c7d97c5SJed Brown   PetscFunctionBegin;
6120c7d97c5SJed Brown   /* free data created by PCIS */
6130c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
6140c7d97c5SJed Brown   /* free BDDC data  */
61553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
61653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
61753cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
61853cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
61953cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
62053cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
62153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
62253cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
62353cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
62453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
62553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
62653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
62753cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
62853cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
62953cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
63053cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
63153cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
63253cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
63353cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
6343b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
6353b03a366Sstefano_zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
63653cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
63753cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
6380c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
63953cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
64053cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
6419c0446d6SStefano Zampini   PetscInt i;
6423b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
6433b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
6443b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
6453b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
6463b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
6473b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
6483b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
6490c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
6500c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
6510c7d97c5SJed Brown   PetscFunctionReturn(0);
6520c7d97c5SJed Brown }
6530c7d97c5SJed Brown 
6540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6550c7d97c5SJed Brown /*MC
6560c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
6570c7d97c5SJed Brown 
6580c7d97c5SJed Brown    Options Database Keys:
659a0ba757dSStefano Zampini .    -pcbddc ??? -
6600c7d97c5SJed Brown 
6610c7d97c5SJed Brown    Level: intermediate
6620c7d97c5SJed Brown 
6630c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
6640c7d97c5SJed Brown 
6650c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
6660c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
6670c7d97c5SJed Brown           on the subdomains).
6680c7d97c5SJed Brown 
669a0ba757dSStefano Zampini           Options for the coarse grid preconditioner can be set with -
670a0ba757dSStefano Zampini           Options for the Dirichlet subproblem can be set with -
671a0ba757dSStefano Zampini           Options for the Neumann subproblem can be set with -
6720c7d97c5SJed Brown 
6730c7d97c5SJed Brown    Contributed by Stefano Zampini
6740c7d97c5SJed Brown 
6750c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
6760c7d97c5SJed Brown M*/
6770c7d97c5SJed Brown EXTERN_C_BEGIN
6780c7d97c5SJed Brown #undef __FUNCT__
6790c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
6800c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
6810c7d97c5SJed Brown {
6820c7d97c5SJed Brown   PetscErrorCode ierr;
6830c7d97c5SJed Brown   PC_BDDC          *pcbddc;
6840c7d97c5SJed Brown 
6850c7d97c5SJed Brown   PetscFunctionBegin;
6860c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
6870c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
6880c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
6890c7d97c5SJed Brown   /* create PCIS data structure */
6900c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
6910c7d97c5SJed Brown   /* BDDC specific */
6920c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
6930c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
69453cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
6950c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
6960c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
6970c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
6980c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
6990c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
7000c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
7010c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
7020c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
7030c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
70453cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
70553cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
7060c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
7070c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
70853cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
7093b03a366Sstefano_zampini   pcbddc->ISForDofs                  = 0;
7103b03a366Sstefano_zampini   pcbddc->ISForVertices              = 0;
7113b03a366Sstefano_zampini   pcbddc->n_ISForFaces               = 0;
7123b03a366Sstefano_zampini   pcbddc->n_ISForEdges               = 0;
7133b03a366Sstefano_zampini   pcbddc->ConstraintMatrix           = 0;
7143b03a366Sstefano_zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
7150c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
7160c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
7170c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
7180c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
7190c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
720e269702eSStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
7210c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
7220c7d97c5SJed Brown   /* function pointers */
7230c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
7240c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
7250c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
7260c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
7270c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
7280c7d97c5SJed Brown   pc->ops->view                = 0;
7290c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
7300c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
7310c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
7320c7d97c5SJed Brown   /* composing function */
7333b03a366Sstefano_zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
7343b03a366Sstefano_zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
7350c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
7360c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
73753cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
73853cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
7390c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
7400c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
7419c0446d6SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
7429c0446d6SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
7430c7d97c5SJed Brown   PetscFunctionReturn(0);
7440c7d97c5SJed Brown }
7450c7d97c5SJed Brown EXTERN_C_END
7460c7d97c5SJed Brown 
7470c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7480c7d97c5SJed Brown /*
7493b03a366Sstefano_zampini    Create C matrix [I 0; 0 const]
7503b03a366Sstefano_zampini */
7513b03a366Sstefano_zampini /* for testing only */
7523b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
7533b03a366Sstefano_zampini #define BDDC_USE_POD
7543b03a366Sstefano_zampini #define PETSC_MISSING_LAPACK_GESVD 1
7553b03a366Sstefano_zampini #endif
7563b03a366Sstefano_zampini 
7573b03a366Sstefano_zampini #undef __FUNCT__
7583b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
7593b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
7603b03a366Sstefano_zampini {
7613b03a366Sstefano_zampini   PetscErrorCode ierr;
7623b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
7633b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7643b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
7653b03a366Sstefano_zampini   PetscInt       *nnz,*vertices,*is_indices;
7663b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
7673b03a366Sstefano_zampini   PetscInt       *temp_indices,*temp_indices_to_constraint;
7683b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
7693b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
7703b03a366Sstefano_zampini   PetscReal      quad_value;
7713b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
7723b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
7733b03a366Sstefano_zampini   IS             *used_IS;
7743b03a366Sstefano_zampini   const MatType  impMatType=MATSEQAIJ;
7753b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
7763b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
7773b03a366Sstefano_zampini   Vec            *localnearnullsp;
7783b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
7793b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
7803b03a366Sstefano_zampini /* some conditional variables */
7813b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
7823b03a366Sstefano_zampini   PetscScalar dot_result;
7833b03a366Sstefano_zampini   PetscScalar  one=1.0,zero=0.0;
7843b03a366Sstefano_zampini   PetscInt ii;
7853b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
7863b03a366Sstefano_zampini   PetscScalar val1,val2;
7873b03a366Sstefano_zampini #else
7883b03a366Sstefano_zampini   PetscBLASInt Bone=1;
7893b03a366Sstefano_zampini #endif
7903b03a366Sstefano_zampini #else
7913b03a366Sstefano_zampini   PetscBLASInt dummy_int;
7923b03a366Sstefano_zampini   PetscScalar dummy_scalar;
7933b03a366Sstefano_zampini #endif
7943b03a366Sstefano_zampini 
7953b03a366Sstefano_zampini 
7963b03a366Sstefano_zampini   PetscFunctionBegin;
7973b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
7983b03a366Sstefano_zampini   if(pc->pmat->nearnullsp) {
7993b03a366Sstefano_zampini     nnsp_has_cnst = pc->pmat->nearnullsp->has_cnst;
8003b03a366Sstefano_zampini     nnsp_size = pc->pmat->nearnullsp->n;
8013b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
8023b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
8033b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
8043b03a366Sstefano_zampini   }
8053b03a366Sstefano_zampini   if(nnsp_has_cnst) {
8063b03a366Sstefano_zampini     nnsp_addone = 1;
8073b03a366Sstefano_zampini   }
8083b03a366Sstefano_zampini   /*
8093b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
8103b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
8113b03a366Sstefano_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
8123b03a366Sstefano_zampini        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
8133b03a366Sstefano_zampini                                                                                                                                                          */
8143b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
8153b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8163b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
8173b03a366Sstefano_zampini   total_counts = 0;
8183b03a366Sstefano_zampini   max_size_of_constraint = 0;
8193b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
8203b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
8213b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
8223b03a366Sstefano_zampini     } else {
8233b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
8243b03a366Sstefano_zampini     }
8253b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
8263b03a366Sstefano_zampini     total_counts += j;
8273b03a366Sstefano_zampini     if(j>max_size_of_constraint) max_size_of_constraint=j;
8283b03a366Sstefano_zampini   }
8293b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8303b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
8313b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
8323b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
8333b03a366Sstefano_zampini   rwork = 0;
8343b03a366Sstefano_zampini   work = 0;
8353b03a366Sstefano_zampini   singular_vals = 0;
8363b03a366Sstefano_zampini   temp_basis = 0;
8373b03a366Sstefano_zampini   correlation_mat = 0;
8383b03a366Sstefano_zampini   if(!pcbddc->use_nnsp_true) {
8393b03a366Sstefano_zampini     PetscScalar temp_work;
8403b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8413b03a366Sstefano_zampini     /* POD */
8423b03a366Sstefano_zampini     PetscInt max_n;
8433b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
8443b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
8453b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
8463b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
8473b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
8483b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8493b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
8503b03a366Sstefano_zampini #endif
8513b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
8523b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
8533b03a366Sstefano_zampini     lwork=-1;
8543b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
8553b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
8563b03a366Sstefano_zampini #else
8573b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
8583b03a366Sstefano_zampini #endif
8593b03a366Sstefano_zampini #else /* on missing GESVD */
8603b03a366Sstefano_zampini     /* SVD */
8613b03a366Sstefano_zampini     PetscInt max_n,min_n;
8623b03a366Sstefano_zampini     max_n = max_size_of_constraint;
8633b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
8643b03a366Sstefano_zampini     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
8653b03a366Sstefano_zampini       min_n = max_size_of_constraint;
8663b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
8673b03a366Sstefano_zampini     }
8683b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
8693b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8703b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
8713b03a366Sstefano_zampini #endif
8723b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
8733b03a366Sstefano_zampini     lwork=-1;
8743b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
8753b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
8763b03a366Sstefano_zampini     dummy_int = Bs;
877*670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
8783b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
8793b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
8803b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
8813b03a366Sstefano_zampini #else
8823b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
8833b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
8843b03a366Sstefano_zampini #endif
8853b03a366Sstefano_zampini     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
886*670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
8873b03a366Sstefano_zampini #endif
8883b03a366Sstefano_zampini     /* Allocate optimal workspace */
8893b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
8903b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
8913b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
8923b03a366Sstefano_zampini   }
8933b03a366Sstefano_zampini   /* get local part of global near null space vectors */
8943b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
8953b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) {
8963b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
8973b03a366Sstefano_zampini     ierr = VecScatterBegin(matis->ctx,pc->pmat->nearnullsp->vecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8983b03a366Sstefano_zampini     ierr = VecScatterEnd  (matis->ctx,pc->pmat->nearnullsp->vecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8993b03a366Sstefano_zampini   }
9003b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
9013b03a366Sstefano_zampini   total_counts=0;
9023b03a366Sstefano_zampini   temp_indices[0]=0;
9033b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
9043b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
9053b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
9063b03a366Sstefano_zampini     } else {
9073b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
9083b03a366Sstefano_zampini     }
9093b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
9103b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
9113b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
9123b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
9133b03a366Sstefano_zampini     if(nnsp_has_cnst) {
9143b03a366Sstefano_zampini       temp_constraints++;
9153b03a366Sstefano_zampini       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
9163b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9173b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9183b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
9193b03a366Sstefano_zampini       }
9203b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9213b03a366Sstefano_zampini       total_counts++;
9223b03a366Sstefano_zampini     }
9233b03a366Sstefano_zampini     for(k=0;k<nnsp_size;k++) {
9243b03a366Sstefano_zampini       temp_constraints++;
9253b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
9263b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9273b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9283b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
9293b03a366Sstefano_zampini       }
9303b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
9313b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9323b03a366Sstefano_zampini       total_counts++;
9333b03a366Sstefano_zampini     }
9343b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
9353b03a366Sstefano_zampini     /* perform SVD on the constraint if use true has not be requested by the user */
9363b03a366Sstefano_zampini     if(!use_nnsp_true) {
9373b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
9383b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
9393b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
9403b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
9413b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
9423b03a366Sstefano_zampini       for(j=0;j<temp_constraints;j++) {
9433b03a366Sstefano_zampini         for(k=0;k<j+1;k++) {
9443b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9453b03a366Sstefano_zampini           /* hand made complex dot product */
9463b03a366Sstefano_zampini           dot_result = 0.0;
9473b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
9483b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
9493b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
9503b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
9513b03a366Sstefano_zampini           }
9523b03a366Sstefano_zampini #else
9533b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
9543b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
9553b03a366Sstefano_zampini #endif
9563b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
9573b03a366Sstefano_zampini         }
9583b03a366Sstefano_zampini       }
9593b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9603b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
9613b03a366Sstefano_zampini #else
9623b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
9633b03a366Sstefano_zampini #endif
9643b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
9653b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
9663b03a366Sstefano_zampini       j=0;
9673b03a366Sstefano_zampini       while( j < Bt && singular_vals[j] < tol) j++;
9683b03a366Sstefano_zampini       total_counts=total_counts-j;
9693b03a366Sstefano_zampini       if(j<temp_constraints) {
9703b03a366Sstefano_zampini         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
9713b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
9723b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
9733b03a366Sstefano_zampini         for(k=0;k<Bt-j;k++) {
9743b03a366Sstefano_zampini           for(ii=0;ii<size_of_constraint;ii++) {
9753b03a366Sstefano_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];
9763b03a366Sstefano_zampini           }
9773b03a366Sstefano_zampini         }
9783b03a366Sstefano_zampini       }
9793b03a366Sstefano_zampini #else  /* on missing GESVD */
9803b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
9813b03a366Sstefano_zampini       if(min_n > size_of_constraint) min_n = size_of_constraint;
9823b03a366Sstefano_zampini       dummy_int = Bs;
983*670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
9843b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9853b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
9863b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
9873b03a366Sstefano_zampini #else
9883b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
9893b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
9903b03a366Sstefano_zampini #endif
9913b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
992*670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
9933b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
9943b03a366Sstefano_zampini       j=0;
9953b03a366Sstefano_zampini       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
9963b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
9973b03a366Sstefano_zampini #endif
9983b03a366Sstefano_zampini     }
9993b03a366Sstefano_zampini   }
10003b03a366Sstefano_zampini   n_constraints=total_counts;
10013b03a366Sstefano_zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
10023b03a366Sstefano_zampini   local_primal_size = n_vertices+n_constraints;
10033b03a366Sstefano_zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
10043b03a366Sstefano_zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
10053b03a366Sstefano_zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
10063b03a366Sstefano_zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
10073b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { nnz[i]= 1; }
10083b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) { nnz[i+n_vertices]=temp_indices[i+1]-temp_indices[i]; }
10093b03a366Sstefano_zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
10103b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10113b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { ierr = MatSetValue(pcbddc->ConstraintMatrix,i,vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr); }
10123b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10133b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
10143b03a366Sstefano_zampini     j=i+n_vertices;
10153b03a366Sstefano_zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
10163b03a366Sstefano_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);
10173b03a366Sstefano_zampini   }
10183b03a366Sstefano_zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10193b03a366Sstefano_zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10203b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
10213b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
10223b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
10233b03a366Sstefano_zampini   pcbddc->local_primal_size = n_vertices+n_constraints;
10243b03a366Sstefano_zampini   /* free workspace no longer needed */
10253b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
10263b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
10273b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
10283b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
10293b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
10303b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
10313b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
10323b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
10333b03a366Sstefano_zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
10343b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) { ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr); }
10353b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
10363b03a366Sstefano_zampini   PetscFunctionReturn(0);
10373b03a366Sstefano_zampini }
10383b03a366Sstefano_zampini #ifdef BDDC_USE_POD
10393b03a366Sstefano_zampini #undef PETSC_MISSING_LAPACK_GESVD
10403b03a366Sstefano_zampini #endif
10413b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
10423b03a366Sstefano_zampini /*
10430c7d97c5SJed Brown    PCBDDCCoarseSetUp -
10440c7d97c5SJed Brown */
10450c7d97c5SJed Brown #undef __FUNCT__
10460c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
104753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
10480c7d97c5SJed Brown {
10490c7d97c5SJed Brown   PetscErrorCode  ierr;
10500c7d97c5SJed Brown 
10510c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
10520c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
10530c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
10540c7d97c5SJed Brown   IS                is_R_local;
10550c7d97c5SJed Brown   IS                is_V_local;
10560c7d97c5SJed Brown   IS                is_C_local;
10570c7d97c5SJed Brown   IS                is_aux1;
10580c7d97c5SJed Brown   IS                is_aux2;
10590c7d97c5SJed Brown   const VecType     impVecType;
10600c7d97c5SJed Brown   const MatType     impMatType;
10610c7d97c5SJed Brown   PetscInt          n_R=0;
10620c7d97c5SJed Brown   PetscInt          n_D=0;
10630c7d97c5SJed Brown   PetscInt          n_B=0;
10640c7d97c5SJed Brown   PetscScalar       zero=0.0;
10650c7d97c5SJed Brown   PetscScalar       one=1.0;
10660c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
10670c7d97c5SJed Brown   PetscScalar*      array;
10680c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
10690c7d97c5SJed Brown   PetscInt          *idx_R_local;
10700c7d97c5SJed Brown   PetscInt          *idx_V_B;
10710c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
10720c7d97c5SJed Brown   PetscScalar       *constraints_errors;
10730c7d97c5SJed Brown   /* auxiliary indices */
10740c7d97c5SJed Brown   PetscInt s,i,j,k;
1075e269702eSStefano Zampini   /* for verbose output of bddc */
1076e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1077e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1078a0ba757dSStefano Zampini   /* for counting coarse dofs */
1079a0ba757dSStefano Zampini   PetscScalar       coarsesum;
10803b03a366Sstefano_zampini   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
10813b03a366Sstefano_zampini   PetscInt          size_of_constraint;
10823b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
10833b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
10843b03a366Sstefano_zampini   const PetscInt    *vertices;
10850c7d97c5SJed Brown 
10860c7d97c5SJed Brown   PetscFunctionBegin;
10870c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
10880c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
10893b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,&vertices);CHKERRQ(ierr);
1090a0ba757dSStefano 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) */
1091a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1092a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
10933b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { array[ vertices[i] ] = one; }
10943b03a366Sstefano_zampini 
10953b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
10963b03a366Sstefano_zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
10973b03a366Sstefano_zampini     for (j=0; j<size_of_constraint; j++) {
10983b03a366Sstefano_zampini       k = row_cmat_indices[j];
1099a0ba757dSStefano Zampini       if( array[k] == zero ) {
1100a0ba757dSStefano Zampini         array[k] = one;
1101a0ba757dSStefano Zampini         break;
1102a0ba757dSStefano Zampini       }
1103a0ba757dSStefano Zampini     }
11043b03a366Sstefano_zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1105a0ba757dSStefano Zampini   }
1106a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1107a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1108a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1109a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1110a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1111a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1112a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1113a0ba757dSStefano Zampini   for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1114a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1115a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1116a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1117a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1118a0ba757dSStefano Zampini   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1119a0ba757dSStefano Zampini   pcbddc->coarse_size = (PetscInt) coarsesum;
1120a0ba757dSStefano Zampini 
11210c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
11220c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
11230c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11243b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
11253b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
11260c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
11270c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1128e269702eSStefano Zampini   if(dbg_flag) {
11290c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
11300c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11310c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
11320c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
11333b03a366Sstefano_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);
11340c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1135a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1136a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1137a0ba757dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11380c7d97c5SJed Brown   }
11390c7d97c5SJed Brown   /* Allocate needed vectors */
11400c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
11410c7d97c5SJed Brown   impMatType = MATSEQDENSE;
11420c7d97c5SJed Brown   impVecType = VECSEQ;
11430c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
11440c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
11450c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
11460c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
11470c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1148d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
11490c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
11500c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
11510c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
11520c7d97c5SJed Brown 
11530c7d97c5SJed Brown   /* Creating some index sets needed  */
11540c7d97c5SJed Brown   /* For submatrices */
11550c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
11563b03a366Sstefano_zampini   if(n_vertices)    {
11573b03a366Sstefano_zampini     ierr = ISDuplicate(pcbddc->ISForVertices,&is_V_local);CHKERRQ(ierr);
11583b03a366Sstefano_zampini     ierr = ISCopy(pcbddc->ISForVertices,is_V_local);CHKERRQ(ierr);
11593b03a366Sstefano_zampini   }
11603b03a366Sstefano_zampini   if(n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr); }
11610c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
11620c7d97c5SJed Brown   {
11630c7d97c5SJed Brown     PetscInt   *aux_array1;
11640c7d97c5SJed Brown     PetscInt   *aux_array2;
11650c7d97c5SJed Brown     PetscScalar      value;
11660c7d97c5SJed Brown 
11673b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
11683b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
11690c7d97c5SJed Brown 
1170d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
11710c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11720c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11730c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11740c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11750c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11760c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11770c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11780c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
11790c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11800c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
11810c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
11820c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
11833828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
11840c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
11850c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
11860c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
11870c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
11880c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
11890c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
11900c7d97c5SJed Brown 
1191e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
11920c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
11930c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11940c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
11950c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11960c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
11970c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
11980c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
11990c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
12000c7d97c5SJed Brown     }
12010c7d97c5SJed Brown 
12020c7d97c5SJed Brown     /* Check scatters */
1203e269702eSStefano Zampini     if(dbg_flag) {
12040c7d97c5SJed Brown 
12050c7d97c5SJed Brown       Vec            vec_aux;
12060c7d97c5SJed Brown 
12070c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12080c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
12090c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1210d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1211d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1212d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1213d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1214d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1215d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1216d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1217d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1218d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1219d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12200c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1221d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12220c7d97c5SJed Brown 
1223d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1224d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1225d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
1226d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
1227d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1228d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1229d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1230d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1231d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
1232d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12330c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1234d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12350c7d97c5SJed Brown 
12360c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12370c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
12380c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12390c7d97c5SJed Brown 
1240d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1241d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1242d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1243d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1244d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1245d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1246d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1247d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1248d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1249d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12500c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1251d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12520c7d97c5SJed Brown 
1253d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1254d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1255d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
1256d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
1257d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1258d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1259d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1260d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1261d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
1262d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12630c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1264d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12650c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12660c7d97c5SJed Brown 
12670c7d97c5SJed Brown     }
12680c7d97c5SJed Brown   }
12690c7d97c5SJed Brown 
12700c7d97c5SJed Brown   /* vertices in boundary numbering */
12713b03a366Sstefano_zampini   if(n_vertices) {
1272d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
12730c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12743b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
12750c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1276d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1277d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12783b03a366Sstefano_zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
12790c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12803b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) {
12810c7d97c5SJed Brown       s=0;
12820c7d97c5SJed Brown       while (array[s] != i ) {s++;}
12830c7d97c5SJed Brown       idx_V_B[i]=s;
12840c7d97c5SJed Brown     }
12850c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12860c7d97c5SJed Brown   }
12870c7d97c5SJed Brown 
12880c7d97c5SJed Brown 
12890c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
12900c7d97c5SJed Brown   {
12910c7d97c5SJed Brown     Mat  A_RR;
129253cdbc3dSStefano Zampini     PC   pc_temp;
12930c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
129453cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
129553cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
129653cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
129753cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1298a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
12990c7d97c5SJed Brown     /* default */
130053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
130153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13020c7d97c5SJed Brown     /* Allow user's customization */
130353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
130453cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
130553cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
13060c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
13070c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
130853cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
130953cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
131053cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
131153cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1312a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
13130c7d97c5SJed Brown     /* default */
131453cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
131553cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13160c7d97c5SJed Brown     /* Allow user's customization */
131753cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
131853cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
131953cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1320a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1321e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
13220c7d97c5SJed Brown       Vec temp_vec;
13230c7d97c5SJed Brown       PetscScalar value;
13240c7d97c5SJed Brown 
1325a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1326a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1327a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1328a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1329a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1330a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1331a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1332a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1333a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1334a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1335a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1336d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1337d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1338d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1339d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1340d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1341d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1342e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
13430c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1344d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13450c7d97c5SJed Brown     }
13460c7d97c5SJed Brown     /* free Neumann problem's matrix */
13470c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
13480c7d97c5SJed Brown   }
13490c7d97c5SJed Brown 
13500c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
13510c7d97c5SJed Brown   {
13520c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
13530c7d97c5SJed Brown     Mat          M1,M2;
13540c7d97c5SJed Brown     Mat          C_CR;
13553b03a366Sstefano_zampini     Mat          AUXMAT;
13560c7d97c5SJed Brown     Vec          vec1_C;
13570c7d97c5SJed Brown     Vec          vec2_C;
13580c7d97c5SJed Brown     Vec          vec1_V;
13590c7d97c5SJed Brown     Vec          vec2_V;
13600c7d97c5SJed Brown     PetscInt     *nnz;
13610c7d97c5SJed Brown     PetscInt     *auxindices;
136253cdbc3dSStefano Zampini     PetscInt     index;
13630c7d97c5SJed Brown     PetscScalar* array2;
13640c7d97c5SJed Brown     MatFactorInfo matinfo;
13650c7d97c5SJed Brown 
13660c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
13670c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
13680c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
13690c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
13700c7d97c5SJed Brown 
13710c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
13723b03a366Sstefano_zampini     if(n_vertices) {
13730c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
13743b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
13750c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
13760c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
13770c7d97c5SJed Brown     }
13780c7d97c5SJed Brown     if(pcbddc->n_constraints) {
13790c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
13800c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
13810c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
13820c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
13830c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
13840c7d97c5SJed Brown     }
13850c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
13863b03a366Sstefano_zampini     if(n_constraints) {
13870c7d97c5SJed Brown       /* some work vectors */
13880c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
13893b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
13900c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
13913b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
13920c7d97c5SJed Brown 
13930c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
13943b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
1395d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
13963b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
13973b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
13980c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
13993b03a366Sstefano_zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14003b03a366Sstefano_zampini         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
14013b03a366Sstefano_zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14020c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14030c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
14040c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14050c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14063b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
140753cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14083b03a366Sstefano_zampini         /* Set values */
14090c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14103b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14110c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14120c7d97c5SJed Brown       }
14130c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14140c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14150c7d97c5SJed Brown 
14160c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
14173b03a366Sstefano_zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
14180c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
14190c7d97c5SJed Brown 
14200c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14210c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1422d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14233b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14240c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14250c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14260c7d97c5SJed Brown 
14273b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1428d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14293b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14300c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14313b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
14323b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
14330c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14340c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14350c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14360c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14370c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14380c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14390c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14403b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14410c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14420c7d97c5SJed Brown       }
14430c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14440c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14450c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
14460c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
14470c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
14480c7d97c5SJed Brown 
14490c7d97c5SJed Brown     }
14500c7d97c5SJed Brown 
14510c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
14523b03a366Sstefano_zampini     if(n_vertices){
14530c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
14540c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
14550c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
14560c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1457d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
14583b03a366Sstefano_zampini       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
14590c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
14603b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
14613b03a366Sstefano_zampini       for(i=0;i<n_vertices;i++) {
14620c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
14630c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
14640c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
14650c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
14660c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
146753cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14680c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14693b03a366Sstefano_zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14700c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14710c7d97c5SJed Brown       }
14720c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14730c7d97c5SJed Brown       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14740c7d97c5SJed Brown     }
14750c7d97c5SJed Brown 
14760c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1477d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
14780c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
14790c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
14803b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1481e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1482d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
14830c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
14840c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
14853b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
14860c7d97c5SJed Brown     }
14870c7d97c5SJed Brown 
1488e269702eSStefano Zampini     if(dbg_flag) {
14890c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
14900c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
14910c7d97c5SJed Brown     }
14923b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
14930c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
14940c7d97c5SJed Brown 
14950c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
14963b03a366Sstefano_zampini     for(i=0;i<n_vertices;i++){
14970c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
14980c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
14990c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15000c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15010c7d97c5SJed Brown       /* solution of saddle point problem */
15020c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15030c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15043b03a366Sstefano_zampini       if(n_constraints) {
15050c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15060c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15070c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15080c7d97c5SJed Brown       }
15090c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15100c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15110c7d97c5SJed Brown 
15120c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15130c7d97c5SJed Brown       /* coarse basis functions */
15140c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15150c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15160c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15170c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15183b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15190c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15200c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1521e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
15220c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15230c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15240c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15253b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15260c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15270c7d97c5SJed Brown       }
15280c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15290c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15303b03a366Sstefano_zampini       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } //WARNING -> column major ordering
15310c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15323b03a366Sstefano_zampini       if(n_constraints) {
15330c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15343b03a366Sstefano_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
15350c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15360c7d97c5SJed Brown       }
15370c7d97c5SJed Brown 
1538e269702eSStefano Zampini       if( dbg_flag ) {
15390c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1540d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15410c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15420c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15430c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
15443b03a366Sstefano_zampini         array[ vertices[i] ] = one;
15450c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15460c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15470c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1548d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
15490c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15500c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15513b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
15520c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15533b03a366Sstefano_zampini         if(n_constraints) {
15540c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15553b03a366Sstefano_zampini           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
15560c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15570c7d97c5SJed Brown         }
15580c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15590c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
15600c7d97c5SJed Brown         /* check saddle point solution */
15610c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
15623b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
15633b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
15643b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
15650c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15663b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
15670c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15683b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
15690c7d97c5SJed Brown       }
15700c7d97c5SJed Brown     }
15710c7d97c5SJed Brown 
15723b03a366Sstefano_zampini     for(i=0;i<n_constraints;i++){
1573d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
15740c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
15750c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
15760c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
15770c7d97c5SJed Brown       /* solution of saddle point problem */
15780c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
15790c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
15800c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15813b03a366Sstefano_zampini       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
15820c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15830c7d97c5SJed Brown       /* coarse basis functions */
15843b03a366Sstefano_zampini       index=i+n_vertices;
15850c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15860c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15870c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15880c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
158953cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
15900c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1591e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
15920c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15930c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15940c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
159553cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
15960c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15970c7d97c5SJed Brown       }
15980c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15993b03a366Sstefano_zampini       if(n_vertices) {
16000c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16013b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
16020c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16030c7d97c5SJed Brown       }
16040c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16053b03a366Sstefano_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
16060c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16070c7d97c5SJed Brown 
1608e269702eSStefano Zampini       if( dbg_flag ) {
16090c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
161053cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16110c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16120c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16130c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
16140c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16150c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16160c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
161753cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16180c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16193b03a366Sstefano_zampini         if( n_vertices) {
16200c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16213b03a366Sstefano_zampini           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
16220c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16230c7d97c5SJed Brown         }
16240c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16253b03a366Sstefano_zampini         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16260c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16270c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16280c7d97c5SJed Brown         /* check saddle point solution */
16290c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16303b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
163153cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16323b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16330c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
163453cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16350c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
163653cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16370c7d97c5SJed Brown       }
16380c7d97c5SJed Brown     }
16390c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16400c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1641e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
16420c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16430c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16440c7d97c5SJed Brown     }
16450c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
16460c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
16479d2fce94SStefano Zampini     if(dbg_flag) {
16480c7d97c5SJed Brown 
16490c7d97c5SJed Brown       Mat coarse_sub_mat;
16500c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
16510c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1652a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
16530c7d97c5SJed Brown       PetscScalar      value;
16540c7d97c5SJed Brown 
1655c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1656c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1657c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1658c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1659c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1660c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1661c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1662c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
16630c7d97c5SJed Brown 
16640c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
16650c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
16660c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
166753cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
166853cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
166953cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1670c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
167153cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
167253cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1673c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
167453cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
167553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
167653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
167753cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
167853cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
167953cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
16800c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
16810c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
16820c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
16830c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
168453cdbc3dSStefano 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); }
16850c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
168653cdbc3dSStefano 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); }
16870c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
168853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
168953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
169053cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
169153cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
169253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
169353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
169453cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
169553cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
169653cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
169753cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
169853cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
16990c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
17000c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
17010c7d97c5SJed Brown     }
17020c7d97c5SJed Brown 
17030c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
17040c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
17050c7d97c5SJed Brown     /* free memory */
17060c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
17070c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
17080c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
17093b03a366Sstefano_zampini     if(n_vertices) {
17100c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
17110c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
17120c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
17130c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
17140c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
17150c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
17160c7d97c5SJed Brown     }
17170c7d97c5SJed Brown     if(pcbddc->n_constraints) {
17180c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
17190c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
17200c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
17210c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
17220c7d97c5SJed Brown     }
17230c7d97c5SJed Brown   }
17240c7d97c5SJed Brown   /* free memory */
17253b03a366Sstefano_zampini   if(n_vertices) {
17260c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17270c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17280c7d97c5SJed Brown   }
17290c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
17300c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
17313b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
17320c7d97c5SJed Brown 
17330c7d97c5SJed Brown   PetscFunctionReturn(0);
17340c7d97c5SJed Brown }
17350c7d97c5SJed Brown 
17360c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
17370c7d97c5SJed Brown 
17380c7d97c5SJed Brown #undef __FUNCT__
17390c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
174053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
17410c7d97c5SJed Brown {
17420c7d97c5SJed Brown 
17430c7d97c5SJed Brown 
17440c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
17450c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
17460c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
17470c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
17480c7d97c5SJed Brown   MPI_Comm  coarse_comm;
17490c7d97c5SJed Brown 
17500c7d97c5SJed Brown   /* common to all choiches */
17510c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
17520c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
17530c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
17540c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
17550c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
17560c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
17570c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
17580c7d97c5SJed Brown   PetscMPIInt master_proc=0;
17590c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
17600c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
17610c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
17620c7d97c5SJed Brown   PetscMPIInt count_recv=0;
17630c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
17640c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
17650c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
17660c7d97c5SJed Brown   /* some other variables */
17670c7d97c5SJed Brown   PetscErrorCode ierr;
17680c7d97c5SJed Brown   const MatType coarse_mat_type;
17690c7d97c5SJed Brown   const PCType  coarse_pc_type;
177053cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
177153cdbc3dSStefano Zampini   PC pc_temp;
17720c7d97c5SJed Brown   PetscInt i,j,k,bs;
17733b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1774e269702eSStefano Zampini   /* verbose output viewer */
1775e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1776e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
17770c7d97c5SJed Brown 
17780c7d97c5SJed Brown   PetscFunctionBegin;
17790c7d97c5SJed Brown 
17800c7d97c5SJed Brown   ins_local_primal_indices = 0;
17810c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
17820c7d97c5SJed Brown   localsizes2              = 0;
17830c7d97c5SJed Brown   localdispl2              = 0;
17840c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
17850c7d97c5SJed Brown   coarse_ISLG              = 0;
17860c7d97c5SJed Brown 
178753cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
178853cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
17890c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
17900c7d97c5SJed Brown 
1791beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1792beed3852SStefano Zampini   {
1793a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1794beed3852SStefano Zampini     PetscScalar    *array;
1795beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1796beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1797beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1798beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1799beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
18003b03a366Sstefano_zampini     PetscInt       *vertices,*row_cmat_indices;
18013b03a366Sstefano_zampini     PetscInt       size_of_constraint;
1802beed3852SStefano Zampini 
1803beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1804beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1805beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1806beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1807beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
18085619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1809beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1810beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1811beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1812beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1813beed3852SStefano Zampini     }
18145619798eSStefano Zampini     if(rank_prec_comm == 0) {
1815beed3852SStefano Zampini       /* allocate some auxiliary space */
1816beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1817beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1818beed3852SStefano Zampini     }
1819beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1820beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1821beed3852SStefano Zampini 
1822beed3852SStefano 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)
1823beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1824beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1825beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
18263b03a366Sstefano_zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1827beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18283b03a366Sstefano_zampini     ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1829beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18303b03a366Sstefano_zampini     for(i=0;i<pcbddc->n_vertices;i++) {  /* note that  pcbddc->n_vertices can be different from size of ISForVertices */
18313b03a366Sstefano_zampini       array[ vertices[i] ] = one;
18323b03a366Sstefano_zampini       auxlocal_primal[i] = vertices[i];
1833beed3852SStefano Zampini     }
18343b03a366Sstefano_zampini     ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1835beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
18363b03a366Sstefano_zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
18373b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
18383b03a366Sstefano_zampini         k = row_cmat_indices[j];
1839beed3852SStefano Zampini         if( array[k] == zero ) {
1840beed3852SStefano Zampini           array[k] = one;
1841beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1842beed3852SStefano Zampini           break;
1843beed3852SStefano Zampini         }
1844beed3852SStefano Zampini       }
18453b03a366Sstefano_zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1846beed3852SStefano Zampini     }
1847beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1848a0ba757dSStefano Zampini 
1849beed3852SStefano Zampini     /* Now assign them a global numbering */
1850beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1851beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1852beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1853beed3852SStefano 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);
1854beed3852SStefano Zampini 
1855beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1856beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1857beed3852SStefano Zampini     if(rank_prec_comm==0) {
1858beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1859beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1860beed3852SStefano Zampini       k=1;
1861beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1862beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1863beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1864beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1865beed3852SStefano Zampini           k++;
1866beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1867beed3852SStefano Zampini         }
1868beed3852SStefano Zampini       }
1869beed3852SStefano Zampini     } else {
1870beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1871beed3852SStefano Zampini     }
18725619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1873beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1874beed3852SStefano Zampini 
1875beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1876beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1877beed3852SStefano Zampini       k=0;
1878beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1879beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1880beed3852SStefano Zampini     }
1881e269702eSStefano Zampini     if(dbg_flag) {
1882e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1883e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1884e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1885e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1886e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1887e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1888e269702eSStefano Zampini       }
1889e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1890e269702eSStefano Zampini     }
1891beed3852SStefano Zampini     /* free allocated memory */
1892beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1893beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1894beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1895e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1896beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1897beed3852SStefano Zampini     }
1898e269702eSStefano Zampini   }
1899beed3852SStefano Zampini 
19000c7d97c5SJed Brown   /* adapt coarse problem type */
19010c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
19020c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
19030c7d97c5SJed Brown 
19040c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
19050c7d97c5SJed Brown 
19060c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
19070c7d97c5SJed Brown     {
19080c7d97c5SJed Brown       /* we need additional variables */
19090c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
19100c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
19110c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
19120c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
19130c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
19140c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
19150c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
19160c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
19170c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
19180c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
19190c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
19200c7d97c5SJed Brown       MetisInt    *faces_adjncy;
19210c7d97c5SJed Brown       MetisInt    *faces_xadj;
19220c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
19230c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
19240c7d97c5SJed Brown       PetscInt    *array_int;
19250c7d97c5SJed Brown       PetscMPIInt my_faces=0;
19260c7d97c5SJed Brown       PetscMPIInt total_faces=0;
19273828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
19280c7d97c5SJed Brown 
19290c7d97c5SJed Brown       /* define some quantities */
19300c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
19310c7d97c5SJed Brown       coarse_mat_type = MATIS;
19320c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
19333b03a366Sstefano_zampini       coarse_ksp_type  = KSPCHEBYCHEV;
19340c7d97c5SJed Brown 
19350c7d97c5SJed Brown       /* details of coarse decomposition */
19360c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
19370c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
19383828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
19393828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
19403828260eSStefano Zampini 
19413828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1942a0ba757dSStefano 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));
19430c7d97c5SJed Brown 
19440c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
19450c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
19463828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
19470c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
19480c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19490c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
19500c7d97c5SJed Brown         }
19510c7d97c5SJed Brown       }
19520c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
19530c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19540c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
19550c7d97c5SJed Brown             my_faces++;
19560c7d97c5SJed Brown             break;
19570c7d97c5SJed Brown           }
19580c7d97c5SJed Brown         }
19590c7d97c5SJed Brown       }
19600c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
19610c7d97c5SJed Brown 
196253cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
19630c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
19640c7d97c5SJed Brown       my_faces=0;
19650c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
19660c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19670c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
19680c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
19690c7d97c5SJed Brown             my_faces++;
19700c7d97c5SJed Brown             break;
19710c7d97c5SJed Brown           }
19720c7d97c5SJed Brown         }
19730c7d97c5SJed Brown       }
19740c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
19750c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
19760c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
19770c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
19780c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
19790c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
19800c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
19810c7d97c5SJed Brown       }
198253cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
19830c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
19840c7d97c5SJed Brown         faces_xadj[0]=0;
19850c7d97c5SJed Brown         faces_displacements[0]=0;
19860c7d97c5SJed Brown         j=0;
19870c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
19880c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
19890c7d97c5SJed Brown           if(number_of_faces[i-1]) {
19900c7d97c5SJed Brown             j++;
19910c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
19920c7d97c5SJed Brown           }
19930c7d97c5SJed Brown         }
19940c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
19950c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
19960c7d97c5SJed Brown       }
199753cdbc3dSStefano 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);
19980c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
19990c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
20000c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20013828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
20023828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
20030c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
20040c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
20050c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
20060c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
20070c7d97c5SJed Brown           printf("\n");
20080c7d97c5SJed Brown         }
20090c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
20100c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
20110c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
20120c7d97c5SJed Brown       }
20130c7d97c5SJed Brown 
20140c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
20150c7d97c5SJed Brown 
20163828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
20173828260eSStefano Zampini 
20180c7d97c5SJed Brown         ncon=1;
20190c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
20200c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
20210c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
20220c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
20230c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
20240c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
20250c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
20260c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
20270c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
20283828260eSStefano Zampini         printf("METIS PART GRAPH\n");
20293828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
20303828260eSStefano Zampini           printf("Using Kway\n");
20313828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
20323828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
20330c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20343828260eSStefano Zampini         } else {
20353828260eSStefano Zampini           printf("Using Recursive\n");
20363828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20373828260eSStefano Zampini         }
20380c7d97c5SJed 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);
20393828260eSStefano Zampini         printf("Partition done!\n");
20400c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
20410c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
20420c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
20430c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
20443828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
20453828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
20460c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
20470c7d97c5SJed Brown       }
20480c7d97c5SJed Brown 
20490c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
20500c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
20510c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
20520c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
20530c7d97c5SJed Brown       }
20540c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
20550c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
205653cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
20570c7d97c5SJed Brown 
20580c7d97c5SJed Brown       if( coarse_color == 0 ) {
205953cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
206053cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
20613828260eSStefano Zampini         printf("Details of coarse comm\n");
20623828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
20633828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
20640c7d97c5SJed Brown       } else {
20650c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
20660c7d97c5SJed Brown       }
20670c7d97c5SJed Brown 
20680c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
20690c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
20700c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
20710c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
20720c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
20730c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
20740c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
20750c7d97c5SJed Brown         /* some initializations */
20760c7d97c5SJed Brown         displacements_recv[0]=0;
20770c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
20780c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
20790c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
20803828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
20810c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
20820c7d97c5SJed Brown               total_count_recv[j]++;
20830c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
20840c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
20850c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
20860c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
20870c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
20883828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
20890c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
20900c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
20913828260eSStefano Zampini               total_count_recv[j]+=1;
20920c7d97c5SJed Brown             }
20930c7d97c5SJed Brown           }
20940c7d97c5SJed Brown         }
20953828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
20963828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
20973828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
20983828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
20993828260eSStefano Zampini           }
21003828260eSStefano Zampini           printf("\n");
21013828260eSStefano Zampini         }
21020c7d97c5SJed Brown 
21030c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
21043828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
21050c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
21060c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
21073828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
21083828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
21093828260eSStefano Zampini           } else {
21103828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
21113828260eSStefano Zampini           }
21120c7d97c5SJed Brown         printf("\n");
21130c7d97c5SJed Brown       }
21140c7d97c5SJed Brown 
21150c7d97c5SJed Brown       /* Scatter new decomposition for send details */
211653cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21170c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
21180c7d97c5SJed Brown       if( coarse_color == 0) {
211953cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21200c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
212153cdbc3dSStefano 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);
21220c7d97c5SJed Brown       }
21230c7d97c5SJed Brown 
21240c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
21250c7d97c5SJed Brown       //if(coarse_color == 0) {
21260c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
21270c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
21280c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
21290c7d97c5SJed Brown       //  printf("\n");
21300c7d97c5SJed Brown       //}
21310c7d97c5SJed Brown 
21320c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
21330c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
21340c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
21350c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
21360c7d97c5SJed Brown         free(coarse_subdivision);
21370c7d97c5SJed Brown         free(total_count_recv);
21380c7d97c5SJed Brown         free(total_ranks_recv);
21390c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
21400c7d97c5SJed Brown       }
21410c7d97c5SJed Brown       break;
21420c7d97c5SJed Brown     }
21430c7d97c5SJed Brown 
21440c7d97c5SJed Brown     case(REPLICATED_BDDC):
21450c7d97c5SJed Brown 
21460c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
21470c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
21480c7d97c5SJed Brown       coarse_pc_type  = PCLU;
214953cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21500c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
21510c7d97c5SJed Brown       active_rank = rank_prec_comm;
21520c7d97c5SJed Brown       break;
21530c7d97c5SJed Brown 
21540c7d97c5SJed Brown     case(PARALLEL_BDDC):
21550c7d97c5SJed Brown 
21560c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
21570c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
21580c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
215953cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21600c7d97c5SJed Brown       coarse_comm = prec_comm;
21610c7d97c5SJed Brown       active_rank = rank_prec_comm;
21620c7d97c5SJed Brown       break;
21630c7d97c5SJed Brown 
21640c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
21650c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
21660c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
21670c7d97c5SJed Brown       coarse_pc_type = PCLU;
216853cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21690c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
21700c7d97c5SJed Brown       active_rank = master_proc;
21710c7d97c5SJed Brown       break;
21720c7d97c5SJed Brown   }
21730c7d97c5SJed Brown 
21740c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
21750c7d97c5SJed Brown 
21760c7d97c5SJed Brown     case(SCATTERS_BDDC):
21770c7d97c5SJed Brown       {
21780c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
21790c7d97c5SJed Brown 
21800c7d97c5SJed Brown           PetscMPIInt send_size;
21810c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
21820c7d97c5SJed Brown           PetscInt    ii,jj;
21830c7d97c5SJed Brown           MPI_Request *requests;
21840c7d97c5SJed Brown 
21850c7d97c5SJed Brown           /* allocate auxiliary space */
21865619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
21875619798eSStefano 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);
21880c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
21890c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
21900c7d97c5SJed Brown           /* allocate stuffs for message massing */
21910c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
21920c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
21930c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
21940c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
21950c7d97c5SJed Brown           /* fill up quantities */
21960c7d97c5SJed Brown           j=0;
21970c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
21980c7d97c5SJed Brown             ii = ranks_recv[i];
21990c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
22000c7d97c5SJed Brown             localdispl2[i]=j;
22010c7d97c5SJed Brown             j+=localsizes2[i];
22020c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
22030c7d97c5SJed 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
22040c7d97c5SJed Brown           }
22050c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
22060c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22070c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22080c7d97c5SJed Brown           //printf("\n");
22090c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
22100c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
22110c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
22120c7d97c5SJed Brown           ins_local_primal_size=0;
22130c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22140c7d97c5SJed Brown             if(aux_ins_indices[i])
22150c7d97c5SJed Brown               ins_local_primal_size++;
22160c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
22170c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
22180c7d97c5SJed Brown           j=0;
22190c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22200c7d97c5SJed Brown             if(aux_ins_indices[i])
22210c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
22220c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
22230c7d97c5SJed Brown           j=0;
22240c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
22250c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
22260c7d97c5SJed Brown               aux_ins_indices[i]=-1;
22270c7d97c5SJed Brown             } else {
22280c7d97c5SJed Brown               aux_ins_indices[i]=j;
22290c7d97c5SJed Brown               j++;
22300c7d97c5SJed Brown             }
22310c7d97c5SJed Brown           }
22320c7d97c5SJed Brown 
22330c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
22340c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
22350c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
22360c7d97c5SJed Brown           //printf("\n");
22370c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
22380c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22390c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22400c7d97c5SJed Brown           //printf("\n");
22410c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
22420c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
22430c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
22440c7d97c5SJed Brown           //printf("\n");
22450c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
22460c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
22470c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
22480c7d97c5SJed 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]);
22490c7d97c5SJed Brown           //printf("\n");
22500c7d97c5SJed Brown 
22510c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
225253cdbc3dSStefano 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);
22530c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
22540c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
225553cdbc3dSStefano 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);
22560c7d97c5SJed Brown           }
225753cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
22580c7d97c5SJed Brown 
22590c7d97c5SJed Brown           //if(coarse_color == 0) {
22600c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
22610c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
22620c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
22630c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
22640c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
22650c7d97c5SJed 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]);
22660c7d97c5SJed Brown           //    printf("\n");
22670c7d97c5SJed Brown           //  }
22680c7d97c5SJed Brown           //}
22690c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
22700c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
22710c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
22720c7d97c5SJed Brown 
22730c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
22740c7d97c5SJed Brown           PetscInt row_ind,col_ind;
22750c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
22760c7d97c5SJed Brown             rr = ranks_recv[k];
22770c7d97c5SJed Brown             kk = localdispl2[k];
22780c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
22790c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
22800c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
22810c7d97c5SJed Brown             for(j=0;j<lps;j++){
22820c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
22830c7d97c5SJed Brown               for(i=0;i<lps;i++){
22840c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
22850c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
22860c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
22870c7d97c5SJed Brown               }
22880c7d97c5SJed Brown             }
22890c7d97c5SJed Brown           }
22900c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
22910c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
22920c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
22930c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
22940c7d97c5SJed Brown 
22950c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
22960c7d97c5SJed Brown           {
22970c7d97c5SJed Brown             IS coarse_IS;
229853cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
22990c7d97c5SJed Brown             coarse_comm = prec_comm;
23000c7d97c5SJed Brown             active_rank=rank_prec_comm;
23010c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
23020c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
23030c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
23040c7d97c5SJed Brown           }
23050c7d97c5SJed Brown         }
23060c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
23070c7d97c5SJed Brown           /* arrays for values insertion */
23080c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
23090c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23100c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23110c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23120c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
23130c7d97c5SJed 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];
23140c7d97c5SJed Brown           }
23150c7d97c5SJed Brown         }
23160c7d97c5SJed Brown         break;
23170c7d97c5SJed Brown 
23180c7d97c5SJed Brown     }
23190c7d97c5SJed Brown 
23200c7d97c5SJed Brown     case(GATHERS_BDDC):
23210c7d97c5SJed Brown       {
23220c7d97c5SJed Brown 
23230c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
23240c7d97c5SJed Brown 
23250c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23260c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23270c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
23280c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23290c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
23300c7d97c5SJed Brown           /* arrays for values insertion */
23310c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
23320c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23330c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23340c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
23350c7d97c5SJed Brown           localdispl2[0]=0;
23360c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
23370c7d97c5SJed Brown           j=0;
23380c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
23390c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
23400c7d97c5SJed Brown         }
23410c7d97c5SJed Brown 
23420c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
23430c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
23440c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
234553cdbc3dSStefano 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);
234653cdbc3dSStefano 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);
23470c7d97c5SJed Brown         } else {
234853cdbc3dSStefano 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);
234953cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
23500c7d97c5SJed Brown         }
23510c7d97c5SJed Brown 
23520c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
23530c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23540c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
23550c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23560c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
23570c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
23580c7d97c5SJed Brown           }
23590c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
23600c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
23610c7d97c5SJed Brown             offset2=localdispl2[k];
23620c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
23630c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
23640c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
23650c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
23660c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
23670c7d97c5SJed Brown               }
23680c7d97c5SJed Brown             }
23690c7d97c5SJed Brown           }
23700c7d97c5SJed Brown         }
23710c7d97c5SJed Brown         break;
23720c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
23730c7d97c5SJed Brown   }
23740c7d97c5SJed Brown 
23750c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
23760c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
23770c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
23780c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
23790c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
23800c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
23813b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
23820c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
23833b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
23840c7d97c5SJed Brown     } else {
23850c7d97c5SJed Brown       Mat matis_coarse_local_mat;
23860c7d97c5SJed Brown       ierr = MatCreateIS(coarse_comm,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
23873b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
23880c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
23893b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
23900c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2391a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
23920c7d97c5SJed Brown     }
2393a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
23940c7d97c5SJed 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);
23950c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23960c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23970c7d97c5SJed Brown     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
23980c7d97c5SJed Brown       Mat matis_coarse_local_mat;
23990c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
24000c7d97c5SJed Brown       ierr = MatSetBlockSize(matis_coarse_local_mat,bs);CHKERRQ(ierr);
24010c7d97c5SJed Brown     }
24020c7d97c5SJed Brown 
24030c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
24040c7d97c5SJed Brown     /* Preconditioner for coarse problem */
240553cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
240653cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
240753cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
24083b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
240953cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
241053cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
241153cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
24120c7d97c5SJed Brown     /* Allow user's customization */
241353cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24140c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
241553cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2416e269702eSStefano Zampini       if(dbg_flag) {
2417e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2418e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2419e269702eSStefano Zampini       }
242053cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
242153cdbc3dSStefano Zampini     }
242253cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
24235619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
24245619798eSStefano Zampini       if(dbg_flag) {
24255619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
24265619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24275619798eSStefano Zampini       }
24285619798eSStefano Zampini     }
24290c7d97c5SJed Brown   }
24300c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
24310c7d97c5SJed Brown      IS local_IS,global_IS;
24320c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
24330c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
24340c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
24350c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
24360c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
24370c7d97c5SJed Brown   }
24380c7d97c5SJed Brown 
24390c7d97c5SJed Brown 
24403b03a366Sstefano_zampini   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
24413b03a366Sstefano_zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
24420c7d97c5SJed Brown     PetscScalar m_one=-1.0;
24435619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
24443b03a366Sstefano_zampini     const KSPType check_ksp_type=KSPGMRES;
24450c7d97c5SJed Brown 
24465619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
24473b03a366Sstefano_zampini     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2448d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
24495619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
24505619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2451d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2452d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2453d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2454d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2455d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
24563b03a366Sstefano_zampini     if(dbg_flag) {
24575619798eSStefano Zampini       kappa_2=lambda_max/lambda_min;
24585619798eSStefano Zampini       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2459d49ef151SStefano Zampini       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2460d49ef151SStefano Zampini       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
24613b03a366Sstefano_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);
2462e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2463e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
24643b03a366Sstefano_zampini     }
24655619798eSStefano Zampini     /* restore coarse ksp to default values */
2466d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
24675619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
24683b03a366Sstefano_zampini     ierr = KSPChebychevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
24693b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
24705619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24715619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
247253cdbc3dSStefano Zampini   }
24730c7d97c5SJed Brown 
24740c7d97c5SJed Brown   /* free data structures no longer needed */
24750c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
24760c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
24770c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
24780c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
24790c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
24800c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
24810c7d97c5SJed Brown 
24820c7d97c5SJed Brown   PetscFunctionReturn(0);
24830c7d97c5SJed Brown }
24840c7d97c5SJed Brown 
24850c7d97c5SJed Brown #undef __FUNCT__
24860c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
248753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
24880c7d97c5SJed Brown {
24890c7d97c5SJed Brown 
24900c7d97c5SJed Brown   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
24910c7d97c5SJed Brown   PC_IS         *pcis = (PC_IS*)pc->data;
24920c7d97c5SJed Brown   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
24930c7d97c5SJed Brown   PCBDDCGraph mat_graph;
24940c7d97c5SJed Brown   Mat         mat_adj;
24953b03a366Sstefano_zampini   PetscInt    **neighbours_set;
2496a0ba757dSStefano Zampini   PetscInt    *queue_in_global_numbering;
24973b03a366Sstefano_zampini   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
24983b03a366Sstefano_zampini   PetscInt    total_counts,nodes_touched=0,where_values=1,vertex_size;
24993b03a366Sstefano_zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
25003b03a366Sstefano_zampini   PetscBool   same_set,flg_row;
25013b03a366Sstefano_zampini   PetscBool   symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2502a0ba757dSStefano Zampini   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
25033b03a366Sstefano_zampini   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
25043b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
25053b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
25060c7d97c5SJed Brown 
25070c7d97c5SJed Brown   PetscFunctionBegin;
2508a0ba757dSStefano Zampini   /* allocate and initialize needed graph structure */
25090c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
25100c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2511a0ba757dSStefano Zampini   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2512a0ba757dSStefano Zampini   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
25130c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2514a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2515a0ba757dSStefano 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);
2516a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2517a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2518a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2519a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2520a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25213828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
25223828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2523a0ba757dSStefano Zampini 
25249c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
25259c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
25269c0446d6SStefano Zampini     PetscInt *is_indices;
25279c0446d6SStefano Zampini     PetscInt is_size;
25289c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
25299c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
25309c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25319c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
25329c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
25339c0446d6SStefano Zampini       }
25349c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25359c0446d6SStefano Zampini     }
25363b03a366Sstefano_zampini     /* use mat block size as vertex size */
25373b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
25383b03a366Sstefano_zampini   } else { /* otherwise it assumes a constant block size */
2539a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
25400c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
25410c7d97c5SJed Brown       for(s=0;s<bs;s++) {
25420c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
25430c7d97c5SJed Brown       }
25440c7d97c5SJed Brown     }
25453b03a366Sstefano_zampini     vertex_size=1;
25469c0446d6SStefano Zampini   }
25473b03a366Sstefano_zampini   /* count number of neigh per node */
25480c7d97c5SJed Brown   total_counts=0;
25493b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
25500c7d97c5SJed Brown     s=pcis->n_shared[i];
25510c7d97c5SJed Brown     total_counts+=s;
255253cdbc3dSStefano Zampini     for(j=0;j<s;j++){
25530c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
25540c7d97c5SJed Brown     }
25550c7d97c5SJed Brown   }
25563b03a366Sstefano_zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
255753cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
25589c0446d6SStefano Zampini     ierr = ISGetSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
255953cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
256053cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
256153cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
25623b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
256353cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
25640c7d97c5SJed Brown         total_counts++;
25650c7d97c5SJed Brown       }
25660c7d97c5SJed Brown     }
25670c7d97c5SJed Brown   }
25683b03a366Sstefano_zampini   /* allocate space for storing the set of neighbours of each node */
256953cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
25703b03a366Sstefano_zampini   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr); }
257153cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2572a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25733b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
25740c7d97c5SJed Brown     s=pcis->n_shared[i];
25750c7d97c5SJed Brown     for(j=0;j<s;j++) {
25760c7d97c5SJed Brown       k=pcis->shared[i][j];
257753cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
25780c7d97c5SJed Brown       mat_graph->count[k]+=1;
25790c7d97c5SJed Brown     }
25800c7d97c5SJed Brown   }
25813b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
258253cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
258353cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
258453cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
25853b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
25863b03a366Sstefano_zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1;
258753cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
25880c7d97c5SJed Brown       }
25890c7d97c5SJed Brown     }
259053cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
25910c7d97c5SJed Brown   }
25923b03a366Sstefano_zampini   /* sort set of sharing subdomains (needed for comparison below) */
259353cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
25943b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
25953b03a366Sstefano_zampini   if(pcbddc->DirichletBoundaries) {
25963b03a366Sstefano_zampini     ierr = ISGetSize(pcbddc->DirichletBoundaries,&dirichlet_bsize);CHKERRQ(ierr);
25973b03a366Sstefano_zampini     ierr = ISGetIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
25983b03a366Sstefano_zampini     for(i=0;i<dirichlet_bsize;i++){
25993b03a366Sstefano_zampini       mat_graph->count[dirichlet_nodes[i]]=0;
26003b03a366Sstefano_zampini     }
26013b03a366Sstefano_zampini     ierr = ISRestoreIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
26023b03a366Sstefano_zampini   }
26030c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
26043b03a366Sstefano_zampini     if(!mat_graph->count[i]){  /* interior nodes */
26050c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
26060c7d97c5SJed Brown       mat_graph->where[i]=0;
26070c7d97c5SJed Brown       nodes_touched++;
26080c7d97c5SJed Brown     }
26090c7d97c5SJed Brown   }
26100c7d97c5SJed Brown   mat_graph->ncmps = 0;
26110c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2612a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
26130c7d97c5SJed Brown     i=0;
26140c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
26150c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2616a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
26170c7d97c5SJed Brown     nodes_touched++;
2618a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
26190c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2620a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
26210c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2622a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
26230c7d97c5SJed Brown         same_set=PETSC_TRUE;
26240c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
262553cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
26260c7d97c5SJed Brown             same_set=PETSC_FALSE;
26270c7d97c5SJed Brown           }
26280c7d97c5SJed Brown         }
2629a0ba757dSStefano Zampini         /* I found a friend of mine */
26300c7d97c5SJed Brown         if(same_set) {
2631a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
26320c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
26330c7d97c5SJed Brown           nodes_touched++;
26340c7d97c5SJed Brown         }
26350c7d97c5SJed Brown       }
26360c7d97c5SJed Brown     }
2637a0ba757dSStefano Zampini     where_values++;
26380c7d97c5SJed Brown   }
2639a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2640a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2641a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2642a0ba757dSStefano Zampini   if(where_values) {
2643a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
26443b03a366Sstefano_zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2645a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2646a0ba757dSStefano 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);
2647a0ba757dSStefano 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);
2648a0ba757dSStefano Zampini     }
2649a0ba757dSStefano Zampini   }
2650a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2651a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
26523b03a366Sstefano_zampini     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
26533b03a366Sstefano_zampini     if(mat_graph->where_ncmps[i]>1) {
2654a0ba757dSStefano Zampini       adapt_interface=1;
2655a0ba757dSStefano Zampini       break;
2656a0ba757dSStefano Zampini     }
2657a0ba757dSStefano Zampini   }
2658a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2659a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
26600c7d97c5SJed Brown 
26613b03a366Sstefano_zampini     printf("Adapting Interface\n");
26623b03a366Sstefano_zampini 
2663a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2664a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2665a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2666a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2667a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2668a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2669a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2670a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2671a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2672a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2673a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2674a0ba757dSStefano Zampini     MPI_Request *send_requests;
2675a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2676a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2677a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2678a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2679a0ba757dSStefano Zampini     PetscInt *add_to_where;
2680a0ba757dSStefano Zampini 
2681a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2682a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2683a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2684a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2685a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2686a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2687a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2688a0ba757dSStefano Zampini       j=0;
2689a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2690a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
26913b03a366Sstefano_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  */
26923b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2693a0ba757dSStefano Zampini     }
2694a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2695a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2696a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2697a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2698a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2699a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2700a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2701a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2702a0ba757dSStefano Zampini     }
2703a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2704a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2705a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2706a0ba757dSStefano Zampini       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2707a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2708a0ba757dSStefano 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);
2709a0ba757dSStefano 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);
2710a0ba757dSStefano Zampini         sum_requests++;
2711a0ba757dSStefano Zampini       }
2712a0ba757dSStefano Zampini     }
2713a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2714a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2715a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2716a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2717a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2718a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2719a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
27203b03a366Sstefano_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 */
27213b03a366Sstefano_zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2722a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2723a0ba757dSStefano Zampini           break;
2724a0ba757dSStefano Zampini         }
2725a0ba757dSStefano Zampini       }
2726a0ba757dSStefano Zampini     }
2727a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2728a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2729a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2730a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2731a0ba757dSStefano Zampini     sum_requests=0;
2732a0ba757dSStefano Zampini     start_of_send=0;
2733a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2734a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2735a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2736a0ba757dSStefano Zampini         size_of_send=0;
2737a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2738a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2739a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2740a0ba757dSStefano Zampini             size_of_send+=1;
2741a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2742a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2743a0ba757dSStefano Zampini             }
2744a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2745a0ba757dSStefano Zampini           }
2746a0ba757dSStefano Zampini         }
2747a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2748a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2749a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2750a0ba757dSStefano 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);
2751a0ba757dSStefano 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);
2752a0ba757dSStefano Zampini           sum_requests++;
2753a0ba757dSStefano Zampini         }
2754a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2755a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2756a0ba757dSStefano Zampini       }
2757a0ba757dSStefano Zampini     }
2758a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2759a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2760a0ba757dSStefano Zampini     buffer_size=0;
2761a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2762a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2763a0ba757dSStefano Zampini     /* now exchange the data */
2764a0ba757dSStefano Zampini     start_of_recv=0;
2765a0ba757dSStefano Zampini     start_of_send=0;
2766a0ba757dSStefano Zampini     sum_requests=0;
2767a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2768a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2769a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2770a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2771a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2772a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2773a0ba757dSStefano 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);
2774a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2775a0ba757dSStefano 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);
2776a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2777a0ba757dSStefano Zampini           sum_requests++;
2778a0ba757dSStefano Zampini         }
2779a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2780a0ba757dSStefano Zampini       }
2781a0ba757dSStefano Zampini     }
2782a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2783a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2784a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2785a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2786a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2787a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2788a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2789a0ba757dSStefano Zampini        j+=k;
2790a0ba757dSStefano Zampini     }
2791a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2792a0ba757dSStefano Zampini     start_of_recv=0;
2793a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2794a0ba757dSStefano Zampini     global_where_counter=0;
2795a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2796a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2797a0ba757dSStefano Zampini         temp_buffer_size=0;
2798a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2799a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2800a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2801a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2802a0ba757dSStefano Zampini             temp_buffer_size++;
2803a0ba757dSStefano Zampini           } else {
2804a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2805a0ba757dSStefano Zampini           }
2806a0ba757dSStefano Zampini         }
2807a0ba757dSStefano Zampini         /* allocate some temporary space */
2808a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2809a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2810a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2811a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2812a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2813a0ba757dSStefano Zampini         }
2814a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2815a0ba757dSStefano Zampini            temp buffer structure:
2816a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2817a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2818a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2819a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2820a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2821a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2822a0ba757dSStefano Zampini              [ 0, 0, 0;
2823a0ba757dSStefano Zampini                0, 0, 1;
2824a0ba757dSStefano Zampini                1, 1, 2;
2825a0ba757dSStefano Zampini                1, 1, 2;
2826a0ba757dSStefano Zampini                0, 1, 0; ];
2827a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2828a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2829a0ba757dSStefano Zampini                                                                                                                                    */
2830a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2831a0ba757dSStefano Zampini           ins_val=0;
2832a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2833a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2834a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2835a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2836a0ba757dSStefano Zampini             }
2837a0ba757dSStefano Zampini             buffer_size+=k;
2838a0ba757dSStefano Zampini             ins_val++;
2839a0ba757dSStefano Zampini           }
2840a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2841a0ba757dSStefano Zampini           sum_requests++;
2842a0ba757dSStefano Zampini         }
2843a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2844a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2845a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2846a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2847a0ba757dSStefano Zampini             global_where_counter++;
2848a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2849a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2850a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2851a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2852a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2853a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2854a0ba757dSStefano Zampini                   break;
2855a0ba757dSStefano Zampini                 }
2856a0ba757dSStefano Zampini               }
2857a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2858a0ba757dSStefano Zampini             }
2859a0ba757dSStefano Zampini           }
2860a0ba757dSStefano Zampini         }
2861a0ba757dSStefano Zampini         /* insert new data in where array */
2862a0ba757dSStefano Zampini         temp_buffer_size=0;
2863a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2864a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2865a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2866a0ba757dSStefano Zampini             temp_buffer_size++;
2867a0ba757dSStefano Zampini           }
2868a0ba757dSStefano Zampini         }
2869a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2870a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2871a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2872a0ba757dSStefano Zampini       }
2873a0ba757dSStefano Zampini     }
2874a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2875a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2876a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2877a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2878a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2879a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2880a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2881a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2882a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2883a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2884a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2885a0ba757dSStefano Zampini     if(global_where_counter) {
2886a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2887a0ba757dSStefano Zampini       global_where_counter=0;
2888a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
2889a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2890a0ba757dSStefano Zampini           global_where_counter++;
2891a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
2892a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2893a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
2894a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
2895a0ba757dSStefano Zampini             }
2896a0ba757dSStefano Zampini           }
2897a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
2898a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
2899a0ba757dSStefano Zampini         }
2900a0ba757dSStefano Zampini       }
2901a0ba757dSStefano Zampini       where_values=global_where_counter;
2902a0ba757dSStefano Zampini     }
2903a0ba757dSStefano Zampini     if(global_where_counter) {
2904a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2905a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2906a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2907a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2908a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2909a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
2910a0ba757dSStefano 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);
2911a0ba757dSStefano 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);
2912a0ba757dSStefano Zampini       }
2913a0ba757dSStefano Zampini     }
29143b03a366Sstefano_zampini   } /* Finished adapting interface */
29150c7d97c5SJed Brown   PetscInt nfc=0;
29160c7d97c5SJed Brown   PetscInt nec=0;
29170c7d97c5SJed Brown   PetscInt nvc=0;
29183b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
29190c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
29203b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
29213b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
29220c7d97c5SJed Brown         nfc++;
29233b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
29243b03a366Sstefano_zampini         nec++;
29253b03a366Sstefano_zampini       }
29260c7d97c5SJed Brown     } else {
29273b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
29283b03a366Sstefano_zampini     }
29293b03a366Sstefano_zampini   }
29303b03a366Sstefano_zampini 
29313b03a366Sstefano_zampini   if(!nec) { /* we are in a 2d case -> no faces, only edges */
29323b03a366Sstefano_zampini     nec = nfc;
29333b03a366Sstefano_zampini     nfc = 0;
29343b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
29353b03a366Sstefano_zampini   }
29363b03a366Sstefano_zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set.
29373b03a366Sstefano_zampini      Reusing space allocated in mat_graph->where for creating IS objects */
29383b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
29393b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
29403b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
29413b03a366Sstefano_zampini   }
29423b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
29433b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
29443b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
29453b03a366Sstefano_zampini   }
29463b03a366Sstefano_zampini   nfc=0;
29473b03a366Sstefano_zampini   nec=0;
29483b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
29493b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
29503b03a366Sstefano_zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
29513b03a366Sstefano_zampini         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
29523b03a366Sstefano_zampini       }
29533b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
29543b03a366Sstefano_zampini         if(twodim_flag) {
29553b03a366Sstefano_zampini           if(use_edges) {
29563b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
29573b03a366Sstefano_zampini             nec++;
29583b03a366Sstefano_zampini           }
29593b03a366Sstefano_zampini         } else {
29603b03a366Sstefano_zampini           if(use_faces) {
29613b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
29623b03a366Sstefano_zampini             nfc++;
29633b03a366Sstefano_zampini           }
29643b03a366Sstefano_zampini         }
29653b03a366Sstefano_zampini       } else {
29663b03a366Sstefano_zampini         if(use_edges) {
29673b03a366Sstefano_zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
29680c7d97c5SJed Brown           nec++;
29690c7d97c5SJed Brown         }
29700c7d97c5SJed Brown       }
29710c7d97c5SJed Brown     }
29723b03a366Sstefano_zampini   }
29733b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
29743b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
29753b03a366Sstefano_zampini   nvc=0;
29760c7d97c5SJed Brown   if( !pcbddc->constraints_flag ) {
29773b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
29783b03a366Sstefano_zampini       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
29793b03a366Sstefano_zampini         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
29803b03a366Sstefano_zampini           mat_graph->where[nvc]=mat_graph->queue[j];
29810c7d97c5SJed Brown           nvc++;
29820c7d97c5SJed Brown         }
29830c7d97c5SJed Brown       }
29840c7d97c5SJed Brown     }
29850c7d97c5SJed Brown   }
2986a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
29873b03a366Sstefano_zampini   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
29883b03a366Sstefano_zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
29890c7d97c5SJed Brown 
2990e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
2991e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
2992e269702eSStefano Zampini 
2993d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2994d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2995d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2996a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
2997a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2998e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
2999a0ba757dSStefano 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);
3000e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
3001a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
3002e269702eSStefano Zampini       }
3003a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
30043b03a366Sstefano_zampini     }
3005d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
30060c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
30073b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
30083b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
30090c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
30103828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
30110c7d97c5SJed Brown       }
30120c7d97c5SJed Brown     }
30133b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);*/
30143b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
30153b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
30163b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3017d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
30180c7d97c5SJed Brown   }
30190c7d97c5SJed Brown 
3020a0ba757dSStefano Zampini   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
3021a0ba757dSStefano Zampini   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
30220c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
3023a0ba757dSStefano Zampini   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
3024a0ba757dSStefano Zampini   /* Free graph structure */
30250c7d97c5SJed Brown   if(mat_graph->nvtxs){
3026a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
3027a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
3028a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3029a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3030a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
30310c7d97c5SJed Brown   }
30320c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
30330c7d97c5SJed Brown 
30340c7d97c5SJed Brown   PetscFunctionReturn(0);
30350c7d97c5SJed Brown 
30360c7d97c5SJed Brown }
30370c7d97c5SJed Brown 
30380c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
30390c7d97c5SJed Brown 
30400c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
30410c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
30420c7d97c5SJed Brown 
30430c7d97c5SJed Brown #undef __FUNCT__
30440c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
30459c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
30460c7d97c5SJed Brown {
30470c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
30480c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
30490c7d97c5SJed Brown   PetscInt *cptr;
30500c7d97c5SJed Brown   PetscBool *touched;
30510c7d97c5SJed Brown 
30520c7d97c5SJed Brown   PetscFunctionBegin;
30530c7d97c5SJed Brown 
30540c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
30550c7d97c5SJed Brown   xadj    = graph->xadj;
30560c7d97c5SJed Brown   adjncy  = graph->adjncy;
30570c7d97c5SJed Brown   where   = graph->where;
30580c7d97c5SJed Brown   touched = graph->touched;
30590c7d97c5SJed Brown   queue   = graph->queue;
30600c7d97c5SJed Brown   cptr    = graph->cptr;
30610c7d97c5SJed Brown 
30620c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
30630c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
30640c7d97c5SJed Brown 
30650c7d97c5SJed Brown   cum_queue=0;
30660c7d97c5SJed Brown   ncmps=0;
30670c7d97c5SJed Brown 
30680c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
3069a0ba757dSStefano Zampini     pid = n+1;
30700c7d97c5SJed Brown     nleft = 0;
30710c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
30720c7d97c5SJed Brown       if (where[i] == pid)
30730c7d97c5SJed Brown         nleft++;
30740c7d97c5SJed Brown     }
30750c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
30760c7d97c5SJed Brown       if (where[i] == pid)
30770c7d97c5SJed Brown         break;
30780c7d97c5SJed Brown     }
30790c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
30800c7d97c5SJed Brown     queue[cum_queue] = i;
30810c7d97c5SJed Brown     first = 0; last = 1;
30820c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
30830c7d97c5SJed Brown     ncmps_pid = 0;
30840c7d97c5SJed Brown     while (first != nleft) {
30850c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
30860c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
30870c7d97c5SJed Brown         ncmps_pid++;
30880c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
30890c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
30900c7d97c5SJed Brown             break;
30910c7d97c5SJed Brown         }
30920c7d97c5SJed Brown         queue[cum_queue+last] = i;
30930c7d97c5SJed Brown         last++;
30940c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
30950c7d97c5SJed Brown       }
30960c7d97c5SJed Brown       i = queue[cum_queue+first];
30970c7d97c5SJed Brown       first++;
30980c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
30990c7d97c5SJed Brown         k = adjncy[j];
31000c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
31010c7d97c5SJed Brown           queue[cum_queue+last] = k;
31020c7d97c5SJed Brown           last++;
31030c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
31040c7d97c5SJed Brown         }
31050c7d97c5SJed Brown       }
31060c7d97c5SJed Brown     }
31070c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
31080c7d97c5SJed Brown     ncmps_pid++;
31090c7d97c5SJed Brown     cum_queue=cptr[ncmps];
3110a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
31110c7d97c5SJed Brown   }
31120c7d97c5SJed Brown   graph->ncmps = ncmps;
31130c7d97c5SJed Brown 
31140c7d97c5SJed Brown   PetscFunctionReturn(0);
31150c7d97c5SJed Brown }
31160c7d97c5SJed Brown 
3117