xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision f34684f1ec6d42f1be6f8f2de4992eb43c62fbb1)
1674ae819SStefano Zampini #include "bddc.h"
2674ae819SStefano Zampini #include "bddcprivate.h"
3674ae819SStefano Zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
5674ae819SStefano Zampini #undef __FUNCT__
6c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
7c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
8c8587f34SStefano Zampini {
9c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
108629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
11c8587f34SStefano Zampini   PetscErrorCode ierr;
12c8587f34SStefano Zampini 
13c8587f34SStefano Zampini   PetscFunctionBegin;
14c8587f34SStefano Zampini   /* Compute matrix after change of basis and extract local submatrices */
15c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalMatrices(pc);CHKERRQ(ierr);
16c8587f34SStefano Zampini 
17c8587f34SStefano Zampini   /* Allocate needed vectors */
18c8587f34SStefano Zampini   ierr = PCBDDCCreateWorkVectors(pc);CHKERRQ(ierr);
19c8587f34SStefano Zampini 
20c8587f34SStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D : PCBDDCCreateWorkVectors should be called first! */
21c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
22c8587f34SStefano Zampini 
23c8587f34SStefano Zampini   /* Setup local solvers ksp_D and ksp_R */
24c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc);CHKERRQ(ierr);
25c8587f34SStefano Zampini 
26c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
27c8587f34SStefano Zampini   if (pcbddc->NullSpace && pcbddc->use_change_of_basis) {
28c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
29c8587f34SStefano Zampini   }
30c8587f34SStefano Zampini 
318629588bSStefano Zampini   /*
328629588bSStefano Zampini      Setup local correction and local part of coarse basis.
338629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
348629588bSStefano Zampini   */
358629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseLocal(pc,&coarse_submat_vals);CHKERRQ(ierr);
368629588bSStefano Zampini 
378629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
388629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
398629588bSStefano Zampini 
408629588bSStefano Zampini   /* free */
418629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
42c8587f34SStefano Zampini   PetscFunctionReturn(0);
43c8587f34SStefano Zampini }
44c8587f34SStefano Zampini 
45c8587f34SStefano Zampini #undef __FUNCT__
46a401a8b6SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
47a401a8b6SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
48a401a8b6SStefano Zampini {
49a401a8b6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
50a401a8b6SStefano Zampini 
51a401a8b6SStefano Zampini   PetscFunctionBegin;
52a401a8b6SStefano Zampini   pcbddc->current_level=level;
53a401a8b6SStefano Zampini   PetscFunctionReturn(0);
54a401a8b6SStefano Zampini }
55a401a8b6SStefano Zampini 
56a401a8b6SStefano Zampini #undef __FUNCT__
57674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
58674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
59674ae819SStefano Zampini {
60674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
61674ae819SStefano Zampini   PetscInt       i;
62674ae819SStefano Zampini   PetscErrorCode ierr;
63674ae819SStefano Zampini 
64674ae819SStefano Zampini   PetscFunctionBegin;
65674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
66674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
67674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
68674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
69674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
70674ae819SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
71674ae819SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
72674ae819SStefano Zampini   }
73674ae819SStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
74674ae819SStefano Zampini   PetscFunctionReturn(0);
75674ae819SStefano Zampini }
76674ae819SStefano Zampini 
77674ae819SStefano Zampini #undef __FUNCT__
78674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
79674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
80674ae819SStefano Zampini {
81674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
82674ae819SStefano Zampini   PetscErrorCode ierr;
83674ae819SStefano Zampini 
84674ae819SStefano Zampini   PetscFunctionBegin;
85674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
86674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
87674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
88674ae819SStefano Zampini   PetscFunctionReturn(0);
89674ae819SStefano Zampini }
90674ae819SStefano Zampini 
91674ae819SStefano Zampini #undef __FUNCT__
92674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
93674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
94674ae819SStefano Zampini {
95674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
96674ae819SStefano Zampini   PetscErrorCode ierr;
97674ae819SStefano Zampini 
98674ae819SStefano Zampini   PetscFunctionBegin;
99674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
100674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
101674ae819SStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
102674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
103674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
10415aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
10515aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
106674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
107674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
108674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
109674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
110674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
111674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
112674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec4_D);CHKERRQ(ierr);
1138ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
114674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
115674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
116674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
117674ae819SStefano Zampini   PetscFunctionReturn(0);
118674ae819SStefano Zampini }
119674ae819SStefano Zampini 
120674ae819SStefano Zampini #undef __FUNCT__
1216bfb1811SStefano Zampini #define __FUNCT__ "PCBDDCCreateWorkVectors"
1226bfb1811SStefano Zampini PetscErrorCode PCBDDCCreateWorkVectors(PC pc)
1236bfb1811SStefano Zampini {
1246bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1256bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1266bfb1811SStefano Zampini   VecType        impVecType;
1276bfb1811SStefano Zampini   PetscInt       n_vertices,n_constraints,local_primal_size,n_R;
1286bfb1811SStefano Zampini   PetscErrorCode ierr;
1296bfb1811SStefano Zampini 
1306bfb1811SStefano Zampini   PetscFunctionBegin;
1316bfb1811SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,NULL);CHKERRQ(ierr);
1326bfb1811SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&n_constraints,NULL);CHKERRQ(ierr);
1336bfb1811SStefano Zampini   local_primal_size = n_constraints+n_vertices;
1346bfb1811SStefano Zampini   n_R = pcis->n-n_vertices;
1356bfb1811SStefano Zampini   /* local work vectors */
1366bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
1376bfb1811SStefano Zampini   ierr = VecDuplicate(pcis->vec1_D,&pcbddc->vec4_D);CHKERRQ(ierr);
1386bfb1811SStefano Zampini   ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
1396bfb1811SStefano Zampini   ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
1406bfb1811SStefano Zampini   ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1416bfb1811SStefano Zampini   ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
14283b7ccabSStefano Zampini   ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
1436bfb1811SStefano Zampini   ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,local_primal_size);CHKERRQ(ierr);
1446bfb1811SStefano Zampini   ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
14583b7ccabSStefano Zampini   if (n_constraints) {
14683b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
14783b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
14883b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
14983b7ccabSStefano Zampini   }
1506bfb1811SStefano Zampini   PetscFunctionReturn(0);
1516bfb1811SStefano Zampini }
1526bfb1811SStefano Zampini 
1536bfb1811SStefano Zampini #undef __FUNCT__
1544a78082cSStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseLocal"
1558629588bSStefano Zampini PetscErrorCode PCBDDCSetUpCoarseLocal(PC pc, PetscScalar **coarse_submat_vals_n)
15688ebb749SStefano Zampini {
15725084f0cSStefano Zampini   PetscErrorCode         ierr;
15825084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
15988ebb749SStefano Zampini   PC_IS*                 pcis = (PC_IS*)pc->data;
16088ebb749SStefano Zampini   PC_BDDC*               pcbddc = (PC_BDDC*)pc->data;
16125084f0cSStefano Zampini   /* submatrices of local problem */
16288ebb749SStefano Zampini   Mat                    A_RV,A_VR,A_VV;
16325084f0cSStefano Zampini   /* working matrices */
16425084f0cSStefano Zampini   Mat                    M1,M2,M3,C_CR;
16525084f0cSStefano Zampini   /* working vectors */
16625084f0cSStefano Zampini   Vec                    vec1_C,vec2_C,vec1_V,vec2_V;
16725084f0cSStefano Zampini   /* additional working stuff */
16825084f0cSStefano Zampini   IS                     is_aux;
16988ebb749SStefano Zampini   ISLocalToGlobalMapping BtoNmap;
17025084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
17125084f0cSStefano Zampini   const PetscScalar      *array,*row_cmat_values;
17225084f0cSStefano Zampini   const PetscInt         *row_cmat_indices,*idx_R_local;
17325084f0cSStefano Zampini   PetscInt               *vertices,*idx_V_B,*auxindices;
17425084f0cSStefano Zampini   PetscInt               n_vertices,n_constraints,size_of_constraint;
17525084f0cSStefano Zampini   PetscInt               i,j,n_R,n_D,n_B;
17688ebb749SStefano Zampini   PetscBool              setsym=PETSC_FALSE,issym=PETSC_FALSE;
17725084f0cSStefano Zampini   /* Vector and matrix types */
17888ebb749SStefano Zampini   VecType                impVecType;
17988ebb749SStefano Zampini   MatType                impMatType;
18025084f0cSStefano Zampini   /* some shortcuts to scalars */
18125084f0cSStefano Zampini   PetscScalar            zero=0.0,one=1.0,m_one=-1.0;
18225084f0cSStefano Zampini   /* for debugging purposes */
18388ebb749SStefano Zampini   PetscReal              *coarsefunctions_errors,*constraints_errors;
18488ebb749SStefano Zampini 
18588ebb749SStefano Zampini   PetscFunctionBegin;
18625084f0cSStefano Zampini   /* get number of vertices and their local indices */
18725084f0cSStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
18888ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
18988ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
19088ebb749SStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
19188ebb749SStefano Zampini   n_R = pcis->n-n_vertices;
19288ebb749SStefano Zampini 
19388ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
19488ebb749SStefano Zampini   impMatType = MATSEQDENSE;
19525084f0cSStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
19688ebb749SStefano Zampini 
19788ebb749SStefano Zampini   /* Allocating some extra storage just to be safe */
19888ebb749SStefano Zampini   ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
19988ebb749SStefano Zampini   for (i=0;i<pcis->n;i++) auxindices[i]=i;
20088ebb749SStefano Zampini 
20188ebb749SStefano Zampini   /* vertices in boundary numbering */
20288ebb749SStefano Zampini   ierr = PetscMalloc(n_vertices*sizeof(PetscInt),&idx_V_B);CHKERRQ(ierr);
20388ebb749SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(pcis->is_B_local,&BtoNmap);CHKERRQ(ierr);
20488ebb749SStefano Zampini   ierr = ISGlobalToLocalMappingApply(BtoNmap,IS_GTOLM_DROP,n_vertices,vertices,&i,idx_V_B);CHKERRQ(ierr);
20588ebb749SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr);
20688ebb749SStefano Zampini   if (i != n_vertices) {
20788ebb749SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
20888ebb749SStefano Zampini   }
20988ebb749SStefano Zampini 
21088ebb749SStefano Zampini   /* some work vectors on vertices and/or constraints */
21188ebb749SStefano Zampini   if (n_vertices) {
21288ebb749SStefano Zampini     ierr = VecCreate(PETSC_COMM_SELF,&vec1_V);CHKERRQ(ierr);
21388ebb749SStefano Zampini     ierr = VecSetSizes(vec1_V,n_vertices,n_vertices);CHKERRQ(ierr);
21488ebb749SStefano Zampini     ierr = VecSetType(vec1_V,impVecType);CHKERRQ(ierr);
21588ebb749SStefano Zampini     ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
21688ebb749SStefano Zampini   }
21788ebb749SStefano Zampini   if (n_constraints) {
21888ebb749SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec1_C);CHKERRQ(ierr);
21988ebb749SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec2_C);CHKERRQ(ierr);
22088ebb749SStefano Zampini   }
22125084f0cSStefano Zampini 
22288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
22388ebb749SStefano Zampini   if (n_constraints) {
22488ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
22525084f0cSStefano Zampini     ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
22688ebb749SStefano Zampini     ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
22725084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->local_auxmat2);CHKERRQ(ierr);
22888ebb749SStefano Zampini 
22925084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
23025084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
2318ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
23225084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
23388ebb749SStefano Zampini 
23488ebb749SStefano Zampini     /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
23588ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
23688ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
23788ebb749SStefano Zampini       /* Get row of constraint matrix in R numbering */
23825084f0cSStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
23925084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_R,size_of_constraint,row_cmat_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
24025084f0cSStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
24125084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_R);CHKERRQ(ierr);
24225084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_R);CHKERRQ(ierr);
24388ebb749SStefano Zampini       /* Solve for row of constraint matrix in R numbering */
24488ebb749SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
24525084f0cSStefano Zampini       /* Set values in local_auxmat2 */
24625084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
24788ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
24825084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
24988ebb749SStefano Zampini     }
25088ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25188ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25225084f0cSStefano Zampini     ierr = MatScale(pcbddc->local_auxmat2,m_one);CHKERRQ(ierr);
25388ebb749SStefano Zampini 
25488ebb749SStefano Zampini     /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
25525084f0cSStefano Zampini     ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
25625084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
25788ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
25888ebb749SStefano Zampini     ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
25988ebb749SStefano Zampini     ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
26025084f0cSStefano Zampini     ierr = MatSetUp(M1);CHKERRQ(ierr);
26125084f0cSStefano Zampini     ierr = MatDuplicate(M1,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
26225084f0cSStefano Zampini     ierr = MatZeroEntries(M2);CHKERRQ(ierr);
26325084f0cSStefano Zampini     ierr = VecSet(vec1_C,m_one);CHKERRQ(ierr);
26425084f0cSStefano Zampini     ierr = MatDiagonalSet(M2,vec1_C,INSERT_VALUES);CHKERRQ(ierr);
26525084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
26625084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
26725084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
26888ebb749SStefano Zampini     /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
26988ebb749SStefano Zampini     ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
27088ebb749SStefano Zampini   }
27188ebb749SStefano Zampini 
27288ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
27388ebb749SStefano Zampini   if (n_vertices) {
27425084f0cSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,n_vertices,vertices,PETSC_COPY_VALUES,&is_aux);CHKERRQ(ierr);
2758ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
2768ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
27725084f0cSStefano Zampini     ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
27825084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
27988ebb749SStefano Zampini   }
28088ebb749SStefano Zampini 
28188ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
28288ebb749SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
28388ebb749SStefano Zampini   ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
28488ebb749SStefano Zampini   ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
28525084f0cSStefano Zampini   ierr = MatSetUp(pcbddc->coarse_phi_B);CHKERRQ(ierr);
2868eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
28788ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
28888ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
28988ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
29025084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_phi_D);CHKERRQ(ierr);
29188ebb749SStefano Zampini   }
29288ebb749SStefano Zampini 
29325084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
2948ce42a96SStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
29588ebb749SStefano Zampini     ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*coarsefunctions_errors),&coarsefunctions_errors);CHKERRQ(ierr);
29688ebb749SStefano Zampini     ierr = PetscMalloc(2*pcbddc->local_primal_size*sizeof(*constraints_errors),&constraints_errors);CHKERRQ(ierr);
29788ebb749SStefano Zampini   }
29888ebb749SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
29988ebb749SStefano Zampini   ierr = PetscMalloc((pcbddc->local_primal_size)*(pcbddc->local_primal_size)*sizeof(PetscScalar),&coarse_submat_vals);CHKERRQ(ierr);
30088ebb749SStefano Zampini 
30188ebb749SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
30225084f0cSStefano Zampini 
30325084f0cSStefano Zampini   /* vertices */
30488ebb749SStefano Zampini   for (i=0;i<n_vertices;i++) {
30588ebb749SStefano Zampini     ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
30688ebb749SStefano Zampini     ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
30788ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
30888ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
30925084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on constraints multipliers */
31088ebb749SStefano Zampini     ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
31188ebb749SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
31288ebb749SStefano Zampini     ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
31388ebb749SStefano Zampini     if (n_constraints) {
31488ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
31588ebb749SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
31688ebb749SStefano Zampini       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
31788ebb749SStefano Zampini     }
31888ebb749SStefano Zampini     ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
31988ebb749SStefano Zampini     ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
32088ebb749SStefano Zampini 
32188ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
32288ebb749SStefano Zampini     /* coarse basis functions */
32388ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
32488ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32588ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
32625084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
32788ebb749SStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
32825084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
32988ebb749SStefano Zampini     ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
3308eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
33188ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
33288ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
33325084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
33488ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
33525084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
33688ebb749SStefano Zampini     }
33725084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
33825084f0cSStefano Zampini     ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
33925084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
34025084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
34188ebb749SStefano Zampini     if (n_constraints) {
34225084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
34325084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
34425084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
34588ebb749SStefano Zampini     }
34688ebb749SStefano Zampini 
34725084f0cSStefano Zampini     /* check */
34825084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
34925084f0cSStefano Zampini       /* assemble subdomain vector on local nodes */
35088ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
35125084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
35225084f0cSStefano Zampini       ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
35325084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
35425084f0cSStefano Zampini       ierr = VecSetValue(pcis->vec1_N,vertices[i],one,INSERT_VALUES);CHKERRQ(ierr);
35525084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
35625084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
35788ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
35888ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
35925084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
36025084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
36125084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
36288ebb749SStefano Zampini       if (n_constraints) {
36325084f0cSStefano Zampini         ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
36425084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
36525084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
36688ebb749SStefano Zampini       }
36725084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
36825084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
36988ebb749SStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
37088ebb749SStefano Zampini       /* check saddle point solution */
37188ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
37288ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
37388ebb749SStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
37488ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
37525084f0cSStefano Zampini       /* shift by the identity matrix */
37625084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
37725084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
37825084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
37988ebb749SStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
38088ebb749SStefano Zampini     }
38188ebb749SStefano Zampini   }
38288ebb749SStefano Zampini 
38325084f0cSStefano Zampini   /* constraints */
38488ebb749SStefano Zampini   for (i=0;i<n_constraints;i++) {
38588ebb749SStefano Zampini     ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
38688ebb749SStefano Zampini     ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
38788ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
38888ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
38925084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on vertices multipliers */
39088ebb749SStefano Zampini     ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
39188ebb749SStefano Zampini     ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
39288ebb749SStefano Zampini     ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
39325084f0cSStefano Zampini     if (n_vertices) {
39425084f0cSStefano Zampini       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
39525084f0cSStefano Zampini     }
39688ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
39788ebb749SStefano Zampini     /* coarse basis functions */
39825084f0cSStefano Zampini     j = i+n_vertices; /* don't touch this! */
39988ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
40088ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
40188ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
40225084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
40325084f0cSStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
40425084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
4058eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
40688ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
40788ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
40825084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
40925084f0cSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
41025084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
41188ebb749SStefano Zampini     }
41225084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
41388ebb749SStefano Zampini     if (n_vertices) {
41425084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
41525084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
41625084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
41788ebb749SStefano Zampini     }
41825084f0cSStefano Zampini     ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
41925084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
42025084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
42188ebb749SStefano Zampini 
42225084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
42388ebb749SStefano Zampini       /* assemble subdomain vector on nodes */
42488ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
42525084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
42625084f0cSStefano Zampini       ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
42725084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
42825084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
42925084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
43088ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers */
43188ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
43288ebb749SStefano Zampini       if (n_vertices) {
43325084f0cSStefano Zampini         ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
43425084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
43525084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
43688ebb749SStefano Zampini       }
43725084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
43825084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
43925084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
44025084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
44125084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
44225084f0cSStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
44388ebb749SStefano Zampini       /* check saddle point solution */
44488ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
44588ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
44625084f0cSStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[j]);CHKERRQ(ierr);
44788ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
44825084f0cSStefano Zampini       /* shift by the identity matrix */
44925084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,j,m_one,ADD_VALUES);CHKERRQ(ierr);
45025084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
45125084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
45225084f0cSStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[j]);CHKERRQ(ierr);
45388ebb749SStefano Zampini     }
45488ebb749SStefano Zampini   }
45525084f0cSStefano Zampini   /* call assembling routines for local coarse basis */
45688ebb749SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
45788ebb749SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4588eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
45988ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46088ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
46188ebb749SStefano Zampini   }
46225084f0cSStefano Zampini 
46388ebb749SStefano Zampini   /* compute other basis functions for non-symmetric problems */
46488ebb749SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
46588ebb749SStefano Zampini   if (!setsym || (setsym && !issym)) {
46688ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
46788ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
46888ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
46925084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_psi_B);CHKERRQ(ierr);
4708eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
47188ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
47288ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
47388ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
47425084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_D);CHKERRQ(ierr);
47588ebb749SStefano Zampini     }
47688ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
47788ebb749SStefano Zampini       if (n_constraints) {
47888ebb749SStefano Zampini         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
47988ebb749SStefano Zampini         for (j=0;j<n_constraints;j++) {
48025084f0cSStefano Zampini           ierr = VecSetValue(vec1_C,j,coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
48188ebb749SStefano Zampini         }
48225084f0cSStefano Zampini         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
48325084f0cSStefano Zampini         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
48488ebb749SStefano Zampini       }
48588ebb749SStefano Zampini       if (i<n_vertices) {
48688ebb749SStefano Zampini         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
48788ebb749SStefano Zampini         ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
48888ebb749SStefano Zampini         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
48988ebb749SStefano Zampini         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
49088ebb749SStefano Zampini         ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
49188ebb749SStefano Zampini         if (n_constraints) {
49288ebb749SStefano Zampini           ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
49388ebb749SStefano Zampini         }
49488ebb749SStefano Zampini       } else {
49588ebb749SStefano Zampini         ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
49688ebb749SStefano Zampini       }
49788ebb749SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
49888ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
49988ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
50088ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
50125084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
50288ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
50325084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
50488ebb749SStefano Zampini       if (i<n_vertices) {
50588ebb749SStefano Zampini         ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
50688ebb749SStefano Zampini       }
5078eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
50888ebb749SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
50988ebb749SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
51025084f0cSStefano Zampini         ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
51188ebb749SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
51225084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
51388ebb749SStefano Zampini       }
51488ebb749SStefano Zampini 
51525084f0cSStefano Zampini       if (pcbddc->dbg_flag) {
51688ebb749SStefano Zampini         /* assemble subdomain vector on nodes */
51788ebb749SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
51825084f0cSStefano Zampini         ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
51925084f0cSStefano Zampini         ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
52025084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
52125084f0cSStefano Zampini         if (i<n_vertices) {
52225084f0cSStefano Zampini           ierr = VecSetValue(pcis->vec1_N,vertices[i],one,INSERT_VALUES);CHKERRQ(ierr);
52388ebb749SStefano Zampini         }
52425084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
52525084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
52625084f0cSStefano Zampini         /* assemble subdomain vector of lagrange multipliers */
52725084f0cSStefano Zampini         for (j=0;j<pcbddc->local_primal_size;j++) {
52825084f0cSStefano Zampini           ierr = VecSetValue(pcbddc->vec1_P,j,-coarse_submat_vals[j*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
52925084f0cSStefano Zampini         }
53025084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
53125084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
53288ebb749SStefano Zampini         /* check saddle point solution */
53388ebb749SStefano Zampini         ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
53488ebb749SStefano Zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
53588ebb749SStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
53688ebb749SStefano Zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
53725084f0cSStefano Zampini         /* shift by the identity matrix */
53825084f0cSStefano Zampini         ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
53925084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
54025084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
54188ebb749SStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
54288ebb749SStefano Zampini       }
54388ebb749SStefano Zampini     }
54488ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
54588ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5468eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
54788ebb749SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
54888ebb749SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
54988ebb749SStefano Zampini     }
55088ebb749SStefano Zampini   }
55188ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
55288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
55388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
55488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
55525084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
55688ebb749SStefano Zampini     Mat         coarse_sub_mat;
55725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
55888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
55988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
56088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
56188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
56288ebb749SStefano Zampini     PetscReal   real_value;
56388ebb749SStefano Zampini 
56488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
56588ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
56688ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
56788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
56888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
56988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
57088ebb749SStefano Zampini     if (pcbddc->coarse_psi_B) {
57188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
57288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
57388ebb749SStefano Zampini     }
57488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
57588ebb749SStefano Zampini 
57625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
57725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
57825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
57988ebb749SStefano Zampini     if (pcbddc->coarse_psi_B) {
58088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
58188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
58288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
58388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
58488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
58588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
58688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
58788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
58888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
58988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
59088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
59188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
59288ebb749SStefano Zampini     } else {
59388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
59488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
59588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
59688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
59788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
59888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
59988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
60088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
60188ebb749SStefano Zampini     }
60288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
60388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
60488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
60588ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
60688ebb749SStefano Zampini     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
60788ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
60825084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"----------------------------------\n");CHKERRQ(ierr);
60925084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
61025084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
61125084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
61288ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
61325084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
61488ebb749SStefano Zampini     }
61525084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
61688ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
61725084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
61888ebb749SStefano Zampini     }
61988ebb749SStefano Zampini     if (pcbddc->coarse_psi_B) {
62025084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
62188ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
62225084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
62388ebb749SStefano Zampini       }
62425084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
62588ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
62625084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
62788ebb749SStefano Zampini       }
62888ebb749SStefano Zampini     }
62925084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
63088ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
63188ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
63288ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
63388ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
63488ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
63588ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
63688ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
63788ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
63888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
63988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
64088ebb749SStefano Zampini     if (pcbddc->coarse_psi_B) {
64188ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
64288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
64388ebb749SStefano Zampini     }
64488ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
6458ce42a96SStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
64688ebb749SStefano Zampini     ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
64788ebb749SStefano Zampini     ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
64888ebb749SStefano Zampini   }
64988ebb749SStefano Zampini   /* free memory */
65088ebb749SStefano Zampini   if (n_vertices) {
65188ebb749SStefano Zampini     ierr = PetscFree(vertices);CHKERRQ(ierr);
65288ebb749SStefano Zampini     ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
65388ebb749SStefano Zampini     ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
65488ebb749SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
65588ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
65688ebb749SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
65788ebb749SStefano Zampini   }
65888ebb749SStefano Zampini   if (n_constraints) {
65988ebb749SStefano Zampini     ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
66088ebb749SStefano Zampini     ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
66188ebb749SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
66288ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
66388ebb749SStefano Zampini   }
66488ebb749SStefano Zampini   ierr = PetscFree(auxindices);CHKERRQ(ierr);
6658629588bSStefano Zampini   /* get back data */
6668629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
66788ebb749SStefano Zampini   PetscFunctionReturn(0);
66888ebb749SStefano Zampini }
66988ebb749SStefano Zampini 
67088ebb749SStefano Zampini #undef __FUNCT__
671aa0d41d4SStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalMatrices"
672aa0d41d4SStefano Zampini PetscErrorCode PCBDDCSetUpLocalMatrices(PC pc)
673aa0d41d4SStefano Zampini {
674aa0d41d4SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
675aa0d41d4SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
676aa0d41d4SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
677aa0d41d4SStefano Zampini   /* manage repeated solves */
678aa0d41d4SStefano Zampini   MatReuse          reuse;
679aa0d41d4SStefano Zampini   MatStructure      matstruct;
680aa0d41d4SStefano Zampini   PetscErrorCode    ierr;
681aa0d41d4SStefano Zampini 
682aa0d41d4SStefano Zampini   PetscFunctionBegin;
683aa0d41d4SStefano Zampini   /* get mat flags */
684aa0d41d4SStefano Zampini   ierr = PCGetOperators(pc,NULL,NULL,&matstruct);CHKERRQ(ierr);
685aa0d41d4SStefano Zampini   reuse = MAT_INITIAL_MATRIX;
686aa0d41d4SStefano Zampini   if (pc->setupcalled) {
687aa0d41d4SStefano Zampini     /* when matstruct is SAME_PRECONDITIONER, we shouldn't be here */
688aa0d41d4SStefano Zampini     if (matstruct == SAME_PRECONDITIONER) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen");
689aa0d41d4SStefano Zampini     if (matstruct == SAME_NONZERO_PATTERN) {
690aa0d41d4SStefano Zampini       reuse = MAT_REUSE_MATRIX;
691aa0d41d4SStefano Zampini     } else {
692aa0d41d4SStefano Zampini       reuse = MAT_INITIAL_MATRIX;
693aa0d41d4SStefano Zampini     }
694aa0d41d4SStefano Zampini   }
695aa0d41d4SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
696aa0d41d4SStefano Zampini     ierr = MatDestroy(&pcis->A_II);CHKERRQ(ierr);
697aa0d41d4SStefano Zampini     ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
698aa0d41d4SStefano Zampini     ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
699aa0d41d4SStefano Zampini     ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
700aa0d41d4SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
701aa0d41d4SStefano Zampini   }
702aa0d41d4SStefano Zampini 
703aa0d41d4SStefano Zampini   /* transform local matrices if needed */
704aa0d41d4SStefano Zampini   if (pcbddc->use_change_of_basis) {
705aa0d41d4SStefano Zampini     Mat         change_mat_all;
706aa0d41d4SStefano Zampini     PetscScalar *row_cmat_values;
707aa0d41d4SStefano Zampini     PetscInt    *row_cmat_indices;
708aa0d41d4SStefano Zampini     PetscInt    *nnz,*is_indices,*temp_indices;
709aa0d41d4SStefano Zampini     PetscInt    i,j,k,n_D,n_B;
710aa0d41d4SStefano Zampini 
711aa0d41d4SStefano Zampini     /* Get Non-overlapping dimensions */
712aa0d41d4SStefano Zampini     n_B = pcis->n_B;
713aa0d41d4SStefano Zampini     n_D = pcis->n-n_B;
714aa0d41d4SStefano Zampini 
715aa0d41d4SStefano Zampini     /* compute nonzero structure of change of basis on all local nodes */
716aa0d41d4SStefano Zampini     ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
717aa0d41d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
718aa0d41d4SStefano Zampini     for (i=0;i<n_D;i++) nnz[is_indices[i]] = 1;
719aa0d41d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
720aa0d41d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
721aa0d41d4SStefano Zampini     k=1;
722aa0d41d4SStefano Zampini     for (i=0;i<n_B;i++) {
723aa0d41d4SStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
724aa0d41d4SStefano Zampini       nnz[is_indices[i]]=j;
725aa0d41d4SStefano Zampini       if (k < j) k = j;
726aa0d41d4SStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,NULL,NULL);CHKERRQ(ierr);
727aa0d41d4SStefano Zampini     }
728aa0d41d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
729aa0d41d4SStefano Zampini     /* assemble change of basis matrix on the whole set of local dofs */
730aa0d41d4SStefano Zampini     ierr = PetscMalloc(k*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
731aa0d41d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&change_mat_all);CHKERRQ(ierr);
732aa0d41d4SStefano Zampini     ierr = MatSetSizes(change_mat_all,pcis->n,pcis->n,pcis->n,pcis->n);CHKERRQ(ierr);
733aa0d41d4SStefano Zampini     ierr = MatSetType(change_mat_all,MATSEQAIJ);CHKERRQ(ierr);
734aa0d41d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(change_mat_all,0,nnz);CHKERRQ(ierr);
735aa0d41d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
736aa0d41d4SStefano Zampini     for (i=0;i<n_D;i++) {
737aa0d41d4SStefano Zampini       ierr = MatSetValue(change_mat_all,is_indices[i],is_indices[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
738aa0d41d4SStefano Zampini     }
739aa0d41d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
740aa0d41d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
741aa0d41d4SStefano Zampini     for (i=0;i<n_B;i++) {
742aa0d41d4SStefano Zampini       ierr = MatGetRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
743aa0d41d4SStefano Zampini       for (k=0; k<j; k++) temp_indices[k]=is_indices[row_cmat_indices[k]];
744aa0d41d4SStefano Zampini       ierr = MatSetValues(change_mat_all,1,&is_indices[i],j,temp_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
745aa0d41d4SStefano Zampini       ierr = MatRestoreRow(pcbddc->ChangeOfBasisMatrix,i,&j,(const PetscInt**)&row_cmat_indices,(const PetscScalar**)&row_cmat_values);CHKERRQ(ierr);
746aa0d41d4SStefano Zampini     }
747aa0d41d4SStefano Zampini     ierr = MatAssemblyBegin(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
748aa0d41d4SStefano Zampini     ierr = MatAssemblyEnd(change_mat_all,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
749aa0d41d4SStefano Zampini     /* TODO: HOW TO WORK WITH BAIJ? PtAP not provided */
750aa0d41d4SStefano Zampini     ierr = MatGetBlockSize(matis->A,&i);CHKERRQ(ierr);
751aa0d41d4SStefano Zampini     if (i==1) {
752aa0d41d4SStefano Zampini       ierr = MatPtAP(matis->A,change_mat_all,reuse,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
753aa0d41d4SStefano Zampini     } else {
754aa0d41d4SStefano Zampini       Mat work_mat;
755aa0d41d4SStefano Zampini       ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
756aa0d41d4SStefano Zampini       ierr = MatPtAP(work_mat,change_mat_all,reuse,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
757aa0d41d4SStefano Zampini       ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
758aa0d41d4SStefano Zampini     }
759aa0d41d4SStefano Zampini     ierr = MatDestroy(&change_mat_all);CHKERRQ(ierr);
760aa0d41d4SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
761aa0d41d4SStefano Zampini     ierr = PetscFree(temp_indices);CHKERRQ(ierr);
762aa0d41d4SStefano Zampini   } else {
763aa0d41d4SStefano Zampini     /* without change of basis, the local matrix is unchanged */
764aa0d41d4SStefano Zampini     if (!pcbddc->local_mat) {
765aa0d41d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
766aa0d41d4SStefano Zampini       pcbddc->local_mat = matis->A;
767aa0d41d4SStefano Zampini     }
768aa0d41d4SStefano Zampini   }
769aa0d41d4SStefano Zampini 
770aa0d41d4SStefano Zampini   /* get submatrices */
771aa0d41d4SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_I_local,reuse,&pcis->A_II);CHKERRQ(ierr);
772aa0d41d4SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,reuse,&pcis->A_IB);CHKERRQ(ierr);
773aa0d41d4SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,reuse,&pcis->A_BI);CHKERRQ(ierr);
774aa0d41d4SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,reuse,&pcis->A_BB);CHKERRQ(ierr);
775aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
776aa0d41d4SStefano Zampini }
777aa0d41d4SStefano Zampini 
778aa0d41d4SStefano Zampini #undef __FUNCT__
779a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
7808ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
781a64d13efSStefano Zampini {
782a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
783a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7848ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
785a64d13efSStefano Zampini   PetscInt       *vertices,*aux_array1,*aux_array2,*is_indices,*idx_R_local;
786a64d13efSStefano Zampini   PetscInt       n_vertices,n_constraints,i,j,n_R,n_D,n_B;
7874641a718SStefano Zampini   PetscBT        bitmask;
788a64d13efSStefano Zampini   PetscErrorCode ierr;
789a64d13efSStefano Zampini 
790a64d13efSStefano Zampini   PetscFunctionBegin;
791a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
792a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
793a64d13efSStefano Zampini   /* get vertex indices from constraint matrix */
794a64d13efSStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&n_vertices,&vertices);CHKERRQ(ierr);
795a64d13efSStefano Zampini   /* Set number of constraints */
796a64d13efSStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
7974641a718SStefano Zampini   /* create auxiliary bitmask */
7984641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
7994641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
8004641a718SStefano Zampini     ierr = PetscBTSet(bitmask,vertices[i]);CHKERRQ(ierr);
8014641a718SStefano Zampini   }
802a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
803a64d13efSStefano Zampini   ierr = PetscMalloc((pcis->n-n_vertices)*sizeof(PetscInt),&idx_R_local);CHKERRQ(ierr);
804a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
8054641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
806a64d13efSStefano Zampini       idx_R_local[n_R] = i;
807a64d13efSStefano Zampini       n_R++;
808a64d13efSStefano Zampini     }
809a64d13efSStefano Zampini   }
810a64d13efSStefano Zampini   ierr = PetscFree(vertices);CHKERRQ(ierr);
8118ce42a96SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_R,idx_R_local,PETSC_OWN_POINTER,&pcbddc->is_R_local);CHKERRQ(ierr);
812a64d13efSStefano Zampini 
813a64d13efSStefano Zampini   /* print some info if requested */
814a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
815a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
816a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
817a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
818a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
819a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_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);
820a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
821a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
822a64d13efSStefano Zampini   }
823a64d13efSStefano Zampini 
824a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
825a64d13efSStefano Zampini   ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
826a64d13efSStefano Zampini   ierr = PetscMalloc((pcis->n_B-n_vertices)*sizeof(PetscInt),&aux_array2);CHKERRQ(ierr);
827a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
8284641a718SStefano Zampini   for (i=0; i<n_D; i++) {
8294641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
8304641a718SStefano Zampini   }
831a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
832a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
8334641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
8344641a718SStefano Zampini       aux_array1[j++] = i;
835a64d13efSStefano Zampini     }
836a64d13efSStefano Zampini   }
837a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
838a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
839a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
8404641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
8414641a718SStefano Zampini       aux_array2[j++] = i;
842a64d13efSStefano Zampini     }
843a64d13efSStefano Zampini   }
844a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
845a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
846a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
847a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
848a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
849a64d13efSStefano Zampini 
8508eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
851a64d13efSStefano Zampini     ierr = PetscMalloc(n_D*sizeof(PetscInt),&aux_array1);CHKERRQ(ierr);
852a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
8534641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
8544641a718SStefano Zampini         aux_array1[j++] = i;
855a64d13efSStefano Zampini       }
856a64d13efSStefano Zampini     }
857a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
858a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
859a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
860a64d13efSStefano Zampini   }
8614641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
862a64d13efSStefano Zampini   PetscFunctionReturn(0);
863a64d13efSStefano Zampini }
864a64d13efSStefano Zampini 
865a64d13efSStefano Zampini #undef __FUNCT__
866304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
867304d26faSStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool use)
868304d26faSStefano Zampini {
869304d26faSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
870304d26faSStefano Zampini 
871304d26faSStefano Zampini   PetscFunctionBegin;
872304d26faSStefano Zampini   pcbddc->use_exact_dirichlet=use;
873304d26faSStefano Zampini   PetscFunctionReturn(0);
874304d26faSStefano Zampini }
875304d26faSStefano Zampini 
876304d26faSStefano Zampini #undef __FUNCT__
877304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
8788ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc)
879304d26faSStefano Zampini {
880304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
881304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
882304d26faSStefano Zampini   PC             pc_temp;
883304d26faSStefano Zampini   Mat            A_RR;
884304d26faSStefano Zampini   Vec            vec1,vec2,vec3;
885304d26faSStefano Zampini   MatStructure   matstruct;
886304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
887304d26faSStefano Zampini   PetscReal      value;
888304d26faSStefano Zampini   PetscInt       n_D,n_R,use_exact,use_exact_reduced;
889304d26faSStefano Zampini   PetscErrorCode ierr;
890304d26faSStefano Zampini 
891304d26faSStefano Zampini   PetscFunctionBegin;
892304d26faSStefano Zampini   /* Creating PC contexts for local Dirichlet and Neumann problems */
893304d26faSStefano Zampini   ierr = PCGetOperators(pc,NULL,NULL,&matstruct);CHKERRQ(ierr);
894304d26faSStefano Zampini 
895304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
896ac78edfcSStefano Zampini   /* Matrix for Dirichlet problem is pcis->A_II */
8978ce42a96SStefano Zampini   ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
898304d26faSStefano Zampini   if (!pcbddc->ksp_D) { /* create object if not yet build */
899304d26faSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
900304d26faSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
901304d26faSStefano Zampini     /* default */
902304d26faSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
903304d26faSStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,"dirichlet_");CHKERRQ(ierr);
904304d26faSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
905304d26faSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
906304d26faSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
907304d26faSStefano Zampini   }
908304d26faSStefano Zampini   ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II,matstruct);CHKERRQ(ierr);
909304d26faSStefano Zampini   /* Allow user's customization */
910304d26faSStefano Zampini   ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
911304d26faSStefano Zampini   /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
912304d26faSStefano Zampini   if (!n_D) {
913304d26faSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
914304d26faSStefano Zampini     ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
915304d26faSStefano Zampini   }
916304d26faSStefano Zampini   /* Set Up KSP for Dirichlet problem of BDDC */
917304d26faSStefano Zampini   ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
918304d26faSStefano Zampini   /* set ksp_D into pcis data */
919304d26faSStefano Zampini   ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
920304d26faSStefano Zampini   ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
921304d26faSStefano Zampini   pcis->ksp_D = pcbddc->ksp_D;
922304d26faSStefano Zampini 
923304d26faSStefano Zampini   /* NEUMANN PROBLEM */
924304d26faSStefano Zampini   /* Matrix for Neumann problem is A_RR -> we need to create it */
9258ce42a96SStefano Zampini   ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
9268ce42a96SStefano Zampini   ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_RR);CHKERRQ(ierr);
927304d26faSStefano Zampini   if (!pcbddc->ksp_R) { /* create object if not yet build */
928304d26faSStefano Zampini     ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
929304d26faSStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
930304d26faSStefano Zampini     /* default */
931304d26faSStefano Zampini     ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
932304d26faSStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,"neumann_");CHKERRQ(ierr);
933304d26faSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
934304d26faSStefano Zampini     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
935304d26faSStefano Zampini     ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
936304d26faSStefano Zampini   }
937304d26faSStefano Zampini   ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR,matstruct);CHKERRQ(ierr);
938304d26faSStefano Zampini   /* Allow user's customization */
939304d26faSStefano Zampini   ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
940304d26faSStefano Zampini   /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
941304d26faSStefano Zampini   if (!n_R) {
942304d26faSStefano Zampini     ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
943304d26faSStefano Zampini     ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
944304d26faSStefano Zampini   }
945304d26faSStefano Zampini   /* Set Up KSP for Neumann problem of BDDC */
946304d26faSStefano Zampini   ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
947304d26faSStefano Zampini 
948304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
949304d26faSStefano Zampini 
950304d26faSStefano Zampini   /* Dirichlet */
951304d26faSStefano Zampini   ierr = MatGetVecs(pcis->A_II,&vec1,&vec2);CHKERRQ(ierr);
952304d26faSStefano Zampini   ierr = VecDuplicate(vec1,&vec3);CHKERRQ(ierr);
953304d26faSStefano Zampini   ierr = VecSetRandom(vec1,NULL);CHKERRQ(ierr);
954304d26faSStefano Zampini   ierr = MatMult(pcis->A_II,vec1,vec2);CHKERRQ(ierr);
955304d26faSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,vec2,vec3);CHKERRQ(ierr);
956304d26faSStefano Zampini   ierr = VecAXPY(vec3,m_one,vec1);CHKERRQ(ierr);
957304d26faSStefano Zampini   ierr = VecNorm(vec3,NORM_INFINITY,&value);CHKERRQ(ierr);
958304d26faSStefano Zampini   ierr = VecDestroy(&vec1);CHKERRQ(ierr);
959304d26faSStefano Zampini   ierr = VecDestroy(&vec2);CHKERRQ(ierr);
960304d26faSStefano Zampini   ierr = VecDestroy(&vec3);CHKERRQ(ierr);
961304d26faSStefano Zampini   /* need to be adapted? */
962304d26faSStefano Zampini   use_exact = (PetscAbsReal(value) > 1.e-4 ? 0 : 1);
963304d26faSStefano Zampini   ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
964304d26faSStefano Zampini   ierr = PCBDDCSetUseExactDirichlet(pc,(PetscBool)use_exact_reduced);CHKERRQ(ierr);
965304d26faSStefano Zampini   /* print info */
966304d26faSStefano Zampini   if (pcbddc->dbg_flag) {
967304d26faSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
968304d26faSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
969304d26faSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Checking solution of Dirichlet and Neumann problems\n");CHKERRQ(ierr);
970304d26faSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
971304d26faSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
972304d26faSStefano Zampini   }
9738eeda7d8SStefano Zampini   if (n_D && pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
9748ce42a96SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
975304d26faSStefano Zampini   }
976304d26faSStefano Zampini 
977304d26faSStefano Zampini   /* Neumann */
978304d26faSStefano Zampini   ierr = MatGetVecs(A_RR,&vec1,&vec2);CHKERRQ(ierr);
979304d26faSStefano Zampini   ierr = VecDuplicate(vec1,&vec3);CHKERRQ(ierr);
980304d26faSStefano Zampini   ierr = VecSetRandom(vec1,NULL);CHKERRQ(ierr);
981304d26faSStefano Zampini   ierr = MatMult(A_RR,vec1,vec2);CHKERRQ(ierr);
982304d26faSStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,vec2,vec3);CHKERRQ(ierr);
983304d26faSStefano Zampini   ierr = VecAXPY(vec3,m_one,vec1);CHKERRQ(ierr);
984304d26faSStefano Zampini   ierr = VecNorm(vec3,NORM_INFINITY,&value);CHKERRQ(ierr);
985304d26faSStefano Zampini   ierr = VecDestroy(&vec1);CHKERRQ(ierr);
986304d26faSStefano Zampini   ierr = VecDestroy(&vec2);CHKERRQ(ierr);
987304d26faSStefano Zampini   ierr = VecDestroy(&vec3);CHKERRQ(ierr);
988304d26faSStefano Zampini   /* need to be adapted? */
989304d26faSStefano Zampini   use_exact = (PetscAbsReal(value) > 1.e-4 ? 0 : 1);
990304d26faSStefano Zampini   if (PetscAbsReal(value) > 1.e-4) use_exact = 0;
991304d26faSStefano Zampini   ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_INT,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
992304d26faSStefano Zampini   /* print info */
993304d26faSStefano Zampini   if (pcbddc->dbg_flag) {
994304d26faSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for  Neumann  solve = % 1.14e \n",PetscGlobalRank,value);CHKERRQ(ierr);
995304d26faSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
996304d26faSStefano Zampini   }
997304d26faSStefano Zampini   if (n_R && pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
9988ce42a96SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
999304d26faSStefano Zampini   }
1000304d26faSStefano Zampini 
1001304d26faSStefano Zampini   /* free Neumann problem's matrix */
1002304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1003304d26faSStefano Zampini   PetscFunctionReturn(0);
1004304d26faSStefano Zampini }
1005304d26faSStefano Zampini 
1006304d26faSStefano Zampini #undef __FUNCT__
1007674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSolveSaddlePoint"
1008674ae819SStefano Zampini static PetscErrorCode  PCBDDCSolveSaddlePoint(PC pc)
1009674ae819SStefano Zampini {
1010674ae819SStefano Zampini   PetscErrorCode ierr;
1011674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1012674ae819SStefano Zampini 
1013674ae819SStefano Zampini   PetscFunctionBegin;
1014674ae819SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
1015674ae819SStefano Zampini   if (pcbddc->local_auxmat1) {
1016674ae819SStefano Zampini     ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec2_R,pcbddc->vec1_C);CHKERRQ(ierr);
1017674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->local_auxmat2,pcbddc->vec1_C,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
1018674ae819SStefano Zampini   }
1019674ae819SStefano Zampini   PetscFunctionReturn(0);
1020674ae819SStefano Zampini }
1021674ae819SStefano Zampini 
1022674ae819SStefano Zampini #undef __FUNCT__
1023674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1024674ae819SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc)
1025674ae819SStefano Zampini {
1026674ae819SStefano Zampini   PetscErrorCode ierr;
1027674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1028674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1029674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1030674ae819SStefano Zampini 
1031674ae819SStefano Zampini   PetscFunctionBegin;
103215aaf578SStefano Zampini   /* Application of PHI^T (or PSI^T)  */
103315aaf578SStefano Zampini   if (pcbddc->coarse_psi_B) {
103415aaf578SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
10358eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
103615aaf578SStefano Zampini   } else {
1037674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
10388eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
103915aaf578SStefano Zampini   }
1040674ae819SStefano Zampini   /* Scatter data of coarse_rhs */
1041674ae819SStefano Zampini   if (pcbddc->coarse_rhs) { ierr = VecSet(pcbddc->coarse_rhs,zero);CHKERRQ(ierr); }
1042674ae819SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1043674ae819SStefano Zampini 
1044674ae819SStefano Zampini   /* Local solution on R nodes */
1045674ae819SStefano Zampini   ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1046674ae819SStefano Zampini   ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1047674ae819SStefano Zampini   ierr = VecScatterEnd  (pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10488eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
1049674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1050674ae819SStefano Zampini     ierr = VecScatterEnd  (pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1051674ae819SStefano Zampini   }
1052674ae819SStefano Zampini   ierr = PCBDDCSolveSaddlePoint(pc);CHKERRQ(ierr);
1053674ae819SStefano Zampini   ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1054674ae819SStefano Zampini   ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1055674ae819SStefano Zampini   ierr = VecScatterEnd  (pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10568eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
1057674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1058674ae819SStefano Zampini     ierr = VecScatterEnd  (pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1059674ae819SStefano Zampini   }
1060674ae819SStefano Zampini 
1061674ae819SStefano Zampini   /* Coarse solution */
1062674ae819SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,pcbddc->vec1_P,pcbddc->coarse_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1063674ae819SStefano Zampini   if (pcbddc->coarse_rhs) { /* TODO remove null space when doing multilevel */
1064674ae819SStefano Zampini     ierr = KSPSolve(pcbddc->coarse_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
1065674ae819SStefano Zampini   }
1066674ae819SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1067674ae819SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd  (pc,pcbddc->coarse_vec,pcbddc->vec1_P,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1068674ae819SStefano Zampini 
1069674ae819SStefano Zampini   /* Sum contributions from two levels */
1070674ae819SStefano Zampini   ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
10718eeda7d8SStefano Zampini   if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1072674ae819SStefano Zampini   PetscFunctionReturn(0);
1073674ae819SStefano Zampini }
1074674ae819SStefano Zampini 
1075674ae819SStefano Zampini #undef __FUNCT__
1076674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
1077674ae819SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
1078674ae819SStefano Zampini {
1079674ae819SStefano Zampini   PetscErrorCode ierr;
1080674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1081674ae819SStefano Zampini 
1082674ae819SStefano Zampini   PetscFunctionBegin;
1083674ae819SStefano Zampini   switch (pcbddc->coarse_communications_type) {
1084674ae819SStefano Zampini     case SCATTERS_BDDC:
1085674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
1086674ae819SStefano Zampini       break;
1087674ae819SStefano Zampini   }
1088674ae819SStefano Zampini   PetscFunctionReturn(0);
1089674ae819SStefano Zampini }
1090674ae819SStefano Zampini 
1091674ae819SStefano Zampini #undef __FUNCT__
1092674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
1093674ae819SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc,Vec vec_from, Vec vec_to, InsertMode imode, ScatterMode smode)
1094674ae819SStefano Zampini {
1095674ae819SStefano Zampini   PetscErrorCode ierr;
1096674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1097674ae819SStefano Zampini 
1098674ae819SStefano Zampini   PetscFunctionBegin;
1099674ae819SStefano Zampini   switch (pcbddc->coarse_communications_type) {
1100674ae819SStefano Zampini     case SCATTERS_BDDC:
1101674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,vec_from,vec_to,imode,smode);CHKERRQ(ierr);
1102674ae819SStefano Zampini       break;
1103674ae819SStefano Zampini   }
1104674ae819SStefano Zampini   PetscFunctionReturn(0);
1105674ae819SStefano Zampini }
1106674ae819SStefano Zampini 
1107984c4197SStefano Zampini /* uncomment for testing purposes */
1108984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1109674ae819SStefano Zampini #undef __FUNCT__
1110674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1111674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1112674ae819SStefano Zampini {
1113674ae819SStefano Zampini   PetscErrorCode    ierr;
1114674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1115674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1116674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1117984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1118674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1119984c4197SStefano Zampini   /* one and zero */
1120984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1121984c4197SStefano Zampini   /* space to store constraints and their local indices */
1122984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1123984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1124984c4197SStefano Zampini   /* iterators */
1125984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1126984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1127984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1128984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1129984c4197SStefano Zampini   /* near null space stuff */
1130674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1131674ae819SStefano Zampini   const Vec         *nearnullvecs;
1132674ae819SStefano Zampini   Vec               *localnearnullsp;
1133984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1134984c4197SStefano Zampini   PetscInt          nnsp_size;
1135984c4197SStefano Zampini   PetscScalar       *array;
1136984c4197SStefano Zampini   /* BLAS integers */
1137e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1138e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1139c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1140984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1141242a89d7SStefano Zampini   PetscBool         skip_lapack;
1142984c4197SStefano Zampini   PetscScalar       *work;
1143984c4197SStefano Zampini   PetscReal         *singular_vals;
1144984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1145984c4197SStefano Zampini   PetscReal         *rwork;
1146674ae819SStefano Zampini #endif
1147984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1148e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1149984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1150b7d8b9f8SStefano Zampini #else
1151b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1152b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1153984c4197SStefano Zampini #endif
1154984c4197SStefano Zampini   /* change of basis */
1155984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
11564641a718SStefano Zampini   PetscBool         boolforchange;
11574641a718SStefano Zampini   PetscBT           touched,change_basis;
1158984c4197SStefano Zampini   /* auxiliary stuff */
1159984c4197SStefano Zampini   PetscInt          *nnz,*is_indices,*local_to_B;
1160984c4197SStefano Zampini   /* some quantities */
1161984c4197SStefano Zampini   PetscInt          n_vertices,total_primal_vertices;
1162984c4197SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint,max_constraints,temp_constraints;
1163984c4197SStefano Zampini 
1164674ae819SStefano Zampini 
1165674ae819SStefano Zampini   PetscFunctionBegin;
1166674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
11678eeda7d8SStefano Zampini   if (!pcbddc->use_faces && !pcbddc->use_edges && !pcbddc->use_vertices) {
11688eeda7d8SStefano Zampini     pcbddc->use_vertices = PETSC_TRUE;
1169674ae819SStefano Zampini   }
11708eeda7d8SStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,pcbddc->use_faces,pcbddc->use_edges,pcbddc->use_vertices,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);
1171984c4197SStefano Zampini   /* print some info */
1172674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
1173674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1174674ae819SStefano Zampini     i = 0;
1175674ae819SStefano Zampini     if (ISForVertices) {
1176674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1177674ae819SStefano Zampini     }
1178674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1179674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
118015aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1181674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1182674ae819SStefano Zampini   }
1183674ae819SStefano Zampini   /* check if near null space is attached to global mat */
1184674ae819SStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1185674ae819SStefano Zampini   if (nearnullsp) {
1186674ae819SStefano Zampini     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1187984c4197SStefano Zampini   } else { /* if near null space is not provided BDDC uses constants by default */
1188984c4197SStefano Zampini     nnsp_size = 0;
1189674ae819SStefano Zampini     nnsp_has_cnst = PETSC_TRUE;
1190674ae819SStefano Zampini   }
1191984c4197SStefano Zampini   /* get max number of constraints on a single cc */
1192984c4197SStefano Zampini   max_constraints = nnsp_size;
1193984c4197SStefano Zampini   if (nnsp_has_cnst) max_constraints++;
1194984c4197SStefano Zampini 
1195674ae819SStefano Zampini   /*
1196674ae819SStefano Zampini        Evaluate maximum storage size needed by the procedure
1197674ae819SStefano Zampini        - temp_indices will contain start index of each constraint stored as follows
1198674ae819SStefano 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
1199674ae819SStefano Zampini        - temp_indices_to_constraint_B[temp_indices[i],...,temp[indices[i+1]-1] will contain the indices (in boundary numbering) on which the constraint acts
1200674ae819SStefano Zampini        - temp_quadrature_constraint  [temp_indices[i],...,temp[indices[i+1]-1] will contain the scalars representing the constraint itself
1201674ae819SStefano Zampini                                                                                                                                                          */
1202674ae819SStefano Zampini   total_counts = n_ISForFaces+n_ISForEdges;
1203984c4197SStefano Zampini   total_counts *= max_constraints;
1204674ae819SStefano Zampini   n_vertices = 0;
1205674ae819SStefano Zampini   if (ISForVertices) {
1206674ae819SStefano Zampini     ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1207674ae819SStefano Zampini   }
1208674ae819SStefano Zampini   total_counts += n_vertices;
1209674ae819SStefano Zampini   ierr = PetscMalloc((total_counts+1)*sizeof(PetscInt),&temp_indices);CHKERRQ(ierr);
12104641a718SStefano Zampini   ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1211674ae819SStefano Zampini   total_counts = 0;
1212674ae819SStefano Zampini   max_size_of_constraint = 0;
1213674ae819SStefano Zampini   for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1214674ae819SStefano Zampini     if (i<n_ISForEdges) {
1215674ae819SStefano Zampini       used_IS = &ISForEdges[i];
1216674ae819SStefano Zampini     } else {
1217674ae819SStefano Zampini       used_IS = &ISForFaces[i-n_ISForEdges];
1218674ae819SStefano Zampini     }
1219674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1220674ae819SStefano Zampini     total_counts += j;
1221674ae819SStefano Zampini     max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1222674ae819SStefano Zampini   }
1223984c4197SStefano Zampini   total_counts *= max_constraints;
1224674ae819SStefano Zampini   total_counts += n_vertices;
1225674ae819SStefano Zampini   ierr = PetscMalloc(total_counts*sizeof(PetscScalar),&temp_quadrature_constraint);CHKERRQ(ierr);
1226674ae819SStefano Zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint);CHKERRQ(ierr);
1227674ae819SStefano Zampini   ierr = PetscMalloc(total_counts*sizeof(PetscInt),&temp_indices_to_constraint_B);CHKERRQ(ierr);
1228984c4197SStefano Zampini   /* local to boundary numbering */
1229674ae819SStefano Zampini   ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&local_to_B);CHKERRQ(ierr);
1230674ae819SStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1231984c4197SStefano Zampini   for (i=0;i<pcis->n;i++) local_to_B[i]=-1;
1232984c4197SStefano Zampini   for (i=0;i<pcis->n_B;i++) local_to_B[is_indices[i]]=i;
1233674ae819SStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1234984c4197SStefano Zampini   /* get local part of global near null space vectors */
1235984c4197SStefano Zampini   ierr = PetscMalloc(nnsp_size*sizeof(Vec),&localnearnullsp);CHKERRQ(ierr);
1236984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1237984c4197SStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1238984c4197SStefano Zampini     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1239984c4197SStefano Zampini     ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1240984c4197SStefano Zampini   }
1241674ae819SStefano Zampini 
1242242a89d7SStefano Zampini   /* whether or not to skip lapack calls */
1243242a89d7SStefano Zampini   skip_lapack = PETSC_TRUE;
1244242a89d7SStefano Zampini   if (n_ISForFaces+n_ISForEdges) skip_lapack = PETSC_FALSE;
1245242a89d7SStefano Zampini 
1246984c4197SStefano Zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1247242a89d7SStefano Zampini   if (!pcbddc->use_nnsp_true && !skip_lapack) {
1248674ae819SStefano Zampini     PetscScalar temp_work;
1249674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1250984c4197SStefano Zampini     /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1251984c4197SStefano Zampini     ierr = PetscMalloc(max_constraints*max_constraints*sizeof(PetscScalar),&correlation_mat);CHKERRQ(ierr);
1252984c4197SStefano Zampini     ierr = PetscMalloc(max_constraints*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
1253984c4197SStefano Zampini     ierr = PetscMalloc(max_size_of_constraint*max_constraints*sizeof(PetscScalar),&temp_basis);CHKERRQ(ierr);
1254674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1255984c4197SStefano Zampini     ierr = PetscMalloc(3*max_constraints*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
1256674ae819SStefano Zampini #endif
1257674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1258c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1259c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1260674ae819SStefano Zampini     lwork = -1;
1261674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1262674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1263c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1264674ae819SStefano Zampini #else
1265c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1266674ae819SStefano Zampini #endif
1267674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1268984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1269674ae819SStefano Zampini #else /* on missing GESVD */
1270674ae819SStefano Zampini     /* SVD */
1271674ae819SStefano Zampini     PetscInt max_n,min_n;
1272674ae819SStefano Zampini     max_n = max_size_of_constraint;
1273984c4197SStefano Zampini     min_n = max_constraints;
1274984c4197SStefano Zampini     if (max_size_of_constraint < max_constraints) {
1275674ae819SStefano Zampini       min_n = max_size_of_constraint;
1276984c4197SStefano Zampini       max_n = max_constraints;
1277674ae819SStefano Zampini     }
1278674ae819SStefano Zampini     ierr = PetscMalloc(min_n*sizeof(PetscReal),&singular_vals);CHKERRQ(ierr);
1279674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1280674ae819SStefano Zampini     ierr = PetscMalloc(5*min_n*sizeof(PetscReal),&rwork);CHKERRQ(ierr);
1281674ae819SStefano Zampini #endif
1282674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1283674ae819SStefano Zampini     lwork = -1;
1284e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1285e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1286b7d8b9f8SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1287674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1288674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1289e310c8b4SStefano Zampini     PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[0],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,&temp_work,&lwork,&lierr));
1290674ae819SStefano Zampini #else
1291e310c8b4SStefano Zampini     PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[0],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,&temp_work,&lwork,rwork,&lierr));
1292674ae819SStefano Zampini #endif
1293674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1294984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1295984c4197SStefano Zampini #endif /* on missing GESVD */
1296674ae819SStefano Zampini     /* Allocate optimal workspace */
1297674ae819SStefano Zampini     ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1298984c4197SStefano Zampini     ierr = PetscMalloc((PetscInt)lwork*sizeof(PetscScalar),&work);CHKERRQ(ierr);
1299674ae819SStefano Zampini   }
1300674ae819SStefano Zampini   /* Now we can loop on constraining sets */
1301674ae819SStefano Zampini   total_counts = 0;
1302674ae819SStefano Zampini   temp_indices[0] = 0;
1303674ae819SStefano Zampini   /* vertices */
1304674ae819SStefano Zampini   if (ISForVertices) {
1305674ae819SStefano Zampini     ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1306674ae819SStefano Zampini     if (nnsp_has_cnst) { /* consider all vertices */
1307674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1308674ae819SStefano Zampini         temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1309674ae819SStefano Zampini         temp_indices_to_constraint_B[temp_indices[total_counts]]=local_to_B[is_indices[i]];
1310674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1311674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1312674ae819SStefano Zampini         total_counts++;
1313674ae819SStefano Zampini       }
1314674ae819SStefano Zampini     } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1315984c4197SStefano Zampini       PetscBool used_vertex;
1316674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1317674ae819SStefano Zampini         used_vertex = PETSC_FALSE;
1318674ae819SStefano Zampini         k = 0;
1319674ae819SStefano Zampini         while (!used_vertex && k<nnsp_size) {
1320984c4197SStefano Zampini           ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1321984c4197SStefano Zampini           if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1322674ae819SStefano Zampini             temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1323674ae819SStefano Zampini             temp_indices_to_constraint_B[temp_indices[total_counts]]=local_to_B[is_indices[i]];
1324674ae819SStefano Zampini             temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1325674ae819SStefano Zampini             temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1326674ae819SStefano Zampini             total_counts++;
1327674ae819SStefano Zampini             used_vertex = PETSC_TRUE;
1328674ae819SStefano Zampini           }
1329984c4197SStefano Zampini           ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1330674ae819SStefano Zampini           k++;
1331674ae819SStefano Zampini         }
1332674ae819SStefano Zampini       }
1333674ae819SStefano Zampini     }
1334674ae819SStefano Zampini     ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1335674ae819SStefano Zampini     n_vertices = total_counts;
1336674ae819SStefano Zampini   }
1337984c4197SStefano Zampini 
1338674ae819SStefano Zampini   /* edges and faces */
1339674ae819SStefano Zampini   for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1340674ae819SStefano Zampini     if (i<n_ISForEdges) {
1341674ae819SStefano Zampini       used_IS = &ISForEdges[i];
1342984c4197SStefano Zampini       boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1343674ae819SStefano Zampini     } else {
1344674ae819SStefano Zampini       used_IS = &ISForFaces[i-n_ISForEdges];
1345984c4197SStefano Zampini       boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1346674ae819SStefano Zampini     }
1347674ae819SStefano Zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1348674ae819SStefano Zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1349674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1350674ae819SStefano Zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1351984c4197SStefano Zampini     /* change of basis should not be performed on local periodic nodes */
1352984c4197SStefano Zampini     if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1353674ae819SStefano Zampini     if (nnsp_has_cnst) {
13545b08dc53SStefano Zampini       PetscScalar quad_value;
1355674ae819SStefano Zampini       temp_constraints++;
1356674ae819SStefano Zampini       quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1357674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1358674ae819SStefano Zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
1359674ae819SStefano Zampini         temp_indices_to_constraint_B[temp_indices[total_counts]+j]=local_to_B[is_indices[j]];
1360674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1361674ae819SStefano Zampini       }
1362674ae819SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
13634641a718SStefano Zampini       if (boolforchange) {
13644641a718SStefano Zampini         ierr = PetscBTSet(change_basis,total_counts);CHKERRQ(ierr);
13654641a718SStefano Zampini       }
1366674ae819SStefano Zampini       total_counts++;
1367674ae819SStefano Zampini     }
1368674ae819SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1369984c4197SStefano Zampini       PetscReal real_value;
1370984c4197SStefano Zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1371674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1372674ae819SStefano Zampini         temp_indices_to_constraint[temp_indices[total_counts]+j]=is_indices[j];
1373674ae819SStefano Zampini         temp_indices_to_constraint_B[temp_indices[total_counts]+j]=local_to_B[is_indices[j]];
1374984c4197SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
1375674ae819SStefano Zampini       }
1376984c4197SStefano Zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1377984c4197SStefano Zampini       /* check if array is null on the connected component */
1378e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1379e310c8b4SStefano Zampini       PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
13805b08dc53SStefano Zampini       if (real_value > 0.0) { /* keep indices and values */
1381674ae819SStefano Zampini         temp_constraints++;
1382674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
13834641a718SStefano Zampini         if (boolforchange) {
13844641a718SStefano Zampini           ierr = PetscBTSet(change_basis,total_counts);CHKERRQ(ierr);
13854641a718SStefano Zampini         }
1386674ae819SStefano Zampini         total_counts++;
1387674ae819SStefano Zampini       }
1388674ae819SStefano Zampini     }
1389674ae819SStefano Zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1390984c4197SStefano Zampini     /* perform SVD on the constraints if use_nnsp_true has not be requested by the user */
1391984c4197SStefano Zampini     if (!pcbddc->use_nnsp_true) {
1392984c4197SStefano Zampini       PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
1393674ae819SStefano Zampini 
1394674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1395984c4197SStefano Zampini       /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
1396984c4197SStefano Zampini          POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
1397984c4197SStefano Zampini          -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
1398984c4197SStefano Zampini             the constraints basis will differ (by a complex factor with absolute value equal to 1)
1399984c4197SStefano Zampini             from that computed using LAPACKgesvd
1400984c4197SStefano Zampini          -> This is due to a different computation of eigenvectors in LAPACKheev
1401984c4197SStefano Zampini          -> The quality of the POD-computed basis will be the same */
1402984c4197SStefano Zampini       ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
1403674ae819SStefano Zampini       /* Store upper triangular part of correlation matrix */
1404e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1405984c4197SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1406674ae819SStefano Zampini       for (j=0;j<temp_constraints;j++) {
1407674ae819SStefano Zampini         for (k=0;k<j+1;k++) {
1408e310c8b4SStefano Zampini           PetscStackCallBLAS("BLASdot",correlation_mat[j*temp_constraints+k]=BLASdot_(&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr+k]],&Blas_one,&temp_quadrature_constraint[temp_indices[temp_start_ptr+j]],&Blas_one_2));
1409674ae819SStefano Zampini         }
1410674ae819SStefano Zampini       }
1411e310c8b4SStefano Zampini       /* compute eigenvalues and eigenvectors of correlation matrix */
1412e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1413e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
1414674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1415c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
1416674ae819SStefano Zampini #else
1417c8244a33SStefano Zampini       PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
1418674ae819SStefano Zampini #endif
1419674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1420984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
1421984c4197SStefano Zampini       /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
1422674ae819SStefano Zampini       j=0;
1423984c4197SStefano Zampini       while (j < temp_constraints && singular_vals[j] < tol) j++;
1424674ae819SStefano Zampini       total_counts=total_counts-j;
1425e310c8b4SStefano Zampini       /* scale and copy POD basis into used quadrature memory */
1426c4303822SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1427c4303822SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1428c4303822SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
1429c4303822SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1430c4303822SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
1431c4303822SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
1432674ae819SStefano Zampini       if (j<temp_constraints) {
1433984c4197SStefano Zampini         PetscInt ii;
1434984c4197SStefano Zampini         for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
1435674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1436c4303822SStefano Zampini         PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,correlation_mat,&Blas_LDB,&zero,temp_basis,&Blas_LDC));
1437674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1438984c4197SStefano Zampini         for (k=0;k<temp_constraints-j;k++) {
1439674ae819SStefano Zampini           for (ii=0;ii<size_of_constraint;ii++) {
1440984c4197SStefano Zampini             temp_quadrature_constraint[temp_indices[temp_start_ptr+k]+ii]=singular_vals[temp_constraints-1-k]*temp_basis[(temp_constraints-1-k)*size_of_constraint+ii];
1441674ae819SStefano Zampini           }
1442674ae819SStefano Zampini         }
1443674ae819SStefano Zampini       }
1444674ae819SStefano Zampini #else  /* on missing GESVD */
1445e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1446e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1447b7d8b9f8SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1448674ae819SStefano Zampini       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1449674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1450e310c8b4SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,work,&lwork,&lierr));
1451674ae819SStefano Zampini #else
1452e310c8b4SStefano Zampini       PetscStackCallBLAS("LAPACKgesvd",LAPACKgesvd_("O","N",&Blas_M,&Blas_N,&temp_quadrature_constraint[temp_indices[temp_start_ptr]],&Blas_LDA,singular_vals,&dummy_scalar_1,&dummy_int_1,&dummy_scalar_2,&dummy_int_2,work,&lwork,rwork,&lierr));
1453674ae819SStefano Zampini #endif
1454984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
1455674ae819SStefano Zampini       ierr = PetscFPTrapPop();CHKERRQ(ierr);
1456984c4197SStefano Zampini       /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
1457e310c8b4SStefano Zampini       k = temp_constraints;
1458e310c8b4SStefano Zampini       if (k > size_of_constraint) k = size_of_constraint;
1459674ae819SStefano Zampini       j = 0;
1460e310c8b4SStefano Zampini       while (j < k && singular_vals[k-j-1] < tol) j++;
1461e310c8b4SStefano Zampini       total_counts = total_counts-temp_constraints+k-j;
1462984c4197SStefano Zampini #endif /* on missing GESVD */
1463674ae819SStefano Zampini     }
1464674ae819SStefano Zampini   }
1465674ae819SStefano Zampini   /* free index sets of faces, edges and vertices */
1466674ae819SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
1467674ae819SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1468674ae819SStefano Zampini   }
1469674ae819SStefano Zampini   ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1470674ae819SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
1471674ae819SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1472674ae819SStefano Zampini   }
1473674ae819SStefano Zampini   ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1474674ae819SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1475674ae819SStefano Zampini 
1476984c4197SStefano Zampini   /* free workspace */
1477242a89d7SStefano Zampini   if (!pcbddc->use_nnsp_true && !skip_lapack) {
1478984c4197SStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
1479984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1480984c4197SStefano Zampini     ierr = PetscFree(rwork);CHKERRQ(ierr);
1481984c4197SStefano Zampini #endif
1482984c4197SStefano Zampini     ierr = PetscFree(singular_vals);CHKERRQ(ierr);
1483984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1484984c4197SStefano Zampini     ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
1485984c4197SStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
1486984c4197SStefano Zampini #endif
1487984c4197SStefano Zampini   }
1488984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1489984c4197SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1490984c4197SStefano Zampini   }
1491984c4197SStefano Zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
1492984c4197SStefano Zampini 
1493674ae819SStefano Zampini   /* set quantities in pcbddc data structure */
1494984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
1495674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
1496984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
1497674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
1498984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
1499674ae819SStefano Zampini 
1500674ae819SStefano Zampini   /* Create constraint matrix */
1501674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
1502674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
1503674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1504674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
1505984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
1506984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
1507984c4197SStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&aux_primal_numbering);CHKERRQ(ierr);
1508984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
1509984c4197SStefano Zampini   /* note: it should not be needed since IS for faces and edges are already sorted by global ordering when analyzing the graph but... just in case */
1510984c4197SStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&aux_primal_minloc);CHKERRQ(ierr);
1511984c4197SStefano Zampini   /* auxiliary stuff for basis change */
1512984c4197SStefano Zampini   ierr = PetscMalloc(max_size_of_constraint*sizeof(PetscInt),&global_indices);CHKERRQ(ierr);
15134641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
1514984c4197SStefano Zampini 
1515984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
1516984c4197SStefano Zampini   total_primal_vertices=0;
1517984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
1518674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1519984c4197SStefano Zampini     if (size_of_constraint == 1) {
15204641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
1521984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
1522984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
1523984c4197SStefano Zampini       total_primal_vertices++;
15244641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
1525984c4197SStefano Zampini       PetscInt min_loc,min_index;
1526984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
1527984c4197SStefano Zampini       /* find first untouched local node */
1528674ae819SStefano Zampini       k = 0;
15294641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
1530984c4197SStefano Zampini       min_index = global_indices[k];
1531984c4197SStefano Zampini       min_loc = k;
1532984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
1533984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
1534984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
15354641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
1536984c4197SStefano Zampini           min_index = global_indices[k];
1537984c4197SStefano Zampini           min_loc = k;
1538674ae819SStefano Zampini         }
1539674ae819SStefano Zampini       }
15404641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
1541984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
1542984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
1543984c4197SStefano Zampini       total_primal_vertices++;
1544984c4197SStefano Zampini     }
1545984c4197SStefano Zampini   }
1546984c4197SStefano Zampini   /* free workspace */
1547984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
15484641a718SStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
1549674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
1550984c4197SStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);
1551984c4197SStefano Zampini 
1552984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
1553984c4197SStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1554984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
1555984c4197SStefano Zampini   j=total_primal_vertices;
1556984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
15574641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
1558674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
1559674ae819SStefano Zampini       j++;
1560674ae819SStefano Zampini     }
1561674ae819SStefano Zampini   }
1562674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
1563674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
1564674ae819SStefano Zampini   /* set values in constraint matrix */
1565984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
1566984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
1567674ae819SStefano Zampini   }
1568984c4197SStefano Zampini   total_counts = total_primal_vertices;
1569984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
15704641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
1571674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
1572674ae819SStefano Zampini       ierr = MatSetValues(pcbddc->ConstraintMatrix,1,&total_counts,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],&temp_quadrature_constraint[temp_indices[i]],INSERT_VALUES);CHKERRQ(ierr);
1573674ae819SStefano Zampini       total_counts++;
1574674ae819SStefano Zampini     }
1575674ae819SStefano Zampini   }
1576674ae819SStefano Zampini   /* assembling */
1577674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1578674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1579984c4197SStefano Zampini   /*
1580984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
1581984c4197SStefano Zampini   */
1582674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
1583674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
1584984c4197SStefano Zampini     PetscBool qr_needed = PETSC_FALSE;
1585984c4197SStefano Zampini     /* change of basis acts on local interfaces -> dimension is n_B x n_B */
1586674ae819SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
1587674ae819SStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
1588674ae819SStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
1589674ae819SStefano Zampini     /* work arrays */
1590674ae819SStefano Zampini     ierr = PetscMalloc(pcis->n_B*sizeof(PetscInt),&nnz);CHKERRQ(ierr);
1591984c4197SStefano Zampini     for (i=0;i<pcis->n_B;i++) nnz[i]=1;
1592984c4197SStefano Zampini     /* nonzeros per row */
1593984c4197SStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
15944641a718SStefano Zampini       if (PetscBTLookup(change_basis,i)) {
1595984c4197SStefano Zampini         qr_needed = PETSC_TRUE;
1596674ae819SStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
1597984c4197SStefano Zampini         for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
1598674ae819SStefano Zampini       }
1599674ae819SStefano Zampini     }
1600674ae819SStefano Zampini     ierr = MatSeqAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
1601674ae819SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
1602674ae819SStefano Zampini     /* Set initial identity in the matrix */
1603674ae819SStefano Zampini     for (i=0;i<pcis->n_B;i++) {
1604674ae819SStefano Zampini       ierr = MatSetValue(pcbddc->ChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
1605674ae819SStefano Zampini     }
1606984c4197SStefano Zampini 
1607674ae819SStefano Zampini     /* Now we loop on the constraints which need a change of basis */
1608674ae819SStefano Zampini     /* Change of basis matrix is evaluated as the FIRST APPROACH in */
1609984c4197SStefano Zampini     /* Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1) */
1610984c4197SStefano Zampini     /* Change of basis matrix T computed via QR decomposition of constraints */
1611984c4197SStefano Zampini     if (qr_needed) {
1612026de310SStefano Zampini       /* dual and primal dofs on a single cc */
1613984c4197SStefano Zampini       PetscInt     dual_dofs,primal_dofs;
1614026de310SStefano Zampini       /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
1615026de310SStefano Zampini       PetscInt     primal_counter;
1616984c4197SStefano Zampini       /* working stuff for GEQRF */
1617984c4197SStefano Zampini       PetscScalar  *qr_basis,*qr_tau,*qr_work,lqr_work_t;
1618984c4197SStefano Zampini       PetscBLASInt lqr_work;
1619984c4197SStefano Zampini       /* working stuff for UNGQR */
1620984c4197SStefano Zampini       PetscScalar  *gqr_work,lgqr_work_t;
1621984c4197SStefano Zampini       PetscBLASInt lgqr_work;
1622984c4197SStefano Zampini       /* working stuff for TRTRS */
1623984c4197SStefano Zampini       PetscScalar  *trs_rhs;
16243f08241aSStefano Zampini       PetscBLASInt Blas_NRHS;
1625984c4197SStefano Zampini       /* pointers for values insertion into change of basis matrix */
1626984c4197SStefano Zampini       PetscInt     *start_rows,*start_cols;
1627984c4197SStefano Zampini       PetscScalar  *start_vals;
1628984c4197SStefano Zampini       /* working stuff for values insertion */
16294641a718SStefano Zampini       PetscBT      is_primal;
1630984c4197SStefano Zampini 
1631984c4197SStefano Zampini       /* space to store Q */
1632984c4197SStefano Zampini       ierr = PetscMalloc((max_size_of_constraint)*(max_size_of_constraint)*sizeof(PetscScalar),&qr_basis);CHKERRQ(ierr);
1633984c4197SStefano Zampini       /* first we issue queries for optimal work */
16343f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
16353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
16363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1637984c4197SStefano Zampini       lqr_work = -1;
16383f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
1639984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
1640984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
1641984c4197SStefano Zampini       ierr = PetscMalloc((PetscInt)PetscRealPart(lqr_work_t)*sizeof(*qr_work),&qr_work);CHKERRQ(ierr);
1642984c4197SStefano Zampini       lgqr_work = -1;
16433f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
16443f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
16453f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
16463f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
16473f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
16483f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
1649984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
1650984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
1651984c4197SStefano Zampini       ierr = PetscMalloc((PetscInt)PetscRealPart(lgqr_work_t)*sizeof(*gqr_work),&gqr_work);CHKERRQ(ierr);
1652984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
1653984c4197SStefano Zampini       ierr = PetscMalloc(max_constraints*sizeof(*qr_tau),&qr_tau);CHKERRQ(ierr);
1654984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
1655984c4197SStefano Zampini       ierr = PetscMalloc(max_constraints*max_constraints*sizeof(*trs_rhs),&trs_rhs);CHKERRQ(ierr);
1656984c4197SStefano Zampini       /* array to store whether a node is primal or not */
16574641a718SStefano Zampini       ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
16584641a718SStefano Zampini       for (i=0;i<total_primal_vertices;i++) {
16594641a718SStefano Zampini         ierr = PetscBTSet(is_primal,local_to_B[aux_primal_numbering[i]]);CHKERRQ(ierr);
16604641a718SStefano Zampini       }
1661984c4197SStefano Zampini 
1662984c4197SStefano Zampini       /* allocating workspace for check */
1663984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
1664984c4197SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1665984c4197SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
1666984c4197SStefano Zampini         ierr = PetscMalloc(max_size_of_constraint*(max_constraints+max_size_of_constraint)*sizeof(*work),&work);CHKERRQ(ierr);
1667674ae819SStefano Zampini       }
1668984c4197SStefano Zampini 
1669026de310SStefano Zampini       /* loop on constraints and see whether or not they need a change of basis */
1670026de310SStefano Zampini       /* -> using implicit ordering contained in temp_indices data */
1671026de310SStefano Zampini       total_counts = pcbddc->n_vertices;
1672026de310SStefano Zampini       primal_counter = total_counts;
1673026de310SStefano Zampini       while (total_counts<pcbddc->local_primal_size) {
1674026de310SStefano Zampini         primal_dofs = 1;
16754641a718SStefano Zampini         if (PetscBTLookup(change_basis,total_counts)) {
1676026de310SStefano Zampini           /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
1677026de310SStefano Zampini           while (total_counts+primal_dofs < pcbddc->local_primal_size && temp_indices_to_constraint_B[temp_indices[total_counts]] == temp_indices_to_constraint_B[temp_indices[total_counts+primal_dofs]]) {
1678026de310SStefano Zampini             primal_dofs++;
1679674ae819SStefano Zampini           }
1680984c4197SStefano Zampini           /* get constraint info */
1681026de310SStefano Zampini           size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
1682984c4197SStefano Zampini           dual_dofs = size_of_constraint-primal_dofs;
1683984c4197SStefano Zampini 
1684984c4197SStefano Zampini           /* copy quadrature constraints for change of basis check */
1685984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
1686026de310SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d to %d need a change of basis (size %d)\n",total_counts,total_counts+primal_dofs,size_of_constraint);CHKERRQ(ierr);
1687026de310SStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
1688674ae819SStefano Zampini           }
1689984c4197SStefano Zampini 
1690984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
1691026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
1692984c4197SStefano Zampini 
1693984c4197SStefano Zampini           /* compute QR decomposition of constraints */
16943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
16953f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
16963f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1697674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
16983f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
1699984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
1700674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1701984c4197SStefano Zampini 
1702984c4197SStefano Zampini           /* explictly compute R^-T */
1703984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
1704984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
17053f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
17063f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
17073f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
17083f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
1709984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
17103f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
1711984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
1712984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1713984c4197SStefano Zampini 
1714984c4197SStefano Zampini           /* explcitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
17153f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
17163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
17173f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
17183f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1719984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
17203f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
1721984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
1722984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1723984c4197SStefano Zampini 
1724984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
1725984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
1726984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
17273f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
17283f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
17293f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
17303f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
17313f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
17323f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
1733984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1734c4303822SStefano Zampini           PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&Blas_M,&Blas_N,&Blas_K,&one,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&zero,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_LDC));
1735984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1736026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
1737984c4197SStefano Zampini 
1738984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
1739026de310SStefano Zampini           start_rows = &temp_indices_to_constraint_B[temp_indices[total_counts]];
1740984c4197SStefano Zampini           /* insert cols for primal dofs */
1741984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
1742984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
1743026de310SStefano Zampini             start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
1744984c4197SStefano Zampini             ierr = MatSetValues(pcbddc->ChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
1745984c4197SStefano Zampini           }
1746984c4197SStefano Zampini           /* insert cols for dual dofs */
1747984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
17484641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
1749984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
1750026de310SStefano Zampini               start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+k];
1751984c4197SStefano Zampini               ierr = MatSetValues(pcbddc->ChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
1752984c4197SStefano Zampini               j++;
1753674ae819SStefano Zampini             }
1754674ae819SStefano Zampini           }
1755984c4197SStefano Zampini 
1756984c4197SStefano Zampini           /* check change of basis */
1757984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
1758984c4197SStefano Zampini             PetscInt   ii,jj;
1759984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
1760c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
1761c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1762c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
1763c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1764c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
1765c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
1766984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1767c4303822SStefano Zampini             PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&Blas_M,&Blas_N,&Blas_K,&one,work,&Blas_LDA,qr_basis,&Blas_LDB,&zero,&work[size_of_constraint*primal_dofs],&Blas_LDC));
1768984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
1769984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
1770984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
1771984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
1772984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
1773674ae819SStefano Zampini               }
1774674ae819SStefano Zampini             }
1775984c4197SStefano Zampini             if (!valid_qr) {
1776984c4197SStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n",PetscGlobalRank);CHKERRQ(ierr);
1777984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
1778984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
1779984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
1780984c4197SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not orthogonal to constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
1781674ae819SStefano Zampini                   }
1782984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
1783984c4197SStefano Zampini                     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\tQr basis function %d is not unitary w.r.t constraint %d (%1.14e)!\n",jj,ii,PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]));
1784984c4197SStefano Zampini                   }
1785984c4197SStefano Zampini                 }
1786984c4197SStefano Zampini               }
1787674ae819SStefano Zampini             } else {
1788984c4197SStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n",PetscGlobalRank);CHKERRQ(ierr);
1789674ae819SStefano Zampini             }
1790674ae819SStefano Zampini           }
1791026de310SStefano Zampini           /* increment primal counter */
1792026de310SStefano Zampini           primal_counter += primal_dofs;
1793984c4197SStefano Zampini         } else {
1794984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
1795026de310SStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraint %d does not need a change of basis (size %d)\n",total_counts,temp_indices[total_counts+1]-temp_indices[total_counts]);CHKERRQ(ierr);
1796674ae819SStefano Zampini           }
1797674ae819SStefano Zampini         }
1798026de310SStefano Zampini         /* increment constraint counter total_counts */
1799026de310SStefano Zampini         total_counts += primal_dofs;
1800674ae819SStefano Zampini       }
1801984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
1802984c4197SStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1803984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
1804984c4197SStefano Zampini       }
1805984c4197SStefano Zampini       /* free workspace */
1806984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
1807984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
1808984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
1809984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
18104641a718SStefano Zampini       ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
1811984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
1812674ae819SStefano Zampini     }
1813674ae819SStefano Zampini     /* assembling */
1814674ae819SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1815674ae819SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1816984c4197SStefano Zampini     /*
1817984c4197SStefano Zampini     ierr = MatView(pcbddc->ChangeOfBasisMatrix,(PetscViewer)0);CHKERRQ(ierr);
1818984c4197SStefano Zampini     */
1819674ae819SStefano Zampini   }
1820e310c8b4SStefano Zampini   /* free workspace */
1821984c4197SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
1822984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
1823674ae819SStefano Zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
18244641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
1825674ae819SStefano Zampini   ierr = PetscFree(temp_indices_to_constraint);CHKERRQ(ierr);
1826674ae819SStefano Zampini   ierr = PetscFree(temp_indices_to_constraint_B);CHKERRQ(ierr);
1827674ae819SStefano Zampini   ierr = PetscFree(local_to_B);CHKERRQ(ierr);
1828674ae819SStefano Zampini   ierr = PetscFree(temp_quadrature_constraint);CHKERRQ(ierr);
1829674ae819SStefano Zampini   PetscFunctionReturn(0);
1830674ae819SStefano Zampini }
1831674ae819SStefano Zampini 
1832674ae819SStefano Zampini #undef __FUNCT__
1833674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
1834674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
1835674ae819SStefano Zampini {
1836674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
1837674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
1838674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
1839674ae819SStefano Zampini   PetscInt    bs,ierr,i,vertex_size;
1840674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
1841674ae819SStefano Zampini 
1842674ae819SStefano Zampini   PetscFunctionBegin;
1843674ae819SStefano Zampini   /* Init local Graph struct */
1844674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
1845674ae819SStefano Zampini 
1846575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
1847575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
1848575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
1849575ad6abSStefano Zampini   }
1850674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
1851674ae819SStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
1852674ae819SStefano Zampini     Mat mat_adj;
1853674ae819SStefano Zampini     const PetscInt *xadj,*adjncy;
1854674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
1855674ae819SStefano Zampini 
1856674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
1857674ae819SStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&i,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1858674ae819SStefano Zampini     if (!flg_row) {
1859674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
1860674ae819SStefano Zampini     }
1861674ae819SStefano Zampini     ierr = PCBDDCSetLocalAdjacencyGraph(pc,i,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
1862674ae819SStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&i,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
1863674ae819SStefano Zampini     if (!flg_row) {
1864674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
1865674ae819SStefano Zampini     }
1866674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
1867674ae819SStefano Zampini   }
1868674ae819SStefano Zampini 
1869674ae819SStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting */
1870674ae819SStefano Zampini   vertex_size = 1;
1871674ae819SStefano Zampini   if (!pcbddc->n_ISForDofs) {
1872674ae819SStefano Zampini     IS *custom_ISForDofs;
1873674ae819SStefano Zampini 
1874674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1875674ae819SStefano Zampini     ierr = PetscMalloc(bs*sizeof(IS),&custom_ISForDofs);CHKERRQ(ierr);
1876674ae819SStefano Zampini     for (i=0;i<bs;i++) {
1877674ae819SStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n/bs,i,bs,&custom_ISForDofs[i]);CHKERRQ(ierr);
1878674ae819SStefano Zampini     }
1879674ae819SStefano Zampini     ierr = PCBDDCSetDofsSplitting(pc,bs,custom_ISForDofs);CHKERRQ(ierr);
1880674ae819SStefano Zampini     /* remove my references to IS objects */
1881674ae819SStefano Zampini     for (i=0;i<bs;i++) {
1882674ae819SStefano Zampini       ierr = ISDestroy(&custom_ISForDofs[i]);CHKERRQ(ierr);
1883674ae819SStefano Zampini     }
1884674ae819SStefano Zampini     ierr = PetscFree(custom_ISForDofs);CHKERRQ(ierr);
1885674ae819SStefano Zampini   } else { /* mat block size as vertex size (used for elasticity) */
1886674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
1887674ae819SStefano Zampini   }
1888674ae819SStefano Zampini 
1889674ae819SStefano Zampini   /* Setup of Graph */
1890674ae819SStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundaries,pcbddc->DirichletBoundaries,pcbddc->n_ISForDofs,pcbddc->ISForDofs,pcbddc->user_primal_vertices);
1891674ae819SStefano Zampini 
1892674ae819SStefano Zampini   /* Graph's connected components analysis */
1893674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
1894674ae819SStefano Zampini 
1895674ae819SStefano Zampini   /* print some info to stdout */
1896674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
1897e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
1898674ae819SStefano Zampini   }
1899674ae819SStefano Zampini   PetscFunctionReturn(0);
1900674ae819SStefano Zampini }
1901674ae819SStefano Zampini 
1902674ae819SStefano Zampini #undef __FUNCT__
1903674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
1904*f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
1905674ae819SStefano Zampini {
1906674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
1907674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
1908674ae819SStefano Zampini   PetscErrorCode ierr;
1909674ae819SStefano Zampini 
1910674ae819SStefano Zampini   PetscFunctionBegin;
1911674ae819SStefano Zampini   n = 0;
1912674ae819SStefano Zampini   vertices = 0;
1913674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
1914674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
1915b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
1916b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
1917b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
1918b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
1919b120a5c6SStefano Zampini     }
1920811e8ca2SStefano Zampini     if (vertices_idx) {
1921b120a5c6SStefano Zampini       ierr = PetscMalloc(n*sizeof(PetscInt),&vertices);CHKERRQ(ierr);
1922b120a5c6SStefano Zampini       n = 0;
1923674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
1924674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
1925674ae819SStefano Zampini         if (size_of_constraint == 1) {
1926674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
1927674ae819SStefano Zampini         }
1928674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
1929674ae819SStefano Zampini       }
1930674ae819SStefano Zampini     }
1931811e8ca2SStefano Zampini   }
1932674ae819SStefano Zampini   *n_vertices = n;
1933811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
1934674ae819SStefano Zampini   PetscFunctionReturn(0);
1935674ae819SStefano Zampini }
1936674ae819SStefano Zampini 
1937674ae819SStefano Zampini #undef __FUNCT__
1938674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
1939*f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
1940674ae819SStefano Zampini {
1941674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
1942674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
1943674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
19444641a718SStefano Zampini   PetscBT        touched;
1945674ae819SStefano Zampini   PetscErrorCode ierr;
1946674ae819SStefano Zampini 
1947*f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
1948*f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
1949*f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
1950674ae819SStefano Zampini   PetscFunctionBegin;
1951674ae819SStefano Zampini   n = 0;
1952674ae819SStefano Zampini   constraints_index = 0;
1953674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
1954674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
1955674ae819SStefano Zampini     max_size_of_constraint = 0;
1956674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
1957674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
1958674ae819SStefano Zampini       if (size_of_constraint > 1) {
1959674ae819SStefano Zampini         n++;
1960674ae819SStefano Zampini       }
1961674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
1962674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
1963674ae819SStefano Zampini     }
1964811e8ca2SStefano Zampini     if (constraints_idx) {
1965674ae819SStefano Zampini       ierr = PetscMalloc(n*sizeof(PetscInt),&constraints_index);CHKERRQ(ierr);
1966674ae819SStefano Zampini       ierr = PetscMalloc(max_size_of_constraint*sizeof(PetscInt),&row_cmat_global_indices);CHKERRQ(ierr);
19674641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
1968674ae819SStefano Zampini       n = 0;
1969674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
1970674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
1971674ae819SStefano Zampini         if (size_of_constraint > 1) {
1972674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
197382d3d8afSStefano Zampini           /* find first untouched local node */
197482d3d8afSStefano Zampini           j = 0;
19754641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
197682d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
197782d3d8afSStefano Zampini           min_loc = j;
197882d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
197982d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
1980674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
19814641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
1982674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
1983674ae819SStefano Zampini               min_loc = j;
1984674ae819SStefano Zampini             }
1985674ae819SStefano Zampini           }
19864641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
1987674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
1988674ae819SStefano Zampini         }
1989674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
1990674ae819SStefano Zampini       }
19914641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
1992674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
1993811e8ca2SStefano Zampini     }
1994811e8ca2SStefano Zampini   }
1995674ae819SStefano Zampini   *n_constraints = n;
1996811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
1997674ae819SStefano Zampini   PetscFunctionReturn(0);
1998674ae819SStefano Zampini }
1999674ae819SStefano Zampini 
2000674ae819SStefano Zampini /* the next two functions has been adapted from pcis.c */
2001674ae819SStefano Zampini #undef __FUNCT__
2002674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplySchur"
2003674ae819SStefano Zampini PetscErrorCode  PCBDDCApplySchur(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D)
2004674ae819SStefano Zampini {
2005674ae819SStefano Zampini   PetscErrorCode ierr;
2006674ae819SStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
2007674ae819SStefano Zampini 
2008674ae819SStefano Zampini   PetscFunctionBegin;
2009674ae819SStefano Zampini   if (!vec2_B) { vec2_B = v; }
2010674ae819SStefano Zampini   ierr = MatMult(pcis->A_BB,v,vec1_B);CHKERRQ(ierr);
2011674ae819SStefano Zampini   ierr = MatMult(pcis->A_IB,v,vec1_D);CHKERRQ(ierr);
2012674ae819SStefano Zampini   ierr = KSPSolve(pcis->ksp_D,vec1_D,vec2_D);CHKERRQ(ierr);
2013674ae819SStefano Zampini   ierr = MatMult(pcis->A_BI,vec2_D,vec2_B);CHKERRQ(ierr);
2014674ae819SStefano Zampini   ierr = VecAXPY(vec1_B,-1.0,vec2_B);CHKERRQ(ierr);
2015674ae819SStefano Zampini   PetscFunctionReturn(0);
2016674ae819SStefano Zampini }
2017674ae819SStefano Zampini 
2018674ae819SStefano Zampini #undef __FUNCT__
2019674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplySchurTranspose"
2020674ae819SStefano Zampini PetscErrorCode  PCBDDCApplySchurTranspose(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D)
2021674ae819SStefano Zampini {
2022674ae819SStefano Zampini   PetscErrorCode ierr;
2023674ae819SStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
2024674ae819SStefano Zampini 
2025674ae819SStefano Zampini   PetscFunctionBegin;
2026674ae819SStefano Zampini   if (!vec2_B) { vec2_B = v; }
2027674ae819SStefano Zampini   ierr = MatMultTranspose(pcis->A_BB,v,vec1_B);CHKERRQ(ierr);
2028674ae819SStefano Zampini   ierr = MatMultTranspose(pcis->A_BI,v,vec1_D);CHKERRQ(ierr);
2029674ae819SStefano Zampini   ierr = KSPSolveTranspose(pcis->ksp_D,vec1_D,vec2_D);CHKERRQ(ierr);
2030674ae819SStefano Zampini   ierr = MatMultTranspose(pcis->A_IB,vec2_D,vec2_B);CHKERRQ(ierr);
2031674ae819SStefano Zampini   ierr = VecAXPY(vec1_B,-1.0,vec2_B);CHKERRQ(ierr);
2032674ae819SStefano Zampini   PetscFunctionReturn(0);
2033674ae819SStefano Zampini }
2034674ae819SStefano Zampini 
2035674ae819SStefano Zampini #undef __FUNCT__
2036674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
2037674ae819SStefano Zampini PetscErrorCode PCBDDCSubsetNumbering(MPI_Comm comm,ISLocalToGlobalMapping l2gmap, PetscInt n_local_dofs, PetscInt local_dofs[], PetscInt local_dofs_mult[], PetscInt* n_global_subset, PetscInt* global_numbering_subset[])
2038674ae819SStefano Zampini {
2039674ae819SStefano Zampini   Vec            local_vec,global_vec;
2040674ae819SStefano Zampini   IS             seqis,paris;
2041674ae819SStefano Zampini   VecScatter     scatter_ctx;
2042674ae819SStefano Zampini   PetscScalar    *array;
2043674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
2044674ae819SStefano Zampini   PetscScalar    globalsum;
2045674ae819SStefano Zampini   PetscInt       i,j,s;
2046674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
2047674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
2048674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
2049674ae819SStefano Zampini   PetscBool      first_found;
2050674ae819SStefano Zampini   PetscErrorCode ierr;
2051674ae819SStefano Zampini 
2052674ae819SStefano Zampini   PetscFunctionBegin;
2053674ae819SStefano Zampini   /* mpi buffers */
2054674ae819SStefano Zampini   MPI_Comm_size(comm,&size_prec_comm);
2055674ae819SStefano Zampini   MPI_Comm_rank(comm,&rank_prec_comm);
2056674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
2057674ae819SStefano Zampini   ierr = PetscMalloc(j*sizeof(*dof_sizes),&dof_sizes);CHKERRQ(ierr);
2058674ae819SStefano Zampini   ierr = PetscMalloc(j*sizeof(*dof_displs),&dof_displs);CHKERRQ(ierr);
2059674ae819SStefano Zampini   /* get maximum size of subset */
2060674ae819SStefano Zampini   ierr = PetscMalloc(n_local_dofs*sizeof(PetscInt),&temp_global_dofs);CHKERRQ(ierr);
2061674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
2062674ae819SStefano Zampini   max_local = 0;
2063674ae819SStefano Zampini   if (n_local_dofs) {
2064674ae819SStefano Zampini     max_local = temp_global_dofs[0];
2065674ae819SStefano Zampini     for (i=1;i<n_local_dofs;i++) {
2066674ae819SStefano Zampini       if (max_local < temp_global_dofs[i] ) {
2067674ae819SStefano Zampini         max_local = temp_global_dofs[i];
2068674ae819SStefano Zampini       }
2069674ae819SStefano Zampini     }
2070674ae819SStefano Zampini   }
2071674ae819SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);
2072674ae819SStefano Zampini   max_global++;
2073674ae819SStefano Zampini   max_local = 0;
2074674ae819SStefano Zampini   if (n_local_dofs) {
2075674ae819SStefano Zampini     max_local = local_dofs[0];
2076674ae819SStefano Zampini     for (i=1;i<n_local_dofs;i++) {
2077674ae819SStefano Zampini       if (max_local < local_dofs[i] ) {
2078674ae819SStefano Zampini         max_local = local_dofs[i];
2079674ae819SStefano Zampini       }
2080674ae819SStefano Zampini     }
2081674ae819SStefano Zampini   }
2082674ae819SStefano Zampini   max_local++;
2083674ae819SStefano Zampini   /* allocate workspace */
2084674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
2085674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
2086674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
2087674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
2088674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
2089674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
2090674ae819SStefano Zampini   /* create scatter */
2091674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
2092674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
2093674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
2094674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
2095674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
2096674ae819SStefano Zampini   /* init array */
2097674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
2098674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2099674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2100674ae819SStefano Zampini   if (local_dofs_mult) {
2101674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2102674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
2103674ae819SStefano Zampini     }
2104674ae819SStefano Zampini   } else {
2105674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2106674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
2107674ae819SStefano Zampini     }
2108674ae819SStefano Zampini   }
2109674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2110674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
2111674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2112674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2113674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
21145b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
2115674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
2116674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
2117674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
2118674ae819SStefano Zampini   nlocals = 0;
2119674ae819SStefano Zampini   first_index = -1;
2120674ae819SStefano Zampini   first_found = PETSC_FALSE;
2121674ae819SStefano Zampini   for (i=0;i<s;i++) {
21225b08dc53SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.0) {
2123674ae819SStefano Zampini       first_found = PETSC_TRUE;
2124674ae819SStefano Zampini       first_index = i;
2125674ae819SStefano Zampini     }
21265b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
2127674ae819SStefano Zampini   }
2128674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2129674ae819SStefano Zampini   if (!rank_prec_comm) {
2130674ae819SStefano Zampini     dof_displs[0]=0;
2131674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
2132674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
2133674ae819SStefano Zampini     }
2134674ae819SStefano Zampini   }
2135674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2136674ae819SStefano Zampini   if (first_found) {
2137674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
2138674ae819SStefano Zampini     old_index = first_index;
2139674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
21405b08dc53SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) {
2141674ae819SStefano Zampini         array[i] += array[old_index];
2142674ae819SStefano Zampini         old_index = i;
2143674ae819SStefano Zampini       }
2144674ae819SStefano Zampini     }
2145674ae819SStefano Zampini   }
2146674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
2147674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2148674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2149674ae819SStefano Zampini   ierr = VecScatterEnd  (scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2150674ae819SStefano Zampini   /* get global ordering of local dofs */
2151674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2152674ae819SStefano Zampini   if (local_dofs_mult) {
2153674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
21545b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
2155674ae819SStefano Zampini     }
2156674ae819SStefano Zampini   } else {
2157674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
21585b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
2159674ae819SStefano Zampini     }
2160674ae819SStefano Zampini   }
2161674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2162674ae819SStefano Zampini   /* free workspace */
2163674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
2164674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
2165674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
2166674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
2167674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
2168674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
2169674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
2170674ae819SStefano Zampini   PetscFunctionReturn(0);
2171674ae819SStefano Zampini }
21729a7d3425SStefano Zampini 
21739a7d3425SStefano Zampini #undef __FUNCT__
21749a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
21759a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
21769a7d3425SStefano Zampini {
21779a7d3425SStefano Zampini   PetscInt       i,j;
21789a7d3425SStefano Zampini   PetscScalar    *alphas;
21799a7d3425SStefano Zampini   PetscErrorCode ierr;
21809a7d3425SStefano Zampini 
21819a7d3425SStefano Zampini   PetscFunctionBegin;
21829a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
21839a7d3425SStefano Zampini   ierr = PetscMalloc(n*sizeof(PetscScalar),&alphas);CHKERRQ(ierr);
21849a7d3425SStefano Zampini   for (i=0;i<n;i++) {
21859a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
21869a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
21879a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
21889a7d3425SStefano Zampini   }
21899a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
21909a7d3425SStefano Zampini   PetscFunctionReturn(0);
21919a7d3425SStefano Zampini }
21929a7d3425SStefano Zampini 
2193c8587f34SStefano Zampini /* BDDC requires metis 5.0.1 for multilevel */
2194c8587f34SStefano Zampini #if defined(PETSC_HAVE_METIS)
2195c8587f34SStefano Zampini #include "metis.h"
2196c8587f34SStefano Zampini #define MetisInt    idx_t
2197c8587f34SStefano Zampini #define MetisScalar real_t
2198c8587f34SStefano Zampini #endif
2199c8587f34SStefano Zampini 
2200c8587f34SStefano Zampini #undef __FUNCT__
22018629588bSStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
22028629588bSStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
2203c8587f34SStefano Zampini {
2204c8587f34SStefano Zampini   PC_BDDC   *pcbddc   = (PC_BDDC*)pc->data;
2205c8587f34SStefano Zampini   PC_IS     *pcis     = (PC_IS*)pc->data;
2206c8587f34SStefano Zampini   MPI_Comm  prec_comm;
2207c8587f34SStefano Zampini   MPI_Comm  coarse_comm;
2208fdc635d7SStefano Zampini   Mat coarse_mat;
2209c8587f34SStefano Zampini 
2210983f5fd7SStefano Zampini   PetscInt  coarse_size;
2211983f5fd7SStefano Zampini 
2212c8587f34SStefano Zampini   MatNullSpace CoarseNullSpace;
2213c8587f34SStefano Zampini 
2214c8587f34SStefano Zampini   /* common to all choiches */
2215c8587f34SStefano Zampini   PetscScalar *temp_coarse_mat_vals;
2216c8587f34SStefano Zampini   PetscScalar *ins_coarse_mat_vals;
2217c8587f34SStefano Zampini   PetscInt    *ins_local_primal_indices;
2218c8587f34SStefano Zampini   PetscMPIInt *localsizes2,*localdispl2;
2219c8587f34SStefano Zampini   PetscMPIInt size_prec_comm;
2220c8587f34SStefano Zampini   PetscMPIInt rank_prec_comm;
2221c8587f34SStefano Zampini   PetscMPIInt active_rank=MPI_PROC_NULL;
2222c8587f34SStefano Zampini   PetscMPIInt master_proc=0;
2223c8587f34SStefano Zampini   PetscInt    ins_local_primal_size;
2224c8587f34SStefano Zampini   /* specific to MULTILEVEL_BDDC */
2225c8587f34SStefano Zampini   PetscMPIInt *ranks_recv=0;
2226c8587f34SStefano Zampini   PetscMPIInt count_recv=0;
2227c8587f34SStefano Zampini   PetscMPIInt rank_coarse_proc_send_to=-1;
2228c8587f34SStefano Zampini   PetscMPIInt coarse_color = MPI_UNDEFINED;
2229c8587f34SStefano Zampini   ISLocalToGlobalMapping coarse_ISLG;
2230c8587f34SStefano Zampini   /* some other variables */
2231c8587f34SStefano Zampini   PetscErrorCode ierr;
2232c8587f34SStefano Zampini   MatType coarse_mat_type;
2233c8587f34SStefano Zampini   PCType  coarse_pc_type;
2234c8587f34SStefano Zampini   KSPType coarse_ksp_type;
2235c8587f34SStefano Zampini   PC pc_temp;
2236c8587f34SStefano Zampini   PetscInt i,j,k;
2237c8587f34SStefano Zampini   PetscInt max_it_coarse_ksp=1;  /* don't increase this value */
2238c8587f34SStefano Zampini   /* verbose output viewer */
2239c8587f34SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2240c8587f34SStefano Zampini   PetscInt    dbg_flag=pcbddc->dbg_flag;
2241c8587f34SStefano Zampini 
2242c8587f34SStefano Zampini   PetscInt      offset,offset2;
2243c8587f34SStefano Zampini   PetscMPIInt   im_active,active_procs;
2244c8587f34SStefano Zampini   PetscInt      *dnz,*onz;
2245c8587f34SStefano Zampini 
2246c8587f34SStefano Zampini   PetscBool     setsym,issym=PETSC_FALSE;
2247c8587f34SStefano Zampini 
2248fdc09c96SStefano Zampini   PetscInt      *replicated_local_primal_indices=0,*local_primal_indices=0,*local_primal_displacements=0,*local_primal_sizes=0;
2249fdc09c96SStefano Zampini   PetscInt      replicated_primal_size=0;
2250fdc09c96SStefano Zampini 
2251c8587f34SStefano Zampini   PetscFunctionBegin;
2252c8587f34SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)pc,&prec_comm);CHKERRQ(ierr);
2253c8587f34SStefano Zampini   ins_local_primal_indices = 0;
2254c8587f34SStefano Zampini   ins_coarse_mat_vals      = 0;
2255c8587f34SStefano Zampini   localsizes2              = 0;
2256c8587f34SStefano Zampini   localdispl2              = 0;
2257c8587f34SStefano Zampini   temp_coarse_mat_vals     = 0;
2258c8587f34SStefano Zampini   coarse_ISLG              = 0;
2259c8587f34SStefano Zampini 
2260c8587f34SStefano Zampini   ierr = MPI_Comm_size(prec_comm,&size_prec_comm);CHKERRQ(ierr);
2261c8587f34SStefano Zampini   ierr = MPI_Comm_rank(prec_comm,&rank_prec_comm);CHKERRQ(ierr);
2262c8587f34SStefano Zampini   ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
2263c8587f34SStefano Zampini 
22649ffa7720SStefano Zampini   if (pcbddc->coarse_problem_type == SEQUENTIAL_BDDC || pcbddc->coarse_problem_type == REPLICATED_BDDC) {
22659ffa7720SStefano Zampini     pcbddc->coarse_problem_type = PARALLEL_BDDC;
22669ffa7720SStefano Zampini     pcbddc->coarse_communications_type = SCATTERS_BDDC;
22679ffa7720SStefano Zampini   }
22689ffa7720SStefano Zampini 
2269c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
2270*f34684f1SStefano Zampini   ierr = PCBDDCComputePrimalNumbering(pc,&coarse_size,&local_primal_indices);CHKERRQ(ierr);
2271c8587f34SStefano Zampini 
2272c8587f34SStefano Zampini   im_active = 0;
2273c8587f34SStefano Zampini   if (pcis->n) im_active = 1;
2274c8587f34SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,prec_comm);CHKERRQ(ierr);
2275c8587f34SStefano Zampini 
2276c8587f34SStefano Zampini   /* adapt coarse problem type */
2277c8587f34SStefano Zampini #if defined(PETSC_HAVE_METIS)
2278c8587f34SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2279c8587f34SStefano Zampini     if (pcbddc->current_level < pcbddc->max_levels) {
2280c8587f34SStefano Zampini       if ( (active_procs/pcbddc->coarsening_ratio) < 2 ) {
2281c8587f34SStefano Zampini         if (dbg_flag) {
2282c8587f34SStefano Zampini           ierr = PetscViewerASCIIPrintf(viewer,"Not enough active processes on level %d (active %d,ratio %d). Parallel direct solve for coarse problem\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
2283c8587f34SStefano Zampini          ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2284c8587f34SStefano Zampini         }
2285c8587f34SStefano Zampini         pcbddc->coarse_problem_type = PARALLEL_BDDC;
2286c8587f34SStefano Zampini       }
2287c8587f34SStefano Zampini     } else {
2288c8587f34SStefano Zampini       if (dbg_flag) {
2289c8587f34SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"Max number of levels reached. Using parallel direct solve for coarse problem\n",pcbddc->max_levels,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
2290c8587f34SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2291c8587f34SStefano Zampini       }
2292c8587f34SStefano Zampini       pcbddc->coarse_problem_type = PARALLEL_BDDC;
2293c8587f34SStefano Zampini     }
2294c8587f34SStefano Zampini   }
2295c8587f34SStefano Zampini #else
2296c8587f34SStefano Zampini   pcbddc->coarse_problem_type = PARALLEL_BDDC;
2297c8587f34SStefano Zampini #endif
2298*f34684f1SStefano Zampini 
2299*f34684f1SStefano Zampini   /* OLD version from here */
2300*f34684f1SStefano Zampini 
2301bb714bf2SStefano Zampini   /* Construct needed data structures for message passing */
2302bb714bf2SStefano Zampini   j = 0;
2303bb714bf2SStefano Zampini   if (rank_prec_comm == 0 || pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2304bb714bf2SStefano Zampini     j = size_prec_comm;
2305bb714bf2SStefano Zampini   }
2306bb714bf2SStefano Zampini   ierr = PetscMalloc(j*sizeof(*local_primal_sizes),&local_primal_sizes);CHKERRQ(ierr);
2307bb714bf2SStefano Zampini   ierr = PetscMalloc(j*sizeof(*local_primal_displacements),&local_primal_displacements);CHKERRQ(ierr);
2308bb714bf2SStefano Zampini   /* Gather local_primal_size information for all processes  */
2309bb714bf2SStefano Zampini   if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2310bb714bf2SStefano Zampini     ierr = MPI_Allgather(&pcbddc->local_primal_size,1,MPIU_INT,&local_primal_sizes[0],1,MPIU_INT,prec_comm);CHKERRQ(ierr);
2311bb714bf2SStefano Zampini   } else {
2312bb714bf2SStefano Zampini     ierr = MPI_Gather(&pcbddc->local_primal_size,1,MPIU_INT,&local_primal_sizes[0],1,MPIU_INT,0,prec_comm);CHKERRQ(ierr);
2313bb714bf2SStefano Zampini   }
2314bb714bf2SStefano Zampini   replicated_primal_size = 0;
2315bb714bf2SStefano Zampini   for (i=0; i<j; i++) {
2316bb714bf2SStefano Zampini     local_primal_displacements[i] = replicated_primal_size ;
2317bb714bf2SStefano Zampini     replicated_primal_size += local_primal_sizes[i];
2318bb714bf2SStefano Zampini   }
2319c8587f34SStefano Zampini 
2320c8587f34SStefano Zampini   switch(pcbddc->coarse_problem_type){
2321c8587f34SStefano Zampini 
2322c8587f34SStefano Zampini     case(MULTILEVEL_BDDC):   /* we define a coarse mesh where subdomains are elements */
2323c8587f34SStefano Zampini     {
2324c8587f34SStefano Zampini #if defined(PETSC_HAVE_METIS)
2325c8587f34SStefano Zampini       /* we need additional variables */
2326c8587f34SStefano Zampini       MetisInt    n_subdomains,n_parts,objval,ncon,faces_nvtxs;
2327c8587f34SStefano Zampini       MetisInt    *metis_coarse_subdivision;
2328c8587f34SStefano Zampini       MetisInt    options[METIS_NOPTIONS];
2329c8587f34SStefano Zampini       PetscMPIInt size_coarse_comm,rank_coarse_comm;
2330c8587f34SStefano Zampini       PetscMPIInt procs_jumps_coarse_comm;
2331c8587f34SStefano Zampini       PetscMPIInt *coarse_subdivision;
2332c8587f34SStefano Zampini       PetscMPIInt *total_count_recv;
2333c8587f34SStefano Zampini       PetscMPIInt *total_ranks_recv;
2334c8587f34SStefano Zampini       PetscMPIInt *displacements_recv;
2335c8587f34SStefano Zampini       PetscMPIInt *my_faces_connectivity;
2336c8587f34SStefano Zampini       PetscMPIInt *petsc_faces_adjncy;
2337c8587f34SStefano Zampini       MetisInt    *faces_adjncy;
2338c8587f34SStefano Zampini       MetisInt    *faces_xadj;
2339c8587f34SStefano Zampini       PetscMPIInt *number_of_faces;
2340c8587f34SStefano Zampini       PetscMPIInt *faces_displacements;
2341c8587f34SStefano Zampini       PetscInt    *array_int;
2342c8587f34SStefano Zampini       PetscMPIInt my_faces=0;
2343c8587f34SStefano Zampini       PetscMPIInt total_faces=0;
2344c8587f34SStefano Zampini       PetscInt    ranks_stretching_ratio;
2345c8587f34SStefano Zampini 
2346c8587f34SStefano Zampini       /* define some quantities */
2347c8587f34SStefano Zampini       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2348c8587f34SStefano Zampini       coarse_mat_type = MATIS;
2349c8587f34SStefano Zampini       coarse_pc_type  = PCBDDC;
2350c8587f34SStefano Zampini       coarse_ksp_type = KSPRICHARDSON;
2351c8587f34SStefano Zampini 
2352c8587f34SStefano Zampini       /* details of coarse decomposition */
2353c8587f34SStefano Zampini       n_subdomains = active_procs;
2354c8587f34SStefano Zampini       n_parts      = n_subdomains/pcbddc->coarsening_ratio;
2355c8587f34SStefano Zampini       ranks_stretching_ratio = size_prec_comm/active_procs;
2356c8587f34SStefano Zampini       procs_jumps_coarse_comm = pcbddc->coarsening_ratio*ranks_stretching_ratio;
2357c8587f34SStefano Zampini 
2358c8587f34SStefano Zampini #if 0
2359c8587f34SStefano Zampini       PetscMPIInt *old_ranks;
2360c8587f34SStefano Zampini       PetscInt    *new_ranks,*jj,*ii;
2361c8587f34SStefano Zampini       MatPartitioning mat_part;
2362c8587f34SStefano Zampini       IS coarse_new_decomposition,is_numbering;
2363c8587f34SStefano Zampini       PetscViewer viewer_test;
2364c8587f34SStefano Zampini       MPI_Comm    test_coarse_comm;
2365c8587f34SStefano Zampini       PetscMPIInt test_coarse_color;
2366c8587f34SStefano Zampini       Mat         mat_adj;
2367c8587f34SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2368c8587f34SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2369c8587f34SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2370c8587f34SStefano Zampini       test_coarse_color = ( im_active ? 0 : MPI_UNDEFINED );
2371c8587f34SStefano Zampini       test_coarse_comm = MPI_COMM_NULL;
2372c8587f34SStefano Zampini       ierr = MPI_Comm_split(prec_comm,test_coarse_color,rank_prec_comm,&test_coarse_comm);CHKERRQ(ierr);
2373c8587f34SStefano Zampini       if (im_active) {
2374c8587f34SStefano Zampini         ierr = PetscMalloc(n_subdomains*sizeof(PetscMPIInt),&old_ranks);
2375c8587f34SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscInt),&new_ranks);
2376c8587f34SStefano Zampini         ierr = MPI_Comm_rank(test_coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2377c8587f34SStefano Zampini         ierr = MPI_Comm_size(test_coarse_comm,&j);CHKERRQ(ierr);
2378c8587f34SStefano Zampini         ierr = MPI_Allgather(&rank_prec_comm,1,MPIU_INT,old_ranks,1,MPIU_INT,test_coarse_comm);CHKERRQ(ierr);
2379c8587f34SStefano Zampini         for (i=0; i<size_prec_comm; i++) new_ranks[i] = -1;
2380c8587f34SStefano Zampini         for (i=0; i<n_subdomains; i++) new_ranks[old_ranks[i]] = i;
2381c8587f34SStefano Zampini         ierr = PetscViewerASCIIOpen(test_coarse_comm,"test_mat_part.out",&viewer_test);CHKERRQ(ierr);
2382c8587f34SStefano Zampini         k = pcis->n_neigh-1;
2383c8587f34SStefano Zampini         ierr = PetscMalloc(2*sizeof(PetscInt),&ii);
2384c8587f34SStefano Zampini         ii[0]=0;
2385c8587f34SStefano Zampini         ii[1]=k;
2386c8587f34SStefano Zampini         ierr = PetscMalloc(k*sizeof(PetscInt),&jj);
2387c8587f34SStefano Zampini         for (i=0; i<k; i++) jj[i]=new_ranks[pcis->neigh[i+1]];
2388c8587f34SStefano Zampini         ierr = PetscSortInt(k,jj);CHKERRQ(ierr);
2389c8587f34SStefano Zampini         ierr = MatCreateMPIAdj(test_coarse_comm,1,n_subdomains,ii,jj,NULL,&mat_adj);CHKERRQ(ierr);
2390c8587f34SStefano Zampini         ierr = MatView(mat_adj,viewer_test);CHKERRQ(ierr);
2391c8587f34SStefano Zampini         ierr = MatPartitioningCreate(test_coarse_comm,&mat_part);CHKERRQ(ierr);
2392c8587f34SStefano Zampini         ierr = MatPartitioningSetAdjacency(mat_part,mat_adj);CHKERRQ(ierr);
2393c8587f34SStefano Zampini         ierr = MatPartitioningSetFromOptions(mat_part);CHKERRQ(ierr);
2394c8587f34SStefano Zampini         printf("Setting Nparts %d\n",n_parts);
2395c8587f34SStefano Zampini         ierr = MatPartitioningSetNParts(mat_part,n_parts);CHKERRQ(ierr);
2396c8587f34SStefano Zampini         ierr = MatPartitioningView(mat_part,viewer_test);CHKERRQ(ierr);
2397c8587f34SStefano Zampini         ierr = MatPartitioningApply(mat_part,&coarse_new_decomposition);CHKERRQ(ierr);
2398c8587f34SStefano Zampini         ierr = ISView(coarse_new_decomposition,viewer_test);CHKERRQ(ierr);
2399c8587f34SStefano Zampini         ierr = ISPartitioningToNumbering(coarse_new_decomposition,&is_numbering);CHKERRQ(ierr);
2400c8587f34SStefano Zampini         ierr = ISView(is_numbering,viewer_test);CHKERRQ(ierr);
2401c8587f34SStefano Zampini         ierr = PetscViewerDestroy(&viewer_test);CHKERRQ(ierr);
2402c8587f34SStefano Zampini         ierr = ISDestroy(&coarse_new_decomposition);CHKERRQ(ierr);
2403c8587f34SStefano Zampini         ierr = ISDestroy(&is_numbering);CHKERRQ(ierr);
2404c8587f34SStefano Zampini         ierr = MatPartitioningDestroy(&mat_part);CHKERRQ(ierr);
2405c8587f34SStefano Zampini         ierr = PetscFree(old_ranks);CHKERRQ(ierr);
2406c8587f34SStefano Zampini         ierr = PetscFree(new_ranks);CHKERRQ(ierr);
2407c8587f34SStefano Zampini         ierr = MPI_Comm_free(&test_coarse_comm);CHKERRQ(ierr);
2408c8587f34SStefano Zampini       }
2409c8587f34SStefano Zampini #endif
2410c8587f34SStefano Zampini 
2411c8587f34SStefano Zampini       /* build CSR graph of subdomains' connectivity */
2412c8587f34SStefano Zampini       ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&array_int);CHKERRQ(ierr);
2413c8587f34SStefano Zampini       ierr = PetscMemzero(array_int,pcis->n*sizeof(PetscInt));CHKERRQ(ierr);
2414c8587f34SStefano Zampini       for (i=1;i<pcis->n_neigh;i++){/* i=1 so I don't count myself -> faces nodes counts to 1 */
2415c8587f34SStefano Zampini         for (j=0;j<pcis->n_shared[i];j++){
2416c8587f34SStefano Zampini           array_int[ pcis->shared[i][j] ]+=1;
2417c8587f34SStefano Zampini         }
2418c8587f34SStefano Zampini       }
2419c8587f34SStefano Zampini       for (i=1;i<pcis->n_neigh;i++){
2420c8587f34SStefano Zampini         for (j=0;j<pcis->n_shared[i];j++){
2421c8587f34SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
2422c8587f34SStefano Zampini             my_faces++;
2423c8587f34SStefano Zampini             break;
2424c8587f34SStefano Zampini           }
2425c8587f34SStefano Zampini         }
2426c8587f34SStefano Zampini       }
2427c8587f34SStefano Zampini 
2428c8587f34SStefano Zampini       ierr = MPI_Reduce(&my_faces,&total_faces,1,MPIU_INT,MPI_SUM,master_proc,prec_comm);CHKERRQ(ierr);
2429c8587f34SStefano Zampini       ierr = PetscMalloc (my_faces*sizeof(PetscInt),&my_faces_connectivity);CHKERRQ(ierr);
2430c8587f34SStefano Zampini       my_faces=0;
2431c8587f34SStefano Zampini       for (i=1;i<pcis->n_neigh;i++){
2432c8587f34SStefano Zampini         for (j=0;j<pcis->n_shared[i];j++){
2433c8587f34SStefano Zampini           if (array_int[ pcis->shared[i][j] ] > 0 ){
2434c8587f34SStefano Zampini             my_faces_connectivity[my_faces]=pcis->neigh[i];
2435c8587f34SStefano Zampini             my_faces++;
2436c8587f34SStefano Zampini             break;
2437c8587f34SStefano Zampini           }
2438c8587f34SStefano Zampini         }
2439c8587f34SStefano Zampini       }
2440c8587f34SStefano Zampini       if (rank_prec_comm == master_proc) {
2441c8587f34SStefano Zampini         ierr = PetscMalloc (total_faces*sizeof(PetscMPIInt),&petsc_faces_adjncy);CHKERRQ(ierr);
2442c8587f34SStefano Zampini         ierr = PetscMalloc (size_prec_comm*sizeof(PetscMPIInt),&number_of_faces);CHKERRQ(ierr);
2443c8587f34SStefano Zampini         ierr = PetscMalloc (total_faces*sizeof(MetisInt),&faces_adjncy);CHKERRQ(ierr);
2444c8587f34SStefano Zampini         ierr = PetscMalloc ((n_subdomains+1)*sizeof(MetisInt),&faces_xadj);CHKERRQ(ierr);
2445c8587f34SStefano Zampini         ierr = PetscMalloc ((size_prec_comm+1)*sizeof(PetscMPIInt),&faces_displacements);CHKERRQ(ierr);
2446c8587f34SStefano Zampini       }
2447c8587f34SStefano Zampini       ierr = MPI_Gather(&my_faces,1,MPIU_INT,&number_of_faces[0],1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
2448c8587f34SStefano Zampini       if (rank_prec_comm == master_proc) {
2449c8587f34SStefano Zampini         faces_xadj[0]=0;
2450c8587f34SStefano Zampini         faces_displacements[0]=0;
2451c8587f34SStefano Zampini         j=0;
2452c8587f34SStefano Zampini         for (i=1;i<size_prec_comm+1;i++) {
2453c8587f34SStefano Zampini           faces_displacements[i]=faces_displacements[i-1]+number_of_faces[i-1];
2454c8587f34SStefano Zampini           if (number_of_faces[i-1]) {
2455c8587f34SStefano Zampini             j++;
2456c8587f34SStefano Zampini             faces_xadj[j]=faces_xadj[j-1]+number_of_faces[i-1];
2457c8587f34SStefano Zampini           }
2458c8587f34SStefano Zampini         }
2459c8587f34SStefano Zampini       }
2460c8587f34SStefano 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);
2461c8587f34SStefano Zampini       ierr = PetscFree(my_faces_connectivity);CHKERRQ(ierr);
2462c8587f34SStefano Zampini       ierr = PetscFree(array_int);CHKERRQ(ierr);
2463c8587f34SStefano Zampini       if (rank_prec_comm == master_proc) {
2464c8587f34SStefano Zampini         for (i=0;i<total_faces;i++) faces_adjncy[i]=(MetisInt)(petsc_faces_adjncy[i]/ranks_stretching_ratio); /* cast to MetisInt */
2465c8587f34SStefano Zampini         ierr = PetscFree(faces_displacements);CHKERRQ(ierr);
2466c8587f34SStefano Zampini         ierr = PetscFree(number_of_faces);CHKERRQ(ierr);
2467c8587f34SStefano Zampini         ierr = PetscFree(petsc_faces_adjncy);CHKERRQ(ierr);
2468c8587f34SStefano Zampini       }
2469c8587f34SStefano Zampini 
2470c8587f34SStefano Zampini       if ( rank_prec_comm == master_proc ) {
2471c8587f34SStefano Zampini 
2472c8587f34SStefano Zampini         PetscInt heuristic_for_metis=3;
2473c8587f34SStefano Zampini 
2474c8587f34SStefano Zampini         ncon=1;
2475c8587f34SStefano Zampini         faces_nvtxs=n_subdomains;
2476c8587f34SStefano Zampini         /* partition graoh induced by face connectivity */
2477c8587f34SStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(MetisInt),&metis_coarse_subdivision);CHKERRQ(ierr);
2478c8587f34SStefano Zampini         ierr = METIS_SetDefaultOptions(options);
2479c8587f34SStefano Zampini         /* we need a contiguous partition of the coarse mesh */
2480c8587f34SStefano Zampini         options[METIS_OPTION_CONTIG]=1;
2481c8587f34SStefano Zampini         options[METIS_OPTION_NITER]=30;
2482c8587f34SStefano Zampini         if (pcbddc->coarsening_ratio > 1) {
2483c8587f34SStefano Zampini           if (n_subdomains>n_parts*heuristic_for_metis) {
2484c8587f34SStefano Zampini             options[METIS_OPTION_IPTYPE]=METIS_IPTYPE_EDGE;
2485c8587f34SStefano Zampini             options[METIS_OPTION_OBJTYPE]=METIS_OBJTYPE_CUT;
2486c8587f34SStefano Zampini             ierr = METIS_PartGraphKway(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2487c8587f34SStefano Zampini             if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphKway (metis error code %D) called from PCBDDCSetUpCoarseEnvironment\n",ierr);
2488c8587f34SStefano Zampini           } else {
2489c8587f34SStefano Zampini             ierr = METIS_PartGraphRecursive(&faces_nvtxs,&ncon,faces_xadj,faces_adjncy,NULL,NULL,NULL,&n_parts,NULL,NULL,options,&objval,metis_coarse_subdivision);
2490c8587f34SStefano Zampini             if (ierr != METIS_OK) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in METIS_PartGraphRecursive (metis error code %D) called from PCBDDCSetUpCoarseEnvironment\n",ierr);
2491c8587f34SStefano Zampini           }
2492c8587f34SStefano Zampini         } else {
2493c8587f34SStefano Zampini           for (i=0;i<n_subdomains;i++) metis_coarse_subdivision[i]=i;
2494c8587f34SStefano Zampini         }
2495c8587f34SStefano Zampini         ierr = PetscFree(faces_xadj);CHKERRQ(ierr);
2496c8587f34SStefano Zampini         ierr = PetscFree(faces_adjncy);CHKERRQ(ierr);
2497c8587f34SStefano Zampini         ierr = PetscMalloc(size_prec_comm*sizeof(PetscMPIInt),&coarse_subdivision);CHKERRQ(ierr);
2498c8587f34SStefano Zampini 
2499c8587f34SStefano Zampini         /* copy/cast values avoiding possible type conflicts between PETSc, MPI and METIS */
2500c8587f34SStefano Zampini         for (i=0;i<size_prec_comm;i++) coarse_subdivision[i]=MPI_PROC_NULL;
2501c8587f34SStefano Zampini         for (i=0;i<n_subdomains;i++) coarse_subdivision[ranks_stretching_ratio*i]=(PetscInt)(metis_coarse_subdivision[i]);
2502c8587f34SStefano Zampini         ierr = PetscFree(metis_coarse_subdivision);CHKERRQ(ierr);
2503c8587f34SStefano Zampini       }
2504c8587f34SStefano Zampini 
2505c8587f34SStefano Zampini       /* Create new communicator for coarse problem splitting the old one */
2506c8587f34SStefano Zampini       if ( !(rank_prec_comm%procs_jumps_coarse_comm) && rank_prec_comm < procs_jumps_coarse_comm*n_parts ){
2507c8587f34SStefano Zampini         coarse_color=0;              /* for communicator splitting */
2508c8587f34SStefano Zampini         active_rank=rank_prec_comm;  /* for insertion of matrix values */
2509c8587f34SStefano Zampini       }
2510c8587f34SStefano Zampini       /* procs with coarse_color = MPI_UNDEFINED will have coarse_comm = MPI_COMM_NULL (from mpi standards)
2511c8587f34SStefano Zampini          key = rank_prec_comm -> keep same ordering of ranks from the old to the new communicator */
2512c8587f34SStefano Zampini       ierr = MPI_Comm_split(prec_comm,coarse_color,rank_prec_comm,&coarse_comm);CHKERRQ(ierr);
2513c8587f34SStefano Zampini 
2514c8587f34SStefano Zampini       if ( coarse_color == 0 ) {
2515c8587f34SStefano Zampini         ierr = MPI_Comm_size(coarse_comm,&size_coarse_comm);CHKERRQ(ierr);
2516c8587f34SStefano Zampini         ierr = MPI_Comm_rank(coarse_comm,&rank_coarse_comm);CHKERRQ(ierr);
2517c8587f34SStefano Zampini       } else {
2518c8587f34SStefano Zampini         rank_coarse_comm = MPI_PROC_NULL;
2519c8587f34SStefano Zampini       }
2520c8587f34SStefano Zampini 
2521c8587f34SStefano Zampini       /* master proc take care of arranging and distributing coarse information */
2522c8587f34SStefano Zampini       if (rank_coarse_comm == master_proc) {
2523c8587f34SStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&displacements_recv);CHKERRQ(ierr);
2524c8587f34SStefano Zampini         ierr = PetscMalloc (size_coarse_comm*sizeof(PetscMPIInt),&total_count_recv);CHKERRQ(ierr);
2525c8587f34SStefano Zampini         ierr = PetscMalloc (n_subdomains*sizeof(PetscMPIInt),&total_ranks_recv);CHKERRQ(ierr);
2526c8587f34SStefano Zampini         /* some initializations */
2527c8587f34SStefano Zampini         displacements_recv[0]=0;
2528c8587f34SStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
2529c8587f34SStefano Zampini         /* count from how many processes the j-th process of the coarse decomposition will receive data */
2530c8587f34SStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
2531c8587f34SStefano Zampini           for (i=0;i<size_prec_comm;i++) {
2532c8587f34SStefano Zampini           if (coarse_subdivision[i]==j) total_count_recv[j]++;
2533c8587f34SStefano Zampini           }
2534c8587f34SStefano Zampini         }
2535c8587f34SStefano Zampini         /* displacements needed for scatterv of total_ranks_recv */
2536c8587f34SStefano Zampini       for (i=1; i<size_coarse_comm; i++) displacements_recv[i]=displacements_recv[i-1]+total_count_recv[i-1];
2537c8587f34SStefano Zampini 
2538c8587f34SStefano Zampini         /* Now fill properly total_ranks_recv -> each coarse process will receive the ranks (in prec_comm communicator) of its friend (sending) processes */
2539c8587f34SStefano Zampini         ierr = PetscMemzero(total_count_recv,size_coarse_comm*sizeof(PetscMPIInt));CHKERRQ(ierr);
2540c8587f34SStefano Zampini         for (j=0;j<size_coarse_comm;j++) {
2541c8587f34SStefano Zampini           for (i=0;i<size_prec_comm;i++) {
2542c8587f34SStefano Zampini             if (coarse_subdivision[i]==j) {
2543c8587f34SStefano Zampini               total_ranks_recv[displacements_recv[j]+total_count_recv[j]]=i;
2544c8587f34SStefano Zampini               total_count_recv[j]+=1;
2545c8587f34SStefano Zampini             }
2546c8587f34SStefano Zampini           }
2547c8587f34SStefano Zampini         }
2548c8587f34SStefano Zampini         /*for (j=0;j<size_coarse_comm;j++) {
2549c8587f34SStefano Zampini           printf("process %d in new rank will receive from %d processes (original ranks follows)\n",j,total_count_recv[j]);
2550c8587f34SStefano Zampini           for (i=0;i<total_count_recv[j];i++) {
2551c8587f34SStefano Zampini             printf("%d ",total_ranks_recv[displacements_recv[j]+i]);
2552c8587f34SStefano Zampini           }
2553c8587f34SStefano Zampini           printf("\n");
2554c8587f34SStefano Zampini         }*/
2555c8587f34SStefano Zampini 
2556c8587f34SStefano Zampini         /* identify new decomposition in terms of ranks in the old communicator */
2557c8587f34SStefano Zampini         for (i=0;i<n_subdomains;i++) {
2558c8587f34SStefano Zampini           coarse_subdivision[ranks_stretching_ratio*i]=coarse_subdivision[ranks_stretching_ratio*i]*procs_jumps_coarse_comm;
2559c8587f34SStefano Zampini         }
2560c8587f34SStefano Zampini         /*printf("coarse_subdivision in old end new ranks\n");
2561c8587f34SStefano Zampini         for (i=0;i<size_prec_comm;i++)
2562c8587f34SStefano Zampini           if (coarse_subdivision[i]!=MPI_PROC_NULL) {
2563c8587f34SStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]/procs_jumps_coarse_comm);
2564c8587f34SStefano Zampini           } else {
2565c8587f34SStefano Zampini             printf("%d=(%d %d), ",i,coarse_subdivision[i],coarse_subdivision[i]);
2566c8587f34SStefano Zampini           }
2567c8587f34SStefano Zampini         printf("\n");*/
2568c8587f34SStefano Zampini       }
2569c8587f34SStefano Zampini 
2570c8587f34SStefano Zampini       /* Scatter new decomposition for send details */
2571c8587f34SStefano Zampini       ierr = MPI_Scatter(&coarse_subdivision[0],1,MPIU_INT,&rank_coarse_proc_send_to,1,MPIU_INT,master_proc,prec_comm);CHKERRQ(ierr);
2572c8587f34SStefano Zampini       /* Scatter receiving details to members of coarse decomposition */
2573c8587f34SStefano Zampini       if ( coarse_color == 0) {
2574c8587f34SStefano Zampini         ierr = MPI_Scatter(&total_count_recv[0],1,MPIU_INT,&count_recv,1,MPIU_INT,master_proc,coarse_comm);CHKERRQ(ierr);
2575c8587f34SStefano Zampini         ierr = PetscMalloc (count_recv*sizeof(PetscMPIInt),&ranks_recv);CHKERRQ(ierr);
2576c8587f34SStefano 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);
2577c8587f34SStefano Zampini       }
2578c8587f34SStefano Zampini 
2579c8587f34SStefano Zampini       /*printf("I will send my matrix data to proc  %d\n",rank_coarse_proc_send_to);
2580c8587f34SStefano Zampini       if (coarse_color == 0) {
2581c8587f34SStefano Zampini         printf("I will receive some matrix data from %d processes (ranks follows)\n",count_recv);
2582c8587f34SStefano Zampini         for (i=0;i<count_recv;i++)
2583c8587f34SStefano Zampini           printf("%d ",ranks_recv[i]);
2584c8587f34SStefano Zampini         printf("\n");
2585c8587f34SStefano Zampini       }*/
2586c8587f34SStefano Zampini 
2587c8587f34SStefano Zampini       if (rank_prec_comm == master_proc) {
2588c8587f34SStefano Zampini         ierr = PetscFree(coarse_subdivision);CHKERRQ(ierr);
2589c8587f34SStefano Zampini         ierr = PetscFree(total_count_recv);CHKERRQ(ierr);
2590c8587f34SStefano Zampini         ierr = PetscFree(total_ranks_recv);CHKERRQ(ierr);
2591c8587f34SStefano Zampini         ierr = PetscFree(displacements_recv);CHKERRQ(ierr);
2592c8587f34SStefano Zampini       }
2593c8587f34SStefano Zampini #endif
2594c8587f34SStefano Zampini       break;
2595c8587f34SStefano Zampini     }
2596c8587f34SStefano Zampini 
2597c8587f34SStefano Zampini     case(PARALLEL_BDDC):
2598c8587f34SStefano Zampini 
2599c8587f34SStefano Zampini       pcbddc->coarse_communications_type = SCATTERS_BDDC;
2600c8587f34SStefano Zampini       coarse_mat_type = MATAIJ;
2601c8587f34SStefano Zampini       coarse_pc_type  = PCREDUNDANT;
2602c8587f34SStefano Zampini       coarse_ksp_type  = KSPPREONLY;
2603c8587f34SStefano Zampini       coarse_comm = prec_comm;
2604c8587f34SStefano Zampini       active_rank = rank_prec_comm;
2605c8587f34SStefano Zampini       break;
2606c8587f34SStefano Zampini 
2607c8587f34SStefano Zampini   }
2608c8587f34SStefano Zampini 
2609c8587f34SStefano Zampini   switch(pcbddc->coarse_communications_type){
2610c8587f34SStefano Zampini 
2611c8587f34SStefano Zampini     case(SCATTERS_BDDC):
2612c8587f34SStefano Zampini       {
2613c8587f34SStefano Zampini         if (pcbddc->coarse_problem_type==MULTILEVEL_BDDC) {
2614c8587f34SStefano Zampini 
2615c8587f34SStefano Zampini           IS coarse_IS;
2616c8587f34SStefano Zampini 
2617c8587f34SStefano Zampini           if(pcbddc->coarsening_ratio == 1) {
2618c8587f34SStefano Zampini             ins_local_primal_size = pcbddc->local_primal_size;
2619fdc09c96SStefano Zampini             ins_local_primal_indices = local_primal_indices;
2620c8587f34SStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2621c8587f34SStefano Zampini             /* nonzeros */
2622c8587f34SStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2623c8587f34SStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2624c8587f34SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2625c8587f34SStefano Zampini               dnz[i] = ins_local_primal_size;
2626c8587f34SStefano Zampini             }
2627c8587f34SStefano Zampini           } else {
2628c8587f34SStefano Zampini             PetscMPIInt send_size;
2629c8587f34SStefano Zampini             PetscMPIInt *send_buffer;
2630c8587f34SStefano Zampini             PetscInt    *aux_ins_indices;
2631c8587f34SStefano Zampini             PetscInt    ii,jj;
2632c8587f34SStefano Zampini             MPI_Request *requests;
2633c8587f34SStefano Zampini 
2634c8587f34SStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localdispl2);CHKERRQ(ierr);
2635fdc09c96SStefano Zampini             /* reusing local_primal_displacements and replicated_primal_size */
2636fdc09c96SStefano Zampini             ierr = PetscFree(local_primal_displacements);CHKERRQ(ierr);
2637fdc09c96SStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(PetscMPIInt),&local_primal_displacements);CHKERRQ(ierr);
2638fdc09c96SStefano Zampini             replicated_primal_size = count_recv;
2639c8587f34SStefano Zampini             j = 0;
2640c8587f34SStefano Zampini             for (i=0;i<count_recv;i++) {
2641fdc09c96SStefano Zampini               local_primal_displacements[i] = j;
2642fdc09c96SStefano Zampini               j += local_primal_sizes[ranks_recv[i]];
2643c8587f34SStefano Zampini             }
2644fdc09c96SStefano Zampini             local_primal_displacements[count_recv] = j;
2645fdc09c96SStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscMPIInt),&replicated_local_primal_indices);CHKERRQ(ierr);
2646c8587f34SStefano Zampini             /* allocate auxiliary space */
2647c8587f34SStefano Zampini             ierr = PetscMalloc(count_recv*sizeof(PetscMPIInt),&localsizes2);CHKERRQ(ierr);
2648983f5fd7SStefano Zampini             ierr = PetscMalloc(coarse_size*sizeof(PetscInt),&aux_ins_indices);CHKERRQ(ierr);
2649983f5fd7SStefano Zampini             ierr = PetscMemzero(aux_ins_indices,coarse_size*sizeof(PetscInt));CHKERRQ(ierr);
2650c8587f34SStefano Zampini             /* allocate stuffs for message massing */
2651c8587f34SStefano Zampini             ierr = PetscMalloc((count_recv+1)*sizeof(MPI_Request),&requests);CHKERRQ(ierr);
2652c8587f34SStefano Zampini             for (i=0;i<count_recv+1;i++) { requests[i]=MPI_REQUEST_NULL; }
2653c8587f34SStefano Zampini             /* send indices to be inserted */
2654c8587f34SStefano Zampini             for (i=0;i<count_recv;i++) {
2655fdc09c96SStefano Zampini               send_size = local_primal_sizes[ranks_recv[i]];
2656fdc09c96SStefano Zampini               ierr = MPI_Irecv(&replicated_local_primal_indices[local_primal_displacements[i]],send_size,MPIU_INT,ranks_recv[i],999,prec_comm,&requests[i]);CHKERRQ(ierr);
2657c8587f34SStefano Zampini             }
2658c8587f34SStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2659c8587f34SStefano Zampini               send_size = pcbddc->local_primal_size;
2660c8587f34SStefano Zampini               ierr = PetscMalloc(send_size*sizeof(PetscMPIInt),&send_buffer);CHKERRQ(ierr);
2661c8587f34SStefano Zampini               for (i=0;i<send_size;i++) {
2662fdc09c96SStefano Zampini                 send_buffer[i]=(PetscMPIInt)local_primal_indices[i];
2663c8587f34SStefano Zampini               }
2664c8587f34SStefano Zampini               ierr = MPI_Isend(send_buffer,send_size,MPIU_INT,rank_coarse_proc_send_to,999,prec_comm,&requests[count_recv]);CHKERRQ(ierr);
2665c8587f34SStefano Zampini             }
2666c8587f34SStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2667c8587f34SStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2668c8587f34SStefano Zampini               ierr = PetscFree(send_buffer);CHKERRQ(ierr);
2669c8587f34SStefano Zampini             }
2670c8587f34SStefano Zampini             j = 0;
2671c8587f34SStefano Zampini             for (i=0;i<count_recv;i++) {
2672fdc09c96SStefano Zampini               ii = local_primal_displacements[i+1]-local_primal_displacements[i];
2673c8587f34SStefano Zampini               localsizes2[i] = ii*ii;
2674c8587f34SStefano Zampini               localdispl2[i] = j;
2675c8587f34SStefano Zampini               j += localsizes2[i];
2676fdc09c96SStefano Zampini               jj = local_primal_displacements[i];
2677c8587f34SStefano Zampini               /* it counts the coarse subdomains sharing the coarse node */
2678c8587f34SStefano Zampini               for (k=0;k<ii;k++) {
2679fdc09c96SStefano Zampini                 aux_ins_indices[replicated_local_primal_indices[jj+k]] += 1;
2680c8587f34SStefano Zampini               }
2681c8587f34SStefano Zampini             }
2682c8587f34SStefano Zampini             /* temp_coarse_mat_vals used to store matrix values to be received */
2683c8587f34SStefano Zampini             ierr = PetscMalloc(j*sizeof(PetscScalar),&temp_coarse_mat_vals);CHKERRQ(ierr);
2684c8587f34SStefano Zampini             /* evaluate how many values I will insert in coarse mat */
2685c8587f34SStefano Zampini             ins_local_primal_size = 0;
2686983f5fd7SStefano Zampini             for (i=0;i<coarse_size;i++) {
2687c8587f34SStefano Zampini               if (aux_ins_indices[i]) {
2688c8587f34SStefano Zampini                 ins_local_primal_size++;
2689c8587f34SStefano Zampini               }
2690c8587f34SStefano Zampini             }
2691c8587f34SStefano Zampini             /* evaluate indices I will insert in coarse mat */
2692c8587f34SStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2693c8587f34SStefano Zampini             j = 0;
2694983f5fd7SStefano Zampini             for(i=0;i<coarse_size;i++) {
2695c8587f34SStefano Zampini               if(aux_ins_indices[i]) {
2696c8587f34SStefano Zampini                 ins_local_primal_indices[j] = i;
2697c8587f34SStefano Zampini                 j++;
2698c8587f34SStefano Zampini               }
2699c8587f34SStefano Zampini             }
2700c8587f34SStefano Zampini             /* processes partecipating in coarse problem receive matrix data from their friends */
2701c8587f34SStefano Zampini             for (i=0;i<count_recv;i++) {
2702c8587f34SStefano Zampini               ierr = MPI_Irecv(&temp_coarse_mat_vals[localdispl2[i]],localsizes2[i],MPIU_SCALAR,ranks_recv[i],666,prec_comm,&requests[i]);CHKERRQ(ierr);
2703c8587f34SStefano Zampini             }
2704c8587f34SStefano Zampini             if (rank_coarse_proc_send_to != MPI_PROC_NULL ) {
2705c8587f34SStefano Zampini               send_size = pcbddc->local_primal_size*pcbddc->local_primal_size;
2706c8587f34SStefano 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);
2707c8587f34SStefano Zampini             }
2708c8587f34SStefano Zampini             ierr = MPI_Waitall(count_recv+1,requests,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
2709c8587f34SStefano Zampini             /* nonzeros */
2710c8587f34SStefano Zampini             ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&dnz);CHKERRQ(ierr);
2711c8587f34SStefano Zampini             ierr = PetscMemzero(dnz,ins_local_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2712c8587f34SStefano Zampini             /* use aux_ins_indices to realize a global to local mapping */
2713c8587f34SStefano Zampini             j=0;
2714983f5fd7SStefano Zampini             for(i=0;i<coarse_size;i++){
2715c8587f34SStefano Zampini               if(aux_ins_indices[i]==0){
2716c8587f34SStefano Zampini                 aux_ins_indices[i]=-1;
2717c8587f34SStefano Zampini               } else {
2718c8587f34SStefano Zampini                 aux_ins_indices[i]=j;
2719c8587f34SStefano Zampini                 j++;
2720c8587f34SStefano Zampini               }
2721c8587f34SStefano Zampini             }
2722c8587f34SStefano Zampini             for (i=0;i<count_recv;i++) {
2723fdc09c96SStefano Zampini               j = local_primal_sizes[ranks_recv[i]];
2724c8587f34SStefano Zampini               for (k=0;k<j;k++) {
2725fdc09c96SStefano Zampini                 dnz[aux_ins_indices[replicated_local_primal_indices[local_primal_displacements[i]+k]]] += j;
2726c8587f34SStefano Zampini               }
2727c8587f34SStefano Zampini             }
2728c8587f34SStefano Zampini             /* check */
2729c8587f34SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2730c8587f34SStefano Zampini               if (dnz[i] > ins_local_primal_size) {
2731c8587f34SStefano Zampini                 dnz[i] = ins_local_primal_size;
2732c8587f34SStefano Zampini               }
2733c8587f34SStefano Zampini             }
2734c8587f34SStefano Zampini             ierr = PetscFree(requests);CHKERRQ(ierr);
2735c8587f34SStefano Zampini             ierr = PetscFree(aux_ins_indices);CHKERRQ(ierr);
2736c8587f34SStefano Zampini             if (coarse_color == 0) { ierr = PetscFree(ranks_recv);CHKERRQ(ierr); }
2737c8587f34SStefano Zampini           }
2738c8587f34SStefano Zampini           /* create local to global mapping needed by coarse MATIS */
2739c8587f34SStefano Zampini           if (coarse_comm != MPI_COMM_NULL ) {ierr = MPI_Comm_free(&coarse_comm);CHKERRQ(ierr);}
2740c8587f34SStefano Zampini           coarse_comm = prec_comm;
2741c8587f34SStefano Zampini           active_rank = rank_prec_comm;
2742c8587f34SStefano Zampini           ierr = ISCreateGeneral(coarse_comm,ins_local_primal_size,ins_local_primal_indices,PETSC_COPY_VALUES,&coarse_IS);CHKERRQ(ierr);
2743c8587f34SStefano Zampini           ierr = ISLocalToGlobalMappingCreateIS(coarse_IS,&coarse_ISLG);CHKERRQ(ierr);
2744c8587f34SStefano Zampini           ierr = ISDestroy(&coarse_IS);CHKERRQ(ierr);
2745c8587f34SStefano Zampini         } else if (pcbddc->coarse_problem_type==PARALLEL_BDDC) {
2746c8587f34SStefano Zampini           /* arrays for values insertion */
2747c8587f34SStefano Zampini           ins_local_primal_size = pcbddc->local_primal_size;
2748c8587f34SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2749c8587f34SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*ins_local_primal_size*sizeof(PetscScalar),&ins_coarse_mat_vals);CHKERRQ(ierr);
2750c8587f34SStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2751fdc09c96SStefano Zampini             ins_local_primal_indices[j]=local_primal_indices[j];
2752c8587f34SStefano Zampini             for (i=0;i<ins_local_primal_size;i++) {
2753c8587f34SStefano Zampini               ins_coarse_mat_vals[j*ins_local_primal_size+i]=coarse_submat_vals[j*ins_local_primal_size+i];
2754c8587f34SStefano Zampini             }
2755c8587f34SStefano Zampini           }
2756c8587f34SStefano Zampini         }
2757c8587f34SStefano Zampini         break;
2758c8587f34SStefano Zampini 
2759c8587f34SStefano Zampini     }
2760c8587f34SStefano Zampini 
2761c8587f34SStefano Zampini   }
2762c8587f34SStefano Zampini 
2763c8587f34SStefano Zampini   /* Now create and fill up coarse matrix */
2764c8587f34SStefano Zampini   if ( rank_prec_comm == active_rank ) {
2765c8587f34SStefano Zampini 
2766c8587f34SStefano Zampini     Mat matis_coarse_local_mat;
2767c8587f34SStefano Zampini 
2768c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2769fdc635d7SStefano Zampini       ierr = MatCreate(coarse_comm,&coarse_mat);CHKERRQ(ierr);
2770fdc635d7SStefano Zampini       ierr = MatSetSizes(coarse_mat,PETSC_DECIDE,PETSC_DECIDE,coarse_size,coarse_size);CHKERRQ(ierr);
2771fdc635d7SStefano Zampini       ierr = MatSetType(coarse_mat,coarse_mat_type);CHKERRQ(ierr);
2772fdc635d7SStefano Zampini       ierr = MatSetOptionsPrefix(coarse_mat,"coarse_");CHKERRQ(ierr);
2773fdc635d7SStefano Zampini       ierr = MatSetFromOptions(coarse_mat);CHKERRQ(ierr);
2774fdc635d7SStefano Zampini       ierr = MatSetUp(coarse_mat);CHKERRQ(ierr);
2775fdc635d7SStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2776fdc635d7SStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
2777c8587f34SStefano Zampini     } else {
2778fdc635d7SStefano Zampini       ierr = MatCreateIS(coarse_comm,1,PETSC_DECIDE,PETSC_DECIDE,coarse_size,coarse_size,coarse_ISLG,&coarse_mat);CHKERRQ(ierr);
2779fdc635d7SStefano Zampini       ierr = MatSetUp(coarse_mat);CHKERRQ(ierr);
2780fdc635d7SStefano Zampini       ierr = MatISGetLocalMat(coarse_mat,&matis_coarse_local_mat);CHKERRQ(ierr);
2781fdc635d7SStefano Zampini       ierr = MatSetOptionsPrefix(coarse_mat,"coarse_");CHKERRQ(ierr);
2782fdc635d7SStefano Zampini       ierr = MatSetFromOptions(coarse_mat);CHKERRQ(ierr);
2783c8587f34SStefano Zampini       ierr = MatSetUp(matis_coarse_local_mat);CHKERRQ(ierr);
2784c8587f34SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); /* local values stored in column major */
2785c8587f34SStefano Zampini       ierr = MatSetOption(matis_coarse_local_mat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
2786c8587f34SStefano Zampini     }
2787c8587f34SStefano Zampini     /* preallocation */
2788c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type != MULTILEVEL_BDDC) {
2789c8587f34SStefano Zampini 
2790c8587f34SStefano Zampini       PetscInt lrows,lcols,bs;
2791c8587f34SStefano Zampini 
2792fdc635d7SStefano Zampini       ierr = MatGetLocalSize(coarse_mat,&lrows,&lcols);CHKERRQ(ierr);
2793c8587f34SStefano Zampini       ierr = MatPreallocateInitialize(coarse_comm,lrows,lcols,dnz,onz);CHKERRQ(ierr);
2794fdc635d7SStefano Zampini       ierr = MatGetBlockSize(coarse_mat,&bs);CHKERRQ(ierr);
2795c8587f34SStefano Zampini 
2796c8587f34SStefano Zampini       if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2797c8587f34SStefano Zampini 
2798c8587f34SStefano Zampini         Vec         vec_dnz,vec_onz;
2799c8587f34SStefano Zampini         PetscScalar *my_dnz,*my_onz,*array;
2800c8587f34SStefano Zampini         PetscInt    *mat_ranges,*row_ownership;
2801c8587f34SStefano Zampini         PetscInt    coarse_index_row,coarse_index_col,owner;
2802c8587f34SStefano Zampini 
2803c8587f34SStefano Zampini         ierr = VecCreate(prec_comm,&vec_dnz);CHKERRQ(ierr);
2804c8587f34SStefano Zampini         ierr = VecSetBlockSize(vec_dnz,bs);CHKERRQ(ierr);
2805983f5fd7SStefano Zampini         ierr = VecSetSizes(vec_dnz,PETSC_DECIDE,coarse_size);CHKERRQ(ierr);
2806c8587f34SStefano Zampini         ierr = VecSetType(vec_dnz,VECMPI);CHKERRQ(ierr);
2807c8587f34SStefano Zampini         ierr = VecDuplicate(vec_dnz,&vec_onz);CHKERRQ(ierr);
2808c8587f34SStefano Zampini 
2809c8587f34SStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_dnz);CHKERRQ(ierr);
2810c8587f34SStefano Zampini         ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscScalar),&my_onz);CHKERRQ(ierr);
2811c8587f34SStefano Zampini         ierr = PetscMemzero(my_dnz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2812c8587f34SStefano Zampini         ierr = PetscMemzero(my_onz,pcbddc->local_primal_size*sizeof(PetscScalar));CHKERRQ(ierr);
2813c8587f34SStefano Zampini 
2814983f5fd7SStefano Zampini         ierr = PetscMalloc(coarse_size*sizeof(PetscInt),&row_ownership);CHKERRQ(ierr);
2815fdc635d7SStefano Zampini         ierr = MatGetOwnershipRanges(coarse_mat,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
2816c8587f34SStefano Zampini         for (i=0;i<size_prec_comm;i++) {
2817c8587f34SStefano Zampini           for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
2818c8587f34SStefano Zampini             row_ownership[j]=i;
2819c8587f34SStefano Zampini           }
2820c8587f34SStefano Zampini         }
2821c8587f34SStefano Zampini 
2822c8587f34SStefano Zampini         for (i=0;i<pcbddc->local_primal_size;i++) {
2823fdc09c96SStefano Zampini           coarse_index_row = local_primal_indices[i];
2824c8587f34SStefano Zampini           owner = row_ownership[coarse_index_row];
2825c8587f34SStefano Zampini           for (j=i;j<pcbddc->local_primal_size;j++) {
2826c8587f34SStefano Zampini             owner = row_ownership[coarse_index_row];
2827fdc09c96SStefano Zampini             coarse_index_col = local_primal_indices[j];
2828c8587f34SStefano Zampini             if (coarse_index_col > mat_ranges[owner]-1 && coarse_index_col < mat_ranges[owner+1] ) {
2829c8587f34SStefano Zampini               my_dnz[i] += 1.0;
2830c8587f34SStefano Zampini             } else {
2831c8587f34SStefano Zampini               my_onz[i] += 1.0;
2832c8587f34SStefano Zampini             }
2833c8587f34SStefano Zampini             if (i != j) {
2834c8587f34SStefano Zampini               owner = row_ownership[coarse_index_col];
2835c8587f34SStefano Zampini               if (coarse_index_row > mat_ranges[owner]-1 && coarse_index_row < mat_ranges[owner+1] ) {
2836c8587f34SStefano Zampini                 my_dnz[j] += 1.0;
2837c8587f34SStefano Zampini               } else {
2838c8587f34SStefano Zampini                 my_onz[j] += 1.0;
2839c8587f34SStefano Zampini               }
2840c8587f34SStefano Zampini             }
2841c8587f34SStefano Zampini           }
2842c8587f34SStefano Zampini         }
2843c8587f34SStefano Zampini         ierr = VecSet(vec_dnz,0.0);CHKERRQ(ierr);
2844c8587f34SStefano Zampini         ierr = VecSet(vec_onz,0.0);CHKERRQ(ierr);
2845c8587f34SStefano Zampini         if (pcbddc->local_primal_size) {
2846fdc09c96SStefano Zampini           ierr = VecSetValues(vec_dnz,pcbddc->local_primal_size,local_primal_indices,my_dnz,ADD_VALUES);CHKERRQ(ierr);
2847fdc09c96SStefano Zampini           ierr = VecSetValues(vec_onz,pcbddc->local_primal_size,local_primal_indices,my_onz,ADD_VALUES);CHKERRQ(ierr);
2848c8587f34SStefano Zampini         }
2849c8587f34SStefano Zampini         ierr = VecAssemblyBegin(vec_dnz);CHKERRQ(ierr);
2850c8587f34SStefano Zampini         ierr = VecAssemblyBegin(vec_onz);CHKERRQ(ierr);
2851c8587f34SStefano Zampini         ierr = VecAssemblyEnd(vec_dnz);CHKERRQ(ierr);
2852c8587f34SStefano Zampini         ierr = VecAssemblyEnd(vec_onz);CHKERRQ(ierr);
2853c8587f34SStefano Zampini         j = mat_ranges[rank_prec_comm+1]-mat_ranges[rank_prec_comm];
2854c8587f34SStefano Zampini         ierr = VecGetArray(vec_dnz,&array);CHKERRQ(ierr);
2855c8587f34SStefano Zampini         for (i=0; i<j; i++) dnz[i] = (PetscInt)PetscRealPart(array[i]);
2856c8587f34SStefano Zampini 
2857c8587f34SStefano Zampini         ierr = VecRestoreArray(vec_dnz,&array);CHKERRQ(ierr);
2858c8587f34SStefano Zampini         ierr = VecGetArray(vec_onz,&array);CHKERRQ(ierr);
2859c8587f34SStefano Zampini         for (i=0;i<j;i++) onz[i] = (PetscInt)PetscRealPart(array[i]);
2860c8587f34SStefano Zampini 
2861c8587f34SStefano Zampini         ierr = VecRestoreArray(vec_onz,&array);CHKERRQ(ierr);
2862c8587f34SStefano Zampini         ierr = PetscFree(my_dnz);CHKERRQ(ierr);
2863c8587f34SStefano Zampini         ierr = PetscFree(my_onz);CHKERRQ(ierr);
2864c8587f34SStefano Zampini         ierr = PetscFree(row_ownership);CHKERRQ(ierr);
2865c8587f34SStefano Zampini         ierr = VecDestroy(&vec_dnz);CHKERRQ(ierr);
2866c8587f34SStefano Zampini         ierr = VecDestroy(&vec_onz);CHKERRQ(ierr);
2867c8587f34SStefano Zampini       }
2868c8587f34SStefano Zampini 
2869c8587f34SStefano Zampini       /* check */
2870c8587f34SStefano Zampini       for (i=0;i<lrows;i++) {
2871c8587f34SStefano Zampini         if (dnz[i]>lcols) dnz[i]=lcols;
2872983f5fd7SStefano Zampini         if (onz[i]>coarse_size-lcols) onz[i]=coarse_size-lcols;
2873c8587f34SStefano Zampini       }
2874fdc635d7SStefano Zampini       ierr = MatSeqAIJSetPreallocation(coarse_mat,0,dnz);CHKERRQ(ierr);
2875fdc635d7SStefano Zampini       ierr = MatMPIAIJSetPreallocation(coarse_mat,0,dnz,0,onz);CHKERRQ(ierr);
2876c8587f34SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2877c8587f34SStefano Zampini     } else {
2878c8587f34SStefano Zampini       ierr = MatSeqAIJSetPreallocation(matis_coarse_local_mat,0,dnz);CHKERRQ(ierr);
2879c8587f34SStefano Zampini       ierr = PetscFree(dnz);CHKERRQ(ierr);
2880c8587f34SStefano Zampini     }
2881c8587f34SStefano Zampini     /* insert values */
2882c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type == PARALLEL_BDDC) {
2883fdc635d7SStefano Zampini       ierr = MatSetValues(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);
2884c8587f34SStefano Zampini     } else if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2885c8587f34SStefano Zampini       if (pcbddc->coarsening_ratio == 1) {
2886c8587f34SStefano Zampini         ins_coarse_mat_vals = coarse_submat_vals;
2887fdc635d7SStefano Zampini         ierr = MatSetValues(coarse_mat,ins_local_primal_size,ins_local_primal_indices,ins_local_primal_size,ins_local_primal_indices,ins_coarse_mat_vals,INSERT_VALUES);CHKERRQ(ierr);
2888c8587f34SStefano Zampini       } else {
2889c8587f34SStefano Zampini         ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2890fdc09c96SStefano Zampini         for (k=0;k<replicated_primal_size;k++) {
2891fdc09c96SStefano Zampini           offset = local_primal_displacements[k];
2892c8587f34SStefano Zampini           offset2 = localdispl2[k];
2893fdc09c96SStefano Zampini           ins_local_primal_size = local_primal_displacements[k+1]-local_primal_displacements[k];
2894c8587f34SStefano Zampini           ierr = PetscMalloc(ins_local_primal_size*sizeof(PetscInt),&ins_local_primal_indices);CHKERRQ(ierr);
2895c8587f34SStefano Zampini           for (j=0;j<ins_local_primal_size;j++){
2896fdc09c96SStefano Zampini             ins_local_primal_indices[j]=(PetscInt)replicated_local_primal_indices[offset+j];
2897c8587f34SStefano Zampini           }
2898c8587f34SStefano Zampini           ins_coarse_mat_vals = &temp_coarse_mat_vals[offset2];
2899fdc635d7SStefano Zampini           ierr = MatSetValues(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);
2900c8587f34SStefano Zampini           ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr);
2901c8587f34SStefano Zampini         }
2902c8587f34SStefano Zampini       }
2903c8587f34SStefano Zampini       ins_local_primal_indices = 0;
2904c8587f34SStefano Zampini       ins_coarse_mat_vals = 0;
2905c8587f34SStefano Zampini     }
2906fdc635d7SStefano Zampini     ierr = MatAssemblyBegin(coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2907fdc635d7SStefano Zampini     ierr = MatAssemblyEnd(coarse_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2908c8587f34SStefano Zampini     /* symmetry of coarse matrix */
2909c8587f34SStefano Zampini     if (issym) {
2910fdc635d7SStefano Zampini       ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2911c8587f34SStefano Zampini     }
2912fdc635d7SStefano Zampini     ierr = MatGetVecs(coarse_mat,&pcbddc->coarse_vec,&pcbddc->coarse_rhs);CHKERRQ(ierr);
2913c8587f34SStefano Zampini   }
2914c8587f34SStefano Zampini 
2915c8587f34SStefano Zampini   /* create loc to glob scatters if needed */
2916c8587f34SStefano Zampini   if (pcbddc->coarse_communications_type == SCATTERS_BDDC) {
2917c8587f34SStefano Zampini      IS local_IS,global_IS;
2918c8587f34SStefano Zampini      ierr = ISCreateStride(PETSC_COMM_SELF,pcbddc->local_primal_size,0,1,&local_IS);CHKERRQ(ierr);
2919fdc09c96SStefano Zampini      ierr = ISCreateGeneral(PETSC_COMM_SELF,pcbddc->local_primal_size,local_primal_indices,PETSC_COPY_VALUES,&global_IS);CHKERRQ(ierr);
2920c8587f34SStefano Zampini      ierr = VecScatterCreate(pcbddc->vec1_P,local_IS,pcbddc->coarse_vec,global_IS,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
2921c8587f34SStefano Zampini      ierr = ISDestroy(&local_IS);CHKERRQ(ierr);
2922c8587f34SStefano Zampini      ierr = ISDestroy(&global_IS);CHKERRQ(ierr);
2923c8587f34SStefano Zampini   }
2924c8587f34SStefano Zampini 
2925c8587f34SStefano Zampini   /* free memory no longer needed */
2926c8587f34SStefano Zampini   if (coarse_ISLG)              { ierr = ISLocalToGlobalMappingDestroy(&coarse_ISLG);CHKERRQ(ierr); }
2927c8587f34SStefano Zampini   if (ins_local_primal_indices) { ierr = PetscFree(ins_local_primal_indices);CHKERRQ(ierr); }
2928c8587f34SStefano Zampini   if (ins_coarse_mat_vals)      { ierr = PetscFree(ins_coarse_mat_vals);CHKERRQ(ierr); }
2929c8587f34SStefano Zampini   if (localsizes2)              { ierr = PetscFree(localsizes2);CHKERRQ(ierr); }
2930c8587f34SStefano Zampini   if (localdispl2)              { ierr = PetscFree(localdispl2);CHKERRQ(ierr); }
2931c8587f34SStefano Zampini   if (temp_coarse_mat_vals)     { ierr = PetscFree(temp_coarse_mat_vals);CHKERRQ(ierr); }
2932c8587f34SStefano Zampini 
2933fdc09c96SStefano Zampini   ierr = PetscFree(local_primal_indices);CHKERRQ(ierr);
2934fdc09c96SStefano Zampini   ierr = PetscFree(local_primal_sizes);CHKERRQ(ierr);
2935fdc09c96SStefano Zampini   ierr = PetscFree(local_primal_displacements);CHKERRQ(ierr);
2936fdc09c96SStefano Zampini   ierr = PetscFree(replicated_local_primal_indices);CHKERRQ(ierr);
2937fdc09c96SStefano Zampini 
2938c8587f34SStefano Zampini   /* Compute coarse null space */
2939c8587f34SStefano Zampini   CoarseNullSpace = 0;
2940c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
2941fdc635d7SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
2942c8587f34SStefano Zampini   }
2943c8587f34SStefano Zampini 
2944c8587f34SStefano Zampini   /* KSP for coarse problem */
2945c8587f34SStefano Zampini   if (rank_prec_comm == active_rank) {
2946c8587f34SStefano Zampini     PetscBool isbddc=PETSC_FALSE;
2947c8587f34SStefano Zampini 
2948c8587f34SStefano Zampini     ierr = KSPCreate(coarse_comm,&pcbddc->coarse_ksp);CHKERRQ(ierr);
2949c8587f34SStefano Zampini     ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
2950fdc635d7SStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
2951c8587f34SStefano Zampini     ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,max_it_coarse_ksp);CHKERRQ(ierr);
2952c8587f34SStefano Zampini     ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
2953c8587f34SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
2954c8587f34SStefano Zampini     ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
2955c8587f34SStefano Zampini     /* Allow user's customization */
2956c8587f34SStefano Zampini     ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,"coarse_");CHKERRQ(ierr);
2957c8587f34SStefano Zampini     /* Set Up PC for coarse problem BDDC */
2958c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
2959c8587f34SStefano Zampini       i = pcbddc->current_level+1;
2960c8587f34SStefano Zampini       ierr = PCBDDCSetLevel(pc_temp,i);CHKERRQ(ierr);
2961c8587f34SStefano Zampini       ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
2962c8587f34SStefano Zampini       ierr = PCBDDCSetMaxLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
2963c8587f34SStefano Zampini       ierr = PCBDDCSetCoarseProblemType(pc_temp,MULTILEVEL_BDDC);CHKERRQ(ierr);
2964c8587f34SStefano Zampini       if (CoarseNullSpace) {
2965c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
2966c8587f34SStefano Zampini       }
2967c8587f34SStefano Zampini       if (dbg_flag) {
2968c8587f34SStefano Zampini         ierr = PetscViewerASCIIPrintf(viewer,"----------------Level %d: Setting up level %d---------------\n",pcbddc->current_level,i);CHKERRQ(ierr);
2969c8587f34SStefano Zampini         ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2970c8587f34SStefano Zampini       }
2971c8587f34SStefano Zampini     } else {
2972c8587f34SStefano Zampini       if (CoarseNullSpace) {
2973c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
2974c8587f34SStefano Zampini       }
2975c8587f34SStefano Zampini     }
2976c8587f34SStefano Zampini     ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
2977c8587f34SStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
2978c8587f34SStefano Zampini 
2979c8587f34SStefano Zampini     ierr = KSPGetTolerances(pcbddc->coarse_ksp,NULL,NULL,NULL,&j);CHKERRQ(ierr);
2980c8587f34SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
2981c8587f34SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
2982c8587f34SStefano Zampini     if (j == 1) {
2983c8587f34SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
2984c8587f34SStefano Zampini       if (isbddc) {
2985c8587f34SStefano Zampini         ierr = PCBDDCSetUseExactDirichlet(pc_temp,PETSC_FALSE);CHKERRQ(ierr);
2986c8587f34SStefano Zampini       }
2987c8587f34SStefano Zampini     }
2988c8587f34SStefano Zampini   }
2989c8587f34SStefano Zampini   /* Check coarse problem if requested */
2990c8587f34SStefano Zampini   if ( dbg_flag && rank_prec_comm == active_rank ) {
2991c8587f34SStefano Zampini     KSP check_ksp;
2992c8587f34SStefano Zampini     PC  check_pc;
2993c8587f34SStefano Zampini     Vec check_vec;
2994c8587f34SStefano Zampini     PetscReal   abs_infty_error,infty_error,lambda_min,lambda_max;
2995c8587f34SStefano Zampini     KSPType check_ksp_type;
2996c8587f34SStefano Zampini 
2997c8587f34SStefano Zampini     /* Create ksp object suitable for extreme eigenvalues' estimation */
2998c8587f34SStefano Zampini     ierr = KSPCreate(coarse_comm,&check_ksp);CHKERRQ(ierr);
2999fdc635d7SStefano Zampini     ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat,SAME_PRECONDITIONER);CHKERRQ(ierr);
3000983f5fd7SStefano Zampini     ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,coarse_size);CHKERRQ(ierr);
3001c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3002c8587f34SStefano Zampini       if (issym) check_ksp_type = KSPCG;
3003c8587f34SStefano Zampini       else check_ksp_type = KSPGMRES;
3004c8587f34SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
3005c8587f34SStefano Zampini     } else {
3006c8587f34SStefano Zampini       check_ksp_type = KSPPREONLY;
3007c8587f34SStefano Zampini     }
3008c8587f34SStefano Zampini     ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
3009c8587f34SStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
3010c8587f34SStefano Zampini     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
3011c8587f34SStefano Zampini     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
3012c8587f34SStefano Zampini     /* create random vec */
3013c8587f34SStefano Zampini     ierr = VecDuplicate(pcbddc->coarse_vec,&check_vec);CHKERRQ(ierr);
3014c8587f34SStefano Zampini     ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
3015c8587f34SStefano Zampini     if (CoarseNullSpace) {
3016c8587f34SStefano Zampini       ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
3017c8587f34SStefano Zampini     }
3018fdc635d7SStefano Zampini     ierr = MatMult(coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3019c8587f34SStefano Zampini     /* solve coarse problem */
3020c8587f34SStefano Zampini     ierr = KSPSolve(check_ksp,pcbddc->coarse_rhs,pcbddc->coarse_vec);CHKERRQ(ierr);
3021c8587f34SStefano Zampini     if (CoarseNullSpace) {
3022c8587f34SStefano Zampini       ierr = MatNullSpaceRemove(CoarseNullSpace,pcbddc->coarse_vec);CHKERRQ(ierr);
3023c8587f34SStefano Zampini     }
3024c8587f34SStefano Zampini     /* check coarse problem residual error */
3025c8587f34SStefano Zampini     ierr = VecAXPY(check_vec,-1.0,pcbddc->coarse_vec);CHKERRQ(ierr);
3026c8587f34SStefano Zampini     ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3027fdc635d7SStefano Zampini     ierr = MatMult(coarse_mat,check_vec,pcbddc->coarse_rhs);CHKERRQ(ierr);
3028c8587f34SStefano Zampini     ierr = VecNorm(pcbddc->coarse_rhs,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
3029c8587f34SStefano Zampini     ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
3030c8587f34SStefano Zampini     /* get eigenvalue estimation if inexact */
3031c8587f34SStefano Zampini     if (pcbddc->coarse_problem_type == MULTILEVEL_BDDC) {
3032c8587f34SStefano Zampini       ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
3033c8587f34SStefano Zampini       ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
3034c8587f34SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues estimated with %d iterations of %s.\n",k,check_ksp_type);CHKERRQ(ierr);
3035c8587f34SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem eigenvalues: % 1.14e %1.14e\n",lambda_min,lambda_max);CHKERRQ(ierr);
3036c8587f34SStefano Zampini     }
3037c8587f34SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem exact infty_error   : %1.14e\n",infty_error);CHKERRQ(ierr);
3038c8587f34SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"Coarse problem residual infty_error: %1.14e\n",abs_infty_error);CHKERRQ(ierr);
3039c8587f34SStefano Zampini     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
3040c8587f34SStefano Zampini   }
3041c8587f34SStefano Zampini   if (dbg_flag) {
3042c8587f34SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
3043c8587f34SStefano Zampini   }
3044c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
3045fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
3046c8587f34SStefano Zampini   PetscFunctionReturn(0);
3047c8587f34SStefano Zampini }
30489a7d3425SStefano Zampini 
3049*f34684f1SStefano Zampini #undef __FUNCT__
3050*f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
3051*f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
3052*f34684f1SStefano Zampini {
3053*f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
3054*f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
3055*f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
3056*f34684f1SStefano Zampini   PetscInt       i,j,coarse_size;
3057*f34684f1SStefano Zampini   PetscInt       *local_primal_indices,*auxlocal_primal,*aux_idx;
3058*f34684f1SStefano Zampini   PetscErrorCode ierr;
3059*f34684f1SStefano Zampini 
3060*f34684f1SStefano Zampini   PetscFunctionBegin;
3061*f34684f1SStefano Zampini   /* get indices in local ordering for vertices and constraints */
3062*f34684f1SStefano Zampini   ierr = PetscMalloc(pcbddc->local_primal_size*sizeof(PetscInt),&auxlocal_primal);CHKERRQ(ierr);
3063*f34684f1SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_idx);CHKERRQ(ierr);
3064*f34684f1SStefano Zampini   ierr = PetscMemcpy(auxlocal_primal,aux_idx,i*sizeof(PetscInt));CHKERRQ(ierr);
3065*f34684f1SStefano Zampini   ierr = PetscFree(aux_idx);CHKERRQ(ierr);
3066*f34684f1SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_idx);CHKERRQ(ierr);
3067*f34684f1SStefano Zampini   ierr = PetscMemcpy(&auxlocal_primal[i],aux_idx,j*sizeof(PetscInt));CHKERRQ(ierr);
3068*f34684f1SStefano Zampini   ierr = PetscFree(aux_idx);CHKERRQ(ierr);
3069*f34684f1SStefano Zampini 
3070*f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
3071*f34684f1SStefano Zampini   ierr = PCBDDCSubsetNumbering(PetscObjectComm((PetscObject)(pc->pmat)),matis->mapping,pcbddc->local_primal_size,auxlocal_primal,NULL,&coarse_size,&local_primal_indices);CHKERRQ(ierr);
3072*f34684f1SStefano Zampini 
3073*f34684f1SStefano Zampini   /* check numbering */
3074*f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
3075*f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
3076*f34684f1SStefano Zampini 
3077*f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3078*f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
3079*f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
3080*f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
3081*f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
3082*f34684f1SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,auxlocal_primal[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
3083*f34684f1SStefano Zampini     }
3084*f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
3085*f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
3086*f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3087*f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3088*f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3089*f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3090*f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
3091*f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3092*f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
3093*f34684f1SStefano Zampini       if (array[i] == 1.0) {
3094*f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
3095*f34684f1SStefano Zampini       }
3096*f34684f1SStefano Zampini     }
3097*f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3098*f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
3099*f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
3100*f34684f1SStefano Zampini     }
3101*f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
3102*f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
3103*f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3104*f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3105*f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
3106*f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
3107*f34684f1SStefano Zampini     if (pcbddc->dbg_flag > 1) {
3108*f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
3109*f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3110*f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
3111*f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
3112*f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d \n",i,local_primal_indices[i]);
3113*f34684f1SStefano Zampini       }
3114*f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3115*f34684f1SStefano Zampini     }
3116*f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
3117*f34684f1SStefano Zampini   }
3118*f34684f1SStefano Zampini   ierr = PetscFree(auxlocal_primal);CHKERRQ(ierr);
3119*f34684f1SStefano Zampini   /* get back data */
3120*f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
3121*f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
3122*f34684f1SStefano Zampini   PetscFunctionReturn(0);
3123*f34684f1SStefano Zampini }
3124*f34684f1SStefano Zampini 
3125