xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 831a100d645ee317f94a2a60304e7ccc62bfb9ae)
153cdbc3dSStefano Zampini /* TODOLIST
2d11ae9bbSstefano_zampini    DofSplitting and DM attached to pc.
33b03a366Sstefano_zampini    Exact solvers: Solve local saddle point directly for very hard problems
4*831a100dSStefano Zampini      - change prec_type to switch_inexact_prec_type
5*831a100dSStefano Zampini      - add bool solve_exact_saddle_point slot to pdbddc data
63b03a366Sstefano_zampini    Inexact solvers: global preconditioner application is ready, ask to developers (Jed?) on how to best implement Dohrmann's approach (PCSHELL?)
7a0ba757dSStefano Zampini    change how to deal with the coarse problem (PCBDDCSetCoarseEnvironment):
8a0ba757dSStefano Zampini      - mind the problem with coarsening_factor
9a0ba757dSStefano Zampini      - simplify coarse problem structure -> PCBDDC or PCREDUDANT, nothing else -> same comm for all levels?
10a0ba757dSStefano Zampini      - remove coarse enums and allow use of PCBDDCGetCoarseKSP
11a0ba757dSStefano Zampini      - remove metis dependency -> use MatPartitioning for multilevel -> Assemble serial adjacency in ManageLocalBoundaries?
123b03a366Sstefano_zampini      - Add levels' slot to bddc data structure and associated Set/Get functions
13a0ba757dSStefano Zampini    code refactoring:
14a0ba757dSStefano Zampini      - pick up better names for static functions
153b03a366Sstefano_zampini    check log_summary for leaking (actually: 1 Vector per level )
16a0ba757dSStefano Zampini    change options structure:
17a0ba757dSStefano Zampini      - insert BDDC into MG framework?
18a0ba757dSStefano Zampini    provide other ops? Ask to developers
19a0ba757dSStefano Zampini    remove all unused printf
20a0ba757dSStefano Zampini    remove // commments and adhere to PETSc code requirements
21a0ba757dSStefano Zampini    man pages
2253cdbc3dSStefano Zampini */
230c7d97c5SJed Brown 
2453cdbc3dSStefano Zampini /* ----------------------------------------------------------------------------------------------------------------------------------------------
250c7d97c5SJed Brown    Implementation of BDDC preconditioner based on:
260c7d97c5SJed Brown    C. Dohrmann "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
2753cdbc3dSStefano Zampini    ---------------------------------------------------------------------------------------------------------------------------------------------- */
2853cdbc3dSStefano Zampini 
2953cdbc3dSStefano Zampini #include "bddc.h" /*I "petscpc.h" I*/  /* includes for fortran wrappers */
303b03a366Sstefano_zampini #include <petscblaslapack.h>
310c7d97c5SJed Brown 
320c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
330c7d97c5SJed Brown #undef __FUNCT__
340c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
350c7d97c5SJed Brown PetscErrorCode PCSetFromOptions_BDDC(PC pc)
360c7d97c5SJed Brown {
370c7d97c5SJed Brown   PC_BDDC         *pcbddc = (PC_BDDC*)pc->data;
380c7d97c5SJed Brown   PetscErrorCode ierr;
390c7d97c5SJed Brown 
400c7d97c5SJed Brown   PetscFunctionBegin;
410c7d97c5SJed Brown   ierr = PetscOptionsHead("BDDC options");CHKERRQ(ierr);
420c7d97c5SJed Brown   /* Verbose debugging of main data structures */
43e269702eSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_check_all"       ,"Verbose (debugging) output for PCBDDC"                       ,"none",pcbddc->dbg_flag      ,&pcbddc->dbg_flag      ,PETSC_NULL);CHKERRQ(ierr);
440c7d97c5SJed Brown   /* Some customization for default primal space */
450c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_vertices_only"   ,"Use vertices only in coarse space (i.e. discard constraints)","none",pcbddc->vertices_flag   ,&pcbddc->vertices_flag   ,PETSC_NULL);CHKERRQ(ierr);
460c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_constraints_only","Use constraints only in coarse space (i.e. discard vertices)","none",pcbddc->constraints_flag,&pcbddc->constraints_flag,PETSC_NULL);CHKERRQ(ierr);
470c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_faces_only"      ,"Use faces only in coarse space (i.e. discard edges)"         ,"none",pcbddc->faces_flag      ,&pcbddc->faces_flag      ,PETSC_NULL);CHKERRQ(ierr);
480c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_edges_only"      ,"Use edges only in coarse space (i.e. discard faces)"         ,"none",pcbddc->edges_flag      ,&pcbddc->edges_flag      ,PETSC_NULL);CHKERRQ(ierr);
490c7d97c5SJed Brown   /* Coarse solver context */
500c7d97c5SJed Brown   static const char *avail_coarse_problems[] = {"sequential","replicated","parallel","multilevel",""}; //order of choiches depends on ENUM defined in bddc.h
510c7d97c5SJed Brown   ierr = PetscOptionsEnum("-pc_bddc_coarse_problem_type","Set coarse problem type","none",avail_coarse_problems,(PetscEnum)pcbddc->coarse_problem_type,(PetscEnum*)&pcbddc->coarse_problem_type,PETSC_NULL);CHKERRQ(ierr);
520c7d97c5SJed Brown   /* Two different application of BDDC to the whole set of dofs, internal and interface */
530c7d97c5SJed Brown   ierr = PetscOptionsBool("-pc_bddc_switch_preconditioning_type","Switch between M_2 (default) and M_3 preconditioners (as defined by Dohrmann)","none",pcbddc->prec_type,&pcbddc->prec_type,PETSC_NULL);CHKERRQ(ierr);
540c7d97c5SJed Brown   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,PETSC_NULL);CHKERRQ(ierr);
550c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
560c7d97c5SJed Brown   PetscFunctionReturn(0);
570c7d97c5SJed Brown }
580c7d97c5SJed Brown 
590c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
600c7d97c5SJed Brown EXTERN_C_BEGIN
610c7d97c5SJed Brown #undef __FUNCT__
620c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType_BDDC"
6353cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetCoarseProblemType_BDDC(PC pc, CoarseProblemType CPT)
640c7d97c5SJed Brown {
650c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
660c7d97c5SJed Brown 
670c7d97c5SJed Brown   PetscFunctionBegin;
680c7d97c5SJed Brown   pcbddc->coarse_problem_type = CPT;
690c7d97c5SJed Brown   PetscFunctionReturn(0);
700c7d97c5SJed Brown }
710c7d97c5SJed Brown EXTERN_C_END
720c7d97c5SJed Brown 
730c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
740c7d97c5SJed Brown #undef __FUNCT__
750c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetCoarseProblemType"
7653cdbc3dSStefano Zampini /*@
779c0446d6SStefano Zampini  PCBDDCSetCoarseProblemType - Set coarse problem type in PCBDDC.
7853cdbc3dSStefano Zampini 
799c0446d6SStefano Zampini    Not collective
8053cdbc3dSStefano Zampini 
8153cdbc3dSStefano Zampini    Input Parameters:
8253cdbc3dSStefano Zampini +  pc - the preconditioning context
8353cdbc3dSStefano Zampini -  CoarseProblemType - pick a better name and explain what this is
8453cdbc3dSStefano Zampini 
8553cdbc3dSStefano Zampini    Level: intermediate
8653cdbc3dSStefano Zampini 
8753cdbc3dSStefano Zampini    Notes:
889c0446d6SStefano Zampini    Not collective but all procs must call this.
8953cdbc3dSStefano Zampini 
9053cdbc3dSStefano Zampini .seealso: PCBDDC
9153cdbc3dSStefano Zampini @*/
920c7d97c5SJed Brown PetscErrorCode PCBDDCSetCoarseProblemType(PC pc, CoarseProblemType CPT)
930c7d97c5SJed Brown {
940c7d97c5SJed Brown   PetscErrorCode ierr;
950c7d97c5SJed Brown 
960c7d97c5SJed Brown   PetscFunctionBegin;
970c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
980c7d97c5SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseProblemType_C",(PC,CoarseProblemType),(pc,CPT));CHKERRQ(ierr);
990c7d97c5SJed Brown   PetscFunctionReturn(0);
1000c7d97c5SJed Brown }
1010c7d97c5SJed Brown 
1020c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1030c7d97c5SJed Brown EXTERN_C_BEGIN
1040c7d97c5SJed Brown #undef __FUNCT__
1053b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
1063b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
1073b03a366Sstefano_zampini {
1083b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
1093b03a366Sstefano_zampini   PetscErrorCode ierr;
1103b03a366Sstefano_zampini 
1113b03a366Sstefano_zampini   PetscFunctionBegin;
1123b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1133b03a366Sstefano_zampini   ierr = ISDuplicate(DirichletBoundaries,&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1143b03a366Sstefano_zampini   ierr = ISCopy(DirichletBoundaries,pcbddc->DirichletBoundaries);CHKERRQ(ierr);
1153b03a366Sstefano_zampini   PetscFunctionReturn(0);
1163b03a366Sstefano_zampini }
1173b03a366Sstefano_zampini EXTERN_C_END
1183b03a366Sstefano_zampini 
1193b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1203b03a366Sstefano_zampini #undef __FUNCT__
1213b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
1223b03a366Sstefano_zampini /*@
1233b03a366Sstefano_zampini  PCBDDCSetDirichletBoundaries - Set index set defining subdomain part of
1243b03a366Sstefano_zampini                               Dirichlet boundaries for the global problem.
1253b03a366Sstefano_zampini 
1263b03a366Sstefano_zampini    Not collective
1273b03a366Sstefano_zampini 
1283b03a366Sstefano_zampini    Input Parameters:
1293b03a366Sstefano_zampini +  pc - the preconditioning context
1303b03a366Sstefano_zampini -  DirichletBoundaries - sequential index set defining the subdomain part of Dirichlet boundaries (can be PETSC_NULL)
1313b03a366Sstefano_zampini 
1323b03a366Sstefano_zampini    Level: intermediate
1333b03a366Sstefano_zampini 
1343b03a366Sstefano_zampini    Notes:
1353b03a366Sstefano_zampini    The sequential IS is copied; the user must destroy the IS object passed in.
1363b03a366Sstefano_zampini 
1373b03a366Sstefano_zampini .seealso: PCBDDC
1383b03a366Sstefano_zampini @*/
1393b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
1403b03a366Sstefano_zampini {
1413b03a366Sstefano_zampini   PetscErrorCode ierr;
1423b03a366Sstefano_zampini 
1433b03a366Sstefano_zampini   PetscFunctionBegin;
1443b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
1453b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
1463b03a366Sstefano_zampini   PetscFunctionReturn(0);
1473b03a366Sstefano_zampini }
1483b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
1493b03a366Sstefano_zampini EXTERN_C_BEGIN
1503b03a366Sstefano_zampini #undef __FUNCT__
1510c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
15253cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
1530c7d97c5SJed Brown {
1540c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
15553cdbc3dSStefano Zampini   PetscErrorCode ierr;
1560c7d97c5SJed Brown 
1570c7d97c5SJed Brown   PetscFunctionBegin;
15853cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
15953cdbc3dSStefano Zampini   ierr = ISDuplicate(NeumannBoundaries,&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
16053cdbc3dSStefano Zampini   ierr = ISCopy(NeumannBoundaries,pcbddc->NeumannBoundaries);CHKERRQ(ierr);
1610c7d97c5SJed Brown   PetscFunctionReturn(0);
1620c7d97c5SJed Brown }
1630c7d97c5SJed Brown EXTERN_C_END
1640c7d97c5SJed Brown 
1650c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
1660c7d97c5SJed Brown #undef __FUNCT__
1670c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
16857527edcSJed Brown /*@
16953cdbc3dSStefano Zampini  PCBDDCSetNeumannBoundaries - Set index set defining subdomain part of
17053cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
17157527edcSJed Brown 
1729c0446d6SStefano Zampini    Not collective
17357527edcSJed Brown 
17457527edcSJed Brown    Input Parameters:
17557527edcSJed Brown +  pc - the preconditioning context
1769c0446d6SStefano Zampini -  NeumannBoundaries - sequential index set defining the subdomain part of Neumann boundaries (can be PETSC_NULL)
17757527edcSJed Brown 
17857527edcSJed Brown    Level: intermediate
17957527edcSJed Brown 
18057527edcSJed Brown    Notes:
1819c0446d6SStefano Zampini    The sequential IS is copied; the user must destroy the IS object passed in.
18257527edcSJed Brown 
18357527edcSJed Brown .seealso: PCBDDC
18457527edcSJed Brown @*/
18553cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
1860c7d97c5SJed Brown {
1870c7d97c5SJed Brown   PetscErrorCode ierr;
1880c7d97c5SJed Brown 
1890c7d97c5SJed Brown   PetscFunctionBegin;
1900c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
19153cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
19253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
19353cdbc3dSStefano Zampini }
19453cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
19553cdbc3dSStefano Zampini EXTERN_C_BEGIN
19653cdbc3dSStefano Zampini #undef __FUNCT__
19753cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
19853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
19953cdbc3dSStefano Zampini {
20053cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
20153cdbc3dSStefano Zampini 
20253cdbc3dSStefano Zampini   PetscFunctionBegin;
20353cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
20453cdbc3dSStefano Zampini     *NeumannBoundaries = pcbddc->NeumannBoundaries;
20553cdbc3dSStefano Zampini   } else {
2069c0446d6SStefano Zampini     *NeumannBoundaries = PETSC_NULL;
2079c0446d6SStefano Zampini     //SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Error in %s: Neumann boundaries not set!.\n",__FUNCT__);
20853cdbc3dSStefano Zampini   }
20953cdbc3dSStefano Zampini   PetscFunctionReturn(0);
21053cdbc3dSStefano Zampini }
21153cdbc3dSStefano Zampini EXTERN_C_END
21253cdbc3dSStefano Zampini 
21353cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
21453cdbc3dSStefano Zampini #undef __FUNCT__
21553cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
21653cdbc3dSStefano Zampini /*@
21753cdbc3dSStefano Zampini  PCBDDCGetNeumannBoundaries - Get index set defining subdomain part of
21853cdbc3dSStefano Zampini                               Neumann boundaries for the global problem.
21953cdbc3dSStefano Zampini 
2209c0446d6SStefano Zampini    Not collective
22153cdbc3dSStefano Zampini 
22253cdbc3dSStefano Zampini    Input Parameters:
22353cdbc3dSStefano Zampini +  pc - the preconditioning context
22453cdbc3dSStefano Zampini 
22553cdbc3dSStefano Zampini    Output Parameters:
22653cdbc3dSStefano Zampini +  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
22753cdbc3dSStefano Zampini 
22853cdbc3dSStefano Zampini    Level: intermediate
22953cdbc3dSStefano Zampini 
23053cdbc3dSStefano Zampini    Notes:
2319c0446d6SStefano Zampini    If the user has not yet provided such information, PETSC_NULL is returned.
23253cdbc3dSStefano Zampini 
23353cdbc3dSStefano Zampini .seealso: PCBDDC
23453cdbc3dSStefano Zampini @*/
23553cdbc3dSStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
23653cdbc3dSStefano Zampini {
23753cdbc3dSStefano Zampini   PetscErrorCode ierr;
23853cdbc3dSStefano Zampini 
23953cdbc3dSStefano Zampini   PetscFunctionBegin;
24053cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
24153cdbc3dSStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
2420c7d97c5SJed Brown   PetscFunctionReturn(0);
2430c7d97c5SJed Brown }
2440c7d97c5SJed Brown 
2459c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
2469c0446d6SStefano Zampini EXTERN_C_BEGIN
2479c0446d6SStefano Zampini #undef __FUNCT__
2489c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
2499c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
2509c0446d6SStefano Zampini {
2519c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2529c0446d6SStefano Zampini   PetscInt i;
2539c0446d6SStefano Zampini   PetscErrorCode ierr;
2549c0446d6SStefano Zampini 
2559c0446d6SStefano Zampini   PetscFunctionBegin;
256d11ae9bbSstefano_zampini   /* Destroy ISs if they were already set */
2579c0446d6SStefano Zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) {
2589c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2599c0446d6SStefano Zampini   }
260d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
261d11ae9bbSstefano_zampini 
2629c0446d6SStefano Zampini   /* allocate space then copy ISs */
2639c0446d6SStefano Zampini   ierr = PetscMalloc(n_is*sizeof(IS),&pcbddc->ISForDofs);CHKERRQ(ierr);
2649c0446d6SStefano Zampini   for(i=0;i<n_is;i++) {
2659c0446d6SStefano Zampini     ierr = ISDuplicate(ISForDofs[i],&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2669c0446d6SStefano Zampini     ierr = ISCopy(ISForDofs[i],pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2679c0446d6SStefano Zampini   }
2689c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
269d11ae9bbSstefano_zampini 
2709c0446d6SStefano Zampini   PetscFunctionReturn(0);
2719c0446d6SStefano Zampini }
2729c0446d6SStefano Zampini EXTERN_C_END
2739c0446d6SStefano Zampini 
2749c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
2759c0446d6SStefano Zampini #undef __FUNCT__
2769c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
2779c0446d6SStefano Zampini /*@
2789c0446d6SStefano Zampini  PCBDDCSetDofsSplitting - Set index set defining how dofs are splitted.
2799c0446d6SStefano Zampini 
2809c0446d6SStefano Zampini    Not collective
2819c0446d6SStefano Zampini 
2829c0446d6SStefano Zampini    Input Parameters:
2839c0446d6SStefano Zampini +  pc - the preconditioning context
2849c0446d6SStefano Zampini -  n - number of index sets defining dofs spltting
2859c0446d6SStefano Zampini -  IS[] - array of IS describing dofs splitting
2869c0446d6SStefano Zampini 
2879c0446d6SStefano Zampini    Level: intermediate
2889c0446d6SStefano Zampini 
2899c0446d6SStefano Zampini    Notes:
2909c0446d6SStefano Zampini    Sequential ISs are copied, the user must destroy the array of IS passed in.
2919c0446d6SStefano Zampini 
2929c0446d6SStefano Zampini .seealso: PCBDDC
2939c0446d6SStefano Zampini @*/
2949c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
2959c0446d6SStefano Zampini {
2969c0446d6SStefano Zampini   PetscErrorCode ierr;
2979c0446d6SStefano Zampini 
2989c0446d6SStefano Zampini   PetscFunctionBegin;
2999c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3009c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
3019c0446d6SStefano Zampini   PetscFunctionReturn(0);
3029c0446d6SStefano Zampini }
3039c0446d6SStefano Zampini 
30453cdbc3dSStefano Zampini #undef __FUNCT__
30553cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
3060c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3070c7d97c5SJed Brown /*
3080c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
3090c7d97c5SJed Brown                   by setting data structures and options.
3100c7d97c5SJed Brown 
3110c7d97c5SJed Brown    Input Parameter:
31253cdbc3dSStefano Zampini +  pc - the preconditioner context
3130c7d97c5SJed Brown 
3140c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
3150c7d97c5SJed Brown 
3160c7d97c5SJed Brown    Notes:
3170c7d97c5SJed Brown    The interface routine PCSetUp() is not usually called directly by
3180c7d97c5SJed Brown    the user, but instead is called by PCApply() if necessary.
3190c7d97c5SJed Brown */
32053cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
3210c7d97c5SJed Brown {
3220c7d97c5SJed Brown   PetscErrorCode ierr;
3230c7d97c5SJed Brown   PC_BDDC*       pcbddc   = (PC_BDDC*)pc->data;
3240c7d97c5SJed Brown   PC_IS            *pcis = (PC_IS*)(pc->data);
3250c7d97c5SJed Brown 
3260c7d97c5SJed Brown   PetscFunctionBegin;
3270c7d97c5SJed Brown   if (!pc->setupcalled) {
3283b03a366Sstefano_zampini     /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
3299c0446d6SStefano Zampini        So, we set to pcnone the Neumann problem of pcis in order to avoid unneeded computation
3300c7d97c5SJed Brown        Also, we decide to directly build the (same) Dirichlet problem */
3310c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localN_pc_type","none");CHKERRQ(ierr);
3320c7d97c5SJed Brown     ierr = PetscOptionsSetValue("-is_localD_pc_type","none");CHKERRQ(ierr);
3330c7d97c5SJed Brown     /* Set up all the "iterative substructuring" common block */
3340c7d97c5SJed Brown     ierr = PCISSetUp(pc);CHKERRQ(ierr);
3353b03a366Sstefano_zampini     /* Get stdout for dbg */
336e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
337e269702eSStefano Zampini       ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&pcbddc->dbg_viewer);CHKERRQ(ierr);
338e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
339e269702eSStefano Zampini     }
3403b03a366Sstefano_zampini     /* TODO MOVE CODE FRAGMENT */
3410c7d97c5SJed Brown     PetscInt im_active=0;
3420c7d97c5SJed Brown     if(pcis->n) im_active = 1;
34353cdbc3dSStefano Zampini     ierr = MPI_Allreduce(&im_active,&pcbddc->active_procs,1,MPIU_INT,MPI_SUM,((PetscObject)pc)->comm);CHKERRQ(ierr);
3443b03a366Sstefano_zampini     /* Analyze local interface */
3450c7d97c5SJed Brown     ierr = PCBDDCManageLocalBoundaries(pc);CHKERRQ(ierr);
3463b03a366Sstefano_zampini     /* Set up local constraint matrix */
3473b03a366Sstefano_zampini     ierr = PCBDDCCreateConstraintMatrix(pc);CHKERRQ(ierr);
3480c7d97c5SJed Brown     /* Create coarse and local stuffs used for evaluating action of preconditioner */
3490c7d97c5SJed Brown     ierr = PCBDDCCoarseSetUp(pc);CHKERRQ(ierr);
3503b03a366Sstefano_zampini     /* Processes fakely involved in multilevel should not call ISLocalToGlobalMappingRestoreInfo */
3513b03a366Sstefano_zampini     if ( !pcis->n_neigh ) pcis->ISLocalToGlobalMappingGetInfoWasCalled=PETSC_FALSE;
3520c7d97c5SJed Brown   }
3530c7d97c5SJed Brown   PetscFunctionReturn(0);
3540c7d97c5SJed Brown }
3550c7d97c5SJed Brown 
3560c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
3570c7d97c5SJed Brown /*
3580c7d97c5SJed Brown    PCApply_BDDC - Applies the BDDC preconditioner to a vector.
3590c7d97c5SJed Brown 
3600c7d97c5SJed Brown    Input Parameters:
3610c7d97c5SJed Brown .  pc - the preconditioner context
3620c7d97c5SJed Brown .  r - input vector (global)
3630c7d97c5SJed Brown 
3640c7d97c5SJed Brown    Output Parameter:
3650c7d97c5SJed Brown .  z - output vector (global)
3660c7d97c5SJed Brown 
3670c7d97c5SJed Brown    Application Interface Routine: PCApply()
3680c7d97c5SJed Brown  */
3690c7d97c5SJed Brown #undef __FUNCT__
3700c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
37153cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
3720c7d97c5SJed Brown {
3730c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
3740c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
3750c7d97c5SJed Brown   PetscErrorCode    ierr;
3763b03a366Sstefano_zampini   const PetscScalar one = 1.0;
3773b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
3780c7d97c5SJed Brown 
3790c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
3800c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
3810c7d97c5SJed Brown    Added support for M_3 preconditioenr in the reference article (code is active if pcbddc->prec_type = PETSC_TRUE) */
3820c7d97c5SJed Brown 
3830c7d97c5SJed Brown   PetscFunctionBegin;
3840c7d97c5SJed Brown   /* First Dirichlet solve */
3850c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3860c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
38753cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
3880c7d97c5SJed Brown   /*
3890c7d97c5SJed Brown     Assembling right hand side for BDDC operator
3900c7d97c5SJed Brown     - vec1_D for the Dirichlet part (if needed, i.e. prec_flag=PETSC_TRUE)
3910c7d97c5SJed Brown     - the interface part of the global vector z
3920c7d97c5SJed Brown   */
3930c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3940c7d97c5SJed Brown   ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
3950c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
3960c7d97c5SJed Brown   ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
3970c7d97c5SJed Brown   ierr = VecCopy(r,z);CHKERRQ(ierr);
3980c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3990c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4000c7d97c5SJed Brown 
4010c7d97c5SJed Brown   /*
4020c7d97c5SJed Brown     Apply interface preconditioner
4030c7d97c5SJed Brown     Results are stored in:
4040c7d97c5SJed Brown     -  vec1_D (if needed, i.e. with prec_type = PETSC_TRUE)
4050c7d97c5SJed Brown     -  the interface part of the global vector z
4060c7d97c5SJed Brown   */
4070c7d97c5SJed Brown   ierr = PCBDDCApplyInterfacePreconditioner(pc,z);CHKERRQ(ierr);
4080c7d97c5SJed Brown 
4093b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
4100c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4110c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4120c7d97c5SJed Brown   ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
4130c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
41453cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcbddc->vec4_D);CHKERRQ(ierr);
4150c7d97c5SJed Brown   ierr = VecScale(pcbddc->vec4_D,m_one);CHKERRQ(ierr);
4160c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = VecAXPY (pcbddc->vec4_D,one,pcis->vec1_D);CHKERRQ(ierr); }
4170c7d97c5SJed Brown   ierr = VecAXPY (pcis->vec2_D,one,pcbddc->vec4_D);CHKERRQ(ierr);
4180c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4190c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4200c7d97c5SJed Brown 
4210c7d97c5SJed Brown   PetscFunctionReturn(0);
4220c7d97c5SJed Brown 
4230c7d97c5SJed Brown }
4240c7d97c5SJed Brown 
4250c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4260c7d97c5SJed Brown /*
4270c7d97c5SJed Brown    PCBDDCApplyInterfacePreconditioner - Apply the BDDC preconditioner at the interface.
4280c7d97c5SJed Brown 
4290c7d97c5SJed Brown */
4300c7d97c5SJed Brown #undef __FUNCT__
4310c7d97c5SJed Brown #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
43253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, Vec z)
4330c7d97c5SJed Brown {
4340c7d97c5SJed Brown   PetscErrorCode ierr;
4350c7d97c5SJed Brown   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
4360c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)  (pc->data);
4373b03a366Sstefano_zampini   const PetscScalar zero = 0.0;
4380c7d97c5SJed Brown 
4390c7d97c5SJed Brown   PetscFunctionBegin;
4400c7d97c5SJed Brown   /* Get Local boundary and apply partition of unity */
4410c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4420c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4430c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4440c7d97c5SJed Brown 
4450c7d97c5SJed Brown   /* Application of PHI^T  */
4460c7d97c5SJed Brown   ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
4470c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
4480c7d97c5SJed Brown 
4490c7d97c5SJed Brown   /* Scatter data of coarse_rhs */
4500c7d97c5SJed Brown   if(pcbddc->coarse_rhs) ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr);
4510c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4520c7d97c5SJed Brown 
4530c7d97c5SJed Brown   /* Local solution on R nodes */
4540c7d97c5SJed Brown   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
4550c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4560c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4570c7d97c5SJed Brown   if(pcbddc->prec_type) {
4580c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4590c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4600c7d97c5SJed Brown   }
4610c7d97c5SJed Brown   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
4620c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
4630c7d97c5SJed Brown   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4640c7d97c5SJed Brown   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4650c7d97c5SJed Brown   if(pcbddc->prec_type) {
4660c7d97c5SJed Brown     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4670c7d97c5SJed Brown     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4680c7d97c5SJed Brown   }
4690c7d97c5SJed Brown 
4700c7d97c5SJed Brown   /* Coarse solution */
4710c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
47253cdbc3dSStefano Zampini   if(pcbddc->coarse_rhs) ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
4730c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4740c7d97c5SJed Brown   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4750c7d97c5SJed Brown 
4760c7d97c5SJed Brown   /* Sum contributions from two levels */
4770c7d97c5SJed Brown   /* Apply partition of unity and sum boundary values */
4780c7d97c5SJed Brown   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
4790c7d97c5SJed Brown   ierr = VecPointwiseMult(pcis->vec1_B,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
4800c7d97c5SJed Brown   if(pcbddc->prec_type) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
4810c7d97c5SJed Brown   ierr = VecSet(z,zero);CHKERRQ(ierr);
4820c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4830c7d97c5SJed Brown   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4840c7d97c5SJed Brown 
4850c7d97c5SJed Brown   PetscFunctionReturn(0);
4860c7d97c5SJed Brown }
4870c7d97c5SJed Brown 
4880c7d97c5SJed Brown 
4890c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
4900c7d97c5SJed Brown /*
4910c7d97c5SJed Brown    PCBDDCSolveSaddlePoint
4920c7d97c5SJed Brown 
4930c7d97c5SJed Brown */
4940c7d97c5SJed Brown #undef __FUNCT__
4950c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSolveSaddlePoint"
49653cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
4970c7d97c5SJed Brown {
4980c7d97c5SJed Brown   PetscErrorCode ierr;
4990c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5000c7d97c5SJed Brown 
5010c7d97c5SJed Brown   PetscFunctionBegin;
5020c7d97c5SJed Brown 
50353cdbc3dSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
5040c7d97c5SJed Brown   if(pcbddc->n_constraints) {
5050c7d97c5SJed Brown     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
5060c7d97c5SJed Brown     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
5070c7d97c5SJed Brown   }
5080c7d97c5SJed Brown 
5090c7d97c5SJed Brown   PetscFunctionReturn(0);
5100c7d97c5SJed Brown }
5110c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5120c7d97c5SJed Brown /*
5130c7d97c5SJed Brown    PCBDDCScatterCoarseDataBegin
5140c7d97c5SJed Brown 
5150c7d97c5SJed Brown */
5160c7d97c5SJed Brown #undef __FUNCT__
5170c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
51853cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5190c7d97c5SJed Brown {
5200c7d97c5SJed Brown   PetscErrorCode ierr;
5210c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5220c7d97c5SJed Brown 
5230c7d97c5SJed Brown   PetscFunctionBegin;
5240c7d97c5SJed Brown 
5250c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5260c7d97c5SJed Brown     case SCATTERS_BDDC:
5270c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5280c7d97c5SJed Brown       break;
5290c7d97c5SJed Brown     case GATHERS_BDDC:
5300c7d97c5SJed Brown       break;
5310c7d97c5SJed Brown   }
5320c7d97c5SJed Brown   PetscFunctionReturn(0);
5330c7d97c5SJed Brown 
5340c7d97c5SJed Brown }
5350c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5360c7d97c5SJed Brown /*
5370c7d97c5SJed Brown    PCBDDCScatterCoarseDataEnd
5380c7d97c5SJed Brown 
5390c7d97c5SJed Brown */
5400c7d97c5SJed Brown #undef __FUNCT__
5410c7d97c5SJed Brown #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
54253cdbc3dSStefano Zampini static PetscErrorCode  PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
5430c7d97c5SJed Brown {
5440c7d97c5SJed Brown   PetscErrorCode ierr;
5450c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
5460c7d97c5SJed Brown   PetscScalar*   array_to;
5470c7d97c5SJed Brown   PetscScalar*   array_from;
5480c7d97c5SJed Brown   MPI_Comm       comm=((PetscObject)pc)->comm;
5490c7d97c5SJed Brown   PetscInt i;
5500c7d97c5SJed Brown 
5510c7d97c5SJed Brown   PetscFunctionBegin;
5520c7d97c5SJed Brown 
5530c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
5540c7d97c5SJed Brown     case SCATTERS_BDDC:
5550c7d97c5SJed Brown       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
5560c7d97c5SJed Brown       break;
5570c7d97c5SJed Brown     case GATHERS_BDDC:
5580c7d97c5SJed Brown       if(vec_from) VecGetArray(vec_from,&array_from);
5590c7d97c5SJed Brown       if(vec_to)   VecGetArray(vec_to,&array_to);
5600c7d97c5SJed Brown       switch(pcbddc->coarse_problem_type){
5610c7d97c5SJed Brown         case SEQUENTIAL_BDDC:
5620c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
56353cdbc3dSStefano 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);
5640c7d97c5SJed Brown             if(vec_to) {
5650c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5660c7d97c5SJed Brown                 array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5670c7d97c5SJed Brown             }
5680c7d97c5SJed Brown           } else {
5690c7d97c5SJed Brown             if(vec_from)
5700c7d97c5SJed Brown               for(i=0;i<pcbddc->replicated_primal_size;i++)
5710c7d97c5SJed Brown                 pcbddc->replicated_local_primal_values[i]=array_from[pcbddc->replicated_local_primal_indices[i]];
57253cdbc3dSStefano 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);
5730c7d97c5SJed Brown           }
5740c7d97c5SJed Brown           break;
5750c7d97c5SJed Brown         case REPLICATED_BDDC:
5760c7d97c5SJed Brown           if(smode == SCATTER_FORWARD) {
57753cdbc3dSStefano 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);
5780c7d97c5SJed Brown             for(i=0;i<pcbddc->replicated_primal_size;i++)
5790c7d97c5SJed Brown               array_to[pcbddc->replicated_local_primal_indices[i]]+=pcbddc->replicated_local_primal_values[i];
5800c7d97c5SJed Brown           } else { /* no communications needed for SCATTER_REVERSE since needed data is already present */
5810c7d97c5SJed Brown             for(i=0;i<pcbddc->local_primal_size;i++)
5820c7d97c5SJed Brown               array_to[i]=array_from[pcbddc->local_primal_indices[i]];
5830c7d97c5SJed Brown           }
5840c7d97c5SJed Brown           break;
58553cdbc3dSStefano Zampini         case MULTILEVEL_BDDC:
58653cdbc3dSStefano Zampini           break;
58753cdbc3dSStefano Zampini         case PARALLEL_BDDC:
58853cdbc3dSStefano Zampini           break;
5890c7d97c5SJed Brown       }
5900c7d97c5SJed Brown       if(vec_from) VecRestoreArray(vec_from,&array_from);
5910c7d97c5SJed Brown       if(vec_to)   VecRestoreArray(vec_to,&array_to);
5920c7d97c5SJed Brown       break;
5930c7d97c5SJed Brown   }
5940c7d97c5SJed Brown   PetscFunctionReturn(0);
5950c7d97c5SJed Brown 
5960c7d97c5SJed Brown }
5970c7d97c5SJed Brown 
5980c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5990c7d97c5SJed Brown /*
6000c7d97c5SJed Brown    PCDestroy_BDDC - Destroys the private context for the NN preconditioner
6010c7d97c5SJed Brown    that was created with PCCreate_BDDC().
6020c7d97c5SJed Brown 
6030c7d97c5SJed Brown    Input Parameter:
6040c7d97c5SJed Brown .  pc - the preconditioner context
6050c7d97c5SJed Brown 
6060c7d97c5SJed Brown    Application Interface Routine: PCDestroy()
6070c7d97c5SJed Brown */
6080c7d97c5SJed Brown #undef __FUNCT__
6090c7d97c5SJed Brown #define __FUNCT__ "PCDestroy_BDDC"
61053cdbc3dSStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
6110c7d97c5SJed Brown {
6120c7d97c5SJed Brown   PC_BDDC          *pcbddc = (PC_BDDC*)pc->data;
6130c7d97c5SJed Brown   PetscErrorCode ierr;
6140c7d97c5SJed Brown 
6150c7d97c5SJed Brown   PetscFunctionBegin;
6160c7d97c5SJed Brown   /* free data created by PCIS */
6170c7d97c5SJed Brown   ierr = PCISDestroy(pc);CHKERRQ(ierr);
6180c7d97c5SJed Brown   /* free BDDC data  */
61953cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
62053cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
62153cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
62253cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_mat);CHKERRQ(ierr);
62353cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
62453cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
62553cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
62653cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
62753cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
62853cdbc3dSStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
62953cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
63053cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
63153cdbc3dSStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
63253cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
63353cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
63453cdbc3dSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
63553cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
63653cdbc3dSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
63753cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
6383b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
6393b03a366Sstefano_zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
64053cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_indices);CHKERRQ(ierr);
64153cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
6420c7d97c5SJed Brown   if (pcbddc->replicated_local_primal_values)    { free(pcbddc->replicated_local_primal_values); }
64353cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_displacements);CHKERRQ(ierr);
64453cdbc3dSStefano Zampini   ierr = PetscFree(pcbddc->local_primal_sizes);CHKERRQ(ierr);
6459c0446d6SStefano Zampini   PetscInt i;
6463b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForDofs;i++) { ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr); }
6473b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
6483b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForFaces;i++) { ierr = ISDestroy(&pcbddc->ISForFaces[i]);CHKERRQ(ierr); }
6493b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForFaces);CHKERRQ(ierr);
6503b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges;i++) { ierr = ISDestroy(&pcbddc->ISForEdges[i]);CHKERRQ(ierr); }
6513b03a366Sstefano_zampini   ierr = PetscFree(pcbddc->ISForEdges);CHKERRQ(ierr);
6523b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->ISForVertices);CHKERRQ(ierr);
6530c7d97c5SJed Brown   /* Free the private data structure that was hanging off the PC */
6540c7d97c5SJed Brown   ierr = PetscFree(pcbddc);CHKERRQ(ierr);
6550c7d97c5SJed Brown   PetscFunctionReturn(0);
6560c7d97c5SJed Brown }
6570c7d97c5SJed Brown 
6580c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6590c7d97c5SJed Brown /*MC
6600c7d97c5SJed Brown    PCBDDC - Balancing Domain Decomposition by Constraints.
6610c7d97c5SJed Brown 
6620c7d97c5SJed Brown    Options Database Keys:
663a0ba757dSStefano Zampini .    -pcbddc ??? -
6640c7d97c5SJed Brown 
6650c7d97c5SJed Brown    Level: intermediate
6660c7d97c5SJed Brown 
6670c7d97c5SJed Brown    Notes: The matrix used with this preconditioner must be of type MATIS
6680c7d97c5SJed Brown 
6690c7d97c5SJed Brown           Unlike more 'conventional' interface preconditioners, this iterates over ALL the
6700c7d97c5SJed Brown           degrees of freedom, NOT just those on the interface (this allows the use of approximate solvers
6710c7d97c5SJed Brown           on the subdomains).
6720c7d97c5SJed Brown 
673a0ba757dSStefano Zampini           Options for the coarse grid preconditioner can be set with -
674a0ba757dSStefano Zampini           Options for the Dirichlet subproblem can be set with -
675a0ba757dSStefano Zampini           Options for the Neumann subproblem can be set with -
6760c7d97c5SJed Brown 
6770c7d97c5SJed Brown    Contributed by Stefano Zampini
6780c7d97c5SJed Brown 
6790c7d97c5SJed Brown .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
6800c7d97c5SJed Brown M*/
6810c7d97c5SJed Brown EXTERN_C_BEGIN
6820c7d97c5SJed Brown #undef __FUNCT__
6830c7d97c5SJed Brown #define __FUNCT__ "PCCreate_BDDC"
6840c7d97c5SJed Brown PetscErrorCode PCCreate_BDDC(PC pc)
6850c7d97c5SJed Brown {
6860c7d97c5SJed Brown   PetscErrorCode ierr;
6870c7d97c5SJed Brown   PC_BDDC          *pcbddc;
6880c7d97c5SJed Brown 
6890c7d97c5SJed Brown   PetscFunctionBegin;
6900c7d97c5SJed Brown   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
6910c7d97c5SJed Brown   ierr      = PetscNewLog(pc,PC_BDDC,&pcbddc);CHKERRQ(ierr);
6920c7d97c5SJed Brown   pc->data  = (void*)pcbddc;
6930c7d97c5SJed Brown   /* create PCIS data structure */
6940c7d97c5SJed Brown   ierr = PCISCreate(pc);CHKERRQ(ierr);
6950c7d97c5SJed Brown   /* BDDC specific */
6960c7d97c5SJed Brown   pcbddc->coarse_vec                 = 0;
6970c7d97c5SJed Brown   pcbddc->coarse_rhs                 = 0;
69853cdbc3dSStefano Zampini   pcbddc->coarse_ksp                 = 0;
6990c7d97c5SJed Brown   pcbddc->coarse_phi_B               = 0;
7000c7d97c5SJed Brown   pcbddc->coarse_phi_D               = 0;
7010c7d97c5SJed Brown   pcbddc->vec1_P                     = 0;
7020c7d97c5SJed Brown   pcbddc->vec1_R                     = 0;
7030c7d97c5SJed Brown   pcbddc->vec2_R                     = 0;
7040c7d97c5SJed Brown   pcbddc->local_auxmat1              = 0;
7050c7d97c5SJed Brown   pcbddc->local_auxmat2              = 0;
7060c7d97c5SJed Brown   pcbddc->R_to_B                     = 0;
7070c7d97c5SJed Brown   pcbddc->R_to_D                     = 0;
70853cdbc3dSStefano Zampini   pcbddc->ksp_D                      = 0;
70953cdbc3dSStefano Zampini   pcbddc->ksp_R                      = 0;
7100c7d97c5SJed Brown   pcbddc->local_primal_indices       = 0;
7110c7d97c5SJed Brown   pcbddc->prec_type                  = PETSC_FALSE;
71253cdbc3dSStefano Zampini   pcbddc->NeumannBoundaries          = 0;
7133b03a366Sstefano_zampini   pcbddc->ISForDofs                  = 0;
7143b03a366Sstefano_zampini   pcbddc->ISForVertices              = 0;
7153b03a366Sstefano_zampini   pcbddc->n_ISForFaces               = 0;
7163b03a366Sstefano_zampini   pcbddc->n_ISForEdges               = 0;
7173b03a366Sstefano_zampini   pcbddc->ConstraintMatrix           = 0;
7183b03a366Sstefano_zampini   pcbddc->use_nnsp_true              = PETSC_FALSE;
7190c7d97c5SJed Brown   pcbddc->local_primal_sizes         = 0;
7200c7d97c5SJed Brown   pcbddc->local_primal_displacements = 0;
7210c7d97c5SJed Brown   pcbddc->replicated_local_primal_indices = 0;
7220c7d97c5SJed Brown   pcbddc->replicated_local_primal_values  = 0;
7230c7d97c5SJed Brown   pcbddc->coarse_loc_to_glob         = 0;
724e269702eSStefano Zampini   pcbddc->dbg_flag                   = PETSC_FALSE;
7250c7d97c5SJed Brown   pcbddc->coarsening_ratio           = 8;
7260c7d97c5SJed Brown   /* function pointers */
7270c7d97c5SJed Brown   pc->ops->apply               = PCApply_BDDC;
7280c7d97c5SJed Brown   pc->ops->applytranspose      = 0;
7290c7d97c5SJed Brown   pc->ops->setup               = PCSetUp_BDDC;
7300c7d97c5SJed Brown   pc->ops->destroy             = PCDestroy_BDDC;
7310c7d97c5SJed Brown   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
7320c7d97c5SJed Brown   pc->ops->view                = 0;
7330c7d97c5SJed Brown   pc->ops->applyrichardson     = 0;
7340c7d97c5SJed Brown   pc->ops->applysymmetricleft  = 0;
7350c7d97c5SJed Brown   pc->ops->applysymmetricright = 0;
7360c7d97c5SJed Brown   /* composing function */
7373b03a366Sstefano_zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C","PCBDDCSetDirichletBoundaries_BDDC",
7383b03a366Sstefano_zampini                     PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
7390c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C","PCBDDCSetNeumannBoundaries_BDDC",
7400c7d97c5SJed Brown                     PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
74153cdbc3dSStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C","PCBDDCGetNeumannBoundaries_BDDC",
74253cdbc3dSStefano Zampini                     PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
7430c7d97c5SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetCoarseProblemType_C","PCBDDCSetCoarseProblemType_BDDC",
7440c7d97c5SJed Brown                     PCBDDCSetCoarseProblemType_BDDC);CHKERRQ(ierr);
7459c0446d6SStefano Zampini   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCBDDCSetDofsSplitting_C","PCBDDCSetDofsSplitting_BDDC",
7469c0446d6SStefano Zampini                     PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
7470c7d97c5SJed Brown   PetscFunctionReturn(0);
7480c7d97c5SJed Brown }
7490c7d97c5SJed Brown EXTERN_C_END
7500c7d97c5SJed Brown 
7510c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
7520c7d97c5SJed Brown /*
7533b03a366Sstefano_zampini    Create C matrix [I 0; 0 const]
7543b03a366Sstefano_zampini */
755de534f79Sstefano_zampini #ifdef BDDC_USE_POD
756de534f79Sstefano_zampini #if !defined(PETSC_MISSING_LAPACK_GESVD)
7573b03a366Sstefano_zampini #define PETSC_MISSING_LAPACK_GESVD 1
758de534f79Sstefano_zampini #define UNDEF_PETSC_MISSING_LAPACK_GESVD 1
759de534f79Sstefano_zampini #endif
7603b03a366Sstefano_zampini #endif
7613b03a366Sstefano_zampini 
7623b03a366Sstefano_zampini #undef __FUNCT__
7633b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCCreateConstraintMatrix"
7643b03a366Sstefano_zampini static PetscErrorCode PCBDDCCreateConstraintMatrix(PC pc)
7653b03a366Sstefano_zampini {
7663b03a366Sstefano_zampini   PetscErrorCode ierr;
7673b03a366Sstefano_zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
7683b03a366Sstefano_zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7693b03a366Sstefano_zampini   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
7703b03a366Sstefano_zampini   PetscInt       *nnz,*vertices,*is_indices;
7713b03a366Sstefano_zampini   PetscScalar    *temp_quadrature_constraint;
7723b03a366Sstefano_zampini   PetscInt       *temp_indices,*temp_indices_to_constraint;
7733b03a366Sstefano_zampini   PetscInt       local_primal_size,i,j,k,total_counts,max_size_of_constraint;
7743b03a366Sstefano_zampini   PetscInt       n_constraints,n_vertices,size_of_constraint;
7753b03a366Sstefano_zampini   PetscReal      quad_value;
7763b03a366Sstefano_zampini   PetscBool      nnsp_has_cnst=PETSC_FALSE,use_nnsp_true=pcbddc->use_nnsp_true;
7773b03a366Sstefano_zampini   PetscInt       nnsp_size=0,nnsp_addone=0,temp_constraints,temp_start_ptr;
7783b03a366Sstefano_zampini   IS             *used_IS;
7793b03a366Sstefano_zampini   const MatType  impMatType=MATSEQAIJ;
7803b03a366Sstefano_zampini   PetscBLASInt   Bs,Bt,lwork,lierr;
7813b03a366Sstefano_zampini   PetscReal      tol=1.0e-8;
782fcda91b4SJed Brown   MatNullSpace   nearnullsp;
783fcda91b4SJed Brown   const Vec      *nearnullvecs;
7843b03a366Sstefano_zampini   Vec            *localnearnullsp;
7853b03a366Sstefano_zampini   PetscScalar    *work,*temp_basis,*array_vector,*correlation_mat;
7863b03a366Sstefano_zampini   PetscReal      *rwork,*singular_vals;
787de534f79Sstefano_zampini   PetscBLASInt   Bone=1;
788de534f79Sstefano_zampini /* some ugly conditional declarations */
7893b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
7903b03a366Sstefano_zampini   PetscScalar    dot_result;
7913b03a366Sstefano_zampini   PetscScalar    one=1.0,zero=0.0;
7923b03a366Sstefano_zampini   PetscInt       ii;
7933b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
7943b03a366Sstefano_zampini   PetscScalar    val1,val2;
7953b03a366Sstefano_zampini #endif
7963b03a366Sstefano_zampini #else
7973b03a366Sstefano_zampini   PetscBLASInt   dummy_int;
7983b03a366Sstefano_zampini   PetscScalar    dummy_scalar;
7993b03a366Sstefano_zampini #endif
8003b03a366Sstefano_zampini 
8013b03a366Sstefano_zampini   PetscFunctionBegin;
8023b03a366Sstefano_zampini   /* check if near null space is attached to global mat */
803fcda91b4SJed Brown   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
804fcda91b4SJed Brown   if (nearnullsp) {
805fcda91b4SJed Brown     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
8063b03a366Sstefano_zampini   } else { /* if near null space is not provided it uses constants */
8073b03a366Sstefano_zampini     nnsp_has_cnst = PETSC_TRUE;
8083b03a366Sstefano_zampini     use_nnsp_true = PETSC_TRUE;
8093b03a366Sstefano_zampini   }
8103b03a366Sstefano_zampini   if(nnsp_has_cnst) {
8113b03a366Sstefano_zampini     nnsp_addone = 1;
8123b03a366Sstefano_zampini   }
8133b03a366Sstefano_zampini   /*
8143b03a366Sstefano_zampini        Evaluate maximum storage size needed by the procedure
8153b03a366Sstefano_zampini        - temp_indices will contain start index of each constraint stored as follows
8163b03a366Sstefano_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
8173b03a366Sstefano_zampini        - temp_quadrature_constraint[temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
8183b03a366Sstefano_zampini                                                                                                                                                          */
8193b03a366Sstefano_zampini   total_counts = pcbddc->n_ISForFaces+pcbddc->n_ISForEdges;
8203b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8213b03a366Sstefano_zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
8223b03a366Sstefano_zampini   total_counts = 0;
8233b03a366Sstefano_zampini   max_size_of_constraint = 0;
8243b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
8253b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
8263b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
8273b03a366Sstefano_zampini     } else {
8283b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
8293b03a366Sstefano_zampini     }
8303b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
8313b03a366Sstefano_zampini     total_counts += j;
8323b03a366Sstefano_zampini     if(j>max_size_of_constraint) max_size_of_constraint=j;
8333b03a366Sstefano_zampini   }
8343b03a366Sstefano_zampini   total_counts *= (nnsp_addone+nnsp_size);
8353b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
8363b03a366Sstefano_zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
8373b03a366Sstefano_zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd or LAPACKsyev/LAPACKheev */
8383b03a366Sstefano_zampini   rwork = 0;
8393b03a366Sstefano_zampini   work = 0;
8403b03a366Sstefano_zampini   singular_vals = 0;
8413b03a366Sstefano_zampini   temp_basis = 0;
8423b03a366Sstefano_zampini   correlation_mat = 0;
8433b03a366Sstefano_zampini   if(!pcbddc->use_nnsp_true) {
8443b03a366Sstefano_zampini     PetscScalar temp_work;
8453b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
8463b03a366Sstefano_zampini     /* POD */
8473b03a366Sstefano_zampini     PetscInt max_n;
8483b03a366Sstefano_zampini     max_n = nnsp_addone+nnsp_size;
8493b03a366Sstefano_zampini     /* using some techniques borrowed from Proper Orthogonal Decomposition */
8503b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*max_n*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
8513b03a366Sstefano_zampini     ierr = PetscMalloc(max_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
8523b03a366Sstefano_zampini     ierr = PetscMalloc(max_size_of_constraint*(nnsp_addone+nnsp_size)*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
8533b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8543b03a366Sstefano_zampini     ierr = PetscMalloc(3*max_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
8553b03a366Sstefano_zampini #endif
8563b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
8573b03a366Sstefano_zampini     Bt = PetscBLASIntCast(max_n);
8583b03a366Sstefano_zampini     lwork=-1;
8593b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
8603b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,&lierr);
8613b03a366Sstefano_zampini #else
8623b03a366Sstefano_zampini     LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,&temp_work,&lwork,rwork,&lierr);
8633b03a366Sstefano_zampini #endif
8643b03a366Sstefano_zampini #else /* on missing GESVD */
8653b03a366Sstefano_zampini     /* SVD */
8663b03a366Sstefano_zampini     PetscInt max_n,min_n;
8673b03a366Sstefano_zampini     max_n = max_size_of_constraint;
8683b03a366Sstefano_zampini     min_n = nnsp_addone+nnsp_size;
8693b03a366Sstefano_zampini     if(max_size_of_constraint < ( nnsp_addone+nnsp_size ) ) {
8703b03a366Sstefano_zampini       min_n = max_size_of_constraint;
8713b03a366Sstefano_zampini       max_n = nnsp_addone+nnsp_size;
8723b03a366Sstefano_zampini     }
8733b03a366Sstefano_zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
8743b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
8753b03a366Sstefano_zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
8763b03a366Sstefano_zampini #endif
8773b03a366Sstefano_zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
8783b03a366Sstefano_zampini     lwork=-1;
8793b03a366Sstefano_zampini     Bs = PetscBLASIntCast(max_n);
8803b03a366Sstefano_zampini     Bt = PetscBLASIntCast(min_n);
8813b03a366Sstefano_zampini     dummy_int = Bs;
882670f3ff9SJed Brown     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
8833b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
8843b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
8853b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,&lierr);
8863b03a366Sstefano_zampini #else
8873b03a366Sstefano_zampini     LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[0],&Bs,singular_vals,
8883b03a366Sstefano_zampini                  &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,&temp_work,&lwork,rwork,&lierr);
8893b03a366Sstefano_zampini #endif
8903b03a366Sstefano_zampini     if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SVD Lapack routine %d",(int)lierr);
891670f3ff9SJed Brown     ierr = PetscFPTrapPop();CHKERRQ(ierr);
8923b03a366Sstefano_zampini #endif
8933b03a366Sstefano_zampini     /* Allocate optimal workspace */
8943b03a366Sstefano_zampini     lwork = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work));
8953b03a366Sstefano_zampini     total_counts = (PetscInt)lwork;
8963b03a366Sstefano_zampini     ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&work);CHKERRQ(ierr);
8973b03a366Sstefano_zampini   }
8983b03a366Sstefano_zampini   /* get local part of global near null space vectors */
8993b03a366Sstefano_zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
9003b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) {
9013b03a366Sstefano_zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
902fcda91b4SJed Brown     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
903fcda91b4SJed Brown     ierr = VecScatterEnd  (matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9043b03a366Sstefano_zampini   }
9053b03a366Sstefano_zampini   /* Now we can loop on constraining sets */
9063b03a366Sstefano_zampini   total_counts=0;
9073b03a366Sstefano_zampini   temp_indices[0]=0;
9083b03a366Sstefano_zampini   for(i=0;i<pcbddc->n_ISForEdges+pcbddc->n_ISForFaces;i++){
9093b03a366Sstefano_zampini     if(i<pcbddc->n_ISForEdges){
9103b03a366Sstefano_zampini       used_IS = &pcbddc->ISForEdges[i];
9113b03a366Sstefano_zampini     } else {
9123b03a366Sstefano_zampini       used_IS = &pcbddc->ISForFaces[i-pcbddc->n_ISForEdges];
9133b03a366Sstefano_zampini     }
9143b03a366Sstefano_zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
9153b03a366Sstefano_zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
9163b03a366Sstefano_zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
9173b03a366Sstefano_zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
9183b03a366Sstefano_zampini     if(nnsp_has_cnst) {
9193b03a366Sstefano_zampini       temp_constraints++;
9203b03a366Sstefano_zampini       quad_value = 1.0/PetscSqrtReal((PetscReal)size_of_constraint);
9213b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9223b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9233b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
9243b03a366Sstefano_zampini       }
9253b03a366Sstefano_zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9263b03a366Sstefano_zampini       total_counts++;
9273b03a366Sstefano_zampini     }
9283b03a366Sstefano_zampini     for(k=0;k<nnsp_size;k++) {
9293b03a366Sstefano_zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
9303b03a366Sstefano_zampini       for(j=0;j<size_of_constraint;j++) {
9313b03a366Sstefano_zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
9323b03a366Sstefano_zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array_vector[is_indices[j]];
9333b03a366Sstefano_zampini       }
9343b03a366Sstefano_zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array_vector);CHKERRQ(ierr);
935de534f79Sstefano_zampini       quad_value = 1.0;
936de534f79Sstefano_zampini       if( use_nnsp_true ) { /* check if array is null on the connected component in case use_nnsp_true has been requested */
937de534f79Sstefano_zampini         Bs = PetscBLASIntCast(size_of_constraint);
938de534f79Sstefano_zampini         quad_value = BLASasum_(&Bs,&temp_quadrature_constraint[temp_indices[total_counts]],&Bone);
939de534f79Sstefano_zampini       }
940de534f79Sstefano_zampini       if ( quad_value > 0.0 ) { /* keep indices and values */
941de534f79Sstefano_zampini         temp_constraints++;
9423b03a366Sstefano_zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
9433b03a366Sstefano_zampini         total_counts++;
9443b03a366Sstefano_zampini       }
945de534f79Sstefano_zampini     }
9463b03a366Sstefano_zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
947de534f79Sstefano_zampini     /* perform SVD on the constraint if use_nnsp_true has not be requested by the user */
9483b03a366Sstefano_zampini     if(!use_nnsp_true) {
949de534f79Sstefano_zampini 
9503b03a366Sstefano_zampini       Bs = PetscBLASIntCast(size_of_constraint);
9513b03a366Sstefano_zampini       Bt = PetscBLASIntCast(temp_constraints);
952de534f79Sstefano_zampini 
9533b03a366Sstefano_zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
9543b03a366Sstefano_zampini       ierr = PetscMemzero(correlation_mat,Bt*Bt*sizeof(PetscScalar));CHKERRQ(ierr);
9553b03a366Sstefano_zampini       /* Store upper triangular part of correlation matrix */
9563b03a366Sstefano_zampini       for(j=0;j<temp_constraints;j++) {
9573b03a366Sstefano_zampini         for(k=0;k<j+1;k++) {
9583b03a366Sstefano_zampini #if defined(PETSC_USE_COMPLEX)
9593b03a366Sstefano_zampini           /* hand made complex dot product */
9603b03a366Sstefano_zampini           dot_result = 0.0;
9613b03a366Sstefano_zampini           for (ii=0; ii<size_of_constraint; ii++) {
9623b03a366Sstefano_zampini             val1 = temp_quadrature_constraint[temp_indices[temp_start_ptr+j]+ii];
9633b03a366Sstefano_zampini             val2 = temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii];
9643b03a366Sstefano_zampini             dot_result += val1*PetscConj(val2);
9653b03a366Sstefano_zampini           }
9663b03a366Sstefano_zampini #else
9673b03a366Sstefano_zampini           dot_result = BLASdot_(&Bs,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Bone,
9683b03a366Sstefano_zampini                                     &temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Bone);
9693b03a366Sstefano_zampini #endif
9703b03a366Sstefano_zampini           correlation_mat[j*temp_constraints+k]=dot_result;
9713b03a366Sstefano_zampini         }
9723b03a366Sstefano_zampini       }
9733b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
9743b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,&lierr);
9753b03a366Sstefano_zampini #else
9763b03a366Sstefano_zampini       LAPACKsyev_("V","U",&Bt,correlation_mat,&Bt,singular_vals,work,&lwork,rwork,&lierr);
9773b03a366Sstefano_zampini #endif
9783b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in EV Lapack routine %d",(int)lierr);
9793b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SYEV gives eigs in ascending order */
9803b03a366Sstefano_zampini       j=0;
9813b03a366Sstefano_zampini       while( j < Bt && singular_vals[j] < tol) j++;
9823b03a366Sstefano_zampini       total_counts=total_counts-j;
9833b03a366Sstefano_zampini       if(j<temp_constraints) {
9843b03a366Sstefano_zampini         for(k=j;k<Bt;k++) { singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]); }
9853b03a366Sstefano_zampini         BLASgemm_("N","N",&Bs,&Bt,&Bt,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,correlation_mat,&Bt,&zero,temp_basis,&Bs);
9863b03a366Sstefano_zampini         /* copy POD basis into used quadrature memory */
9873b03a366Sstefano_zampini         for(k=0;k<Bt-j;k++) {
9883b03a366Sstefano_zampini           for(ii=0;ii<size_of_constraint;ii++) {
9893b03a366Sstefano_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];
9903b03a366Sstefano_zampini           }
9913b03a366Sstefano_zampini         }
9923b03a366Sstefano_zampini       }
993de534f79Sstefano_zampini 
9943b03a366Sstefano_zampini #else  /* on missing GESVD */
995de534f79Sstefano_zampini 
9963b03a366Sstefano_zampini       PetscInt min_n = temp_constraints;
9973b03a366Sstefano_zampini       if(min_n > size_of_constraint) min_n = size_of_constraint;
9983b03a366Sstefano_zampini       dummy_int = Bs;
999670f3ff9SJed Brown       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
10003b03a366Sstefano_zampini #if !defined(PETSC_USE_COMPLEX)
10013b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
10023b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,&lierr);
10033b03a366Sstefano_zampini #else
10043b03a366Sstefano_zampini       LAPACKgesvd_("O","N",&Bs,&Bt,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Bs,singular_vals,
10053b03a366Sstefano_zampini                    &dummy_scalar,&dummy_int,&dummy_scalar,&dummy_int,work,&lwork,rwork,&lierr);
10063b03a366Sstefano_zampini #endif
10073b03a366Sstefano_zampini       if ( lierr ) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SVD Lapack routine %d",(int)lierr);
1008670f3ff9SJed Brown       ierr = PetscFPTrapPop();CHKERRQ(ierr);
10093b03a366Sstefano_zampini       /* retain eigenvalues greater than tol: note that lapack SVD gives eigs in descending order */
10103b03a366Sstefano_zampini       j=0;
10113b03a366Sstefano_zampini       while( j < min_n && singular_vals[min_n-j-1] < tol) j++;
10123b03a366Sstefano_zampini       total_counts = total_counts-(PetscInt)Bt+(min_n-j);
1013de534f79Sstefano_zampini 
10143b03a366Sstefano_zampini #endif
10153b03a366Sstefano_zampini     }
10163b03a366Sstefano_zampini   }
10173b03a366Sstefano_zampini   n_constraints=total_counts;
10183b03a366Sstefano_zampini   ierr = ISGetSize(pcbddc->ISForVertices,&n_vertices);CHKERRQ(ierr);
10193b03a366Sstefano_zampini   local_primal_size = n_vertices+n_constraints;
10203b03a366Sstefano_zampini   ierr = PetscMalloc(local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
10213b03a366Sstefano_zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
10223b03a366Sstefano_zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
10233b03a366Sstefano_zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,local_primal_size,pcis->n,local_primal_size,pcis->n);CHKERRQ(ierr);
10243b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { nnz[i]= 1; }
10253b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) { nnz[i+n_vertices]=temp_indices[i+1]-temp_indices[i]; }
10263b03a366Sstefano_zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
10273b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10283b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { ierr = MatSetValue(pcbddc->ConstraintMatrix,i,vertices[i],1.0,INSERT_VALUES);CHKERRQ(ierr); }
10293b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
10303b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
10313b03a366Sstefano_zampini     j=i+n_vertices;
10323b03a366Sstefano_zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
10333b03a366Sstefano_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);
10343b03a366Sstefano_zampini   }
10353b03a366Sstefano_zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10363b03a366Sstefano_zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10373b03a366Sstefano_zampini   /* set quantities in pcbddc data structure */
10383b03a366Sstefano_zampini   pcbddc->n_vertices = n_vertices;
10393b03a366Sstefano_zampini   pcbddc->n_constraints = n_constraints;
10403b03a366Sstefano_zampini   pcbddc->local_primal_size = n_vertices+n_constraints;
10413b03a366Sstefano_zampini   /* free workspace no longer needed */
10423b03a366Sstefano_zampini   ierr = PetscFree(rwork);CHKERRQ(ierr);
10433b03a366Sstefano_zampini   ierr = PetscFree(work);CHKERRQ(ierr);
10443b03a366Sstefano_zampini   ierr = PetscFree(temp_basis);CHKERRQ(ierr);
10453b03a366Sstefano_zampini   ierr = PetscFree(singular_vals);CHKERRQ(ierr);
10463b03a366Sstefano_zampini   ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
10473b03a366Sstefano_zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
10483b03a366Sstefano_zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
10493b03a366Sstefano_zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
10503b03a366Sstefano_zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
10513b03a366Sstefano_zampini   for(k=0;k<nnsp_size;k++) { ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr); }
10523b03a366Sstefano_zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
10533b03a366Sstefano_zampini   PetscFunctionReturn(0);
10543b03a366Sstefano_zampini }
1055de534f79Sstefano_zampini #ifdef UNDEF_PETSC_MISSING_LAPACK_GESVD
10563b03a366Sstefano_zampini #undef PETSC_MISSING_LAPACK_GESVD
10573b03a366Sstefano_zampini #endif
1058de534f79Sstefano_zampini 
10593b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
10603b03a366Sstefano_zampini /*
10610c7d97c5SJed Brown    PCBDDCCoarseSetUp -
10620c7d97c5SJed Brown */
10630c7d97c5SJed Brown #undef __FUNCT__
10640c7d97c5SJed Brown #define __FUNCT__ "PCBDDCCoarseSetUp"
106553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCCoarseSetUp(PC pc)
10660c7d97c5SJed Brown {
10670c7d97c5SJed Brown   PetscErrorCode  ierr;
10680c7d97c5SJed Brown 
10690c7d97c5SJed Brown   PC_IS*            pcis = (PC_IS*)(pc->data);
10700c7d97c5SJed Brown   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
10710c7d97c5SJed Brown   Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
10720c7d97c5SJed Brown   IS                is_R_local;
10730c7d97c5SJed Brown   IS                is_V_local;
10740c7d97c5SJed Brown   IS                is_C_local;
10750c7d97c5SJed Brown   IS                is_aux1;
10760c7d97c5SJed Brown   IS                is_aux2;
10770c7d97c5SJed Brown   const VecType     impVecType;
10780c7d97c5SJed Brown   const MatType     impMatType;
10790c7d97c5SJed Brown   PetscInt          n_R=0;
10800c7d97c5SJed Brown   PetscInt          n_D=0;
10810c7d97c5SJed Brown   PetscInt          n_B=0;
10820c7d97c5SJed Brown   PetscScalar       zero=0.0;
10830c7d97c5SJed Brown   PetscScalar       one=1.0;
10840c7d97c5SJed Brown   PetscScalar       m_one=-1.0;
10850c7d97c5SJed Brown   PetscScalar*      array;
10860c7d97c5SJed Brown   PetscScalar       *coarse_submat_vals;
10870c7d97c5SJed Brown   PetscInt          *idx_R_local;
10880c7d97c5SJed Brown   PetscInt          *idx_V_B;
10890c7d97c5SJed Brown   PetscScalar       *coarsefunctions_errors;
10900c7d97c5SJed Brown   PetscScalar       *constraints_errors;
10910c7d97c5SJed Brown   /* auxiliary indices */
10920c7d97c5SJed Brown   PetscInt s,i,j,k;
1093e269702eSStefano Zampini   /* for verbose output of bddc */
1094e269702eSStefano Zampini   PetscViewer       viewer=pcbddc->dbg_viewer;
1095e269702eSStefano Zampini   PetscBool         dbg_flag=pcbddc->dbg_flag;
1096a0ba757dSStefano Zampini   /* for counting coarse dofs */
1097a0ba757dSStefano Zampini   PetscScalar       coarsesum;
10983b03a366Sstefano_zampini   PetscInt          n_vertices=pcbddc->n_vertices,n_constraints=pcbddc->n_constraints;
10993b03a366Sstefano_zampini   PetscInt          size_of_constraint;
11003b03a366Sstefano_zampini   PetscInt          *row_cmat_indices;
11013b03a366Sstefano_zampini   PetscScalar       *row_cmat_values;
11023b03a366Sstefano_zampini   const PetscInt    *vertices;
11030c7d97c5SJed Brown 
11040c7d97c5SJed Brown   PetscFunctionBegin;
11050c7d97c5SJed Brown   /* Set Non-overlapping dimensions */
11060c7d97c5SJed Brown   n_B = pcis->n_B; n_D = pcis->n - n_B;
11073b03a366Sstefano_zampini   ierr = ISGetIndices(pcbddc->ISForVertices,&vertices);CHKERRQ(ierr);
1108a0ba757dSStefano 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) */
1109a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
1110a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11113b03a366Sstefano_zampini   for(i=0;i<n_vertices;i++) { array[ vertices[i] ] = one; }
11123b03a366Sstefano_zampini 
11133b03a366Sstefano_zampini   for(i=0;i<n_constraints;i++) {
11143b03a366Sstefano_zampini     ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
11153b03a366Sstefano_zampini     for (j=0; j<size_of_constraint; j++) {
11163b03a366Sstefano_zampini       k = row_cmat_indices[j];
1117a0ba757dSStefano Zampini       if( array[k] == zero ) {
1118a0ba757dSStefano Zampini         array[k] = one;
1119a0ba757dSStefano Zampini         break;
1120a0ba757dSStefano Zampini       }
1121a0ba757dSStefano Zampini     }
11223b03a366Sstefano_zampini     ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1123a0ba757dSStefano Zampini   }
1124a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1125a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1126a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1127a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1128a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1129a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1130a0ba757dSStefano Zampini   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1131a0ba757dSStefano Zampini   for(i=0;i<pcis->n;i++) { if( array[i] > zero) array[i] = one/array[i]; }
1132a0ba757dSStefano Zampini   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1133a0ba757dSStefano Zampini   ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
1134a0ba757dSStefano Zampini   ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1135a0ba757dSStefano Zampini   ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1136a0ba757dSStefano Zampini   ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
1137a0ba757dSStefano Zampini   pcbddc->coarse_size = (PetscInt) coarsesum;
1138a0ba757dSStefano Zampini 
11390c7d97c5SJed Brown   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
11400c7d97c5SJed Brown   ierr = VecSet(pcis->vec1_N,one);CHKERRQ(ierr);
11410c7d97c5SJed Brown   ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11423b03a366Sstefano_zampini   for (i=0;i<n_vertices;i++) { array[ vertices[i] ] = zero; }
11433b03a366Sstefano_zampini   ierr = PetscMalloc(( pcis->n - n_vertices )*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
11440c7d97c5SJed Brown   for (i=0, n_R=0; i<pcis->n; i++) { if (array[i] == one) { idx_R_local[n_R] = i; n_R++; } }
11450c7d97c5SJed Brown   ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1146e269702eSStefano Zampini   if(dbg_flag) {
11470c7d97c5SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
11480c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11490c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
11500c7d97c5SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
11513b03a366Sstefano_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);
11520c7d97c5SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1153a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1154a0ba757dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Size of coarse problem = %d (%f)\n",pcbddc->coarse_size,coarsesum);CHKERRQ(ierr);
1155a0ba757dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11560c7d97c5SJed Brown   }
11570c7d97c5SJed Brown   /* Allocate needed vectors */
11580c7d97c5SJed Brown   /* Set Mat type for local matrices needed by BDDC precondtioner */
11590c7d97c5SJed Brown   impMatType = MATSEQDENSE;
11600c7d97c5SJed Brown   impVecType = VECSEQ;
11610c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
11620c7d97c5SJed Brown   ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr);
11630c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_R);CHKERRQ(ierr);
11640c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_R,n_R,n_R);CHKERRQ(ierr);
11650c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1166d49ef151SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
11670c7d97c5SJed Brown   ierr = VecCreate(PETSC_COMM_SELF,&pcbddc->vec1_P);CHKERRQ(ierr);
11680c7d97c5SJed Brown   ierr = VecSetSizes(pcbddc->vec1_P,pcbddc->local_primal_size,pcbddc->local_primal_size);CHKERRQ(ierr);
11690c7d97c5SJed Brown   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
11700c7d97c5SJed Brown 
11710c7d97c5SJed Brown   /* Creating some index sets needed  */
11720c7d97c5SJed Brown   /* For submatrices */
11730c7d97c5SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_COPY_VALUES,&is_R_local);CHKERRQ(ierr);
11743b03a366Sstefano_zampini   if(n_vertices)    {
11753b03a366Sstefano_zampini     ierr = ISDuplicate(pcbddc->ISForVertices,&is_V_local);CHKERRQ(ierr);
11763b03a366Sstefano_zampini     ierr = ISCopy(pcbddc->ISForVertices,is_V_local);CHKERRQ(ierr);
11773b03a366Sstefano_zampini   }
11783b03a366Sstefano_zampini   if(n_constraints) { ierr = ISCreateStride (PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_C_local);CHKERRQ(ierr); }
11790c7d97c5SJed Brown   /* For VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
11800c7d97c5SJed Brown   {
11810c7d97c5SJed Brown     PetscInt   *aux_array1;
11820c7d97c5SJed Brown     PetscInt   *aux_array2;
11830c7d97c5SJed Brown     PetscScalar      value;
11840c7d97c5SJed Brown 
11853b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
11863b03a366Sstefano_zampini     ierr = PetscMalloc( (pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
11870c7d97c5SJed Brown 
1188d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_global,zero);CHKERRQ(ierr);
11890c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11900c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11910c7d97c5SJed Brown     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11920c7d97c5SJed Brown     ierr = VecScatterEnd  (matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11930c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11940c7d97c5SJed Brown     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
11950c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11960c7d97c5SJed Brown     for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] > one) { aux_array1[s] = i; s++; } }
11970c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
11980c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
11990c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12000c7d97c5SJed Brown     for (i=0, s=0; i<n_B; i++) { if (array[i] > one) { aux_array2[s] = i; s++; } }
12013828260eSStefano Zampini     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12020c7d97c5SJed Brown     ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array2,PETSC_COPY_VALUES,&is_aux2);CHKERRQ(ierr);
12030c7d97c5SJed Brown     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
12040c7d97c5SJed Brown     ierr = PetscFree(aux_array1);CHKERRQ(ierr);
12050c7d97c5SJed Brown     ierr = PetscFree(aux_array2);CHKERRQ(ierr);
12060c7d97c5SJed Brown     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
12070c7d97c5SJed Brown     ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
12080c7d97c5SJed Brown 
1209e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
12100c7d97c5SJed Brown       ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
12110c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12120c7d97c5SJed Brown       for (i=0, s=0; i<n_R; i++) { if (array[idx_R_local[i]] == one) { aux_array1[s] = i; s++; } }
12130c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12140c7d97c5SJed Brown       ierr = ISCreateGeneral(PETSC_COMM_SELF,s,aux_array1,PETSC_COPY_VALUES,&is_aux1);CHKERRQ(ierr);
12150c7d97c5SJed Brown       ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
12160c7d97c5SJed Brown       ierr = PetscFree(aux_array1);CHKERRQ(ierr);
12170c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
12180c7d97c5SJed Brown     }
12190c7d97c5SJed Brown 
12200c7d97c5SJed Brown     /* Check scatters */
1221e269702eSStefano Zampini     if(dbg_flag) {
12220c7d97c5SJed Brown 
12230c7d97c5SJed Brown       Vec            vec_aux;
12240c7d97c5SJed Brown 
12250c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
12260c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_B scatter\n");CHKERRQ(ierr);
12270c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1228d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1229d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1230d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1231d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1232d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1233d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1234d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1235d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1236d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1237d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12380c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1239d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12400c7d97c5SJed Brown 
1241d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1242d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_B,PETSC_NULL);CHKERRQ(ierr);
1243d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_B,&vec_aux);CHKERRQ(ierr);
1244d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_B,vec_aux);CHKERRQ(ierr);
1245d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1246d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1247d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1248d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1249d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_B);CHKERRQ(ierr);
1250d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12510c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_B REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1252d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12530c7d97c5SJed Brown 
12540c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12550c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Checking pcbddc->R_to_D scatter\n");CHKERRQ(ierr);
12560c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12570c7d97c5SJed Brown 
1258d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1259d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1260d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&vec_aux);CHKERRQ(ierr);
1261d49ef151SStefano Zampini       ierr = VecCopy(pcbddc->vec1_R,vec_aux);CHKERRQ(ierr);
1262d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1263d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1264d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1265d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,vec_aux,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1266d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1267d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12680c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D FORWARD error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1269d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12700c7d97c5SJed Brown 
1271d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1272d49ef151SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1273d49ef151SStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&vec_aux);CHKERRQ(ierr);
1274d49ef151SStefano Zampini       ierr = VecCopy(pcis->vec1_D,vec_aux);CHKERRQ(ierr);
1275d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1276d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1277d49ef151SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1278d49ef151SStefano Zampini       ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec1_R,vec_aux,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1279d49ef151SStefano Zampini       ierr = VecAXPY(vec_aux,m_one,pcis->vec1_D);CHKERRQ(ierr);
1280d49ef151SStefano Zampini       ierr = VecNorm(vec_aux,NORM_INFINITY,&value);CHKERRQ(ierr);
12810c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d R_to_D REVERSE error = % 1.14e\n",PetscGlobalRank,value);CHKERRQ(ierr);
1282d49ef151SStefano Zampini       ierr = VecDestroy(&vec_aux);CHKERRQ(ierr);
12830c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
12840c7d97c5SJed Brown 
12850c7d97c5SJed Brown     }
12860c7d97c5SJed Brown   }
12870c7d97c5SJed Brown 
12880c7d97c5SJed Brown   /* vertices in boundary numbering */
12893b03a366Sstefano_zampini   if(n_vertices) {
1290d49ef151SStefano Zampini     ierr = VecSet(pcis->vec1_N,m_one);CHKERRQ(ierr);
12910c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
12923b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) { array[ vertices[i] ] = i; }
12930c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1294d49ef151SStefano Zampini     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1295d49ef151SStefano Zampini     ierr = VecScatterEnd  (pcis->N_to_B,pcis->vec1_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12963b03a366Sstefano_zampini     ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
12970c7d97c5SJed Brown     ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
12983b03a366Sstefano_zampini     for (i=0; i<n_vertices; i++) {
12990c7d97c5SJed Brown       s=0;
13000c7d97c5SJed Brown       while (array[s] != i ) {s++;}
13010c7d97c5SJed Brown       idx_V_B[i]=s;
13020c7d97c5SJed Brown     }
13030c7d97c5SJed Brown     ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
13040c7d97c5SJed Brown   }
13050c7d97c5SJed Brown 
13060c7d97c5SJed Brown 
13070c7d97c5SJed Brown   /* Creating PC contexts for local Dirichlet and Neumann problems */
13080c7d97c5SJed Brown   {
13090c7d97c5SJed Brown     Mat  A_RR;
131053cdbc3dSStefano Zampini     PC   pc_temp;
13110c7d97c5SJed Brown     /* Matrix for Dirichlet problem is A_II -> we already have it from pcis.c code */
131253cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
131353cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
131453cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr);
131553cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1316a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
13170c7d97c5SJed Brown     /* default */
131853cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
131953cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13200c7d97c5SJed Brown     /* Allow user's customization */
132153cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
132253cdbc3dSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
132353cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
13240c7d97c5SJed Brown     /* Matrix for Neumann problem is A_RR -> we need to create it */
13250c7d97c5SJed Brown     ierr = MatGetSubMatrix(matis->A,is_R_local,is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
132653cdbc3dSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
132753cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
132853cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,SAME_PRECONDITIONER);CHKERRQ(ierr);
132953cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1330a0ba757dSStefano Zampini     //ierr = KSPSetOptionsPrefix();CHKERRQ(ierr);
13310c7d97c5SJed Brown     /* default */
133253cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
133353cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
13340c7d97c5SJed Brown     /* Allow user's customization */
133553cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
133653cdbc3dSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
133753cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1338a0ba757dSStefano Zampini     /* check Dirichlet and Neumann solvers */
1339e269702eSStefano Zampini     if(pcbddc->dbg_flag) {
13400c7d97c5SJed Brown       Vec temp_vec;
13410c7d97c5SJed Brown       PetscScalar value;
13420c7d97c5SJed Brown 
1343a0ba757dSStefano Zampini       ierr = VecDuplicate(pcis->vec1_D,&temp_vec);CHKERRQ(ierr);
1344a0ba757dSStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,PETSC_NULL);CHKERRQ(ierr);
1345a0ba757dSStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
1346a0ba757dSStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,temp_vec);CHKERRQ(ierr);
1347a0ba757dSStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcis->vec1_D);CHKERRQ(ierr);
1348a0ba757dSStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1349a0ba757dSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1350a0ba757dSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1351a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1352a0ba757dSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
1353a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1354d49ef151SStefano Zampini       ierr = VecDuplicate(pcbddc->vec1_R,&temp_vec);CHKERRQ(ierr);
1355d49ef151SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,PETSC_NULL);CHKERRQ(ierr);
1356d49ef151SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1357d49ef151SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,temp_vec);CHKERRQ(ierr);
1358d49ef151SStefano Zampini       ierr = VecAXPY(temp_vec,m_one,pcbddc->vec1_R);CHKERRQ(ierr);
1359d49ef151SStefano Zampini       ierr = VecNorm(temp_vec,NORM_INFINITY,&value);CHKERRQ(ierr);
1360e269702eSStefano Zampini       ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
13610c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
1362d49ef151SStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
13630c7d97c5SJed Brown     }
13640c7d97c5SJed Brown     /* free Neumann problem's matrix */
13650c7d97c5SJed Brown     ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
13660c7d97c5SJed Brown   }
13670c7d97c5SJed Brown 
13680c7d97c5SJed Brown   /* Assemble all remaining stuff needed to apply BDDC  */
13690c7d97c5SJed Brown   {
13700c7d97c5SJed Brown     Mat          A_RV,A_VR,A_VV;
13710c7d97c5SJed Brown     Mat          M1,M2;
13720c7d97c5SJed Brown     Mat          C_CR;
13733b03a366Sstefano_zampini     Mat          AUXMAT;
13740c7d97c5SJed Brown     Vec          vec1_C;
13750c7d97c5SJed Brown     Vec          vec2_C;
13760c7d97c5SJed Brown     Vec          vec1_V;
13770c7d97c5SJed Brown     Vec          vec2_V;
13780c7d97c5SJed Brown     PetscInt     *nnz;
13790c7d97c5SJed Brown     PetscInt     *auxindices;
138053cdbc3dSStefano Zampini     PetscInt     index;
13810c7d97c5SJed Brown     PetscScalar* array2;
13820c7d97c5SJed Brown     MatFactorInfo matinfo;
13830c7d97c5SJed Brown 
13840c7d97c5SJed Brown     /* Allocating some extra storage just to be safe */
13850c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
13860c7d97c5SJed Brown     ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
13870c7d97c5SJed Brown     for(i=0;i<pcis->n;i++) {auxindices[i]=i;}
13880c7d97c5SJed Brown 
13890c7d97c5SJed Brown     /* some work vectors on vertices and/or constraints */
13903b03a366Sstefano_zampini     if(n_vertices) {
13910c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
13923b03a366Sstefano_zampini       ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
13930c7d97c5SJed Brown       ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
13940c7d97c5SJed Brown       ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
13950c7d97c5SJed Brown     }
13960c7d97c5SJed Brown     if(pcbddc->n_constraints) {
13970c7d97c5SJed Brown       ierr = VecCreate(PETSC_COMM_SELF,&vec1_C);CHKERRQ(ierr);
13980c7d97c5SJed Brown       ierr = VecSetSizes(vec1_C,pcbddc->n_constraints,pcbddc->n_constraints);CHKERRQ(ierr);
13990c7d97c5SJed Brown       ierr = VecSetType(vec1_C,impVecType);CHKERRQ(ierr);
14000c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&vec2_C);CHKERRQ(ierr);
14010c7d97c5SJed Brown       ierr = VecDuplicate(vec1_C,&pcbddc->vec1_C);CHKERRQ(ierr);
14020c7d97c5SJed Brown     }
14030c7d97c5SJed Brown     /* Precompute stuffs needed for preprocessing and application of BDDC*/
14043b03a366Sstefano_zampini     if(n_constraints) {
14050c7d97c5SJed Brown       /* some work vectors */
14060c7d97c5SJed Brown       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
14073b03a366Sstefano_zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,n_R,n_constraints);CHKERRQ(ierr);
14080c7d97c5SJed Brown       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
14093b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->local_auxmat2,PETSC_NULL);CHKERRQ(ierr);
14100c7d97c5SJed Brown 
14110c7d97c5SJed Brown       /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
14123b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
1413d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
14143b03a366Sstefano_zampini         ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
14153b03a366Sstefano_zampini         /* Get row of constraint matrix in R numbering */
14160c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14173b03a366Sstefano_zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14183b03a366Sstefano_zampini         for(j=0;j<size_of_constraint;j++) { array[ row_cmat_indices[j] ] = - row_cmat_values[j]; }
14193b03a366Sstefano_zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
14200c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14210c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array2[j] = array[ idx_R_local[j] ]; }
14220c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
14230c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
14243b03a366Sstefano_zampini         /* Solve for row of constraint matrix in R numbering */
142553cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14263b03a366Sstefano_zampini         /* Set values */
14270c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14283b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14290c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14300c7d97c5SJed Brown       }
14310c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14320c7d97c5SJed Brown       ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14330c7d97c5SJed Brown 
14340c7d97c5SJed Brown       /* Create Constraint matrix on R nodes: C_{CR}  */
14353b03a366Sstefano_zampini       ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_C_local,is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
14360c7d97c5SJed Brown       ierr = ISDestroy(&is_C_local);CHKERRQ(ierr);
14370c7d97c5SJed Brown 
14380c7d97c5SJed Brown       /* Assemble AUXMAT = ( LUFactor )( -C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} */
14390c7d97c5SJed Brown       ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&AUXMAT);CHKERRQ(ierr);
1440d49ef151SStefano Zampini       ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
14413b03a366Sstefano_zampini       ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,0,1,&is_aux1);CHKERRQ(ierr);
14420c7d97c5SJed Brown       ierr = MatLUFactor(AUXMAT,is_aux1,is_aux1,&matinfo);CHKERRQ(ierr);
14430c7d97c5SJed Brown       ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
14440c7d97c5SJed Brown 
14453b03a366Sstefano_zampini       /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
1446d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
14473b03a366Sstefano_zampini       ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
14480c7d97c5SJed Brown       ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
14493b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M1,PETSC_NULL);CHKERRQ(ierr);
14503b03a366Sstefano_zampini       for(i=0;i<n_constraints;i++) {
14510c7d97c5SJed Brown         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
14520c7d97c5SJed Brown         ierr = VecSetValue(vec1_C,i,one,INSERT_VALUES);CHKERRQ(ierr);
14530c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
14540c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
14550c7d97c5SJed Brown         ierr = MatSolve(AUXMAT,vec1_C,vec2_C);CHKERRQ(ierr);
14560c7d97c5SJed Brown         ierr = VecScale(vec2_C,m_one);CHKERRQ(ierr);
14570c7d97c5SJed Brown         ierr = VecGetArray(vec2_C,&array);CHKERRQ(ierr);
14583b03a366Sstefano_zampini         ierr = MatSetValues(M1,n_constraints,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14590c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_C,&array);CHKERRQ(ierr);
14600c7d97c5SJed Brown       }
14610c7d97c5SJed Brown       ierr = MatAssemblyBegin(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14620c7d97c5SJed Brown       ierr = MatAssemblyEnd(M1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14630c7d97c5SJed Brown       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
14640c7d97c5SJed Brown       /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
14650c7d97c5SJed Brown       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
14660c7d97c5SJed Brown 
14670c7d97c5SJed Brown     }
14680c7d97c5SJed Brown 
14690c7d97c5SJed Brown     /* Get submatrices from subdomain matrix */
14703b03a366Sstefano_zampini     if(n_vertices){
14710c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_R_local,is_V_local,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
14720c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
14730c7d97c5SJed Brown       ierr = MatGetSubMatrix(matis->A,is_V_local,is_V_local,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
14740c7d97c5SJed Brown       /* Assemble M2 = A_RR^{-1}A_RV */
1475d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&M2);CHKERRQ(ierr);
14763b03a366Sstefano_zampini       ierr = MatSetSizes(M2,n_R,n_vertices,n_R,n_vertices);CHKERRQ(ierr);
14770c7d97c5SJed Brown       ierr = MatSetType(M2,impMatType);CHKERRQ(ierr);
14783b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(M2,PETSC_NULL);CHKERRQ(ierr);
14793b03a366Sstefano_zampini       for(i=0;i<n_vertices;i++) {
14800c7d97c5SJed Brown         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
14810c7d97c5SJed Brown         ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
14820c7d97c5SJed Brown         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
14830c7d97c5SJed Brown         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
14840c7d97c5SJed Brown         ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
148553cdbc3dSStefano Zampini         ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
14860c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14873b03a366Sstefano_zampini         ierr = MatSetValues(M2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
14880c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec2_R,&array);CHKERRQ(ierr);
14890c7d97c5SJed Brown       }
14900c7d97c5SJed Brown       ierr = MatAssemblyBegin(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14910c7d97c5SJed Brown       ierr = MatAssemblyEnd(M2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
14920c7d97c5SJed Brown     }
14930c7d97c5SJed Brown 
14940c7d97c5SJed Brown     /* Matrix of coarse basis functions (local) */
1495d49ef151SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
14960c7d97c5SJed Brown     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
14970c7d97c5SJed Brown     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
14983b03a366Sstefano_zampini     ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_B,PETSC_NULL);CHKERRQ(ierr);
1499e269702eSStefano Zampini     if(pcbddc->prec_type || dbg_flag ) {
1500d49ef151SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
15010c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
15020c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
15033b03a366Sstefano_zampini       ierr = MatSeqDenseSetPreallocation(pcbddc->coarse_phi_D,PETSC_NULL);CHKERRQ(ierr);
15040c7d97c5SJed Brown     }
15050c7d97c5SJed Brown 
1506e269702eSStefano Zampini     if(dbg_flag) {
15070c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&coarsefunctions_errors);CHKERRQ(ierr);
15080c7d97c5SJed Brown       ierr = PetscMalloc( pcbddc->local_primal_size*sizeof(PetscScalar),&constraints_errors);CHKERRQ(ierr);
15090c7d97c5SJed Brown     }
15103b03a366Sstefano_zampini     /* Subdomain contribution (Non-overlapping) to coarse matrix  */
15110c7d97c5SJed Brown     ierr = PetscMalloc ((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
15120c7d97c5SJed Brown 
15130c7d97c5SJed Brown     /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
15143b03a366Sstefano_zampini     for(i=0;i<n_vertices;i++){
15150c7d97c5SJed Brown       ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
15160c7d97c5SJed Brown       ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
15170c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
15180c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
15190c7d97c5SJed Brown       /* solution of saddle point problem */
15200c7d97c5SJed Brown       ierr = MatMult(M2,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
15210c7d97c5SJed Brown       ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
15223b03a366Sstefano_zampini       if(n_constraints) {
15230c7d97c5SJed Brown         ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
15240c7d97c5SJed Brown         ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
15250c7d97c5SJed Brown         ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15260c7d97c5SJed Brown       }
15270c7d97c5SJed Brown       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
15280c7d97c5SJed Brown       ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
15290c7d97c5SJed Brown 
15300c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
15310c7d97c5SJed Brown       /* coarse basis functions */
15320c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
15330c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15340c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15350c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15363b03a366Sstefano_zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15370c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
15380c7d97c5SJed Brown       ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
1539e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag  ) {
15400c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15410c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
15420c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15433b03a366Sstefano_zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
15440c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
15450c7d97c5SJed Brown       }
15460c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
15470c7d97c5SJed Brown       ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15483b03a366Sstefano_zampini       for(j=0;j<n_vertices;j++) { coarse_submat_vals[i*pcbddc->local_primal_size+j] = array[j]; } //WARNING -> column major ordering
15490c7d97c5SJed Brown       ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15503b03a366Sstefano_zampini       if(n_constraints) {
15510c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15523b03a366Sstefano_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
15530c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15540c7d97c5SJed Brown       }
15550c7d97c5SJed Brown 
1556e269702eSStefano Zampini       if( dbg_flag ) {
15570c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
1558d49ef151SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
15590c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15600c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15610c7d97c5SJed Brown         for(j=0;j<n_R;j++) { array[idx_R_local[j]] = array2[j]; }
15623b03a366Sstefano_zampini         array[ vertices[i] ] = one;
15630c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
15640c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
15650c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
1566d49ef151SStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
15670c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15680c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
15693b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) { array2[j]=array[j]; }
15700c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
15713b03a366Sstefano_zampini         if(n_constraints) {
15720c7d97c5SJed Brown           ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
15733b03a366Sstefano_zampini           for(j=0;j<n_constraints;j++) { array2[j+n_vertices]=array[j]; }
15740c7d97c5SJed Brown           ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
15750c7d97c5SJed Brown         }
15760c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
15770c7d97c5SJed Brown         ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
15780c7d97c5SJed Brown         /* check saddle point solution */
15790c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
15803b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
15813b03a366Sstefano_zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
15823b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
15830c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15843b03a366Sstefano_zampini         array[i]=array[i]+m_one;  /* shift by the identity matrix */
15850c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
15863b03a366Sstefano_zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
15870c7d97c5SJed Brown       }
15880c7d97c5SJed Brown     }
15890c7d97c5SJed Brown 
15903b03a366Sstefano_zampini     for(i=0;i<n_constraints;i++){
1591d49ef151SStefano Zampini       ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
15920c7d97c5SJed Brown       ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
15930c7d97c5SJed Brown       ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
15940c7d97c5SJed Brown       ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
15950c7d97c5SJed Brown       /* solution of saddle point problem */
15960c7d97c5SJed Brown       ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
15970c7d97c5SJed Brown       ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
15980c7d97c5SJed Brown       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
15993b03a366Sstefano_zampini       if(n_vertices) { ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr); }
16000c7d97c5SJed Brown       /* Set values in coarse basis function and subdomain part of coarse_mat */
16010c7d97c5SJed Brown       /* coarse basis functions */
16023b03a366Sstefano_zampini       index=i+n_vertices;
16030c7d97c5SJed Brown       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
16040c7d97c5SJed Brown       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16050c7d97c5SJed Brown       ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16060c7d97c5SJed Brown       ierr = VecGetArray(pcis->vec1_B,&array);CHKERRQ(ierr);
160753cdbc3dSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16080c7d97c5SJed Brown       ierr = VecRestoreArray(pcis->vec1_B,&array);CHKERRQ(ierr);
1609e269702eSStefano Zampini       if( pcbddc->prec_type || dbg_flag ) {
16100c7d97c5SJed Brown         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16110c7d97c5SJed Brown         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16120c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_D,&array);CHKERRQ(ierr);
161353cdbc3dSStefano Zampini         ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&index,array,INSERT_VALUES);CHKERRQ(ierr);
16140c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_D,&array);CHKERRQ(ierr);
16150c7d97c5SJed Brown       }
16160c7d97c5SJed Brown       /* subdomain contribution to coarse matrix */
16173b03a366Sstefano_zampini       if(n_vertices) {
16180c7d97c5SJed Brown         ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16193b03a366Sstefano_zampini         for(j=0;j<n_vertices;j++) {coarse_submat_vals[index*pcbddc->local_primal_size+j]=array[j];} //WARNING -> column major ordering
16200c7d97c5SJed Brown         ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16210c7d97c5SJed Brown       }
16220c7d97c5SJed Brown       ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16233b03a366Sstefano_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
16240c7d97c5SJed Brown       ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16250c7d97c5SJed Brown 
1626e269702eSStefano Zampini       if( dbg_flag ) {
16270c7d97c5SJed Brown         /* assemble subdomain vector on nodes */
162853cdbc3dSStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
16290c7d97c5SJed Brown         ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16300c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16310c7d97c5SJed Brown         for(j=0;j<n_R;j++){ array[ idx_R_local[j] ] = array2[j]; }
16320c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_R,&array2);CHKERRQ(ierr);
16330c7d97c5SJed Brown         ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
16340c7d97c5SJed Brown         /* assemble subdomain vector of lagrange multipliers */
163553cdbc3dSStefano Zampini         ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
16360c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16373b03a366Sstefano_zampini         if( n_vertices) {
16380c7d97c5SJed Brown           ierr = VecGetArray(vec2_V,&array);CHKERRQ(ierr);
16393b03a366Sstefano_zampini           for(j=0;j<n_vertices;j++) {array2[j]=-array[j];}
16400c7d97c5SJed Brown           ierr = VecRestoreArray(vec2_V,&array);CHKERRQ(ierr);
16410c7d97c5SJed Brown         }
16420c7d97c5SJed Brown         ierr = VecGetArray(vec1_C,&array);CHKERRQ(ierr);
16433b03a366Sstefano_zampini         for(j=0;j<n_constraints;j++) {array2[j+n_vertices]=-array[j];}
16440c7d97c5SJed Brown         ierr = VecRestoreArray(vec1_C,&array);CHKERRQ(ierr);
16450c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array2);CHKERRQ(ierr);
16460c7d97c5SJed Brown         /* check saddle point solution */
16470c7d97c5SJed Brown         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
16483b03a366Sstefano_zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
164953cdbc3dSStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[index]);CHKERRQ(ierr);
16503b03a366Sstefano_zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
16510c7d97c5SJed Brown         ierr = VecGetArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
165253cdbc3dSStefano Zampini         array[index]=array[index]+m_one; /* shift by the identity matrix */
16530c7d97c5SJed Brown         ierr = VecRestoreArray(pcbddc->vec1_P,&array);CHKERRQ(ierr);
165453cdbc3dSStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[index]);CHKERRQ(ierr);
16550c7d97c5SJed Brown       }
16560c7d97c5SJed Brown     }
16570c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16580c7d97c5SJed Brown     ierr = MatAssemblyEnd  (pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1659e269702eSStefano Zampini     if( pcbddc->prec_type || dbg_flag ) {
16600c7d97c5SJed Brown       ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16610c7d97c5SJed Brown       ierr = MatAssemblyEnd  (pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
16620c7d97c5SJed Brown     }
16630c7d97c5SJed Brown     /* Checking coarse_sub_mat and coarse basis functios */
16640c7d97c5SJed Brown     /* It shuld be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
16659d2fce94SStefano Zampini     if(dbg_flag) {
16660c7d97c5SJed Brown 
16670c7d97c5SJed Brown       Mat coarse_sub_mat;
16680c7d97c5SJed Brown       Mat TM1,TM2,TM3,TM4;
16690c7d97c5SJed Brown       Mat coarse_phi_D,coarse_phi_B,A_II,A_BB,A_IB,A_BI;
1670a0ba757dSStefano Zampini       const MatType checkmattype=MATSEQAIJ;
16710c7d97c5SJed Brown       PetscScalar      value;
16720c7d97c5SJed Brown 
1673c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
1674c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
1675c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
1676c042a7c3SStefano Zampini       ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
1677c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
1678c042a7c3SStefano Zampini       ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
1679c042a7c3SStefano Zampini       ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
1680c042a7c3SStefano Zampini       ierr = MatConvert(coarse_sub_mat,checkmattype,MAT_REUSE_MATRIX,&coarse_sub_mat);CHKERRQ(ierr);
16810c7d97c5SJed Brown 
16820c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
16830c7d97c5SJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
16840c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
168553cdbc3dSStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
168653cdbc3dSStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
168753cdbc3dSStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1688c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
168953cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
169053cdbc3dSStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
1691c042a7c3SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
169253cdbc3dSStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
169353cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
169453cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
169553cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
169653cdbc3dSStefano Zampini       ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
169753cdbc3dSStefano Zampini       ierr = MatNorm(TM1,NORM_INFINITY,&value);CHKERRQ(ierr);
16980c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"----------------------------------\n");CHKERRQ(ierr);
16990c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
17000c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"matrix error = % 1.14e\n",value);CHKERRQ(ierr);
17010c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"coarse functions errors\n");CHKERRQ(ierr);
170253cdbc3dSStefano 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); }
17030c7d97c5SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"constraints errors\n");CHKERRQ(ierr);
170453cdbc3dSStefano 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); }
17050c7d97c5SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
170653cdbc3dSStefano Zampini       ierr = MatDestroy(&A_II);CHKERRQ(ierr);
170753cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
170853cdbc3dSStefano Zampini       ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
170953cdbc3dSStefano Zampini       ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
171053cdbc3dSStefano Zampini       ierr = MatDestroy(&TM1);CHKERRQ(ierr);
171153cdbc3dSStefano Zampini       ierr = MatDestroy(&TM2);CHKERRQ(ierr);
171253cdbc3dSStefano Zampini       ierr = MatDestroy(&TM3);CHKERRQ(ierr);
171353cdbc3dSStefano Zampini       ierr = MatDestroy(&TM4);CHKERRQ(ierr);
171453cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
171553cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
171653cdbc3dSStefano Zampini       ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
17170c7d97c5SJed Brown       ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
17180c7d97c5SJed Brown       ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
17190c7d97c5SJed Brown     }
17200c7d97c5SJed Brown 
17210c7d97c5SJed Brown     /* create coarse matrix and data structures for message passing associated actual choice of coarse problem type */
17220c7d97c5SJed Brown     ierr = PCBDDCSetupCoarseEnvironment(pc,coarse_submat_vals);CHKERRQ(ierr);
17230c7d97c5SJed Brown     /* free memory */
17240c7d97c5SJed Brown     ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
17250c7d97c5SJed Brown     ierr = PetscFree(auxindices);CHKERRQ(ierr);
17260c7d97c5SJed Brown     ierr = PetscFree(nnz);CHKERRQ(ierr);
17273b03a366Sstefano_zampini     if(n_vertices) {
17280c7d97c5SJed Brown       ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
17290c7d97c5SJed Brown       ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
17300c7d97c5SJed Brown       ierr = MatDestroy(&M2);CHKERRQ(ierr);
17310c7d97c5SJed Brown       ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
17320c7d97c5SJed Brown       ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
17330c7d97c5SJed Brown       ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
17340c7d97c5SJed Brown     }
17350c7d97c5SJed Brown     if(pcbddc->n_constraints) {
17360c7d97c5SJed Brown       ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
17370c7d97c5SJed Brown       ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
17380c7d97c5SJed Brown       ierr = MatDestroy(&M1);CHKERRQ(ierr);
17390c7d97c5SJed Brown       ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
17400c7d97c5SJed Brown     }
17410c7d97c5SJed Brown   }
17420c7d97c5SJed Brown   /* free memory */
17433b03a366Sstefano_zampini   if(n_vertices) {
17440c7d97c5SJed Brown     ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
17450c7d97c5SJed Brown     ierr = ISDestroy(&is_V_local);CHKERRQ(ierr);
17460c7d97c5SJed Brown   }
17470c7d97c5SJed Brown   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
17480c7d97c5SJed Brown   ierr = ISDestroy(&is_R_local);CHKERRQ(ierr);
17493b03a366Sstefano_zampini   ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
17500c7d97c5SJed Brown 
17510c7d97c5SJed Brown   PetscFunctionReturn(0);
17520c7d97c5SJed Brown }
17530c7d97c5SJed Brown 
17540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
17550c7d97c5SJed Brown 
17560c7d97c5SJed Brown #undef __FUNCT__
17570c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetupCoarseEnvironment"
175853cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetupCoarseEnvironment(PC pc,PetscScalar* coarse_submat_vals)
17590c7d97c5SJed Brown {
17600c7d97c5SJed Brown 
17610c7d97c5SJed Brown 
17620c7d97c5SJed Brown   Mat_IS    *matis    = (Mat_IS*)pc->pmat->data;
17630c7d97c5SJed Brown   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
17640c7d97c5SJed Brown   PC_IS     *pcis     = (PC_IS*)pc->data;
17650c7d97c5SJed Brown   MPI_Comm  prec_comm = ((PetscObject)pc)->comm;
17660c7d97c5SJed Brown   MPI_Comm  coarse_comm;
17670c7d97c5SJed Brown 
17680c7d97c5SJed Brown   /* common to all choiches */
17690c7d97c5SJed Brown   PetscScalar *temp_coarse_mat_vals;
17700c7d97c5SJed Brown   PetscScalar *ins_coarse_mat_vals;
17710c7d97c5SJed Brown   PetscInt    *ins_local_primal_indices;
17720c7d97c5SJed Brown   PetscMPIInt *localsizes2,*localdispl2;
17730c7d97c5SJed Brown   PetscMPIInt size_prec_comm;
17740c7d97c5SJed Brown   PetscMPIInt rank_prec_comm;
17750c7d97c5SJed Brown   PetscMPIInt active_rank=MPI_PROC_NULL;
17760c7d97c5SJed Brown   PetscMPIInt master_proc=0;
17770c7d97c5SJed Brown   PetscInt    ins_local_primal_size;
17780c7d97c5SJed Brown   /* specific to MULTILEVEL_BDDC */
17790c7d97c5SJed Brown   PetscMPIInt *ranks_recv;
17800c7d97c5SJed Brown   PetscMPIInt count_recv=0;
17810c7d97c5SJed Brown   PetscMPIInt rank_coarse_proc_send_to;
17820c7d97c5SJed Brown   PetscMPIInt coarse_color = MPI_UNDEFINED;
17830c7d97c5SJed Brown   ISLocalToGlobalMapping coarse_ISLG;
17840c7d97c5SJed Brown   /* some other variables */
17850c7d97c5SJed Brown   PetscErrorCode ierr;
17860c7d97c5SJed Brown   const MatType coarse_mat_type;
17870c7d97c5SJed Brown   const PCType  coarse_pc_type;
178853cdbc3dSStefano Zampini   const KSPType  coarse_ksp_type;
178953cdbc3dSStefano Zampini   PC pc_temp;
17900c7d97c5SJed Brown   PetscInt i,j,k,bs;
17913b03a366Sstefano_zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
1792e269702eSStefano Zampini   /* verbose output viewer */
1793e269702eSStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1794e269702eSStefano Zampini   PetscBool   dbg_flag=pcbddc->dbg_flag;
17950c7d97c5SJed Brown 
17960c7d97c5SJed Brown   PetscFunctionBegin;
17970c7d97c5SJed Brown 
17980c7d97c5SJed Brown   ins_local_primal_indices = 0;
17990c7d97c5SJed Brown   ins_coarse_mat_vals      = 0;
18000c7d97c5SJed Brown   localsizes2              = 0;
18010c7d97c5SJed Brown   localdispl2              = 0;
18020c7d97c5SJed Brown   temp_coarse_mat_vals     = 0;
18030c7d97c5SJed Brown   coarse_ISLG              = 0;
18040c7d97c5SJed Brown 
180553cdbc3dSStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
180653cdbc3dSStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
18070c7d97c5SJed Brown   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
18080c7d97c5SJed Brown 
1809beed3852SStefano Zampini   /* Assign global numbering to coarse dofs */
1810beed3852SStefano Zampini   {
1811a0ba757dSStefano Zampini     PetscScalar    one=1.,zero=0.;
1812beed3852SStefano Zampini     PetscScalar    *array;
1813beed3852SStefano Zampini     PetscMPIInt    *auxlocal_primal;
1814beed3852SStefano Zampini     PetscMPIInt    *auxglobal_primal;
1815beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal;
1816beed3852SStefano Zampini     PetscMPIInt    *all_auxglobal_primal_dummy;
1817beed3852SStefano Zampini     PetscMPIInt    mpi_local_primal_size = (PetscMPIInt)pcbddc->local_primal_size;
18183b03a366Sstefano_zampini     PetscInt       *vertices,*row_cmat_indices;
18193b03a366Sstefano_zampini     PetscInt       size_of_constraint;
1820beed3852SStefano Zampini 
1821beed3852SStefano Zampini     /* Construct needed data structures for message passing */
1822beed3852SStefano Zampini     ierr = PetscMalloc(mpi_local_primal_size*sizeof(PetscMPIInt),&pcbddc->local_primal_indices);CHKERRQ(ierr);
1823beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_sizes);CHKERRQ(ierr);
1824beed3852SStefano Zampini     ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&pcbddc->local_primal_displacements);CHKERRQ(ierr);
1825beed3852SStefano Zampini     /* Gather local_primal_size information for all processes  */
18265619798eSStefano Zampini     ierr = MPI_Allgather(&mpi_local_primal_size,1,MPIU_INT,&pcbddc->local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
1827beed3852SStefano Zampini     pcbddc->replicated_primal_size = 0;
1828beed3852SStefano Zampini     for (i=0; i<size_prec_comm; i++) {
1829beed3852SStefano Zampini       pcbddc->local_primal_displacements[i] = pcbddc->replicated_primal_size ;
1830beed3852SStefano Zampini       pcbddc->replicated_primal_size += pcbddc->local_primal_sizes[i];
1831beed3852SStefano Zampini     }
18325619798eSStefano Zampini     if(rank_prec_comm == 0) {
1833beed3852SStefano Zampini       /* allocate some auxiliary space */
1834beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal),&all_auxglobal_primal);CHKERRQ(ierr);
1835beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->replicated_primal_size*sizeof(*all_auxglobal_primal_dummy),&all_auxglobal_primal_dummy);CHKERRQ(ierr);
1836beed3852SStefano Zampini     }
1837beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxlocal_primal);CHKERRQ(ierr);
1838beed3852SStefano Zampini     ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscMPIInt),&auxglobal_primal);CHKERRQ(ierr);
1839beed3852SStefano Zampini 
1840beed3852SStefano 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)
1841beed3852SStefano Zampini        This code fragment assumes that the number of local constraints per connected component
1842beed3852SStefano Zampini        is not greater than the number of nodes defined for the connected component
1843beed3852SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
18443b03a366Sstefano_zampini     /* auxlocal_primal      : primal indices in local nodes numbering (internal and interface) with complete queue sorted by global ordering */
1845beed3852SStefano Zampini     ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
18463b03a366Sstefano_zampini     ierr = ISGetIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1847beed3852SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
18483b03a366Sstefano_zampini     for(i=0;i<pcbddc->n_vertices;i++) {  /* note that  pcbddc->n_vertices can be different from size of ISForVertices */
18493b03a366Sstefano_zampini       array[ vertices[i] ] = one;
18503b03a366Sstefano_zampini       auxlocal_primal[i] = vertices[i];
1851beed3852SStefano Zampini     }
18523b03a366Sstefano_zampini     ierr = ISRestoreIndices(pcbddc->ISForVertices,(const PetscInt**)&vertices);CHKERRQ(ierr);
1853beed3852SStefano Zampini     for(i=0;i<pcbddc->n_constraints;i++) {
18543b03a366Sstefano_zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
18553b03a366Sstefano_zampini       for (j=0; j<size_of_constraint; j++) {
18563b03a366Sstefano_zampini         k = row_cmat_indices[j];
1857beed3852SStefano Zampini         if( array[k] == zero ) {
1858beed3852SStefano Zampini           array[k] = one;
1859beed3852SStefano Zampini           auxlocal_primal[i+pcbddc->n_vertices] = k;
1860beed3852SStefano Zampini           break;
1861beed3852SStefano Zampini         }
1862beed3852SStefano Zampini       }
18633b03a366Sstefano_zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,pcbddc->n_vertices+i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,PETSC_NULL);CHKERRQ(ierr);
1864beed3852SStefano Zampini     }
1865beed3852SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
1866a0ba757dSStefano Zampini 
1867beed3852SStefano Zampini     /* Now assign them a global numbering */
1868beed3852SStefano Zampini     /* auxglobal_primal contains indices in global nodes numbering (internal and interface) */
1869beed3852SStefano Zampini     ierr = ISLocalToGlobalMappingApply(matis->mapping,pcbddc->local_primal_size,auxlocal_primal,auxglobal_primal);CHKERRQ(ierr);
1870beed3852SStefano Zampini     /* all_auxglobal_primal contains all primal nodes indices in global nodes numbering (internal and interface) */
1871beed3852SStefano 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);
1872beed3852SStefano Zampini 
1873beed3852SStefano Zampini     /* After this block all_auxglobal_primal should contains one copy of each primal node's indices in global nodes numbering */
1874beed3852SStefano Zampini     /* It implements a function similar to PetscSortRemoveDupsInt */
1875beed3852SStefano Zampini     if(rank_prec_comm==0) {
1876beed3852SStefano Zampini       /* dummy argument since PetscSortMPIInt doesn't exist! */
1877beed3852SStefano Zampini       ierr = PetscSortMPIIntWithArray(pcbddc->replicated_primal_size,all_auxglobal_primal,all_auxglobal_primal_dummy);CHKERRQ(ierr);
1878beed3852SStefano Zampini       k=1;
1879beed3852SStefano Zampini       j=all_auxglobal_primal[0];  /* first dof in global numbering */
1880beed3852SStefano Zampini       for(i=1;i< pcbddc->replicated_primal_size ;i++) {
1881beed3852SStefano Zampini         if(j != all_auxglobal_primal[i] ) {
1882beed3852SStefano Zampini           all_auxglobal_primal[k]=all_auxglobal_primal[i];
1883beed3852SStefano Zampini           k++;
1884beed3852SStefano Zampini           j=all_auxglobal_primal[i];
1885beed3852SStefano Zampini         }
1886beed3852SStefano Zampini       }
1887beed3852SStefano Zampini     } else {
1888beed3852SStefano Zampini       ierr = PetscMalloc(pcbddc->coarse_size*sizeof(PetscMPIInt),&all_auxglobal_primal);CHKERRQ(ierr);
1889beed3852SStefano Zampini     }
18905619798eSStefano Zampini     /* We only need to broadcast the indices from 0 to pcbddc->coarse_size. Remaning elements of array all_aux_global_primal are garbage. */
1891beed3852SStefano Zampini     ierr = MPI_Bcast(all_auxglobal_primal,pcbddc->coarse_size,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
1892beed3852SStefano Zampini 
1893beed3852SStefano Zampini     /* Now get global coarse numbering of local primal nodes */
1894beed3852SStefano Zampini     for(i=0;i<pcbddc->local_primal_size;i++) {
1895beed3852SStefano Zampini       k=0;
1896beed3852SStefano Zampini       while( all_auxglobal_primal[k] != auxglobal_primal[i] ) { k++;}
1897beed3852SStefano Zampini       pcbddc->local_primal_indices[i]=k;
1898beed3852SStefano Zampini     }
1899e269702eSStefano Zampini     if(dbg_flag) {
1900e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1901e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
1902e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1903e269702eSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1904e269702eSStefano Zampini       for(i=0;i<pcbddc->local_primal_size;i++) {
1905e269702eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"local_primal_indices[%d]=%d \n",i,pcbddc->local_primal_indices[i]);
1906e269702eSStefano Zampini       }
1907e269702eSStefano Zampini       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1908e269702eSStefano Zampini     }
1909beed3852SStefano Zampini     /* free allocated memory */
1910beed3852SStefano Zampini     ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
1911beed3852SStefano Zampini     ierr = PetscFree(auxglobal_primal);CHKERRQ(ierr);
1912beed3852SStefano Zampini     ierr = PetscFree(all_auxglobal_primal);CHKERRQ(ierr);
1913e269702eSStefano Zampini     if(rank_prec_comm == 0) {
1914beed3852SStefano Zampini       ierr = PetscFree(all_auxglobal_primal_dummy);CHKERRQ(ierr);
1915beed3852SStefano Zampini     }
1916e269702eSStefano Zampini   }
1917beed3852SStefano Zampini 
19180c7d97c5SJed Brown   /* adapt coarse problem type */
19190c7d97c5SJed Brown   if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC && pcbddc->active_procs < MIN_PROCS_FOR_BDDC )
19200c7d97c5SJed Brown     pcbddc->coarse_problem_type = PARALLEL_BDDC;
19210c7d97c5SJed Brown 
19220c7d97c5SJed Brown   switch(pcbddc->coarse_problem_type){
19230c7d97c5SJed Brown 
19240c7d97c5SJed Brown     case(MULTILEVEL_BDDC):   //we define a coarse mesh where subdomains are elements
19250c7d97c5SJed Brown     {
19260c7d97c5SJed Brown       /* we need additional variables */
19270c7d97c5SJed Brown       MetisInt   n_subdomains,n_parts,objval,ncon,faces_nvtxs;
19280c7d97c5SJed Brown       MetisInt   *metis_coarse_subdivision;
19290c7d97c5SJed Brown       MetisInt   options[METIS_NOPTIONS];
19300c7d97c5SJed Brown       PetscMPIInt size_coarse_comm,rank_coarse_comm;
19310c7d97c5SJed Brown       PetscMPIInt procs_jumps_coarse_comm;
19320c7d97c5SJed Brown       PetscMPIInt *coarse_subdivision;
19330c7d97c5SJed Brown       PetscMPIInt *total_count_recv;
19340c7d97c5SJed Brown       PetscMPIInt *total_ranks_recv;
19350c7d97c5SJed Brown       PetscMPIInt *displacements_recv;
19360c7d97c5SJed Brown       PetscMPIInt *my_faces_connectivity;
19370c7d97c5SJed Brown       PetscMPIInt *petsc_faces_adjncy;
19380c7d97c5SJed Brown       MetisInt    *faces_adjncy;
19390c7d97c5SJed Brown       MetisInt    *faces_xadj;
19400c7d97c5SJed Brown       PetscMPIInt *number_of_faces;
19410c7d97c5SJed Brown       PetscMPIInt *faces_displacements;
19420c7d97c5SJed Brown       PetscInt    *array_int;
19430c7d97c5SJed Brown       PetscMPIInt my_faces=0;
19440c7d97c5SJed Brown       PetscMPIInt total_faces=0;
19453828260eSStefano Zampini       PetscInt    ranks_stretching_ratio;
19460c7d97c5SJed Brown 
19470c7d97c5SJed Brown       /* define some quantities */
19480c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
19490c7d97c5SJed Brown       coarse_mat_type = MATIS;
19500c7d97c5SJed Brown       coarse_pc_type  = PCBDDC;
19513b03a366Sstefano_zampini       coarse_ksp_type  = KSPCHEBYCHEV;
19520c7d97c5SJed Brown 
19530c7d97c5SJed Brown       /* details of coarse decomposition */
19540c7d97c5SJed Brown       n_subdomains = pcbddc->active_procs;
19550c7d97c5SJed Brown       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
19563828260eSStefano Zampini       ranks_stretching_ratio = size_prec_comm/pcbddc->active_procs;
19573828260eSStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
19583828260eSStefano Zampini 
19593828260eSStefano Zampini       printf("Coarse algorithm details: \n");
1960a0ba757dSStefano 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));
19610c7d97c5SJed Brown 
19620c7d97c5SJed Brown       /* build CSR graph of subdomains' connectivity through faces */
19630c7d97c5SJed Brown       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
19643828260eSStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
19650c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
19660c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19670c7d97c5SJed Brown           array_int[ pcis->shared[i][j] ]+=1;
19680c7d97c5SJed Brown         }
19690c7d97c5SJed Brown       }
19700c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
19710c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19720c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
19730c7d97c5SJed Brown             my_faces++;
19740c7d97c5SJed Brown             break;
19750c7d97c5SJed Brown           }
19760c7d97c5SJed Brown         }
19770c7d97c5SJed Brown       }
19780c7d97c5SJed Brown       //printf("I found %d faces.\n",my_faces);
19790c7d97c5SJed Brown 
198053cdbc3dSStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
19810c7d97c5SJed Brown       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
19820c7d97c5SJed Brown       my_faces=0;
19830c7d97c5SJed Brown       for(i=1;i<pcis->n_neigh;i++){
19840c7d97c5SJed Brown         for(j=0;j<pcis->n_shared[i];j++){
19850c7d97c5SJed Brown           if(array_int[ pcis->shared[i][j] ] == 1 ){
19860c7d97c5SJed Brown             my_faces_connectivity[my_faces]=pcis->neigh[i];
19870c7d97c5SJed Brown             my_faces++;
19880c7d97c5SJed Brown             break;
19890c7d97c5SJed Brown           }
19900c7d97c5SJed Brown         }
19910c7d97c5SJed Brown       }
19920c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
19930c7d97c5SJed Brown         //printf("I found %d total faces.\n",total_faces);
19940c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
19950c7d97c5SJed Brown         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
19960c7d97c5SJed Brown         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
19970c7d97c5SJed Brown         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
19980c7d97c5SJed Brown         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
19990c7d97c5SJed Brown       }
200053cdbc3dSStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
20010c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20020c7d97c5SJed Brown         faces_xadj[0]=0;
20030c7d97c5SJed Brown         faces_displacements[0]=0;
20040c7d97c5SJed Brown         j=0;
20050c7d97c5SJed Brown         for(i=1;i<size_prec_comm+1;i++) {
20060c7d97c5SJed Brown           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
20070c7d97c5SJed Brown           if(number_of_faces[i-1]) {
20080c7d97c5SJed Brown             j++;
20090c7d97c5SJed Brown             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
20100c7d97c5SJed Brown           }
20110c7d97c5SJed Brown         }
20120c7d97c5SJed Brown         printf("The J I count is %d and should be %d\n",j,n_subdomains);
20130c7d97c5SJed Brown         printf("Total faces seem %d and should be %d\n",faces_xadj[j],total_faces);
20140c7d97c5SJed Brown       }
201553cdbc3dSStefano 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);
20160c7d97c5SJed Brown       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
20170c7d97c5SJed Brown       ierr = PetscFree(array_int);CHKERRQ(ierr);
20180c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
20193828260eSStefano Zampini         for(i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
20203828260eSStefano Zampini         printf("This is the face connectivity (actual ranks)\n");
20210c7d97c5SJed Brown         for(i=0;i<n_subdomains;i++){
20220c7d97c5SJed Brown           printf("proc %d is connected with \n",i);
20230c7d97c5SJed Brown           for(j=faces_xadj[i];j<faces_xadj[i+1];j++)
20240c7d97c5SJed Brown             printf("%d ",faces_adjncy[j]);
20250c7d97c5SJed Brown           printf("\n");
20260c7d97c5SJed Brown         }
20270c7d97c5SJed Brown         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
20280c7d97c5SJed Brown         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
20290c7d97c5SJed Brown         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
20300c7d97c5SJed Brown       }
20310c7d97c5SJed Brown 
20320c7d97c5SJed Brown       if( rank_prec_comm == master_proc ) {
20330c7d97c5SJed Brown 
20343828260eSStefano Zampini         PetscInt heuristic_for_metis=3;
20353828260eSStefano Zampini 
20360c7d97c5SJed Brown         ncon=1;
20370c7d97c5SJed Brown         faces_nvtxs=n_subdomains;
20380c7d97c5SJed Brown         /* partition graoh induced by face connectivity */
20390c7d97c5SJed Brown         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
20400c7d97c5SJed Brown         ierr = METIS_SetDefaultOptions(options);
20410c7d97c5SJed Brown         /* we need a contiguous partition of the coarse mesh */
20420c7d97c5SJed Brown         options[METIS_OPTION_CONTIG]=1;
20430c7d97c5SJed Brown         options[METIS_OPTION_DBGLVL]=1;
20440c7d97c5SJed Brown         options[METIS_OPTION_NITER]=30;
20450c7d97c5SJed Brown         //options[METIS_OPTION_NCUTS]=1;
20463828260eSStefano Zampini         printf("METIS PART GRAPH\n");
20473828260eSStefano Zampini         if(n_subdomains>n_parts*heuristic_for_metis) {
20483828260eSStefano Zampini           printf("Using Kway\n");
20493828260eSStefano Zampini           options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
20503828260eSStefano Zampini           options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
20510c7d97c5SJed Brown           ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20523828260eSStefano Zampini         } else {
20533828260eSStefano Zampini           printf("Using Recursive\n");
20543828260eSStefano Zampini           ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
20553828260eSStefano Zampini         }
20560c7d97c5SJed 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);
20573828260eSStefano Zampini         printf("Partition done!\n");
20580c7d97c5SJed Brown         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
20590c7d97c5SJed Brown         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
20600c7d97c5SJed Brown         coarse_subdivision = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt)); /* calloc for contiguous memory since we need to scatter these values later */
20610c7d97c5SJed Brown         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
20623828260eSStefano Zampini         for(i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
20633828260eSStefano Zampini         for(i=0;i<n_subdomains;i++)   coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
20640c7d97c5SJed Brown         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
20650c7d97c5SJed Brown       }
20660c7d97c5SJed Brown 
20670c7d97c5SJed Brown       /* Create new communicator for coarse problem splitting the old one */
20680c7d97c5SJed Brown       if( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
20690c7d97c5SJed Brown         coarse_color=0;              //for communicator splitting
20700c7d97c5SJed Brown         active_rank=rank_prec_comm;  //for insertion of matrix values
20710c7d97c5SJed Brown       }
20720c7d97c5SJed Brown       // procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
20730c7d97c5SJed Brown       // key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator
207453cdbc3dSStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
20750c7d97c5SJed Brown 
20760c7d97c5SJed Brown       if( coarse_color == 0 ) {
207753cdbc3dSStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
207853cdbc3dSStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
20793828260eSStefano Zampini         printf("Details of coarse comm\n");
20803828260eSStefano Zampini         printf("size = %d, myrank = %d\n",size_coarse_comm,rank_coarse_comm);
20813828260eSStefano Zampini         printf("jumps = %d, coarse_color = %d, n_parts = %d\n",procs_jumps_coarse_comm,coarse_color,n_parts);
20820c7d97c5SJed Brown       } else {
20830c7d97c5SJed Brown         rank_coarse_comm = MPI_PROC_NULL;
20840c7d97c5SJed Brown       }
20850c7d97c5SJed Brown 
20860c7d97c5SJed Brown       /* master proc take care of arranging and distributing coarse informations */
20870c7d97c5SJed Brown       if(rank_coarse_comm == master_proc) {
20880c7d97c5SJed Brown         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
20890c7d97c5SJed Brown         //ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
20900c7d97c5SJed Brown         //ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
20910c7d97c5SJed Brown         total_count_recv = (PetscMPIInt*)calloc(size_prec_comm,sizeof(PetscMPIInt));
20920c7d97c5SJed Brown         total_ranks_recv = (PetscMPIInt*)calloc(n_subdomains,sizeof(PetscMPIInt));
20930c7d97c5SJed Brown         /* some initializations */
20940c7d97c5SJed Brown         displacements_recv[0]=0;
20950c7d97c5SJed Brown         //PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt)); not needed -> calloc initializes to zero
20960c7d97c5SJed Brown         /* count from how many processes the j-th process of the coarse decomposition will receive data */
20970c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++)
20983828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++)
20990c7d97c5SJed Brown             if(coarse_subdivision[i]==j)
21000c7d97c5SJed Brown               total_count_recv[j]++;
21010c7d97c5SJed Brown         /* displacements needed for scatterv of total_ranks_recv */
21020c7d97c5SJed Brown         for(i=1;i<size_coarse_comm;i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
21030c7d97c5SJed Brown         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
21040c7d97c5SJed Brown         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
21050c7d97c5SJed Brown         for(j=0;j<size_coarse_comm;j++) {
21063828260eSStefano Zampini           for(i=0;i<size_prec_comm;i++) {
21070c7d97c5SJed Brown             if(coarse_subdivision[i]==j) {
21080c7d97c5SJed Brown               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
21093828260eSStefano Zampini               total_count_recv[j]+=1;
21100c7d97c5SJed Brown             }
21110c7d97c5SJed Brown           }
21120c7d97c5SJed Brown         }
21133828260eSStefano Zampini         for(j=0;j<size_coarse_comm;j++) {
21143828260eSStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
21153828260eSStefano Zampini           for(i=0;i<total_count_recv[j];i++) {
21163828260eSStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
21173828260eSStefano Zampini           }
21183828260eSStefano Zampini           printf("\n");
21193828260eSStefano Zampini         }
21200c7d97c5SJed Brown 
21210c7d97c5SJed Brown         /* identify new decomposition in terms of ranks in the old communicator */
21223828260eSStefano Zampini         for(i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
21230c7d97c5SJed Brown         printf("coarse_subdivision in old end new ranks\n");
21240c7d97c5SJed Brown         for(i=0;i<size_prec_comm;i++)
21253828260eSStefano Zampini           if(coarse_subdivision[i]!=MPI_PROC_NULL) {
21263828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
21273828260eSStefano Zampini           } else {
21283828260eSStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
21293828260eSStefano Zampini           }
21300c7d97c5SJed Brown         printf("\n");
21310c7d97c5SJed Brown       }
21320c7d97c5SJed Brown 
21330c7d97c5SJed Brown       /* Scatter new decomposition for send details */
213453cdbc3dSStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
21350c7d97c5SJed Brown       /* Scatter receiving details to members of coarse decomposition */
21360c7d97c5SJed Brown       if( coarse_color == 0) {
213753cdbc3dSStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
21380c7d97c5SJed Brown         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
213953cdbc3dSStefano 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);
21400c7d97c5SJed Brown       }
21410c7d97c5SJed Brown 
21420c7d97c5SJed Brown       //printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
21430c7d97c5SJed Brown       //if(coarse_color == 0) {
21440c7d97c5SJed Brown       //  printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
21450c7d97c5SJed Brown       //  for(i=0;i<count_recv;i++)
21460c7d97c5SJed Brown       //    printf("%d ",ranks_recv[i]);
21470c7d97c5SJed Brown       //  printf("\n");
21480c7d97c5SJed Brown       //}
21490c7d97c5SJed Brown 
21500c7d97c5SJed Brown       if(rank_prec_comm == master_proc) {
21510c7d97c5SJed Brown         //ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
21520c7d97c5SJed Brown         //ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
21530c7d97c5SJed Brown         //ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
21540c7d97c5SJed Brown         free(coarse_subdivision);
21550c7d97c5SJed Brown         free(total_count_recv);
21560c7d97c5SJed Brown         free(total_ranks_recv);
21570c7d97c5SJed Brown         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
21580c7d97c5SJed Brown       }
21590c7d97c5SJed Brown       break;
21600c7d97c5SJed Brown     }
21610c7d97c5SJed Brown 
21620c7d97c5SJed Brown     case(REPLICATED_BDDC):
21630c7d97c5SJed Brown 
21640c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
21650c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
21660c7d97c5SJed Brown       coarse_pc_type  = PCLU;
216753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21680c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
21690c7d97c5SJed Brown       active_rank = rank_prec_comm;
21700c7d97c5SJed Brown       break;
21710c7d97c5SJed Brown 
21720c7d97c5SJed Brown     case(PARALLEL_BDDC):
21730c7d97c5SJed Brown 
21740c7d97c5SJed Brown       pcbddc->coarse_communications_type = SCATTERS_BDDC;
21750c7d97c5SJed Brown       coarse_mat_type = MATMPIAIJ;
21760c7d97c5SJed Brown       coarse_pc_type  = PCREDUNDANT;
217753cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21780c7d97c5SJed Brown       coarse_comm = prec_comm;
21790c7d97c5SJed Brown       active_rank = rank_prec_comm;
21800c7d97c5SJed Brown       break;
21810c7d97c5SJed Brown 
21820c7d97c5SJed Brown     case(SEQUENTIAL_BDDC):
21830c7d97c5SJed Brown       pcbddc->coarse_communications_type = GATHERS_BDDC;
21840c7d97c5SJed Brown       coarse_mat_type = MATSEQAIJ;
21850c7d97c5SJed Brown       coarse_pc_type = PCLU;
218653cdbc3dSStefano Zampini       coarse_ksp_type  = KSPPREONLY;
21870c7d97c5SJed Brown       coarse_comm = PETSC_COMM_SELF;
21880c7d97c5SJed Brown       active_rank = master_proc;
21890c7d97c5SJed Brown       break;
21900c7d97c5SJed Brown   }
21910c7d97c5SJed Brown 
21920c7d97c5SJed Brown   switch(pcbddc->coarse_communications_type){
21930c7d97c5SJed Brown 
21940c7d97c5SJed Brown     case(SCATTERS_BDDC):
21950c7d97c5SJed Brown       {
21960c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
21970c7d97c5SJed Brown 
21980c7d97c5SJed Brown           PetscMPIInt send_size;
21990c7d97c5SJed Brown           PetscInt    *aux_ins_indices;
22000c7d97c5SJed Brown           PetscInt    ii,jj;
22010c7d97c5SJed Brown           MPI_Request *requests;
22020c7d97c5SJed Brown 
22030c7d97c5SJed Brown           /* allocate auxiliary space */
22045619798eSStefano Zampini           ierr = PetscMalloc (pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
22055619798eSStefano 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);
22060c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
22070c7d97c5SJed Brown           ierr = PetscMemzero(aux_ins_indices,pcbddc->coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
22080c7d97c5SJed Brown           /* allocate stuffs for message massing */
22090c7d97c5SJed Brown           ierr = PetscMalloc ( (count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
22100c7d97c5SJed Brown           for(i=0;i<count_recv+1;i++) requests[i]=MPI_REQUEST_NULL;
22110c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
22120c7d97c5SJed Brown           ierr = PetscMalloc ( count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
22130c7d97c5SJed Brown           /* fill up quantities */
22140c7d97c5SJed Brown           j=0;
22150c7d97c5SJed Brown           for(i=0;i<count_recv;i++){
22160c7d97c5SJed Brown             ii = ranks_recv[i];
22170c7d97c5SJed Brown             localsizes2[i]=pcbddc->local_primal_sizes[ii]*pcbddc->local_primal_sizes[ii];
22180c7d97c5SJed Brown             localdispl2[i]=j;
22190c7d97c5SJed Brown             j+=localsizes2[i];
22200c7d97c5SJed Brown             jj = pcbddc->local_primal_displacements[ii];
22210c7d97c5SJed 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
22220c7d97c5SJed Brown           }
22230c7d97c5SJed Brown           //printf("aux_ins_indices 1\n");
22240c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22250c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22260c7d97c5SJed Brown           //printf("\n");
22270c7d97c5SJed Brown           /* temp_coarse_mat_vals used to store temporarly received matrix values */
22280c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
22290c7d97c5SJed Brown           /* evaluate how many values I will insert in coarse mat */
22300c7d97c5SJed Brown           ins_local_primal_size=0;
22310c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22320c7d97c5SJed Brown             if(aux_ins_indices[i])
22330c7d97c5SJed Brown               ins_local_primal_size++;
22340c7d97c5SJed Brown           /* evaluate indices I will insert in coarse mat */
22350c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
22360c7d97c5SJed Brown           j=0;
22370c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++)
22380c7d97c5SJed Brown             if(aux_ins_indices[i])
22390c7d97c5SJed Brown               ins_local_primal_indices[j++]=i;
22400c7d97c5SJed Brown           /* use aux_ins_indices to realize a global to local mapping */
22410c7d97c5SJed Brown           j=0;
22420c7d97c5SJed Brown           for(i=0;i<pcbddc->coarse_size;i++){
22430c7d97c5SJed Brown             if(aux_ins_indices[i]==0){
22440c7d97c5SJed Brown               aux_ins_indices[i]=-1;
22450c7d97c5SJed Brown             } else {
22460c7d97c5SJed Brown               aux_ins_indices[i]=j;
22470c7d97c5SJed Brown               j++;
22480c7d97c5SJed Brown             }
22490c7d97c5SJed Brown           }
22500c7d97c5SJed Brown 
22510c7d97c5SJed Brown           //printf("New details localsizes2 localdispl2\n");
22520c7d97c5SJed Brown           //for(i=0;i<count_recv;i++)
22530c7d97c5SJed Brown           //  printf("(%d %d) ",localsizes2[i],localdispl2[i]);
22540c7d97c5SJed Brown           //printf("\n");
22550c7d97c5SJed Brown           //printf("aux_ins_indices 2\n");
22560c7d97c5SJed Brown           //for(i=0;i<pcbddc->coarse_size;i++)
22570c7d97c5SJed Brown           //  printf("%d ",aux_ins_indices[i]);
22580c7d97c5SJed Brown           //printf("\n");
22590c7d97c5SJed Brown           //printf("ins_local_primal_indices\n");
22600c7d97c5SJed Brown           //for(i=0;i<ins_local_primal_size;i++)
22610c7d97c5SJed Brown           //  printf("%d ",ins_local_primal_indices[i]);
22620c7d97c5SJed Brown           //printf("\n");
22630c7d97c5SJed Brown           //printf("coarse_submat_vals\n");
22640c7d97c5SJed Brown           //for(i=0;i<pcbddc->local_primal_size;i++)
22650c7d97c5SJed Brown           //  for(j=0;j<pcbddc->local_primal_size;j++)
22660c7d97c5SJed 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]);
22670c7d97c5SJed Brown           //printf("\n");
22680c7d97c5SJed Brown 
22690c7d97c5SJed Brown           /* processes partecipating in coarse problem receive matrix data from their friends */
227053cdbc3dSStefano 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);
22710c7d97c5SJed Brown           if(rank_coarse_proc_send_to != MPI_PROC_NULL ) {
22720c7d97c5SJed Brown             send_size=pcbddc->local_primal_size*pcbddc->local_primal_size;
227353cdbc3dSStefano 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);
22740c7d97c5SJed Brown           }
227553cdbc3dSStefano Zampini           ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
22760c7d97c5SJed Brown 
22770c7d97c5SJed Brown           //if(coarse_color == 0) {
22780c7d97c5SJed Brown           //  printf("temp_coarse_mat_vals\n");
22790c7d97c5SJed Brown           //  for(k=0;k<count_recv;k++){
22800c7d97c5SJed Brown           //    printf("---- %d ----\n",ranks_recv[k]);
22810c7d97c5SJed Brown           //    for(i=0;i<pcbddc->local_primal_sizes[ranks_recv[k]];i++)
22820c7d97c5SJed Brown           //      for(j=0;j<pcbddc->local_primal_sizes[ranks_recv[k]];j++)
22830c7d97c5SJed 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]);
22840c7d97c5SJed Brown           //    printf("\n");
22850c7d97c5SJed Brown           //  }
22860c7d97c5SJed Brown           //}
22870c7d97c5SJed Brown           /* calculate data to insert in coarse mat */
22880c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
22890c7d97c5SJed Brown           PetscMemzero(ins_coarse_mat_vals,ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar));
22900c7d97c5SJed Brown 
22910c7d97c5SJed Brown           PetscMPIInt rr,kk,lps,lpd;
22920c7d97c5SJed Brown           PetscInt row_ind,col_ind;
22930c7d97c5SJed Brown           for(k=0;k<count_recv;k++){
22940c7d97c5SJed Brown             rr = ranks_recv[k];
22950c7d97c5SJed Brown             kk = localdispl2[k];
22960c7d97c5SJed Brown             lps = pcbddc->local_primal_sizes[rr];
22970c7d97c5SJed Brown             lpd = pcbddc->local_primal_displacements[rr];
22980c7d97c5SJed Brown             //printf("Inserting the following indices (received from %d)\n",rr);
22990c7d97c5SJed Brown             for(j=0;j<lps;j++){
23000c7d97c5SJed Brown               col_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+j]];
23010c7d97c5SJed Brown               for(i=0;i<lps;i++){
23020c7d97c5SJed Brown                 row_ind=aux_ins_indices[pcbddc->replicated_local_primal_indices[lpd+i]];
23030c7d97c5SJed Brown                 //printf("%d %d\n",row_ind,col_ind);
23040c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*ins_local_primal_size+row_ind]+=temp_coarse_mat_vals[kk+j*lps+i];
23050c7d97c5SJed Brown               }
23060c7d97c5SJed Brown             }
23070c7d97c5SJed Brown           }
23080c7d97c5SJed Brown           ierr = PetscFree(requests);CHKERRQ(ierr);
23090c7d97c5SJed Brown           ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
23100c7d97c5SJed Brown           ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);
23110c7d97c5SJed Brown           if(coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
23120c7d97c5SJed Brown 
23130c7d97c5SJed Brown           /* create local to global mapping needed by coarse MATIS */
23140c7d97c5SJed Brown           {
23150c7d97c5SJed Brown             IS coarse_IS;
231653cdbc3dSStefano Zampini             if(coarse_comm != MPI_COMM_NULL ) ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);
23170c7d97c5SJed Brown             coarse_comm = prec_comm;
23180c7d97c5SJed Brown             active_rank=rank_prec_comm;
23190c7d97c5SJed Brown             ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
23200c7d97c5SJed Brown             ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
23210c7d97c5SJed Brown             ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
23220c7d97c5SJed Brown           }
23230c7d97c5SJed Brown         }
23240c7d97c5SJed Brown         if(pcbddc->coarse_problem_type==PARALLEL_BDDC) {
23250c7d97c5SJed Brown           /* arrays for values insertion */
23260c7d97c5SJed Brown           ins_local_primal_size = pcbddc->local_primal_size;
23270c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23280c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23290c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23300c7d97c5SJed Brown             ins_local_primal_indices[j]=pcbddc->local_primal_indices[j];
23310c7d97c5SJed 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];
23320c7d97c5SJed Brown           }
23330c7d97c5SJed Brown         }
23340c7d97c5SJed Brown         break;
23350c7d97c5SJed Brown 
23360c7d97c5SJed Brown     }
23370c7d97c5SJed Brown 
23380c7d97c5SJed Brown     case(GATHERS_BDDC):
23390c7d97c5SJed Brown       {
23400c7d97c5SJed Brown 
23410c7d97c5SJed Brown         PetscMPIInt mysize,mysize2;
23420c7d97c5SJed Brown 
23430c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23440c7d97c5SJed Brown           ierr = PetscMalloc ( pcbddc->replicated_primal_size*sizeof(PetscMPIInt),&pcbddc->replicated_local_primal_indices);CHKERRQ(ierr);
23450c7d97c5SJed Brown           pcbddc->replicated_local_primal_values = (PetscScalar*)calloc(pcbddc->replicated_primal_size,sizeof(PetscScalar));
23460c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
23470c7d97c5SJed Brown           ierr = PetscMalloc ( size_prec_comm*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
23480c7d97c5SJed Brown           /* arrays for values insertion */
23490c7d97c5SJed Brown           ins_local_primal_size = pcbddc->coarse_size;
23500c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*sizeof(PetscMPIInt),&ins_local_primal_indices);CHKERRQ(ierr);
23510c7d97c5SJed Brown           ierr = PetscMalloc ( ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
23520c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) localsizes2[i]=pcbddc->local_primal_sizes[i]*pcbddc->local_primal_sizes[i];
23530c7d97c5SJed Brown           localdispl2[0]=0;
23540c7d97c5SJed Brown           for(i=1;i<size_prec_comm;i++) localdispl2[i]=localsizes2[i-1]+localdispl2[i-1];
23550c7d97c5SJed Brown           j=0;
23560c7d97c5SJed Brown           for(i=0;i<size_prec_comm;i++) j+=localsizes2[i];
23570c7d97c5SJed Brown           ierr = PetscMalloc ( j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
23580c7d97c5SJed Brown         }
23590c7d97c5SJed Brown 
23600c7d97c5SJed Brown         mysize=pcbddc->local_primal_size;
23610c7d97c5SJed Brown         mysize2=pcbddc->local_primal_size*pcbddc->local_primal_size;
23620c7d97c5SJed Brown         if(pcbddc->coarse_problem_type == SEQUENTIAL_BDDC){
236353cdbc3dSStefano 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);
236453cdbc3dSStefano 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);
23650c7d97c5SJed Brown         } else {
236653cdbc3dSStefano 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);
236753cdbc3dSStefano Zampini           ierr = MPI_Allgatherv(&coarse_submat_vals[0],mysize2,MPIU_SCALAR,&temp_coarse_mat_vals[0],localsizes2,localdispl2,MPIU_SCALAR,prec_comm);CHKERRQ(ierr);
23680c7d97c5SJed Brown         }
23690c7d97c5SJed Brown 
23700c7d97c5SJed Brown   /* free data structures no longer needed and allocate some space which will be needed in BDDC application */
23710c7d97c5SJed Brown         if(rank_prec_comm==active_rank) {
23720c7d97c5SJed Brown           PetscInt offset,offset2,row_ind,col_ind;
23730c7d97c5SJed Brown           for(j=0;j<ins_local_primal_size;j++){
23740c7d97c5SJed Brown             ins_local_primal_indices[j]=j;
23750c7d97c5SJed Brown             for(i=0;i<ins_local_primal_size;i++) ins_coarse_mat_vals[j*ins_local_primal_size+i]=0.0;
23760c7d97c5SJed Brown           }
23770c7d97c5SJed Brown           for(k=0;k<size_prec_comm;k++){
23780c7d97c5SJed Brown             offset=pcbddc->local_primal_displacements[k];
23790c7d97c5SJed Brown             offset2=localdispl2[k];
23800c7d97c5SJed Brown             for(j=0;j<pcbddc->local_primal_sizes[k];j++){
23810c7d97c5SJed Brown               col_ind=pcbddc->replicated_local_primal_indices[offset+j];
23820c7d97c5SJed Brown               for(i=0;i<pcbddc->local_primal_sizes[k];i++){
23830c7d97c5SJed Brown                 row_ind=pcbddc->replicated_local_primal_indices[offset+i];
23840c7d97c5SJed Brown                 ins_coarse_mat_vals[col_ind*pcbddc->coarse_size+row_ind]+=temp_coarse_mat_vals[offset2+j*pcbddc->local_primal_sizes[k]+i];
23850c7d97c5SJed Brown               }
23860c7d97c5SJed Brown             }
23870c7d97c5SJed Brown           }
23880c7d97c5SJed Brown         }
23890c7d97c5SJed Brown         break;
23900c7d97c5SJed Brown       }//switch on coarse problem and communications associated with finished
23910c7d97c5SJed Brown   }
23920c7d97c5SJed Brown 
23930c7d97c5SJed Brown   /* Now create and fill up coarse matrix */
23940c7d97c5SJed Brown   if( rank_prec_comm == active_rank ) {
23950c7d97c5SJed Brown     if(pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
23960c7d97c5SJed Brown       ierr = MatCreate(coarse_comm,&pcbddc->coarse_mat);CHKERRQ(ierr);
23970c7d97c5SJed Brown       ierr = MatSetSizes(pcbddc->coarse_mat,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size);CHKERRQ(ierr);
23980c7d97c5SJed Brown       ierr = MatSetType(pcbddc->coarse_mat,coarse_mat_type);CHKERRQ(ierr);
23993b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24000c7d97c5SJed Brown       ierr = MatSetOption(pcbddc->coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
24013b03a366Sstefano_zampini       ierr = MatSetOption(pcbddc->coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24020c7d97c5SJed Brown     } else {
24030c7d97c5SJed Brown       Mat matis_coarse_local_mat;
2404d3ee2243SStefano Zampini       /* remind bs */
2405d3ee2243SStefano Zampini       ierr = MatCreateIS(coarse_comm,bs,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_ISLG,&pcbddc->coarse_mat);CHKERRQ(ierr);
24063b03a366Sstefano_zampini       ierr = MatSetUp(pcbddc->coarse_mat);CHKERRQ(ierr);
24070c7d97c5SJed Brown       ierr = MatISGetLocalMat(pcbddc->coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
24083b03a366Sstefano_zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
24090c7d97c5SJed Brown       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); //local values stored in column major
2410a0ba757dSStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
24110c7d97c5SJed Brown     }
2412a0ba757dSStefano Zampini     ierr = MatSetOption(pcbddc->coarse_mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);
24130c7d97c5SJed 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);
24140c7d97c5SJed Brown     ierr = MatAssemblyBegin(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24150c7d97c5SJed Brown     ierr = MatAssemblyEnd(pcbddc->coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
24160c7d97c5SJed Brown 
24170c7d97c5SJed Brown     ierr = MatGetVecs(pcbddc->coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
24180c7d97c5SJed Brown     /* Preconditioner for coarse problem */
241953cdbc3dSStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
242053cdbc3dSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
242153cdbc3dSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,pcbddc->coarse_mat,pcbddc->coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
24223b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
242353cdbc3dSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
242453cdbc3dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
242553cdbc3dSStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
24260c7d97c5SJed Brown     /* Allow user's customization */
242753cdbc3dSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24280c7d97c5SJed Brown     /* Set Up PC for coarse problem BDDC */
242953cdbc3dSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2430e269702eSStefano Zampini       if(dbg_flag) {
2431e269702eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Setting up a new level---------------\n");CHKERRQ(ierr);
2432e269702eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2433e269702eSStefano Zampini       }
243453cdbc3dSStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
243553cdbc3dSStefano Zampini     }
243653cdbc3dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
24375619798eSStefano Zampini     if(pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
24385619798eSStefano Zampini       if(dbg_flag) {
24395619798eSStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------New level set------------------------\n");CHKERRQ(ierr);
24405619798eSStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
24415619798eSStefano Zampini       }
24425619798eSStefano Zampini     }
24430c7d97c5SJed Brown   }
24440c7d97c5SJed Brown   if(pcbddc->coarse_communications_type == SCATTERS_BDDC) {
24450c7d97c5SJed Brown      IS local_IS,global_IS;
24460c7d97c5SJed Brown      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
24470c7d97c5SJed Brown      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
24480c7d97c5SJed Brown      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
24490c7d97c5SJed Brown      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
24500c7d97c5SJed Brown      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
24510c7d97c5SJed Brown   }
24520c7d97c5SJed Brown 
24530c7d97c5SJed Brown 
24543b03a366Sstefano_zampini   /* Evaluate condition number of coarse problem for cheby (and verbose output if requested) */
24553b03a366Sstefano_zampini   if( pcbddc->coarse_problem_type == MULTILEVEL_BDDC && rank_prec_comm == active_rank ) {
24560c7d97c5SJed Brown     PetscScalar m_one=-1.0;
24575619798eSStefano Zampini     PetscReal   infty_error,lambda_min,lambda_max,kappa_2;
24583b03a366Sstefano_zampini     const KSPType check_ksp_type=KSPGMRES;
24590c7d97c5SJed Brown 
24605619798eSStefano Zampini     /* change coarse ksp object to an iterative method suitable for extreme eigenvalues' estimation */
24613b03a366Sstefano_zampini     ierr = KSPSetType(pcbddc->coarse_ksp,check_ksp_type);CHKERRQ(ierr);
2462d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_TRUE);CHKERRQ(ierr);
24635619798eSStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,1.e-8,1.e-8,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
24645619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2465d49ef151SStefano Zampini     ierr = VecSetRandom(pcbddc->coarse_rhs,PETSC_NULL);CHKERRQ(ierr);
2466d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
2467d49ef151SStefano Zampini     ierr = MatMult(pcbddc->coarse_mat,pcbddc->coarse_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
2468d49ef151SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_rhs);CHKERRQ(ierr);
2469d49ef151SStefano Zampini     ierr = KSPComputeExtremeSingularValues(pcbddc->coarse_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
24703b03a366Sstefano_zampini     if(dbg_flag) {
24715619798eSStefano Zampini       kappa_2=lambda_max/lambda_min;
24725619798eSStefano Zampini       ierr = KSPGetIterationNumber(pcbddc->coarse_ksp,&k);CHKERRQ(ierr);
2473d49ef151SStefano Zampini       ierr = VecAXPY(pcbddc->coarse_rhs,m_one,pcbddc->coarse_vec);CHKERRQ(ierr);
2474d49ef151SStefano Zampini       ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
24753b03a366Sstefano_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);
2476e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
2477e269702eSStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem infty_error: %1.14e\n",infty_error);CHKERRQ(ierr);
24783b03a366Sstefano_zampini     }
24795619798eSStefano Zampini     /* restore coarse ksp to default values */
2480d49ef151SStefano Zampini     ierr = KSPSetComputeSingularValues(pcbddc->coarse_ksp,PETSC_FALSE);CHKERRQ(ierr);
24815619798eSStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
24823b03a366Sstefano_zampini     ierr = KSPChebychevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
24833b03a366Sstefano_zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
24845619798eSStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
24855619798eSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
248653cdbc3dSStefano Zampini   }
24870c7d97c5SJed Brown 
24880c7d97c5SJed Brown   /* free data structures no longer needed */
24890c7d97c5SJed Brown   if(coarse_ISLG)                { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
24900c7d97c5SJed Brown   if(ins_local_primal_indices)   { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);  }
24910c7d97c5SJed Brown   if(ins_coarse_mat_vals)        { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr);}
24920c7d97c5SJed Brown   if(localsizes2)                { ierr = PetscFree(localsizes2);CHKERRQ(ierr);}
24930c7d97c5SJed Brown   if(localdispl2)                { ierr = PetscFree(localdispl2);CHKERRQ(ierr);}
24940c7d97c5SJed Brown   if(temp_coarse_mat_vals)       { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr);}
24950c7d97c5SJed Brown 
24960c7d97c5SJed Brown   PetscFunctionReturn(0);
24970c7d97c5SJed Brown }
24980c7d97c5SJed Brown 
24990c7d97c5SJed Brown #undef __FUNCT__
25000c7d97c5SJed Brown #define __FUNCT__ "PCBDDCManageLocalBoundaries"
250153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCManageLocalBoundaries(PC pc)
25020c7d97c5SJed Brown {
25030c7d97c5SJed Brown 
25040c7d97c5SJed Brown   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
25050c7d97c5SJed Brown   PC_IS         *pcis = (PC_IS*)pc->data;
25060c7d97c5SJed Brown   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
25070c7d97c5SJed Brown   PCBDDCGraph mat_graph;
25080c7d97c5SJed Brown   Mat         mat_adj;
25093b03a366Sstefano_zampini   PetscInt    **neighbours_set;
2510a0ba757dSStefano Zampini   PetscInt    *queue_in_global_numbering;
25113b03a366Sstefano_zampini   PetscInt    bs,ierr,i,j,s,k,iindex,neumann_bsize,dirichlet_bsize;
25123b03a366Sstefano_zampini   PetscInt    total_counts,nodes_touched=0,where_values=1,vertex_size;
25133b03a366Sstefano_zampini   PetscMPIInt adapt_interface=0,adapt_interface_reduced=0;
25143b03a366Sstefano_zampini   PetscBool   same_set,flg_row;
25153b03a366Sstefano_zampini   PetscBool   symmetrize_rowij=PETSC_TRUE,compressed_rowij=PETSC_FALSE;
2516a0ba757dSStefano Zampini   MPI_Comm    interface_comm=((PetscObject)pc)->comm;
25173b03a366Sstefano_zampini   PetscBool   use_faces=PETSC_FALSE,use_edges=PETSC_FALSE;
25183b03a366Sstefano_zampini   const PetscInt *neumann_nodes;
25193b03a366Sstefano_zampini   const PetscInt *dirichlet_nodes;
25200c7d97c5SJed Brown 
25210c7d97c5SJed Brown   PetscFunctionBegin;
2522a0ba757dSStefano Zampini   /* allocate and initialize needed graph structure */
25230c7d97c5SJed Brown   ierr = PetscMalloc(sizeof(*mat_graph),&mat_graph);CHKERRQ(ierr);
25240c7d97c5SJed Brown   ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
2525a0ba757dSStefano Zampini   /* ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&mat_adj);CHKERRQ(ierr); */
2526a0ba757dSStefano Zampini   ierr = MatGetRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
25270c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called from PCBDDCManageLocalBoundaries.\n");
2528a0ba757dSStefano Zampini   i = mat_graph->nvtxs;
2529a0ba757dSStefano 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);
2530a0ba757dSStefano Zampini   ierr = PetscMalloc3(i,PetscInt,&mat_graph->which_dof,i,PetscBool,&mat_graph->touched,i,PetscInt,&queue_in_global_numbering);CHKERRQ(ierr);
2531a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->where,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2532a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2533a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->which_dof,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2534a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25353828260eSStefano Zampini   ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
25363828260eSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++){mat_graph->touched[i]=PETSC_FALSE;}
2537a0ba757dSStefano Zampini 
25389c0446d6SStefano Zampini   /* Setting dofs splitting in mat_graph->which_dof */
25399c0446d6SStefano Zampini   if(pcbddc->n_ISForDofs) { /* get information about dofs' splitting if provided by the user */
25409c0446d6SStefano Zampini     PetscInt *is_indices;
25419c0446d6SStefano Zampini     PetscInt is_size;
25429c0446d6SStefano Zampini     for(i=0;i<pcbddc->n_ISForDofs;i++) {
25439c0446d6SStefano Zampini       ierr = ISGetSize(pcbddc->ISForDofs[i],&is_size);CHKERRQ(ierr);
25449c0446d6SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25459c0446d6SStefano Zampini       for(j=0;j<is_size;j++) {
25469c0446d6SStefano Zampini         mat_graph->which_dof[is_indices[j]]=i;
25479c0446d6SStefano Zampini       }
25489c0446d6SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofs[i],(const PetscInt**)&is_indices);CHKERRQ(ierr);
25499c0446d6SStefano Zampini     }
25503b03a366Sstefano_zampini     /* use mat block size as vertex size */
25513b03a366Sstefano_zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
25523b03a366Sstefano_zampini   } else { /* otherwise it assumes a constant block size */
2553a0ba757dSStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
25540c7d97c5SJed Brown     for(i=0;i<mat_graph->nvtxs/bs;i++) {
25550c7d97c5SJed Brown       for(s=0;s<bs;s++) {
25560c7d97c5SJed Brown         mat_graph->which_dof[i*bs+s]=s;
25570c7d97c5SJed Brown       }
25580c7d97c5SJed Brown     }
25593b03a366Sstefano_zampini     vertex_size=1;
25609c0446d6SStefano Zampini   }
25613b03a366Sstefano_zampini   /* count number of neigh per node */
25620c7d97c5SJed Brown   total_counts=0;
25633b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
25640c7d97c5SJed Brown     s=pcis->n_shared[i];
25650c7d97c5SJed Brown     total_counts+=s;
256653cdbc3dSStefano Zampini     for(j=0;j<s;j++){
25670c7d97c5SJed Brown       mat_graph->count[pcis->shared[i][j]] += 1;
25680c7d97c5SJed Brown     }
25690c7d97c5SJed Brown   }
25703b03a366Sstefano_zampini   /* Take into account Neumann data -> it increments number of sharing subdomains for all but faces nodes lying on the interface */
257153cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
25729c0446d6SStefano Zampini     ierr = ISGetSize(pcbddc->NeumannBoundaries,&neumann_bsize);CHKERRQ(ierr);
257353cdbc3dSStefano Zampini     ierr = ISGetIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
257453cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
257553cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
25763b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
257753cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
25780c7d97c5SJed Brown         total_counts++;
25790c7d97c5SJed Brown       }
25800c7d97c5SJed Brown     }
25810c7d97c5SJed Brown   }
25823b03a366Sstefano_zampini   /* allocate space for storing the set of neighbours of each node */
258353cdbc3dSStefano Zampini   ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt*),&neighbours_set);CHKERRQ(ierr);
25843b03a366Sstefano_zampini   if(mat_graph->nvtxs) { ierr = PetscMalloc(total_counts*sizeof(PetscInt),&neighbours_set[0]);CHKERRQ(ierr); }
258553cdbc3dSStefano Zampini   for(i=1;i<mat_graph->nvtxs;i++) neighbours_set[i]=neighbours_set[i-1]+mat_graph->count[i-1];
2586a0ba757dSStefano Zampini   ierr = PetscMemzero(mat_graph->count,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
25873b03a366Sstefano_zampini   for(i=1;i<pcis->n_neigh;i++){
25880c7d97c5SJed Brown     s=pcis->n_shared[i];
25890c7d97c5SJed Brown     for(j=0;j<s;j++) {
25900c7d97c5SJed Brown       k=pcis->shared[i][j];
259153cdbc3dSStefano Zampini       neighbours_set[k][mat_graph->count[k]] = pcis->neigh[i];
25920c7d97c5SJed Brown       mat_graph->count[k]+=1;
25930c7d97c5SJed Brown     }
25940c7d97c5SJed Brown   }
25953b03a366Sstefano_zampini   /* set -1 fake neighbour to mimic Neumann boundary */
259653cdbc3dSStefano Zampini   if(pcbddc->NeumannBoundaries) {
259753cdbc3dSStefano Zampini     for(i=0;i<neumann_bsize;i++){
259853cdbc3dSStefano Zampini       iindex = neumann_nodes[i];
25993b03a366Sstefano_zampini       if(mat_graph->count[iindex] > 1){
26003b03a366Sstefano_zampini         neighbours_set[iindex][mat_graph->count[iindex]] = -1;
260153cdbc3dSStefano Zampini         mat_graph->count[iindex]+=1;
26020c7d97c5SJed Brown       }
26030c7d97c5SJed Brown     }
260453cdbc3dSStefano Zampini     ierr = ISRestoreIndices(pcbddc->NeumannBoundaries,&neumann_nodes);CHKERRQ(ierr);
26050c7d97c5SJed Brown   }
26063b03a366Sstefano_zampini   /* sort set of sharing subdomains (needed for comparison below) */
260753cdbc3dSStefano Zampini   for(i=0;i<mat_graph->nvtxs;i++) { ierr = PetscSortInt(mat_graph->count[i],neighbours_set[i]);CHKERRQ(ierr); }
26083b03a366Sstefano_zampini   /* remove interior nodes and dirichlet boundary nodes from the next search into the graph */
26093b03a366Sstefano_zampini   if(pcbddc->DirichletBoundaries) {
26103b03a366Sstefano_zampini     ierr = ISGetSize(pcbddc->DirichletBoundaries,&dirichlet_bsize);CHKERRQ(ierr);
26113b03a366Sstefano_zampini     ierr = ISGetIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
26123b03a366Sstefano_zampini     for(i=0;i<dirichlet_bsize;i++){
26133b03a366Sstefano_zampini       mat_graph->count[dirichlet_nodes[i]]=0;
26143b03a366Sstefano_zampini     }
26153b03a366Sstefano_zampini     ierr = ISRestoreIndices(pcbddc->DirichletBoundaries,&dirichlet_nodes);CHKERRQ(ierr);
26163b03a366Sstefano_zampini   }
26170c7d97c5SJed Brown   for(i=0;i<mat_graph->nvtxs;i++){
26183b03a366Sstefano_zampini     if(!mat_graph->count[i]){  /* interior nodes */
26190c7d97c5SJed Brown       mat_graph->touched[i]=PETSC_TRUE;
26200c7d97c5SJed Brown       mat_graph->where[i]=0;
26210c7d97c5SJed Brown       nodes_touched++;
26220c7d97c5SJed Brown     }
26230c7d97c5SJed Brown   }
26240c7d97c5SJed Brown   mat_graph->ncmps = 0;
26250c7d97c5SJed Brown   while(nodes_touched<mat_graph->nvtxs) {
2626a0ba757dSStefano Zampini     /*  find first untouched node in local ordering */
26270c7d97c5SJed Brown     i=0;
26280c7d97c5SJed Brown     while(mat_graph->touched[i]) i++;
26290c7d97c5SJed Brown     mat_graph->touched[i]=PETSC_TRUE;
2630a0ba757dSStefano Zampini     mat_graph->where[i]=where_values;
26310c7d97c5SJed Brown     nodes_touched++;
2632a0ba757dSStefano Zampini     /* now find all other nodes having the same set of sharing subdomains */
26330c7d97c5SJed Brown     for(j=i+1;j<mat_graph->nvtxs;j++){
2634a0ba757dSStefano Zampini       /* check for same number of sharing subdomains and dof number */
26350c7d97c5SJed Brown       if(mat_graph->count[i]==mat_graph->count[j] && mat_graph->which_dof[i] == mat_graph->which_dof[j] ){
2636a0ba757dSStefano Zampini         /* check for same set of sharing subdomains */
26370c7d97c5SJed Brown         same_set=PETSC_TRUE;
26380c7d97c5SJed Brown         for(k=0;k<mat_graph->count[j];k++){
263953cdbc3dSStefano Zampini           if(neighbours_set[i][k]!=neighbours_set[j][k]) {
26400c7d97c5SJed Brown             same_set=PETSC_FALSE;
26410c7d97c5SJed Brown           }
26420c7d97c5SJed Brown         }
2643a0ba757dSStefano Zampini         /* I found a friend of mine */
26440c7d97c5SJed Brown         if(same_set) {
2645a0ba757dSStefano Zampini           mat_graph->where[j]=where_values;
26460c7d97c5SJed Brown           mat_graph->touched[j]=PETSC_TRUE;
26470c7d97c5SJed Brown           nodes_touched++;
26480c7d97c5SJed Brown         }
26490c7d97c5SJed Brown       }
26500c7d97c5SJed Brown     }
2651a0ba757dSStefano Zampini     where_values++;
26520c7d97c5SJed Brown   }
2653a0ba757dSStefano Zampini   where_values--; if(where_values<0) where_values=0;
2654a0ba757dSStefano Zampini   ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2655a0ba757dSStefano Zampini   /* Find connected components defined on the shared interface */
2656a0ba757dSStefano Zampini   if(where_values) {
2657a0ba757dSStefano Zampini     ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
26583b03a366Sstefano_zampini     /* For consistency among neughbouring procs, I need to sort (by global ordering) each connected component */
2659a0ba757dSStefano Zampini     for(i=0;i<mat_graph->ncmps;i++) {
2660a0ba757dSStefano 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);
2661a0ba757dSStefano 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);
2662a0ba757dSStefano Zampini     }
2663a0ba757dSStefano Zampini   }
2664a0ba757dSStefano Zampini   /* check consistency of connected components among neighbouring subdomains -> it adapt them in case it is needed */
2665a0ba757dSStefano Zampini   for(i=0;i<where_values;i++) {
26663b03a366Sstefano_zampini     /* We are not sure that two connected components will be the same among subdomains sharing a subset of local interface */
26673b03a366Sstefano_zampini     if(mat_graph->where_ncmps[i]>1) {
2668a0ba757dSStefano Zampini       adapt_interface=1;
2669a0ba757dSStefano Zampini       break;
2670a0ba757dSStefano Zampini     }
2671a0ba757dSStefano Zampini   }
2672a0ba757dSStefano Zampini   ierr = MPI_Allreduce(&adapt_interface,&adapt_interface_reduced,1,MPIU_INT,MPI_LOR,interface_comm);CHKERRQ(ierr);
2673a0ba757dSStefano Zampini   if(where_values && adapt_interface_reduced) {
26740c7d97c5SJed Brown 
26753b03a366Sstefano_zampini     printf("Adapting Interface\n");
26763b03a366Sstefano_zampini 
2677a0ba757dSStefano Zampini     PetscInt sum_requests=0,my_rank;
2678a0ba757dSStefano Zampini     PetscInt buffer_size,start_of_recv,size_of_recv,start_of_send;
2679a0ba757dSStefano Zampini     PetscInt temp_buffer_size,ins_val,global_where_counter;
2680a0ba757dSStefano Zampini     PetscInt *cum_recv_counts;
2681a0ba757dSStefano Zampini     PetscInt *where_to_nodes_indices;
2682a0ba757dSStefano Zampini     PetscInt *petsc_buffer;
2683a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer;
2684a0ba757dSStefano Zampini     PetscMPIInt *recv_buffer_where;
2685a0ba757dSStefano Zampini     PetscMPIInt *send_buffer;
2686a0ba757dSStefano Zampini     PetscMPIInt size_of_send;
2687a0ba757dSStefano Zampini     PetscInt *sizes_of_sends;
2688a0ba757dSStefano Zampini     MPI_Request *send_requests;
2689a0ba757dSStefano Zampini     MPI_Request *recv_requests;
2690a0ba757dSStefano Zampini     PetscInt *where_cc_adapt;
2691a0ba757dSStefano Zampini     PetscInt **temp_buffer;
2692a0ba757dSStefano Zampini     PetscInt *nodes_to_temp_buffer_indices;
2693a0ba757dSStefano Zampini     PetscInt *add_to_where;
2694a0ba757dSStefano Zampini 
2695a0ba757dSStefano Zampini     ierr = MPI_Comm_rank(interface_comm,&my_rank);CHKERRQ(ierr);
2696a0ba757dSStefano Zampini     ierr = PetscMalloc((where_values+1)*sizeof(PetscInt),&cum_recv_counts);CHKERRQ(ierr);
2697a0ba757dSStefano Zampini     ierr = PetscMemzero(cum_recv_counts,(where_values+1)*sizeof(PetscInt));CHKERRQ(ierr);
2698a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_to_nodes_indices);CHKERRQ(ierr);
2699a0ba757dSStefano Zampini     /* first count how many neighbours per connected component I will receive from */
2700a0ba757dSStefano Zampini     cum_recv_counts[0]=0;
2701a0ba757dSStefano Zampini     for(i=1;i<where_values+1;i++){
2702a0ba757dSStefano Zampini       j=0;
2703a0ba757dSStefano Zampini       while(mat_graph->where[j] != i) j++;
2704a0ba757dSStefano Zampini       where_to_nodes_indices[i-1]=j;
27053b03a366Sstefano_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  */
27063b03a366Sstefano_zampini       else { cum_recv_counts[i]=cum_recv_counts[i-1]+mat_graph->count[j]-1; }
2707a0ba757dSStefano Zampini     }
2708a0ba757dSStefano Zampini     buffer_size=2*cum_recv_counts[where_values]+mat_graph->nvtxs;
2709a0ba757dSStefano Zampini     ierr = PetscMalloc(2*cum_recv_counts[where_values]*sizeof(PetscMPIInt),&recv_buffer_where);CHKERRQ(ierr);
2710a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2711a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&send_requests);CHKERRQ(ierr);
2712a0ba757dSStefano Zampini     ierr = PetscMalloc(cum_recv_counts[where_values]*sizeof(MPI_Request),&recv_requests);CHKERRQ(ierr);
2713a0ba757dSStefano Zampini     for(i=0;i<cum_recv_counts[where_values];i++) {
2714a0ba757dSStefano Zampini       send_requests[i]=MPI_REQUEST_NULL;
2715a0ba757dSStefano Zampini       recv_requests[i]=MPI_REQUEST_NULL;
2716a0ba757dSStefano Zampini     }
2717a0ba757dSStefano Zampini     /* exchange with my neighbours the number of my connected components on the shared interface */
2718a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2719a0ba757dSStefano Zampini       j=where_to_nodes_indices[i];
2720a0ba757dSStefano Zampini       k = (neighbours_set[j][0] == -1 ?  1 : 0);
2721a0ba757dSStefano Zampini       for(;k<mat_graph->count[j];k++){
2722a0ba757dSStefano 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);
2723a0ba757dSStefano 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);
2724a0ba757dSStefano Zampini         sum_requests++;
2725a0ba757dSStefano Zampini       }
2726a0ba757dSStefano Zampini     }
2727a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2728a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2729a0ba757dSStefano Zampini     /* determine the connected component I need to adapt */
2730a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&where_cc_adapt);CHKERRQ(ierr);
2731a0ba757dSStefano Zampini     ierr = PetscMemzero(where_cc_adapt,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2732a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2733a0ba757dSStefano Zampini       for(j=cum_recv_counts[i];j<cum_recv_counts[i+1];j++){
27343b03a366Sstefano_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 */
27353b03a366Sstefano_zampini         if( mat_graph->where_ncmps[i]!=recv_buffer_where[j] || mat_graph->where_ncmps[i] > 1 ) {
2736a0ba757dSStefano Zampini           where_cc_adapt[i]=PETSC_TRUE;
2737a0ba757dSStefano Zampini           break;
2738a0ba757dSStefano Zampini         }
2739a0ba757dSStefano Zampini       }
2740a0ba757dSStefano Zampini     }
2741a0ba757dSStefano Zampini     /* now get from neighbours their ccs (in global numbering) and adapt them (in case it is needed) */
2742a0ba757dSStefano Zampini     /* first determine how much data to send (size of each queue plus the global indices) and communicate it to neighbours */
2743a0ba757dSStefano Zampini     ierr = PetscMalloc(where_values*sizeof(PetscInt),&sizes_of_sends);CHKERRQ(ierr);
2744a0ba757dSStefano Zampini     ierr = PetscMemzero(sizes_of_sends,where_values*sizeof(PetscInt));CHKERRQ(ierr);
2745a0ba757dSStefano Zampini     sum_requests=0;
2746a0ba757dSStefano Zampini     start_of_send=0;
2747a0ba757dSStefano Zampini     start_of_recv=cum_recv_counts[where_values];
2748a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2749a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2750a0ba757dSStefano Zampini         size_of_send=0;
2751a0ba757dSStefano Zampini         for(j=i;j<mat_graph->ncmps;j++) {
2752a0ba757dSStefano Zampini           if(mat_graph->where[mat_graph->queue[mat_graph->cptr[j]]] == i+1) { /* WARNING -> where values goes from 1 to where_values included */
2753a0ba757dSStefano Zampini             send_buffer[start_of_send+size_of_send]=mat_graph->cptr[j+1]-mat_graph->cptr[j];
2754a0ba757dSStefano Zampini             size_of_send+=1;
2755a0ba757dSStefano Zampini             for(k=0;k<mat_graph->cptr[j+1]-mat_graph->cptr[j];k++) {
2756a0ba757dSStefano Zampini               send_buffer[start_of_send+size_of_send+k]=queue_in_global_numbering[mat_graph->cptr[j]+k];
2757a0ba757dSStefano Zampini             }
2758a0ba757dSStefano Zampini             size_of_send=size_of_send+mat_graph->cptr[j+1]-mat_graph->cptr[j];
2759a0ba757dSStefano Zampini           }
2760a0ba757dSStefano Zampini         }
2761a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2762a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2763a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2764a0ba757dSStefano 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);
2765a0ba757dSStefano 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);
2766a0ba757dSStefano Zampini           sum_requests++;
2767a0ba757dSStefano Zampini         }
2768a0ba757dSStefano Zampini         sizes_of_sends[i]=size_of_send;
2769a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2770a0ba757dSStefano Zampini       }
2771a0ba757dSStefano Zampini     }
2772a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2773a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2774a0ba757dSStefano Zampini     buffer_size=0;
2775a0ba757dSStefano Zampini     for(k=0;k<sum_requests;k++) { buffer_size+=recv_buffer_where[start_of_recv+k]; }
2776a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscMPIInt),&recv_buffer);CHKERRQ(ierr);
2777a0ba757dSStefano Zampini     /* now exchange the data */
2778a0ba757dSStefano Zampini     start_of_recv=0;
2779a0ba757dSStefano Zampini     start_of_send=0;
2780a0ba757dSStefano Zampini     sum_requests=0;
2781a0ba757dSStefano Zampini     for(i=0;i<where_values;i++) {
2782a0ba757dSStefano Zampini       if(where_cc_adapt[i]) {
2783a0ba757dSStefano Zampini         size_of_send = sizes_of_sends[i];
2784a0ba757dSStefano Zampini         j = where_to_nodes_indices[i];
2785a0ba757dSStefano Zampini         k = (neighbours_set[j][0] == -1 ?  1 : 0);
2786a0ba757dSStefano Zampini         for(;k<mat_graph->count[j];k++){
2787a0ba757dSStefano 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);
2788a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[cum_recv_counts[where_values]+sum_requests];
2789a0ba757dSStefano 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);
2790a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2791a0ba757dSStefano Zampini           sum_requests++;
2792a0ba757dSStefano Zampini         }
2793a0ba757dSStefano Zampini         start_of_send+=size_of_send;
2794a0ba757dSStefano Zampini       }
2795a0ba757dSStefano Zampini     }
2796a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,recv_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2797a0ba757dSStefano Zampini     ierr = MPI_Waitall(sum_requests,send_requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2798a0ba757dSStefano Zampini     ierr = PetscMalloc(buffer_size*sizeof(PetscInt),&petsc_buffer);CHKERRQ(ierr);
2799a0ba757dSStefano Zampini     for(k=0;k<start_of_recv;k++) { petsc_buffer[k]=(PetscInt)recv_buffer[k]; }
2800a0ba757dSStefano Zampini     for(j=0;j<buffer_size;) {
2801a0ba757dSStefano Zampini        ierr = ISGlobalToLocalMappingApply(matis->mapping,IS_GTOLM_MASK,petsc_buffer[j],&petsc_buffer[j+1],&petsc_buffer[j],&petsc_buffer[j+1]);CHKERRQ(ierr);
2802a0ba757dSStefano Zampini        k=petsc_buffer[j]+1;
2803a0ba757dSStefano Zampini        j+=k;
2804a0ba757dSStefano Zampini     }
2805a0ba757dSStefano Zampini     sum_requests=cum_recv_counts[where_values];
2806a0ba757dSStefano Zampini     start_of_recv=0;
2807a0ba757dSStefano Zampini     ierr = PetscMalloc(mat_graph->nvtxs*sizeof(PetscInt),&nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2808a0ba757dSStefano Zampini     global_where_counter=0;
2809a0ba757dSStefano Zampini     for(i=0;i<where_values;i++){
2810a0ba757dSStefano Zampini       if(where_cc_adapt[i]){
2811a0ba757dSStefano Zampini         temp_buffer_size=0;
2812a0ba757dSStefano Zampini         /* find nodes on the shared interface we need to adapt */
2813a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2814a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2815a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=temp_buffer_size;
2816a0ba757dSStefano Zampini             temp_buffer_size++;
2817a0ba757dSStefano Zampini           } else {
2818a0ba757dSStefano Zampini             nodes_to_temp_buffer_indices[j]=-1;
2819a0ba757dSStefano Zampini           }
2820a0ba757dSStefano Zampini         }
2821a0ba757dSStefano Zampini         /* allocate some temporary space */
2822a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt*),&temp_buffer);CHKERRQ(ierr);
2823a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt),&temp_buffer[0]);CHKERRQ(ierr);
2824a0ba757dSStefano Zampini         ierr = PetscMemzero(temp_buffer[0],temp_buffer_size*(cum_recv_counts[i+1]-cum_recv_counts[i])*sizeof(PetscInt));CHKERRQ(ierr);
2825a0ba757dSStefano Zampini         for(j=1;j<temp_buffer_size;j++){
2826a0ba757dSStefano Zampini           temp_buffer[j]=temp_buffer[j-1]+cum_recv_counts[i+1]-cum_recv_counts[i];
2827a0ba757dSStefano Zampini         }
2828a0ba757dSStefano Zampini         /* analyze contributions from neighbouring subdomains for i-th conn comp
2829a0ba757dSStefano Zampini            temp buffer structure:
2830a0ba757dSStefano Zampini            supposing part of the interface has dimension 5 (global nodes 0,1,2,3,4)
2831a0ba757dSStefano Zampini            3 neighs procs with structured connected components:
2832a0ba757dSStefano Zampini              neigh 0: [0 1 4], [2 3];  (2 connected components)
2833a0ba757dSStefano Zampini              neigh 1: [0 1], [2 3 4];  (2 connected components)
2834a0ba757dSStefano Zampini              neigh 2: [0 4], [1], [2 3]; (3 connected components)
2835a0ba757dSStefano Zampini            tempbuffer (row-oriented) should be filled as:
2836a0ba757dSStefano Zampini              [ 0, 0, 0;
2837a0ba757dSStefano Zampini                0, 0, 1;
2838a0ba757dSStefano Zampini                1, 1, 2;
2839a0ba757dSStefano Zampini                1, 1, 2;
2840a0ba757dSStefano Zampini                0, 1, 0; ];
2841a0ba757dSStefano Zampini            This way we can simply recover the resulting structure account for possible intersections of ccs among neighs.
2842a0ba757dSStefano Zampini            The mat_graph->where array will be modified to reproduce the following 4 connected components [0], [1], [2 3], [4];
2843a0ba757dSStefano Zampini                                                                                                                                    */
2844a0ba757dSStefano Zampini         for(j=0;j<cum_recv_counts[i+1]-cum_recv_counts[i];j++) {
2845a0ba757dSStefano Zampini           ins_val=0;
2846a0ba757dSStefano Zampini           size_of_recv=recv_buffer_where[sum_requests];  /* total size of recv from neighs */
2847a0ba757dSStefano Zampini           for(buffer_size=0;buffer_size<size_of_recv;) {  /* loop until all data from neighs has been taken into account */
2848a0ba757dSStefano Zampini             for(k=1;k<petsc_buffer[buffer_size+start_of_recv]+1;k++) { /* filling properly temp_buffer using data from a single recv */
2849a0ba757dSStefano Zampini               temp_buffer[ nodes_to_temp_buffer_indices[ petsc_buffer[ start_of_recv+buffer_size+k ] ] ][j]=ins_val;
2850a0ba757dSStefano Zampini             }
2851a0ba757dSStefano Zampini             buffer_size+=k;
2852a0ba757dSStefano Zampini             ins_val++;
2853a0ba757dSStefano Zampini           }
2854a0ba757dSStefano Zampini           start_of_recv+=size_of_recv;
2855a0ba757dSStefano Zampini           sum_requests++;
2856a0ba757dSStefano Zampini         }
2857a0ba757dSStefano Zampini         ierr = PetscMalloc(temp_buffer_size*sizeof(PetscInt),&add_to_where);CHKERRQ(ierr);
2858a0ba757dSStefano Zampini         ierr = PetscMemzero(add_to_where,temp_buffer_size*sizeof(PetscInt));CHKERRQ(ierr);
2859a0ba757dSStefano Zampini         for(j=0;j<temp_buffer_size;j++){
2860a0ba757dSStefano Zampini           if(!add_to_where[j]){ /* found a new cc  */
2861a0ba757dSStefano Zampini             global_where_counter++;
2862a0ba757dSStefano Zampini             add_to_where[j]=global_where_counter;
2863a0ba757dSStefano Zampini             for(k=j+1;k<temp_buffer_size;k++){ /* check for other nodes in new cc */
2864a0ba757dSStefano Zampini               same_set=PETSC_TRUE;
2865a0ba757dSStefano Zampini               for(s=0;s<cum_recv_counts[i+1]-cum_recv_counts[i];s++){
2866a0ba757dSStefano Zampini                 if(temp_buffer[j][s]!=temp_buffer[k][s]) {
2867a0ba757dSStefano Zampini                   same_set=PETSC_FALSE;
2868a0ba757dSStefano Zampini                   break;
2869a0ba757dSStefano Zampini                 }
2870a0ba757dSStefano Zampini               }
2871a0ba757dSStefano Zampini               if(same_set) add_to_where[k]=global_where_counter;
2872a0ba757dSStefano Zampini             }
2873a0ba757dSStefano Zampini           }
2874a0ba757dSStefano Zampini         }
2875a0ba757dSStefano Zampini         /* insert new data in where array */
2876a0ba757dSStefano Zampini         temp_buffer_size=0;
2877a0ba757dSStefano Zampini         for(j=0;j<mat_graph->nvtxs;j++){
2878a0ba757dSStefano Zampini           if(mat_graph->where[j]==i+1) {
2879a0ba757dSStefano Zampini             mat_graph->where[j]=where_values+add_to_where[temp_buffer_size];
2880a0ba757dSStefano Zampini             temp_buffer_size++;
2881a0ba757dSStefano Zampini           }
2882a0ba757dSStefano Zampini         }
2883a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer[0]);CHKERRQ(ierr);
2884a0ba757dSStefano Zampini         ierr = PetscFree(temp_buffer);CHKERRQ(ierr);
2885a0ba757dSStefano Zampini         ierr = PetscFree(add_to_where);CHKERRQ(ierr);
2886a0ba757dSStefano Zampini       }
2887a0ba757dSStefano Zampini     }
2888a0ba757dSStefano Zampini     ierr = PetscFree(nodes_to_temp_buffer_indices);CHKERRQ(ierr);
2889a0ba757dSStefano Zampini     ierr = PetscFree(sizes_of_sends);CHKERRQ(ierr);
2890a0ba757dSStefano Zampini     ierr = PetscFree(send_requests);CHKERRQ(ierr);
2891a0ba757dSStefano Zampini     ierr = PetscFree(recv_requests);CHKERRQ(ierr);
2892a0ba757dSStefano Zampini     ierr = PetscFree(petsc_buffer);CHKERRQ(ierr);
2893a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer);CHKERRQ(ierr);
2894a0ba757dSStefano Zampini     ierr = PetscFree(recv_buffer_where);CHKERRQ(ierr);
2895a0ba757dSStefano Zampini     ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2896a0ba757dSStefano Zampini     ierr = PetscFree(cum_recv_counts);CHKERRQ(ierr);
2897a0ba757dSStefano Zampini     ierr = PetscFree(where_to_nodes_indices);CHKERRQ(ierr);
2898a0ba757dSStefano Zampini     /* We are ready to evaluate consistent connected components on each part of the shared interface */
2899a0ba757dSStefano Zampini     if(global_where_counter) {
2900a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){ mat_graph->touched[i]=PETSC_FALSE; }
2901a0ba757dSStefano Zampini       global_where_counter=0;
2902a0ba757dSStefano Zampini       for(i=0;i<mat_graph->nvtxs;i++){
2903a0ba757dSStefano Zampini         if(mat_graph->where[i] && !mat_graph->touched[i]) {
2904a0ba757dSStefano Zampini           global_where_counter++;
2905a0ba757dSStefano Zampini           for(j=i+1;j<mat_graph->nvtxs;j++){
2906a0ba757dSStefano Zampini             if(!mat_graph->touched[j] && mat_graph->where[j]==mat_graph->where[i]) {
2907a0ba757dSStefano Zampini               mat_graph->where[j]=global_where_counter;
2908a0ba757dSStefano Zampini               mat_graph->touched[j]=PETSC_TRUE;
2909a0ba757dSStefano Zampini             }
2910a0ba757dSStefano Zampini           }
2911a0ba757dSStefano Zampini           mat_graph->where[i]=global_where_counter;
2912a0ba757dSStefano Zampini           mat_graph->touched[i]=PETSC_TRUE;
2913a0ba757dSStefano Zampini         }
2914a0ba757dSStefano Zampini       }
2915a0ba757dSStefano Zampini       where_values=global_where_counter;
2916a0ba757dSStefano Zampini     }
2917a0ba757dSStefano Zampini     if(global_where_counter) {
2918a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->cptr,(mat_graph->nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
2919a0ba757dSStefano Zampini       ierr = PetscMemzero(mat_graph->queue,mat_graph->nvtxs*sizeof(PetscInt));CHKERRQ(ierr);
2920a0ba757dSStefano Zampini       ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
2921a0ba757dSStefano Zampini       ierr = PetscMalloc(where_values*sizeof(PetscMPIInt),&mat_graph->where_ncmps);CHKERRQ(ierr);
2922a0ba757dSStefano Zampini       ierr = PCBDDCFindConnectedComponents(mat_graph, where_values);
2923a0ba757dSStefano Zampini       for(i=0;i<mat_graph->ncmps;i++) {
2924a0ba757dSStefano 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);
2925a0ba757dSStefano 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);
2926a0ba757dSStefano Zampini       }
2927a0ba757dSStefano Zampini     }
29283b03a366Sstefano_zampini   } /* Finished adapting interface */
29290c7d97c5SJed Brown   PetscInt nfc=0;
29300c7d97c5SJed Brown   PetscInt nec=0;
29310c7d97c5SJed Brown   PetscInt nvc=0;
29323b03a366Sstefano_zampini   PetscBool twodim_flag=PETSC_FALSE;
29330c7d97c5SJed Brown   for (i=0; i<mat_graph->ncmps; i++) {
29343b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
29353b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){ /* 1 neigh */
29360c7d97c5SJed Brown         nfc++;
29373b03a366Sstefano_zampini       } else { /* note that nec will be zero in 2d */
29383b03a366Sstefano_zampini         nec++;
29393b03a366Sstefano_zampini       }
29400c7d97c5SJed Brown     } else {
29413b03a366Sstefano_zampini       nvc+=mat_graph->cptr[i+1]-mat_graph->cptr[i];
29423b03a366Sstefano_zampini     }
29433b03a366Sstefano_zampini   }
29443b03a366Sstefano_zampini 
29453b03a366Sstefano_zampini   if(!nec) { /* we are in a 2d case -> no faces, only edges */
29463b03a366Sstefano_zampini     nec = nfc;
29473b03a366Sstefano_zampini     nfc = 0;
29483b03a366Sstefano_zampini     twodim_flag = PETSC_TRUE;
29493b03a366Sstefano_zampini   }
29503b03a366Sstefano_zampini   /* allocate IS arrays for faces, edges. Vertices need a single index set.
29513b03a366Sstefano_zampini      Reusing space allocated in mat_graph->where for creating IS objects */
29523b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->edges_flag) {
29533b03a366Sstefano_zampini     ierr = PetscMalloc(nfc*sizeof(IS),&pcbddc->ISForFaces);CHKERRQ(ierr);
29543b03a366Sstefano_zampini     use_faces=PETSC_TRUE;
29553b03a366Sstefano_zampini   }
29563b03a366Sstefano_zampini   if(!pcbddc->vertices_flag && !pcbddc->faces_flag) {
29573b03a366Sstefano_zampini     ierr = PetscMalloc(nec*sizeof(IS),&pcbddc->ISForEdges);CHKERRQ(ierr);
29583b03a366Sstefano_zampini     use_edges=PETSC_TRUE;
29593b03a366Sstefano_zampini   }
29603b03a366Sstefano_zampini   nfc=0;
29613b03a366Sstefano_zampini   nec=0;
29623b03a366Sstefano_zampini   for (i=0; i<mat_graph->ncmps; i++) {
29633b03a366Sstefano_zampini     if( mat_graph->cptr[i+1]-mat_graph->cptr[i] > vertex_size ){
29643b03a366Sstefano_zampini       for(j=0;j<mat_graph->cptr[i+1]-mat_graph->cptr[i];j++) {
29653b03a366Sstefano_zampini         mat_graph->where[j]=mat_graph->queue[mat_graph->cptr[i]+j];
29663b03a366Sstefano_zampini       }
29673b03a366Sstefano_zampini       if(mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]==1){
29683b03a366Sstefano_zampini         if(twodim_flag) {
29693b03a366Sstefano_zampini           if(use_edges) {
29703b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
29713b03a366Sstefano_zampini             nec++;
29723b03a366Sstefano_zampini           }
29733b03a366Sstefano_zampini         } else {
29743b03a366Sstefano_zampini           if(use_faces) {
29753b03a366Sstefano_zampini             ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForFaces[nfc]);CHKERRQ(ierr);
29763b03a366Sstefano_zampini             nfc++;
29773b03a366Sstefano_zampini           }
29783b03a366Sstefano_zampini         }
29793b03a366Sstefano_zampini       } else {
29803b03a366Sstefano_zampini         if(use_edges) {
29813b03a366Sstefano_zampini           ierr = ISCreateGeneral(PETSC_COMM_SELF,j,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForEdges[nec]);CHKERRQ(ierr);
29820c7d97c5SJed Brown           nec++;
29830c7d97c5SJed Brown         }
29840c7d97c5SJed Brown       }
29850c7d97c5SJed Brown     }
29863b03a366Sstefano_zampini   }
29873b03a366Sstefano_zampini   pcbddc->n_ISForFaces=nfc;
29883b03a366Sstefano_zampini   pcbddc->n_ISForEdges=nec;
29893b03a366Sstefano_zampini   nvc=0;
29900c7d97c5SJed Brown   if( !pcbddc->constraints_flag ) {
29913b03a366Sstefano_zampini     for (i=0; i<mat_graph->ncmps; i++) {
29923b03a366Sstefano_zampini       if( mat_graph->cptr[i+1]-mat_graph->cptr[i] <= vertex_size ){
29933b03a366Sstefano_zampini         for( j=mat_graph->cptr[i];j<mat_graph->cptr[i+1];j++) {
29943b03a366Sstefano_zampini           mat_graph->where[nvc]=mat_graph->queue[j];
29950c7d97c5SJed Brown           nvc++;
29960c7d97c5SJed Brown         }
29970c7d97c5SJed Brown       }
29980c7d97c5SJed Brown     }
29990c7d97c5SJed Brown   }
3000a0ba757dSStefano Zampini   /* sort vertex set (by local ordering) */
30013b03a366Sstefano_zampini   ierr = PetscSortInt(nvc,mat_graph->where);CHKERRQ(ierr);
30023b03a366Sstefano_zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,nvc,mat_graph->where,PETSC_COPY_VALUES,&pcbddc->ISForVertices);CHKERRQ(ierr);
30030c7d97c5SJed Brown 
3004e269702eSStefano Zampini   if(pcbddc->dbg_flag) {
3005e269702eSStefano Zampini     PetscViewer viewer=pcbddc->dbg_viewer;
3006e269702eSStefano Zampini 
3007d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3008d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Details from PCBDDCManageLocalBoundaries for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3009d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3010a0ba757dSStefano Zampini /*    ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Graph (adjacency structure) of local Neumann mat\n");CHKERRQ(ierr);
3011a0ba757dSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
3012e269702eSStefano Zampini     for(i=0;i<mat_graph->nvtxs;i++) {
3013a0ba757dSStefano 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);
3014e269702eSStefano Zampini       for(j=mat_graph->xadj[i];j<mat_graph->xadj[i+1];j++){
3015a0ba757dSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d ",mat_graph->adjncy[j]);CHKERRQ(ierr);
3016e269702eSStefano Zampini       }
3017a0ba757dSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);
30183b03a366Sstefano_zampini     }
3019d49ef151SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Matrix graph has %d connected components", mat_graph->ncmps);CHKERRQ(ierr);
30200c7d97c5SJed Brown     for(i=0;i<mat_graph->ncmps;i++) {
30213b03a366Sstefano_zampini       ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\nDetails for connected component number %02d: size %04d, count %01d. Nodes follow.\n",
30223b03a366Sstefano_zampini              i,mat_graph->cptr[i+1]-mat_graph->cptr[i],mat_graph->count[mat_graph->queue[mat_graph->cptr[i]]]);CHKERRQ(ierr);
30230c7d97c5SJed Brown       for (j=mat_graph->cptr[i]; j<mat_graph->cptr[i+1]; j++){
30243828260eSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(viewer,"%d (%d), ",queue_in_global_numbering[j],mat_graph->queue[j]);CHKERRQ(ierr);
30250c7d97c5SJed Brown       }
30260c7d97c5SJed Brown     }
30273b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"\n--------------------------------------------------------------\n");CHKERRQ(ierr);*/
30283b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local vertices\n",PetscGlobalRank,nvc);CHKERRQ(ierr);
30293b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local faces\n",PetscGlobalRank,nfc);CHKERRQ(ierr);
30303b03a366Sstefano_zampini     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d detected %02d local edges\n",PetscGlobalRank,nec);CHKERRQ(ierr);
3031d49ef151SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
30320c7d97c5SJed Brown   }
30330c7d97c5SJed Brown 
3034a0ba757dSStefano Zampini   /* Restore CSR structure into sequantial matrix and free memory space no longer needed */
3035a0ba757dSStefano Zampini   ierr = MatRestoreRowIJ(mat_adj,0,symmetrize_rowij,compressed_rowij,&mat_graph->nvtxs,&mat_graph->xadj,&mat_graph->adjncy,&flg_row);CHKERRQ(ierr);
30360c7d97c5SJed Brown   if(!flg_row) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called from PCBDDCManageLocalBoundaries.\n");
3037a0ba757dSStefano Zampini   ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
3038a0ba757dSStefano Zampini   /* Free graph structure */
30390c7d97c5SJed Brown   if(mat_graph->nvtxs){
3040a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set[0]);CHKERRQ(ierr);
3041a0ba757dSStefano Zampini     ierr = PetscFree(neighbours_set);CHKERRQ(ierr);
3042a0ba757dSStefano Zampini     ierr = PetscFree4(mat_graph->where,mat_graph->count,mat_graph->cptr,mat_graph->queue);CHKERRQ(ierr);
3043a0ba757dSStefano Zampini     ierr = PetscFree3(mat_graph->which_dof,mat_graph->touched,queue_in_global_numbering);CHKERRQ(ierr);
3044a0ba757dSStefano Zampini     ierr = PetscFree(mat_graph->where_ncmps);CHKERRQ(ierr);
30450c7d97c5SJed Brown   }
30460c7d97c5SJed Brown   ierr = PetscFree(mat_graph);CHKERRQ(ierr);
30470c7d97c5SJed Brown 
30480c7d97c5SJed Brown   PetscFunctionReturn(0);
30490c7d97c5SJed Brown 
30500c7d97c5SJed Brown }
30510c7d97c5SJed Brown 
30520c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
30530c7d97c5SJed Brown 
30540c7d97c5SJed Brown /* The following code has been adapted from function IsConnectedSubdomain contained
30550c7d97c5SJed Brown    in source file contig.c of METIS library (version 5.0.1)                           */
30560c7d97c5SJed Brown 
30570c7d97c5SJed Brown #undef __FUNCT__
30580c7d97c5SJed Brown #define __FUNCT__ "PCBDDCFindConnectedComponents"
30599c0446d6SStefano Zampini static PetscErrorCode PCBDDCFindConnectedComponents(PCBDDCGraph graph, PetscInt n_dist )
30600c7d97c5SJed Brown {
30610c7d97c5SJed Brown   PetscInt i, j, k, nvtxs, first, last, nleft, ncmps,pid,cum_queue,n,ncmps_pid;
30620c7d97c5SJed Brown   PetscInt *xadj, *adjncy, *where, *queue;
30630c7d97c5SJed Brown   PetscInt *cptr;
30640c7d97c5SJed Brown   PetscBool *touched;
30650c7d97c5SJed Brown 
30660c7d97c5SJed Brown   PetscFunctionBegin;
30670c7d97c5SJed Brown 
30680c7d97c5SJed Brown   nvtxs   = graph->nvtxs;
30690c7d97c5SJed Brown   xadj    = graph->xadj;
30700c7d97c5SJed Brown   adjncy  = graph->adjncy;
30710c7d97c5SJed Brown   where   = graph->where;
30720c7d97c5SJed Brown   touched = graph->touched;
30730c7d97c5SJed Brown   queue   = graph->queue;
30740c7d97c5SJed Brown   cptr    = graph->cptr;
30750c7d97c5SJed Brown 
30760c7d97c5SJed Brown   for (i=0; i<nvtxs; i++)
30770c7d97c5SJed Brown     touched[i] = PETSC_FALSE;
30780c7d97c5SJed Brown 
30790c7d97c5SJed Brown   cum_queue=0;
30800c7d97c5SJed Brown   ncmps=0;
30810c7d97c5SJed Brown 
30820c7d97c5SJed Brown   for(n=0; n<n_dist; n++) {
3083a0ba757dSStefano Zampini     pid = n+1;
30840c7d97c5SJed Brown     nleft = 0;
30850c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
30860c7d97c5SJed Brown       if (where[i] == pid)
30870c7d97c5SJed Brown         nleft++;
30880c7d97c5SJed Brown     }
30890c7d97c5SJed Brown     for (i=0; i<nvtxs; i++) {
30900c7d97c5SJed Brown       if (where[i] == pid)
30910c7d97c5SJed Brown         break;
30920c7d97c5SJed Brown     }
30930c7d97c5SJed Brown     touched[i] = PETSC_TRUE;
30940c7d97c5SJed Brown     queue[cum_queue] = i;
30950c7d97c5SJed Brown     first = 0; last = 1;
30960c7d97c5SJed Brown     cptr[ncmps] = cum_queue;  /* This actually points to queue */
30970c7d97c5SJed Brown     ncmps_pid = 0;
30980c7d97c5SJed Brown     while (first != nleft) {
30990c7d97c5SJed Brown       if (first == last) { /* Find another starting vertex */
31000c7d97c5SJed Brown         cptr[++ncmps] = first+cum_queue;
31010c7d97c5SJed Brown         ncmps_pid++;
31020c7d97c5SJed Brown         for (i=0; i<nvtxs; i++) {
31030c7d97c5SJed Brown           if (where[i] == pid && !touched[i])
31040c7d97c5SJed Brown             break;
31050c7d97c5SJed Brown         }
31060c7d97c5SJed Brown         queue[cum_queue+last] = i;
31070c7d97c5SJed Brown         last++;
31080c7d97c5SJed Brown         touched[i] = PETSC_TRUE;
31090c7d97c5SJed Brown       }
31100c7d97c5SJed Brown       i = queue[cum_queue+first];
31110c7d97c5SJed Brown       first++;
31120c7d97c5SJed Brown       for (j=xadj[i]; j<xadj[i+1]; j++) {
31130c7d97c5SJed Brown         k = adjncy[j];
31140c7d97c5SJed Brown         if (where[k] == pid && !touched[k]) {
31150c7d97c5SJed Brown           queue[cum_queue+last] = k;
31160c7d97c5SJed Brown           last++;
31170c7d97c5SJed Brown           touched[k] = PETSC_TRUE;
31180c7d97c5SJed Brown         }
31190c7d97c5SJed Brown       }
31200c7d97c5SJed Brown     }
31210c7d97c5SJed Brown     cptr[++ncmps] = first+cum_queue;
31220c7d97c5SJed Brown     ncmps_pid++;
31230c7d97c5SJed Brown     cum_queue=cptr[ncmps];
3124a0ba757dSStefano Zampini     graph->where_ncmps[n] = ncmps_pid;
31250c7d97c5SJed Brown   }
31260c7d97c5SJed Brown   graph->ncmps = ncmps;
31270c7d97c5SJed Brown 
31280c7d97c5SJed Brown   PetscFunctionReturn(0);
31290c7d97c5SJed Brown }
31300c7d97c5SJed Brown 
3131