xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b7eb36285fd32db6a2205f2794656e34b279d97c)
1ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3674ae819SStefano Zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
5906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini 
8b1b3d7a2SStefano Zampini #if 0
9b1b3d7a2SStefano Zampini #undef __FUNCT__
10b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
11b1b3d7a2SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc, MatNullSpace* adapt_nnsp)
12b1b3d7a2SStefano Zampini {
13b1b3d7a2SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14b1b3d7a2SStefano Zampini   PetscErrorCode ierr;
15b1b3d7a2SStefano Zampini 
16b1b3d7a2SStefano Zampini   PetscFunctionBegin;
17b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs[0],pcbddc->mat_graph,...);CHKERRQ(ierr);
18b1b3d7a2SStefano Zampini   PetscFunctionReturn(0);
19b1b3d7a2SStefano Zampini }
20b1b3d7a2SStefano Zampini #endif
21b1b3d7a2SStefano Zampini 
22674ae819SStefano Zampini #undef __FUNCT__
23c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
24c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
25c8587f34SStefano Zampini {
26c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
278629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
28c8587f34SStefano Zampini   PetscErrorCode ierr;
29c8587f34SStefano Zampini 
30c8587f34SStefano Zampini   PetscFunctionBegin;
31f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
325e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
33c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
34c8587f34SStefano Zampini 
35684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
360fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
37684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
38c8587f34SStefano Zampini 
39c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
40b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
41c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
42c8587f34SStefano Zampini   }
43c8587f34SStefano Zampini 
448629588bSStefano Zampini   /*
458629588bSStefano Zampini      Setup local correction and local part of coarse basis.
468629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
478629588bSStefano Zampini   */
4847f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
498629588bSStefano Zampini 
508629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
518629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
528629588bSStefano Zampini 
538629588bSStefano Zampini   /* free */
548629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
55c8587f34SStefano Zampini   PetscFunctionReturn(0);
56c8587f34SStefano Zampini }
57c8587f34SStefano Zampini 
58c8587f34SStefano Zampini #undef __FUNCT__
59674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
60674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
61674ae819SStefano Zampini {
62674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
63674ae819SStefano Zampini   PetscErrorCode ierr;
64674ae819SStefano Zampini 
65674ae819SStefano Zampini   PetscFunctionBegin;
66674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
67674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
68674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
69674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
70785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
71674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
72f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
73f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
74785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
7663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
77674ae819SStefano Zampini   PetscFunctionReturn(0);
78674ae819SStefano Zampini }
79674ae819SStefano Zampini 
80674ae819SStefano Zampini #undef __FUNCT__
81674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
82674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
83674ae819SStefano Zampini {
84674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
85674ae819SStefano Zampini   PetscErrorCode ierr;
86674ae819SStefano Zampini 
87674ae819SStefano Zampini   PetscFunctionBegin;
88b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
89674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
90674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
91674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
92b96c3477SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs);CHKERRQ(ierr);
93674ae819SStefano Zampini   PetscFunctionReturn(0);
94674ae819SStefano Zampini }
95674ae819SStefano Zampini 
96674ae819SStefano Zampini #undef __FUNCT__
97674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
98674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
99674ae819SStefano Zampini {
100674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
101674ae819SStefano Zampini   PetscErrorCode ierr;
102674ae819SStefano Zampini 
103674ae819SStefano Zampini   PetscFunctionBegin;
104674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
105674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
106674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
107674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
10815aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
10915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
110674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
111674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
112674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
113674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
114674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
115674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1168ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
117674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
118674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
119674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
120f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
121f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
122f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
123f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
124727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
125f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
12670cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
1276e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
128674ae819SStefano Zampini   PetscFunctionReturn(0);
129674ae819SStefano Zampini }
130674ae819SStefano Zampini 
131674ae819SStefano Zampini #undef __FUNCT__
132f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
133f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
1346bfb1811SStefano Zampini {
1356bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1366bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1376bfb1811SStefano Zampini   VecType        impVecType;
138e9189074SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
1396bfb1811SStefano Zampini   PetscErrorCode ierr;
1406bfb1811SStefano Zampini 
1416bfb1811SStefano Zampini   PetscFunctionBegin;
142f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
143f4ddd8eeSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
144f4ddd8eeSStefano Zampini   }
145e7b262bdSStefano Zampini   /* get sizes */
146e9189074SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->n_actual_vertices;
147e9189074SStefano Zampini   n_R = pcis->n-pcbddc->n_actual_vertices;
1486bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
149e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
150e7b262bdSStefano Zampini   /* R nodes */
151e7b262bdSStefano Zampini   old_size = -1;
152e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
153e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
154e7b262bdSStefano Zampini   }
155e7b262bdSStefano Zampini   if (n_R != old_size) {
156e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
157e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1586bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
1596bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
1606bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1616bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
162e7b262bdSStefano Zampini   }
163e7b262bdSStefano Zampini   /* local primal dofs */
164e7b262bdSStefano Zampini   old_size = -1;
165e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
166e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
167e7b262bdSStefano Zampini   }
168e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
169e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
17083b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
171e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
1726bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
173e7b262bdSStefano Zampini   }
174e7b262bdSStefano Zampini   /* local explicit constraints */
175e7b262bdSStefano Zampini   old_size = -1;
176e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
177e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
178e7b262bdSStefano Zampini   }
179e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
180e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
18183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
18283b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
18383b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
18483b7ccabSStefano Zampini   }
1856bfb1811SStefano Zampini   PetscFunctionReturn(0);
1866bfb1811SStefano Zampini }
1876bfb1811SStefano Zampini 
1886bfb1811SStefano Zampini #undef __FUNCT__
18947f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
19047f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
19188ebb749SStefano Zampini {
19225084f0cSStefano Zampini   PetscErrorCode         ierr;
19325084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
19488ebb749SStefano Zampini   PC_IS*                 pcis = (PC_IS*)pc->data;
19588ebb749SStefano Zampini   PC_BDDC*               pcbddc = (PC_BDDC*)pc->data;
19625084f0cSStefano Zampini   /* submatrices of local problem */
19788ebb749SStefano Zampini   Mat                    A_RV,A_VR,A_VV;
19825084f0cSStefano Zampini   /* working matrices */
19925084f0cSStefano Zampini   Mat                    M1,M2,M3,C_CR;
20025084f0cSStefano Zampini   /* working vectors */
20125084f0cSStefano Zampini   Vec                    vec1_C,vec2_C,vec1_V,vec2_V;
20225084f0cSStefano Zampini   /* additional working stuff */
20325084f0cSStefano Zampini   IS                     is_aux;
20425084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
20525084f0cSStefano Zampini   const PetscScalar      *array,*row_cmat_values;
20625084f0cSStefano Zampini   const PetscInt         *row_cmat_indices,*idx_R_local;
207e9189074SStefano Zampini   PetscInt               *idx_V_B,*auxindices;
20825084f0cSStefano Zampini   PetscInt               n_vertices,n_constraints,size_of_constraint;
20925084f0cSStefano Zampini   PetscInt               i,j,n_R,n_D,n_B;
210b9d89cd5SStefano Zampini   PetscBool              unsymmetric_check;
21145a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
21288ebb749SStefano Zampini   MatType                impMatType;
21325084f0cSStefano Zampini   /* some shortcuts to scalars */
21425084f0cSStefano Zampini   PetscScalar            zero=0.0,one=1.0,m_one=-1.0;
21525084f0cSStefano Zampini   /* for debugging purposes */
21688ebb749SStefano Zampini   PetscReal              *coarsefunctions_errors,*constraints_errors;
21788ebb749SStefano Zampini 
21888ebb749SStefano Zampini   PetscFunctionBegin;
219e9189074SStefano Zampini   /* get number of vertices (corners plus constraints with change of basis)
220e9189074SStefano Zampini      pcbddc->n_actual_vertices stores the actual number of vertices, pcbddc->n_vertices the number of corners computed */
221e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
22288ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
22388ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
22488ebb749SStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
22588ebb749SStefano Zampini   n_R = pcis->n-n_vertices;
22688ebb749SStefano Zampini 
22788ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
22888ebb749SStefano Zampini   impMatType = MATSEQDENSE;
22988ebb749SStefano Zampini 
23088ebb749SStefano Zampini   /* Allocating some extra storage just to be safe */
23188ebb749SStefano Zampini   ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
23288ebb749SStefano Zampini   for (i=0;i<pcis->n;i++) auxindices[i]=i;
23388ebb749SStefano Zampini 
23488ebb749SStefano Zampini   /* vertices in boundary numbering */
235785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
2365e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->primal_indices_local_idxs,&i,idx_V_B);CHKERRQ(ierr);
23788ebb749SStefano Zampini   if (i != n_vertices) {
23822d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
23988ebb749SStefano Zampini   }
24088ebb749SStefano Zampini 
24188ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
24288ebb749SStefano Zampini   if (n_constraints) {
243f4ddd8eeSStefano Zampini     /* see if we can save some allocations */
244f4ddd8eeSStefano Zampini     if (pcbddc->local_auxmat2) {
245f4ddd8eeSStefano Zampini       PetscInt on_R,on_constraints;
246f4ddd8eeSStefano Zampini       ierr = MatGetSize(pcbddc->local_auxmat2,&on_R,&on_constraints);CHKERRQ(ierr);
247f4ddd8eeSStefano Zampini       if (on_R != n_R || on_constraints != n_constraints) {
248f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
249f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
250f4ddd8eeSStefano Zampini       }
251f4ddd8eeSStefano Zampini     }
25245a1bb75SStefano Zampini     /* work vectors */
25345a1bb75SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec1_C);CHKERRQ(ierr);
25445a1bb75SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec2_C);CHKERRQ(ierr);
25545a1bb75SStefano Zampini     /* auxiliary matrices */
256f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat2) {
25788ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
25825084f0cSStefano Zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
25988ebb749SStefano Zampini       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
26025084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->local_auxmat2);CHKERRQ(ierr);
261f4ddd8eeSStefano Zampini     }
26288ebb749SStefano Zampini 
26325084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
26425084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
2658ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
26625084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
26788ebb749SStefano Zampini 
26888ebb749SStefano Zampini     /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
26988ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
27088ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
27188ebb749SStefano Zampini       /* Get row of constraint matrix in R numbering */
27225084f0cSStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
27325084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_R,size_of_constraint,row_cmat_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
27425084f0cSStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
27525084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_R);CHKERRQ(ierr);
27625084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_R);CHKERRQ(ierr);
27788ebb749SStefano Zampini       /* Solve for row of constraint matrix in R numbering */
27888ebb749SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
27925084f0cSStefano Zampini       /* Set values in local_auxmat2 */
28025084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
28188ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
28225084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
28388ebb749SStefano Zampini     }
28488ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28588ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28625084f0cSStefano Zampini     ierr = MatScale(pcbddc->local_auxmat2,m_one);CHKERRQ(ierr);
28788ebb749SStefano Zampini 
28888ebb749SStefano Zampini     /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
28925084f0cSStefano Zampini     ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
29025084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
29188ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
29288ebb749SStefano Zampini     ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
29388ebb749SStefano Zampini     ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
29425084f0cSStefano Zampini     ierr = MatSetUp(M1);CHKERRQ(ierr);
29525084f0cSStefano Zampini     ierr = MatDuplicate(M1,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
29625084f0cSStefano Zampini     ierr = MatZeroEntries(M2);CHKERRQ(ierr);
29725084f0cSStefano Zampini     ierr = VecSet(vec1_C,m_one);CHKERRQ(ierr);
29825084f0cSStefano Zampini     ierr = MatDiagonalSet(M2,vec1_C,INSERT_VALUES);CHKERRQ(ierr);
29925084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
30025084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
30125084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
30288ebb749SStefano Zampini     /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
303f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat1) {
30488ebb749SStefano Zampini       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
305f4ddd8eeSStefano Zampini     } else {
306f4ddd8eeSStefano Zampini       ierr = MatMatMult(M1,C_CR,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
307f4ddd8eeSStefano Zampini     }
30888ebb749SStefano Zampini   }
30988ebb749SStefano Zampini 
31088ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
31188ebb749SStefano Zampini   if (n_vertices) {
3123a50541eSStefano Zampini     PetscInt ibs,mbs;
3133a50541eSStefano Zampini     PetscBool issbaij;
314af732b37SStefano Zampini     Mat newmat;
3153a50541eSStefano Zampini 
3163a50541eSStefano Zampini     ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
3179577ea80SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3189577ea80SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
3193a50541eSStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ */
3209577ea80SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
3219577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3229577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3239577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
3249577ea80SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
3259577ea80SStefano Zampini     } else {
3263a50541eSStefano Zampini       /* this is safe */
3279577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
3283a50541eSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3293a50541eSStefano Zampini       if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
3303a50541eSStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
33145a1bb75SStefano Zampini         /* which of the two approaches is faster? */
3323a50541eSStefano Zampini         /* ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3333a50541eSStefano Zampini         ierr = MatCreateTranspose(A_RV,&A_VR);CHKERRQ(ierr);*/
3343a50541eSStefano Zampini         ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3353a50541eSStefano Zampini         ierr = MatCreateTranspose(A_VR,&A_RV);CHKERRQ(ierr);
3363a50541eSStefano Zampini         ierr = MatDestroy(&newmat);CHKERRQ(ierr);
3373a50541eSStefano Zampini       } else {
3389577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3399577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3409577ea80SStefano Zampini       }
3413a50541eSStefano Zampini     }
3422a7a6963SBarry Smith     ierr = MatCreateVecs(A_RV,&vec1_V,NULL);CHKERRQ(ierr);
34345a1bb75SStefano Zampini     ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
34425084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
34588ebb749SStefano Zampini   }
34688ebb749SStefano Zampini 
34788ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
348f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
349f4ddd8eeSStefano Zampini     PetscInt on_B,on_primal;
350f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
351f4ddd8eeSStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size) {
352f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
353f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
354f4ddd8eeSStefano Zampini     }
355f4ddd8eeSStefano Zampini   }
356f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_D) {
357f4ddd8eeSStefano Zampini     PetscInt on_D,on_primal;
358f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,&on_primal);CHKERRQ(ierr);
359f4ddd8eeSStefano Zampini     if (on_D != n_D || on_primal != pcbddc->local_primal_size) {
360f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
361f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
362f4ddd8eeSStefano Zampini     }
363f4ddd8eeSStefano Zampini   }
364f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
36588ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
36688ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
36788ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
36825084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_phi_B);CHKERRQ(ierr);
369f4ddd8eeSStefano Zampini   }
370f4ddd8eeSStefano Zampini   if ( (pcbddc->switch_static || pcbddc->dbg_flag) && !pcbddc->coarse_phi_D ) {
37188ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
37288ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
37388ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
37425084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_phi_D);CHKERRQ(ierr);
37588ebb749SStefano Zampini   }
37688ebb749SStefano Zampini 
37725084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
3788ce42a96SStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
379785e854fSJed Brown     ierr = PetscMalloc1(2*pcbddc->local_primal_size,&coarsefunctions_errors);CHKERRQ(ierr);
380785e854fSJed Brown     ierr = PetscMalloc1(2*pcbddc->local_primal_size,&constraints_errors);CHKERRQ(ierr);
38188ebb749SStefano Zampini   }
38288ebb749SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
383854ce69bSBarry Smith   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
38488ebb749SStefano Zampini 
38588ebb749SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
38625084f0cSStefano Zampini 
38725084f0cSStefano Zampini   /* vertices */
38888ebb749SStefano Zampini   for (i=0;i<n_vertices;i++) {
38945a1bb75SStefano Zampini     /* this should not be needed, but MatMult_BAIJ is broken when using compressed row routines */
390f4ddd8eeSStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr); /* TODO: REMOVE IT */
39188ebb749SStefano Zampini     ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
39288ebb749SStefano Zampini     ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
39388ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
39488ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
39525084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on constraints multipliers */
39688ebb749SStefano Zampini     ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
39788ebb749SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
39888ebb749SStefano Zampini     ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
39988ebb749SStefano Zampini     if (n_constraints) {
40088ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
40188ebb749SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
40288ebb749SStefano Zampini       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
40388ebb749SStefano Zampini     }
40488ebb749SStefano Zampini     ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
40588ebb749SStefano Zampini     ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
40688ebb749SStefano Zampini 
40788ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
40888ebb749SStefano Zampini     /* coarse basis functions */
40988ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
41088ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41188ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41225084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
41388ebb749SStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
41425084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
41588ebb749SStefano Zampini     ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
4168eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41788ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41888ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41925084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
42088ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
42125084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
42288ebb749SStefano Zampini     }
42325084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
42425084f0cSStefano Zampini     ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
42525084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
42625084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
42788ebb749SStefano Zampini     if (n_constraints) {
42825084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
42925084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
43025084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
43188ebb749SStefano Zampini     }
43288ebb749SStefano Zampini 
43325084f0cSStefano Zampini     /* check */
43425084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
43525084f0cSStefano Zampini       /* assemble subdomain vector on local nodes */
43688ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
43725084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
4389f00e9b4SStefano Zampini       if (n_R) {
43925084f0cSStefano Zampini         ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
4409f00e9b4SStefano Zampini       }
44125084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
442e9189074SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],one,INSERT_VALUES);CHKERRQ(ierr);
44325084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
44425084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
44588ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
44688ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
44725084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
44825084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
44925084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
45088ebb749SStefano Zampini       if (n_constraints) {
45125084f0cSStefano Zampini         ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
45225084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
45325084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
45488ebb749SStefano Zampini       }
45525084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
45625084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
45788ebb749SStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
45888ebb749SStefano Zampini       /* check saddle point solution */
45988ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
46088ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
46188ebb749SStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
46288ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
46325084f0cSStefano Zampini       /* shift by the identity matrix */
46425084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
46525084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
46625084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
46788ebb749SStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
46888ebb749SStefano Zampini     }
46988ebb749SStefano Zampini   }
47088ebb749SStefano Zampini 
47125084f0cSStefano Zampini   /* constraints */
47288ebb749SStefano Zampini   for (i=0;i<n_constraints;i++) {
47388ebb749SStefano Zampini     ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
47488ebb749SStefano Zampini     ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
47588ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
47688ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
47725084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on vertices multipliers */
47888ebb749SStefano Zampini     ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
47988ebb749SStefano Zampini     ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
48088ebb749SStefano Zampini     ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
48125084f0cSStefano Zampini     if (n_vertices) {
48225084f0cSStefano Zampini       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
48325084f0cSStefano Zampini     }
48488ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
48588ebb749SStefano Zampini     /* coarse basis functions */
48625084f0cSStefano Zampini     j = i+n_vertices; /* don't touch this! */
48788ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
48888ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
48988ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49025084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
49125084f0cSStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
49225084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
4938eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
49488ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49588ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49625084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
49725084f0cSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
49825084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
49988ebb749SStefano Zampini     }
50025084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
50188ebb749SStefano Zampini     if (n_vertices) {
50225084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
50325084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
50425084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
50588ebb749SStefano Zampini     }
50625084f0cSStefano Zampini     ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
50725084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
50825084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
50988ebb749SStefano Zampini 
51025084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
51188ebb749SStefano Zampini       /* assemble subdomain vector on nodes */
51288ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
51325084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
5149f00e9b4SStefano Zampini       if (n_R) {
51525084f0cSStefano Zampini         ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
5169f00e9b4SStefano Zampini       }
51725084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
51825084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
51925084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
52088ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers */
52188ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
52288ebb749SStefano Zampini       if (n_vertices) {
52325084f0cSStefano Zampini         ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
52425084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
52525084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
52688ebb749SStefano Zampini       }
52725084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
52825084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
52925084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
53025084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
53125084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
53225084f0cSStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
53388ebb749SStefano Zampini       /* check saddle point solution */
53488ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
53588ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
53625084f0cSStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[j]);CHKERRQ(ierr);
53788ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
53825084f0cSStefano Zampini       /* shift by the identity matrix */
53925084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,j,m_one,ADD_VALUES);CHKERRQ(ierr);
54025084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
54125084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
54225084f0cSStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[j]);CHKERRQ(ierr);
54388ebb749SStefano Zampini     }
54488ebb749SStefano Zampini   }
54525084f0cSStefano Zampini   /* call assembling routines for local coarse basis */
54688ebb749SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
54788ebb749SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5488eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
54988ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55088ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55188ebb749SStefano Zampini   }
55225084f0cSStefano Zampini 
55388ebb749SStefano Zampini   /* compute other basis functions for non-symmetric problems */
554b9d89cd5SStefano Zampini   if (!pcbddc->issym) {
555f4ddd8eeSStefano Zampini     if (!pcbddc->coarse_psi_B) {
55688ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
55788ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
55888ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
55925084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_B);CHKERRQ(ierr);
560f4ddd8eeSStefano Zampini     }
561f4ddd8eeSStefano Zampini     if ( (pcbddc->switch_static || pcbddc->dbg_flag) && !pcbddc->coarse_psi_D) {
56288ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
56388ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
56488ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
56525084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_D);CHKERRQ(ierr);
56688ebb749SStefano Zampini     }
56788ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
56888ebb749SStefano Zampini       if (n_constraints) {
56988ebb749SStefano Zampini         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
57088ebb749SStefano Zampini         for (j=0;j<n_constraints;j++) {
57125084f0cSStefano Zampini           ierr = VecSetValue(vec1_C,j,coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
57288ebb749SStefano Zampini         }
57325084f0cSStefano Zampini         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
57425084f0cSStefano Zampini         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
57588ebb749SStefano Zampini       }
57688ebb749SStefano Zampini       if (i<n_vertices) {
57788ebb749SStefano Zampini         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
57888ebb749SStefano Zampini         ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
57988ebb749SStefano Zampini         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
58088ebb749SStefano Zampini         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
58188ebb749SStefano Zampini         ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
58288ebb749SStefano Zampini         if (n_constraints) {
58388ebb749SStefano Zampini           ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
58488ebb749SStefano Zampini         }
58588ebb749SStefano Zampini       } else {
58688ebb749SStefano Zampini         ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
58788ebb749SStefano Zampini       }
58888ebb749SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
58988ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
59088ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
59188ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
59225084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
59388ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
59425084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
59588ebb749SStefano Zampini       if (i<n_vertices) {
59688ebb749SStefano Zampini         ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
59788ebb749SStefano Zampini       }
5988eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
59988ebb749SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60088ebb749SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60125084f0cSStefano Zampini         ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
60288ebb749SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
60325084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
60488ebb749SStefano Zampini       }
60588ebb749SStefano Zampini 
60625084f0cSStefano Zampini       if (pcbddc->dbg_flag) {
60788ebb749SStefano Zampini         /* assemble subdomain vector on nodes */
60888ebb749SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
60925084f0cSStefano Zampini         ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
6109f00e9b4SStefano Zampini         if (n_R) {
61125084f0cSStefano Zampini           ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
6129f00e9b4SStefano Zampini         }
61325084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
61425084f0cSStefano Zampini         if (i<n_vertices) {
615e9189074SStefano Zampini           ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],one,INSERT_VALUES);CHKERRQ(ierr);
61688ebb749SStefano Zampini         }
61725084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
61825084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
61925084f0cSStefano Zampini         /* assemble subdomain vector of lagrange multipliers */
62025084f0cSStefano Zampini         for (j=0;j<pcbddc->local_primal_size;j++) {
62125084f0cSStefano Zampini           ierr = VecSetValue(pcbddc->vec1_P,j,-coarse_submat_vals[j*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
62225084f0cSStefano Zampini         }
62325084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
62425084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
62588ebb749SStefano Zampini         /* check saddle point solution */
62688ebb749SStefano Zampini         ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
62788ebb749SStefano Zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
62888ebb749SStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
62988ebb749SStefano Zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
63025084f0cSStefano Zampini         /* shift by the identity matrix */
63125084f0cSStefano Zampini         ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
63225084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
63325084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
63488ebb749SStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
63588ebb749SStefano Zampini       }
63688ebb749SStefano Zampini     }
63788ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63888ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6398eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
64088ebb749SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64188ebb749SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64288ebb749SStefano Zampini     }
643c0553b1fSStefano Zampini     unsymmetric_check = PETSC_TRUE;
644c0553b1fSStefano Zampini   } else { /* take references to already computed coarse basis */
645c0553b1fSStefano Zampini     unsymmetric_check = PETSC_FALSE;
646c0553b1fSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
647c0553b1fSStefano Zampini     pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
648c0553b1fSStefano Zampini     if (pcbddc->coarse_phi_D) {
649c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
650c0553b1fSStefano Zampini       pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
651c0553b1fSStefano Zampini     }
65288ebb749SStefano Zampini   }
65388ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
65488ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
65588ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
65688ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
65725084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
65888ebb749SStefano Zampini     Mat         coarse_sub_mat;
65925084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
66088ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
66188ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
66288ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
66388ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
66488ebb749SStefano Zampini     PetscReal   real_value;
66588ebb749SStefano Zampini 
66688ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
66788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
66888ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
66988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
67088ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
67188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
672c0553b1fSStefano Zampini     if (unsymmetric_check) {
67388ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
67488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
67588ebb749SStefano Zampini     }
67688ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
67788ebb749SStefano Zampini 
67825084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
67925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
68025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
681c0553b1fSStefano Zampini     if (unsymmetric_check) {
68288ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
68388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
68488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
68588ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
68688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
68788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
68888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
68988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
69088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
69388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69488ebb749SStefano Zampini     } else {
69588ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
69688ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
69788ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69888ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
69988ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70088ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
70188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
70288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70388ebb749SStefano Zampini     }
70488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70788ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
70881d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70988ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
7100fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
71125084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"----------------------------------\n");CHKERRQ(ierr);
71225084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
71325084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
71425084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
71588ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
71625084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
71788ebb749SStefano Zampini     }
71825084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
71988ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
72025084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
72188ebb749SStefano Zampini     }
722c0553b1fSStefano Zampini     if (unsymmetric_check) {
72325084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
72488ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
72525084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
72688ebb749SStefano Zampini       }
72725084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
72888ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
72925084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
73088ebb749SStefano Zampini       }
73188ebb749SStefano Zampini     }
73225084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
73388ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
73488ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
73588ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
73688ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
73788ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
73888ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
73988ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
74088ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
74188ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
74288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
743c0553b1fSStefano Zampini     if (unsymmetric_check) {
74488ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
74588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
74688ebb749SStefano Zampini     }
74788ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
7488ce42a96SStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
74988ebb749SStefano Zampini     ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
75088ebb749SStefano Zampini     ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
75188ebb749SStefano Zampini   }
75288ebb749SStefano Zampini   /* free memory */
75388ebb749SStefano Zampini   if (n_vertices) {
75488ebb749SStefano Zampini     ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
75588ebb749SStefano Zampini     ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
75688ebb749SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
75788ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
75888ebb749SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
75988ebb749SStefano Zampini   }
76088ebb749SStefano Zampini   if (n_constraints) {
76188ebb749SStefano Zampini     ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
76288ebb749SStefano Zampini     ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
76388ebb749SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
76488ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
76588ebb749SStefano Zampini   }
76688ebb749SStefano Zampini   ierr = PetscFree(auxindices);CHKERRQ(ierr);
7678629588bSStefano Zampini   /* get back data */
7688629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
76988ebb749SStefano Zampini   PetscFunctionReturn(0);
77088ebb749SStefano Zampini }
77188ebb749SStefano Zampini 
77288ebb749SStefano Zampini #undef __FUNCT__
773d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
774b96c3477SStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, MatStructure reuse, Mat* B)
775d65f70fdSStefano Zampini {
776d65f70fdSStefano Zampini   Mat            *work_mat;
777d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
778d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
779d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
780d65f70fdSStefano Zampini   PetscErrorCode ierr;
781d65f70fdSStefano Zampini 
782d65f70fdSStefano Zampini   PetscFunctionBegin;
783d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
784d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
785d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
786d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
787d65f70fdSStefano Zampini 
788d65f70fdSStefano Zampini   if (!rsorted) {
789d65f70fdSStefano Zampini     const PetscInt *idxs;
790d65f70fdSStefano Zampini     PetscInt *idxs_sorted,i;
791d65f70fdSStefano Zampini 
792d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
793d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
794d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
795d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
796d65f70fdSStefano Zampini     }
797d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
798d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
799d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
800d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
801d65f70fdSStefano Zampini     }
802d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
803d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
804d65f70fdSStefano Zampini   } else {
805d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
806d65f70fdSStefano Zampini     isrow_s = isrow;
807d65f70fdSStefano Zampini   }
808d65f70fdSStefano Zampini 
809d65f70fdSStefano Zampini   if (!csorted) {
810d65f70fdSStefano Zampini     if (isrow == iscol) {
811d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
812d65f70fdSStefano Zampini       iscol_s = isrow_s;
813d65f70fdSStefano Zampini     } else {
814d65f70fdSStefano Zampini       const PetscInt *idxs;
815d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
816d65f70fdSStefano Zampini 
817d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
818d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
819d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
820d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
821d65f70fdSStefano Zampini       }
822d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
823d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
824d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
825d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
826d65f70fdSStefano Zampini       }
827d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
828d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
829d65f70fdSStefano Zampini     }
830d65f70fdSStefano Zampini   } else {
831d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
832d65f70fdSStefano Zampini     iscol_s = iscol;
833d65f70fdSStefano Zampini   }
834d65f70fdSStefano Zampini 
835b96c3477SStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,reuse,&work_mat);CHKERRQ(ierr);
836d65f70fdSStefano Zampini 
837d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
838d65f70fdSStefano Zampini     Mat      new_mat;
839d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
840d65f70fdSStefano Zampini 
841d65f70fdSStefano Zampini     if (!rsorted) {
842d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
843d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
844d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
845d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
846d65f70fdSStefano Zampini       }
847d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
848d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
849d65f70fdSStefano Zampini     } else {
850d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
851d65f70fdSStefano Zampini     }
852d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
853d65f70fdSStefano Zampini 
854d65f70fdSStefano Zampini     if (!csorted) {
855d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
856d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
857d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
858d65f70fdSStefano Zampini       } else {
859d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
860d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
861d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
862d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
863d65f70fdSStefano Zampini         }
864d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
865d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
866d65f70fdSStefano Zampini       }
867d65f70fdSStefano Zampini     } else {
868d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
869d65f70fdSStefano Zampini     }
870d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
871d65f70fdSStefano Zampini 
872d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
873d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
874d65f70fdSStefano Zampini     work_mat[0] = new_mat;
875d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
876d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
877d65f70fdSStefano Zampini   }
878d65f70fdSStefano Zampini 
879d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
880d65f70fdSStefano Zampini   *B = work_mat[0];
881d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
882d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
883d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
884d65f70fdSStefano Zampini   PetscFunctionReturn(0);
885d65f70fdSStefano Zampini }
886d65f70fdSStefano Zampini 
887d65f70fdSStefano Zampini #undef __FUNCT__
8885e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
8895e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
890aa0d41d4SStefano Zampini {
891aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8925e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
893d65f70fdSStefano Zampini   Mat            new_mat;
8945e8657edSStefano Zampini   IS             is_local,is_global;
895d65f70fdSStefano Zampini   PetscInt       local_size;
896d65f70fdSStefano Zampini   PetscBool      isseqaij;
897aa0d41d4SStefano Zampini   PetscErrorCode ierr;
898aa0d41d4SStefano Zampini 
899aa0d41d4SStefano Zampini   PetscFunctionBegin;
900aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
9015e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
9025e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
903906d46d4SStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(matis->mapping,is_local,&is_global);CHKERRQ(ierr);
904906d46d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
905b96c3477SStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,MAT_INITIAL_MATRIX,&new_mat);CHKERRQ(ierr);
906906d46d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
907906d46d4SStefano Zampini 
908906d46d4SStefano Zampini   /* check */
909906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
910906d46d4SStefano Zampini     Vec       x,x_change;
911906d46d4SStefano Zampini     PetscReal error;
912906d46d4SStefano Zampini 
9135e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
914906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
9155e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
9165e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9175e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
918d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
9195e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9205e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
921906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
922906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
923906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
924906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
925906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
926906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
927906d46d4SStefano Zampini   }
928906d46d4SStefano Zampini 
92922d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
9309b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
93122d5777bSStefano Zampini   if (isseqaij) {
932d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
933aa0d41d4SStefano Zampini   } else {
934aa0d41d4SStefano Zampini     Mat work_mat;
935aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
936d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
937aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
938aa0d41d4SStefano Zampini   }
939d65f70fdSStefano Zampini   ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
94045a1bb75SStefano Zampini   /*
94145a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
942d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
94345a1bb75SStefano Zampini   */
944d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
945aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
946aa0d41d4SStefano Zampini }
947aa0d41d4SStefano Zampini 
948aa0d41d4SStefano Zampini #undef __FUNCT__
949a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
9508ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
951a64d13efSStefano Zampini {
952a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
953a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
9548ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
955e9189074SStefano Zampini   PetscInt       *aux_array1,*aux_array2,*is_indices,*idx_R_local;
9563a50541eSStefano Zampini   PetscInt       n_vertices,i,j,n_R,n_D,n_B;
9573a50541eSStefano Zampini   PetscInt       vbs,bs;
9584641a718SStefano Zampini   PetscBT        bitmask;
959a64d13efSStefano Zampini   PetscErrorCode ierr;
960a64d13efSStefano Zampini 
961a64d13efSStefano Zampini   PetscFunctionBegin;
962b23d619eSStefano Zampini   /*
963b23d619eSStefano Zampini     No need to setup local scatters if
964b23d619eSStefano Zampini       - primal space is unchanged
965b23d619eSStefano Zampini         AND
966b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
967b23d619eSStefano Zampini         AND
968b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
969b23d619eSStefano Zampini   */
970b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
971f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
972f4ddd8eeSStefano Zampini   }
973f4ddd8eeSStefano Zampini   /* destroy old objects */
974f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
975f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
976f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
977a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
978a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
979e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
9804641a718SStefano Zampini   /* create auxiliary bitmask */
9814641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
9824641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
983e9189074SStefano Zampini     ierr = PetscBTSet(bitmask,pcbddc->primal_indices_local_idxs[i]);CHKERRQ(ierr);
9844641a718SStefano Zampini   }
9853a50541eSStefano Zampini 
986a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
987854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
988a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
9894641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
990a64d13efSStefano Zampini       idx_R_local[n_R] = i;
991a64d13efSStefano Zampini       n_R++;
992a64d13efSStefano Zampini     }
993a64d13efSStefano Zampini   }
9943a50541eSStefano Zampini 
9953a50541eSStefano Zampini   /* Block code */
9963a50541eSStefano Zampini   vbs = 1;
9973a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
9983a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
9993a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
10003a50541eSStefano Zampini     PetscInt  *vary;
10013a50541eSStefano Zampini     /* Verify if the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1002785e854fSJed Brown     ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
10033a50541eSStefano Zampini     ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1004e9189074SStefano Zampini     for (i=0; i<n_vertices; i++) vary[pcbddc->primal_indices_local_idxs[i]/bs]++;
10053a50541eSStefano Zampini     for (i=0; i<n_vertices; i++) {
10063a50541eSStefano Zampini       if (vary[i]!=0 && vary[i]!=bs) {
10073a50541eSStefano Zampini         is_blocked = PETSC_FALSE;
10083a50541eSStefano Zampini         break;
10093a50541eSStefano Zampini       }
10103a50541eSStefano Zampini     }
10113a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
10123a50541eSStefano Zampini       vbs = bs;
10133a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
10143a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
10153a50541eSStefano Zampini       }
10163a50541eSStefano Zampini     }
10173a50541eSStefano Zampini     ierr = PetscFree(vary);CHKERRQ(ierr);
10183a50541eSStefano Zampini   }
10193a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
10203a50541eSStefano Zampini   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1021a64d13efSStefano Zampini 
1022a64d13efSStefano Zampini   /* print some info if requested */
1023a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1024a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1025a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
10260fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1027a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1028a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
10293a50541eSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"r_size = %d, v_size = %d, constraints = %d, local_primal_size = %d\n",n_R,n_vertices,pcbddc->local_primal_size-n_vertices,pcbddc->local_primal_size);CHKERRQ(ierr);
1030a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
1031a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1032a64d13efSStefano Zampini   }
1033a64d13efSStefano Zampini 
1034a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
10353a50541eSStefano Zampini   ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1036854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1037854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1038a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10394641a718SStefano Zampini   for (i=0; i<n_D; i++) {
10404641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
10414641a718SStefano Zampini   }
1042a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1043a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
10444641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
10454641a718SStefano Zampini       aux_array1[j++] = i;
1046a64d13efSStefano Zampini     }
1047a64d13efSStefano Zampini   }
1048a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1049a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1050a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
10514641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
10524641a718SStefano Zampini       aux_array2[j++] = i;
1053a64d13efSStefano Zampini     }
1054a64d13efSStefano Zampini   }
1055a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1056a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1057a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1058a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1059a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1060a64d13efSStefano Zampini 
10618eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
1062785e854fSJed Brown     ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1063a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
10644641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
10654641a718SStefano Zampini         aux_array1[j++] = i;
1066a64d13efSStefano Zampini       }
1067a64d13efSStefano Zampini     }
1068a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1069a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1070a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1071a64d13efSStefano Zampini   }
10724641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
10733a50541eSStefano Zampini   ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1074a64d13efSStefano Zampini   PetscFunctionReturn(0);
1075a64d13efSStefano Zampini }
1076a64d13efSStefano Zampini 
1077304d26faSStefano Zampini 
1078304d26faSStefano Zampini #undef __FUNCT__
1079304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1080684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1081304d26faSStefano Zampini {
1082304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1083304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1084304d26faSStefano Zampini   PC             pc_temp;
1085304d26faSStefano Zampini   Mat            A_RR;
1086f4ddd8eeSStefano Zampini   MatReuse       reuse;
1087304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1088304d26faSStefano Zampini   PetscReal      value;
1089af732b37SStefano Zampini   PetscInt       n_D,n_R,ibs,mbs;
10909577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1091304d26faSStefano Zampini   PetscErrorCode ierr;
1092e604994aSStefano Zampini   /* prefixes stuff */
1093312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1094e604994aSStefano Zampini   size_t         len;
1095304d26faSStefano Zampini 
1096304d26faSStefano Zampini   PetscFunctionBegin;
1097304d26faSStefano Zampini 
1098e604994aSStefano Zampini   /* compute prefixes */
1099e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1100e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1101e604994aSStefano Zampini   if (!pcbddc->current_level) {
1102e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1103e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1104e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1105e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1106e604994aSStefano Zampini   } else {
1107e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1108312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1109e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1110e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1111312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1112312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
111334d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
111434d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1115e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1116e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1117e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1118e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1119e604994aSStefano Zampini   }
1120e604994aSStefano Zampini 
1121304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1122684f6988SStefano Zampini   if (dirichlet) {
1123ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
11248ce42a96SStefano Zampini     ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
1125304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1126304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1127304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1128304d26faSStefano Zampini       /* default */
1129304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1130e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
11319577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1132304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
11339577ea80SStefano Zampini       if (issbaij) {
11349577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
11359577ea80SStefano Zampini       } else {
1136304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
11379577ea80SStefano Zampini       }
1138304d26faSStefano Zampini       /* Allow user's customization */
1139304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1140304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1141304d26faSStefano Zampini     }
1142d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1143304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1144304d26faSStefano Zampini     if (!n_D) {
1145304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1146304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1147304d26faSStefano Zampini     }
1148304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1149304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1150304d26faSStefano Zampini     /* set ksp_D into pcis data */
1151304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1152304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1153304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1154684f6988SStefano Zampini   }
1155304d26faSStefano Zampini 
1156304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1157684f6988SStefano Zampini   A_RR = 0;
1158684f6988SStefano Zampini   if (neumann) {
1159f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
11608ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1161f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1162f4ddd8eeSStefano Zampini       PetscInt nn_R;
116381d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1164f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1165f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1166f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1167f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1168f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1169f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1170f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1171727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1172f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1173f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1174f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1175f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1176f4ddd8eeSStefano Zampini         }
1177f4ddd8eeSStefano Zampini       }
1178f4ddd8eeSStefano Zampini       /* last check */
1179d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1180f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1181f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1182f4ddd8eeSStefano Zampini       }
1183f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1184f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1185f4ddd8eeSStefano Zampini     }
1186f4ddd8eeSStefano Zampini     /* extract A_RR */
1187af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1188af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
11893a50541eSStefano Zampini     if (ibs != mbs) {
1190af732b37SStefano Zampini       Mat newmat;
1191af732b37SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
1192f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1193af732b37SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
1194af732b37SStefano Zampini     } else {
1195f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1196af732b37SStefano Zampini     }
1197f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1198304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1199304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1200304d26faSStefano Zampini       /* default */
1201304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1202e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1203304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
12049577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
12059577ea80SStefano Zampini       if (issbaij) {
12069577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
12079577ea80SStefano Zampini       } else {
1208304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
12099577ea80SStefano Zampini       }
1210304d26faSStefano Zampini       /* Allow user's customization */
1211304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1212304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1213304d26faSStefano Zampini     }
1214d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1215304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1216304d26faSStefano Zampini     if (!n_R) {
1217304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1218304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1219304d26faSStefano Zampini     }
1220304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1221304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1222684f6988SStefano Zampini   }
1223304d26faSStefano Zampini 
1224304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
12250fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1226684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1227684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1228684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1229684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1230684f6988SStefano Zampini     }
1231684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
12320fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
12330fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
12340fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
12350fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
12360fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1237304d26faSStefano Zampini       /* need to be adapted? */
1238b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1239b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1240b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1241304d26faSStefano Zampini       /* print info */
1242304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1243e604994aSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Dirichlet solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_D))->prefix,value);CHKERRQ(ierr);
1244304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1245304d26faSStefano Zampini       }
1246b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
12478ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
1248304d26faSStefano Zampini       }
1249684f6988SStefano Zampini     }
1250684f6988SStefano Zampini     if (neumann) { /* Neumann */
12510fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
12520fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
12530fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
12540fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
12550fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1256304d26faSStefano Zampini       /* need to be adapted? */
1257b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1258b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1259304d26faSStefano Zampini       /* print info */
1260304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1261e604994aSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d infinity error for Neumann solve (%s) = % 1.14e \n",PetscGlobalRank,((PetscObject)(pcbddc->ksp_R))->prefix,value);CHKERRQ(ierr);
1262304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1263304d26faSStefano Zampini       }
1264b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
12658ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
1266304d26faSStefano Zampini       }
12670fccc4e9SStefano Zampini     }
1268684f6988SStefano Zampini   }
1269304d26faSStefano Zampini   /* free Neumann problem's matrix */
1270304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1271304d26faSStefano Zampini   PetscFunctionReturn(0);
1272304d26faSStefano Zampini }
1273304d26faSStefano Zampini 
1274304d26faSStefano Zampini #undef __FUNCT__
1275ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
127620c7b377SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec rhs, Vec sol, Vec work, PetscBool applytranspose)
1277674ae819SStefano Zampini {
1278674ae819SStefano Zampini   PetscErrorCode ierr;
1279674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1280674ae819SStefano Zampini 
1281674ae819SStefano Zampini   PetscFunctionBegin;
128220c7b377SStefano Zampini   if (applytranspose) {
1283674ae819SStefano Zampini     if (pcbddc->local_auxmat1) {
128420c7b377SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,rhs,work);CHKERRQ(ierr);
128520c7b377SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,work,rhs,rhs);CHKERRQ(ierr);
128620c7b377SStefano Zampini     }
128720c7b377SStefano Zampini     ierr = KSPSolveTranspose(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
128820c7b377SStefano Zampini   } else {
128920c7b377SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
129020c7b377SStefano Zampini     if (pcbddc->local_auxmat1) {
129120c7b377SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,sol,work);CHKERRQ(ierr);
129220c7b377SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,work,sol,sol);CHKERRQ(ierr);
129320c7b377SStefano Zampini     }
1294674ae819SStefano Zampini   }
1295674ae819SStefano Zampini   PetscFunctionReturn(0);
1296674ae819SStefano Zampini }
1297674ae819SStefano Zampini 
1298dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1299674ae819SStefano Zampini #undef __FUNCT__
1300674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1301dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1302674ae819SStefano Zampini {
1303674ae819SStefano Zampini   PetscErrorCode ierr;
1304674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1305674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1306674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1307674ae819SStefano Zampini 
1308674ae819SStefano Zampini   PetscFunctionBegin;
1309dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1310dc359a40SStefano Zampini   if (applytranspose) {
1311674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
13128eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1313dc359a40SStefano Zampini   } else {
1314674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1315674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
131615aaf578SStefano Zampini   }
131712edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
131812edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
131912edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
132012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
132112edc857SStefano Zampini 
13229f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
132312edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
132412edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
132512edc857SStefano Zampini     if (applytranspose) {
132612edc857SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
132712edc857SStefano Zampini     } else {
132812edc857SStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
132912edc857SStefano Zampini     }
133012edc857SStefano Zampini   }
1331674ae819SStefano Zampini 
1332674ae819SStefano Zampini   /* Local solution on R nodes */
13339f00e9b4SStefano Zampini   if (pcis->n) {
1334674ae819SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1335674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1336674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13378eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1338674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1339674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1340674ae819SStefano Zampini     }
134120c7b377SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcbddc->vec1_R,pcbddc->vec2_R,pcbddc->vec1_C,applytranspose);CHKERRQ(ierr);
1342674ae819SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1343674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1344674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13458eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1346674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1347674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1348674ae819SStefano Zampini     }
13499f00e9b4SStefano Zampini   }
1350674ae819SStefano Zampini 
13519f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
13529f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
135312edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1354674ae819SStefano Zampini 
1355674ae819SStefano Zampini   /* Sum contributions from two levels */
1356dc359a40SStefano Zampini   if (applytranspose) {
1357dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1358dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1359dc359a40SStefano Zampini   } else {
1360674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
13618eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1362dc359a40SStefano Zampini   }
1363674ae819SStefano Zampini   PetscFunctionReturn(0);
1364674ae819SStefano Zampini }
1365674ae819SStefano Zampini 
136612edc857SStefano Zampini /* TODO: the following two function can be optimized using VecPlaceArray whenever possible and using overlap flag */
1367674ae819SStefano Zampini #undef __FUNCT__
1368674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
136912edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1370674ae819SStefano Zampini {
1371674ae819SStefano Zampini   PetscErrorCode ierr;
1372674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
137312edc857SStefano Zampini   PetscScalar    *array,*array2;
137412edc857SStefano Zampini   Vec            from,to;
1375674ae819SStefano Zampini 
1376674ae819SStefano Zampini   PetscFunctionBegin;
137712edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
137812edc857SStefano Zampini     from = pcbddc->coarse_vec;
137912edc857SStefano Zampini     to = pcbddc->vec1_P;
138012edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
138112edc857SStefano Zampini       Vec tvec;
138212edc857SStefano Zampini       PetscInt lsize;
138312edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
138412edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
138512edc857SStefano Zampini       ierr = VecGetArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
138612edc857SStefano Zampini       ierr = VecGetArray(from,&array2);CHKERRQ(ierr);
138712edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
138812edc857SStefano Zampini       ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
138912edc857SStefano Zampini       ierr = VecRestoreArray(from,&array2);CHKERRQ(ierr);
139012edc857SStefano Zampini     }
139112edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
139212edc857SStefano Zampini     from = pcbddc->vec1_P;
139312edc857SStefano Zampini     to = pcbddc->coarse_vec;
139412edc857SStefano Zampini   }
139512edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1396674ae819SStefano Zampini   PetscFunctionReturn(0);
1397674ae819SStefano Zampini }
1398674ae819SStefano Zampini 
1399674ae819SStefano Zampini #undef __FUNCT__
1400674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
140112edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1402674ae819SStefano Zampini {
1403674ae819SStefano Zampini   PetscErrorCode ierr;
1404674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
140512edc857SStefano Zampini   PetscScalar    *array,*array2;
140612edc857SStefano Zampini   Vec            from,to;
1407674ae819SStefano Zampini 
1408674ae819SStefano Zampini   PetscFunctionBegin;
140912edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
141012edc857SStefano Zampini     from = pcbddc->coarse_vec;
141112edc857SStefano Zampini     to = pcbddc->vec1_P;
141212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
141312edc857SStefano Zampini     from = pcbddc->vec1_P;
141412edc857SStefano Zampini     to = pcbddc->coarse_vec;
141512edc857SStefano Zampini   }
141612edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
141712edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
141812edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
141912edc857SStefano Zampini       Vec tvec;
142012edc857SStefano Zampini       PetscInt lsize;
142112edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
142212edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
142312edc857SStefano Zampini       ierr = VecGetArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
142412edc857SStefano Zampini       ierr = VecGetArray(tvec,&array2);CHKERRQ(ierr);
142512edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
142612edc857SStefano Zampini       ierr = VecRestoreArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
142712edc857SStefano Zampini       ierr = VecRestoreArray(tvec,&array2);CHKERRQ(ierr);
142812edc857SStefano Zampini     }
142912edc857SStefano Zampini   }
1430674ae819SStefano Zampini   PetscFunctionReturn(0);
1431674ae819SStefano Zampini }
1432674ae819SStefano Zampini 
1433984c4197SStefano Zampini /* uncomment for testing purposes */
1434984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1435674ae819SStefano Zampini #undef __FUNCT__
1436674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1437674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1438674ae819SStefano Zampini {
1439674ae819SStefano Zampini   PetscErrorCode    ierr;
1440674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1441674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1442674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1443984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1444674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1445984c4197SStefano Zampini   /* one and zero */
1446984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1447984c4197SStefano Zampini   /* space to store constraints and their local indices */
1448984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1449984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1450984c4197SStefano Zampini   /* iterators */
1451984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1452984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1453984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1454984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1455984c4197SStefano Zampini   /* near null space stuff */
1456674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1457674ae819SStefano Zampini   const Vec         *nearnullvecs;
1458674ae819SStefano Zampini   Vec               *localnearnullsp;
1459984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1460984c4197SStefano Zampini   PetscInt          nnsp_size;
1461984c4197SStefano Zampini   PetscScalar       *array;
1462984c4197SStefano Zampini   /* BLAS integers */
1463e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1464e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1465c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1466984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1467242a89d7SStefano Zampini   PetscBool         skip_lapack;
1468984c4197SStefano Zampini   PetscScalar       *work;
1469984c4197SStefano Zampini   PetscReal         *singular_vals;
1470984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1471984c4197SStefano Zampini   PetscReal         *rwork;
1472674ae819SStefano Zampini #endif
1473984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1474e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1475984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1476b7d8b9f8SStefano Zampini #else
1477b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1478b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1479984c4197SStefano Zampini #endif
1480727cdba6SStefano Zampini   /* reuse */
1481727cdba6SStefano Zampini   PetscInt          olocal_primal_size;
1482727cdba6SStefano Zampini   PetscInt          *oprimal_indices_local_idxs;
1483984c4197SStefano Zampini   /* change of basis */
1484984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
1485a717540cSStefano Zampini   PetscBool         boolforchange,qr_needed;
1486a717540cSStefano Zampini   PetscBT           touched,change_basis,qr_needed_idx;
1487984c4197SStefano Zampini   /* auxiliary stuff */
148839e2fb2aSStefano Zampini   PetscInt          *nnz,*is_indices,*aux_primal_numbering_B;
1489911cabfeSStefano Zampini   PetscInt          ncc,*gidxs,*permutation,*temp_indices_to_constraint_work;
1490911cabfeSStefano Zampini   PetscScalar       *temp_quadrature_constraint_work;
1491984c4197SStefano Zampini   /* some quantities */
149245a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
1493984c4197SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint,max_constraints,temp_constraints;
1494984c4197SStefano Zampini 
1495674ae819SStefano Zampini 
1496674ae819SStefano Zampini   PetscFunctionBegin;
14978e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
14988e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
14998e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1500674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
1501d06fc5fdSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
1502d06fc5fdSStefano Zampini   /* free unneeded index sets */
1503d06fc5fdSStefano Zampini   if (!pcbddc->use_vertices) {
1504d06fc5fdSStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1505674ae819SStefano Zampini   }
1506d06fc5fdSStefano Zampini   if (!pcbddc->use_edges) {
1507d06fc5fdSStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
1508d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1509d06fc5fdSStefano Zampini     }
1510d06fc5fdSStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1511d06fc5fdSStefano Zampini     n_ISForEdges = 0;
1512d06fc5fdSStefano Zampini   }
1513d06fc5fdSStefano Zampini   if (!pcbddc->use_faces) {
1514d06fc5fdSStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
1515d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1516d06fc5fdSStefano Zampini     }
1517d06fc5fdSStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1518d06fc5fdSStefano Zampini     n_ISForFaces = 0;
1519d06fc5fdSStefano Zampini   }
1520d06fc5fdSStefano Zampini   /* HACKS (the following two blocks of code) */
1521b9b85e73SStefano Zampini   if (!ISForVertices && pcbddc->NullSpace && !pcbddc->user_ChangeOfBasisMatrix) {
1522b8ffe317SStefano Zampini     pcbddc->use_change_of_basis = PETSC_TRUE;
1523d06fc5fdSStefano Zampini     if (!ISForEdges) {
1524d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = PETSC_TRUE;
1525d06fc5fdSStefano Zampini     }
1526b8ffe317SStefano Zampini   }
152798a51de6SStefano Zampini   if (pcbddc->NullSpace) {
152898a51de6SStefano Zampini     /* use_change_of_basis should be consistent among processors */
1529d06fc5fdSStefano Zampini     PetscBool tbool[2],gbool[2];
1530d06fc5fdSStefano Zampini     tbool [0] = pcbddc->use_change_of_basis;
1531d06fc5fdSStefano Zampini     tbool [1] = pcbddc->use_change_on_faces;
1532d06fc5fdSStefano Zampini     ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1533d06fc5fdSStefano Zampini     pcbddc->use_change_of_basis = gbool[0];
1534d06fc5fdSStefano Zampini     pcbddc->use_change_on_faces = gbool[1];
153598a51de6SStefano Zampini   }
1536984c4197SStefano Zampini   /* print some info */
1537674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
15380fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1539674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1540674ae819SStefano Zampini     i = 0;
1541674ae819SStefano Zampini     if (ISForVertices) {
1542674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1543674ae819SStefano Zampini     }
1544674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1545674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
154615aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1547674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1548674ae819SStefano Zampini   }
1549674ae819SStefano Zampini   /* check if near null space is attached to global mat */
1550674ae819SStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1551674ae819SStefano Zampini   if (nearnullsp) {
1552674ae819SStefano Zampini     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1553f4ddd8eeSStefano Zampini     /* remove any stored info */
1554f4ddd8eeSStefano Zampini     ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1555f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1556f4ddd8eeSStefano Zampini     /* store information for BDDC solver reuse */
1557f4ddd8eeSStefano Zampini     ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
1558f4ddd8eeSStefano Zampini     pcbddc->onearnullspace = nearnullsp;
1559473ba861SJed Brown     ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1560f4ddd8eeSStefano Zampini     for (i=0;i<nnsp_size;i++) {
1561f4ddd8eeSStefano Zampini       ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
1562f4ddd8eeSStefano Zampini     }
1563984c4197SStefano Zampini   } else { /* if near null space is not provided BDDC uses constants by default */
1564984c4197SStefano Zampini     nnsp_size = 0;
1565674ae819SStefano Zampini     nnsp_has_cnst = PETSC_TRUE;
1566674ae819SStefano Zampini   }
1567984c4197SStefano Zampini   /* get max number of constraints on a single cc */
1568984c4197SStefano Zampini   max_constraints = nnsp_size;
1569984c4197SStefano Zampini   if (nnsp_has_cnst) max_constraints++;
1570984c4197SStefano Zampini 
1571674ae819SStefano Zampini   /*
1572674ae819SStefano Zampini        Evaluate maximum storage size needed by the procedure
1573674ae819SStefano Zampini        - temp_indices will contain start index of each constraint stored as follows
1574911cabfeSStefano 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
1575911cabfeSStefano 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
1576911cabfeSStefano Zampini        - temp_quadrature_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the scalars representing the constraint itself
1577674ae819SStefano Zampini                                                                                                                                                          */
1578674ae819SStefano Zampini   total_counts = n_ISForFaces+n_ISForEdges;
1579984c4197SStefano Zampini   total_counts *= max_constraints;
1580674ae819SStefano Zampini   n_vertices = 0;
1581674ae819SStefano Zampini   if (ISForVertices) {
1582674ae819SStefano Zampini     ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1583674ae819SStefano Zampini   }
1584674ae819SStefano Zampini   total_counts += n_vertices;
1585854ce69bSBarry Smith   ierr = PetscMalloc1(total_counts+1,&temp_indices);CHKERRQ(ierr);
15864641a718SStefano Zampini   ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1587674ae819SStefano Zampini   total_counts = 0;
1588674ae819SStefano Zampini   max_size_of_constraint = 0;
1589674ae819SStefano Zampini   for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1590674ae819SStefano Zampini     if (i<n_ISForEdges) {
1591674ae819SStefano Zampini       used_IS = &ISForEdges[i];
1592674ae819SStefano Zampini     } else {
1593674ae819SStefano Zampini       used_IS = &ISForFaces[i-n_ISForEdges];
1594674ae819SStefano Zampini     }
1595674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1596674ae819SStefano Zampini     total_counts += j;
1597674ae819SStefano Zampini     max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1598674ae819SStefano Zampini   }
1599984c4197SStefano Zampini   total_counts *= max_constraints;
1600674ae819SStefano Zampini   total_counts += n_vertices;
1601906d46d4SStefano Zampini   ierr = PetscMalloc3(total_counts,&temp_quadrature_constraint,total_counts,&temp_indices_to_constraint,total_counts,&temp_indices_to_constraint_B);CHKERRQ(ierr);
1602984c4197SStefano Zampini   /* get local part of global near null space vectors */
1603785e854fSJed Brown   ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
1604984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1605984c4197SStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1606984c4197SStefano Zampini     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1607984c4197SStefano Zampini     ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1608984c4197SStefano Zampini   }
1609674ae819SStefano Zampini 
1610242a89d7SStefano Zampini   /* whether or not to skip lapack calls */
1611242a89d7SStefano Zampini   skip_lapack = PETSC_TRUE;
1612a773dcb8SStefano Zampini   if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
1613242a89d7SStefano Zampini 
16148f1c130eSStefano Zampini   /* allocate some auxiliary stuff */
16158f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
16168f1c130eSStefano Zampini     ierr = PetscMalloc4(max_size_of_constraint,&gidxs,max_size_of_constraint,&permutation,max_size_of_constraint,&temp_indices_to_constraint_work,max_size_of_constraint,&temp_quadrature_constraint_work);CHKERRQ(ierr);
16178f1c130eSStefano Zampini   }
16188f1c130eSStefano Zampini 
1619984c4197SStefano Zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1620a773dcb8SStefano Zampini   if (!skip_lapack) {
1621674ae819SStefano Zampini     PetscScalar temp_work;
1622911cabfeSStefano Zampini 
1623674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1624984c4197SStefano Zampini     /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1625785e854fSJed Brown     ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
1626785e854fSJed Brown     ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
1627785e854fSJed Brown     ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
1628674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1629785e854fSJed Brown     ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
1630674ae819SStefano Zampini #endif
1631674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1632c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1633c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1634674ae819SStefano Zampini     lwork = -1;
1635674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1636674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1637c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1638674ae819SStefano Zampini #else
1639c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1640674ae819SStefano Zampini #endif
1641674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1642984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1643674ae819SStefano Zampini #else /* on missing GESVD */
1644674ae819SStefano Zampini     /* SVD */
1645674ae819SStefano Zampini     PetscInt max_n,min_n;
1646674ae819SStefano Zampini     max_n = max_size_of_constraint;
1647984c4197SStefano Zampini     min_n = max_constraints;
1648984c4197SStefano Zampini     if (max_size_of_constraint < max_constraints) {
1649674ae819SStefano Zampini       min_n = max_size_of_constraint;
1650984c4197SStefano Zampini       max_n = max_constraints;
1651674ae819SStefano Zampini     }
1652785e854fSJed Brown     ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
1653674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1654785e854fSJed Brown     ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
1655674ae819SStefano Zampini #endif
1656674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1657674ae819SStefano Zampini     lwork = -1;
1658e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1659e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1660b7d8b9f8SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1661674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1662674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1663e310c8b4SStefano 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));
1664674ae819SStefano Zampini #else
1665e310c8b4SStefano 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));
1666674ae819SStefano Zampini #endif
1667674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1668984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1669984c4197SStefano Zampini #endif /* on missing GESVD */
1670674ae819SStefano Zampini     /* Allocate optimal workspace */
1671674ae819SStefano Zampini     ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1672854ce69bSBarry Smith     ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
1673674ae819SStefano Zampini   }
1674674ae819SStefano Zampini   /* Now we can loop on constraining sets */
1675674ae819SStefano Zampini   total_counts = 0;
1676674ae819SStefano Zampini   temp_indices[0] = 0;
1677674ae819SStefano Zampini   /* vertices */
1678674ae819SStefano Zampini   if (ISForVertices) {
1679674ae819SStefano Zampini     ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1680674ae819SStefano Zampini     if (nnsp_has_cnst) { /* consider all vertices */
168139e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
1682674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1683674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1684674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1685674ae819SStefano Zampini         total_counts++;
1686674ae819SStefano Zampini       }
1687674ae819SStefano Zampini     } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1688984c4197SStefano Zampini       PetscBool used_vertex;
1689674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1690674ae819SStefano Zampini         used_vertex = PETSC_FALSE;
1691674ae819SStefano Zampini         k = 0;
1692674ae819SStefano Zampini         while (!used_vertex && k<nnsp_size) {
1693984c4197SStefano Zampini           ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1694984c4197SStefano Zampini           if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1695674ae819SStefano Zampini             temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1696674ae819SStefano Zampini             temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1697674ae819SStefano Zampini             temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1698674ae819SStefano Zampini             total_counts++;
1699674ae819SStefano Zampini             used_vertex = PETSC_TRUE;
1700674ae819SStefano Zampini           }
1701984c4197SStefano Zampini           ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1702674ae819SStefano Zampini           k++;
1703674ae819SStefano Zampini         }
1704674ae819SStefano Zampini       }
1705674ae819SStefano Zampini     }
1706674ae819SStefano Zampini     ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1707674ae819SStefano Zampini     n_vertices = total_counts;
1708674ae819SStefano Zampini   }
1709984c4197SStefano Zampini 
1710674ae819SStefano Zampini   /* edges and faces */
1711911cabfeSStefano Zampini   for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
1712911cabfeSStefano Zampini     if (ncc<n_ISForEdges) {
1713911cabfeSStefano Zampini       used_IS = &ISForEdges[ncc];
1714984c4197SStefano Zampini       boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1715674ae819SStefano Zampini     } else {
1716911cabfeSStefano Zampini       used_IS = &ISForFaces[ncc-n_ISForEdges];
1717984c4197SStefano Zampini       boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1718674ae819SStefano Zampini     }
1719674ae819SStefano Zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1720674ae819SStefano Zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1721674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1722674ae819SStefano Zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1723984c4197SStefano Zampini     /* change of basis should not be performed on local periodic nodes */
1724984c4197SStefano Zampini     if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1725674ae819SStefano Zampini     if (nnsp_has_cnst) {
17265b08dc53SStefano Zampini       PetscScalar quad_value;
1727674ae819SStefano Zampini       temp_constraints++;
1728a773dcb8SStefano Zampini       if (!pcbddc->use_nnsp_true) {
1729674ae819SStefano Zampini         quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1730a773dcb8SStefano Zampini       } else {
1731a773dcb8SStefano Zampini         quad_value = 1.0;
1732a773dcb8SStefano Zampini       }
173339e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1734674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1735674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1736674ae819SStefano Zampini       }
1737911cabfeSStefano Zampini       /* sort by global ordering if using lapack subroutines */
17388f1c130eSStefano Zampini       if (!skip_lapack || pcbddc->use_qr_single) {
1739911cabfeSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1740911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1741911cabfeSStefano Zampini           permutation[j]=j;
1742911cabfeSStefano Zampini         }
1743911cabfeSStefano Zampini         ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1744911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1745911cabfeSStefano Zampini           temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1746911cabfeSStefano Zampini           temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1747911cabfeSStefano Zampini         }
1748911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1749911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1750911cabfeSStefano Zampini       }
1751674ae819SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1752674ae819SStefano Zampini       total_counts++;
1753674ae819SStefano Zampini     }
1754674ae819SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1755984c4197SStefano Zampini       PetscReal real_value;
1756984c4197SStefano Zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
175739e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1758674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1759984c4197SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
1760674ae819SStefano Zampini       }
1761984c4197SStefano Zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1762984c4197SStefano Zampini       /* check if array is null on the connected component */
1763e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1764e310c8b4SStefano Zampini       PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
17655b08dc53SStefano Zampini       if (real_value > 0.0) { /* keep indices and values */
1766911cabfeSStefano Zampini         /* sort by global ordering if using lapack subroutines */
17678f1c130eSStefano Zampini         if (!skip_lapack || pcbddc->use_qr_single) {
1768911cabfeSStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1769911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1770911cabfeSStefano Zampini             permutation[j]=j;
1771911cabfeSStefano Zampini           }
1772911cabfeSStefano Zampini           ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1773911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1774911cabfeSStefano Zampini             temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1775911cabfeSStefano Zampini             temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1776911cabfeSStefano Zampini           }
1777911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1778911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1779911cabfeSStefano Zampini         }
1780674ae819SStefano Zampini         temp_constraints++;
1781674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1782674ae819SStefano Zampini         total_counts++;
1783674ae819SStefano Zampini       }
1784674ae819SStefano Zampini     }
1785674ae819SStefano Zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
178645a1bb75SStefano Zampini     valid_constraints = temp_constraints;
1787eb97c9d2SStefano Zampini     if (!pcbddc->use_nnsp_true && temp_constraints) {
1788a773dcb8SStefano Zampini       if (temp_constraints == 1) { /* just normalize the constraint */
1789a773dcb8SStefano Zampini         PetscScalar norm;
1790a773dcb8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1791a773dcb8SStefano Zampini         PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
1792a773dcb8SStefano Zampini         norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
1793a773dcb8SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
1794a773dcb8SStefano Zampini       } else { /* perform SVD */
1795984c4197SStefano Zampini         PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
1796674ae819SStefano Zampini 
1797674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1798984c4197SStefano Zampini         /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
1799984c4197SStefano Zampini            POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
1800984c4197SStefano Zampini            -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
1801984c4197SStefano Zampini               the constraints basis will differ (by a complex factor with absolute value equal to 1)
1802984c4197SStefano Zampini               from that computed using LAPACKgesvd
1803984c4197SStefano Zampini            -> This is due to a different computation of eigenvectors in LAPACKheev
1804984c4197SStefano Zampini            -> The quality of the POD-computed basis will be the same */
1805984c4197SStefano Zampini         ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
1806674ae819SStefano Zampini         /* Store upper triangular part of correlation matrix */
1807e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1808984c4197SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1809674ae819SStefano Zampini         for (j=0;j<temp_constraints;j++) {
1810674ae819SStefano Zampini           for (k=0;k<j+1;k++) {
1811e310c8b4SStefano 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));
1812674ae819SStefano Zampini           }
1813674ae819SStefano Zampini         }
1814e310c8b4SStefano Zampini         /* compute eigenvalues and eigenvectors of correlation matrix */
1815e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1816e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
1817674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1818c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
1819674ae819SStefano Zampini #else
1820c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
1821674ae819SStefano Zampini #endif
1822674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1823984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
1824984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
1825674ae819SStefano Zampini         j = 0;
1826984c4197SStefano Zampini         while (j < temp_constraints && singular_vals[j] < tol) j++;
1827674ae819SStefano Zampini         total_counts = total_counts-j;
182845a1bb75SStefano Zampini         valid_constraints = temp_constraints-j;
1829e310c8b4SStefano Zampini         /* scale and copy POD basis into used quadrature memory */
1830c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1831c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1832c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
1833c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1834c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
1835c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
1836674ae819SStefano Zampini         if (j<temp_constraints) {
1837984c4197SStefano Zampini           PetscInt ii;
1838984c4197SStefano Zampini           for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
1839674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1840c4303822SStefano 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));
1841674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1842984c4197SStefano Zampini           for (k=0;k<temp_constraints-j;k++) {
1843674ae819SStefano Zampini             for (ii=0;ii<size_of_constraint;ii++) {
1844984c4197SStefano 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];
1845674ae819SStefano Zampini             }
1846674ae819SStefano Zampini           }
1847674ae819SStefano Zampini         }
1848674ae819SStefano Zampini #else  /* on missing GESVD */
1849e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1850e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1851b7d8b9f8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1852674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1853674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1854e310c8b4SStefano 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));
1855674ae819SStefano Zampini #else
1856e310c8b4SStefano 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));
1857674ae819SStefano Zampini #endif
1858984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
1859674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1860984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
1861e310c8b4SStefano Zampini         k = temp_constraints;
1862e310c8b4SStefano Zampini         if (k > size_of_constraint) k = size_of_constraint;
1863674ae819SStefano Zampini         j = 0;
1864e310c8b4SStefano Zampini         while (j < k && singular_vals[k-j-1] < tol) j++;
186545a1bb75SStefano Zampini         valid_constraints = k-j;
1866911cabfeSStefano Zampini         total_counts = total_counts-temp_constraints+valid_constraints;
1867984c4197SStefano Zampini #endif /* on missing GESVD */
1868674ae819SStefano Zampini       }
1869a773dcb8SStefano Zampini     }
187045a1bb75SStefano Zampini     /* setting change_of_basis flag is safe now */
187145a1bb75SStefano Zampini     if (boolforchange) {
187245a1bb75SStefano Zampini       for (j=0;j<valid_constraints;j++) {
187345a1bb75SStefano Zampini         PetscBTSet(change_basis,total_counts-j-1);
187445a1bb75SStefano Zampini       }
187545a1bb75SStefano Zampini     }
1876674ae819SStefano Zampini   }
1877674ae819SStefano Zampini   /* free index sets of faces, edges and vertices */
1878674ae819SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
1879674ae819SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1880674ae819SStefano Zampini   }
1881d06fc5fdSStefano Zampini   if (n_ISForFaces) {
1882674ae819SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1883d06fc5fdSStefano Zampini   }
1884674ae819SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
1885674ae819SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1886674ae819SStefano Zampini   }
1887d06fc5fdSStefano Zampini   if (n_ISForEdges) {
1888674ae819SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1889d06fc5fdSStefano Zampini   }
1890674ae819SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
189139e2fb2aSStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
18925e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
189339e2fb2aSStefano Zampini   if (i != temp_indices[total_counts]) {
189439e2fb2aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
189539e2fb2aSStefano Zampini   }
1896674ae819SStefano Zampini 
1897984c4197SStefano Zampini   /* free workspace */
18988f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
1899911cabfeSStefano Zampini     ierr = PetscFree4(gidxs,permutation,temp_indices_to_constraint_work,temp_quadrature_constraint_work);CHKERRQ(ierr);
19008f1c130eSStefano Zampini   }
19018f1c130eSStefano Zampini   if (!skip_lapack) {
1902984c4197SStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
1903984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1904984c4197SStefano Zampini     ierr = PetscFree(rwork);CHKERRQ(ierr);
1905984c4197SStefano Zampini #endif
1906984c4197SStefano Zampini     ierr = PetscFree(singular_vals);CHKERRQ(ierr);
1907984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1908984c4197SStefano Zampini     ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
1909984c4197SStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
1910984c4197SStefano Zampini #endif
1911984c4197SStefano Zampini   }
1912984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1913984c4197SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1914984c4197SStefano Zampini   }
1915984c4197SStefano Zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
1916984c4197SStefano Zampini 
1917727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
1918984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
1919674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
1920727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
1921984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
1922674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
1923984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
1924674ae819SStefano Zampini 
1925674ae819SStefano Zampini   /* Create constraint matrix */
1926674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
1927674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
1928674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1929674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
1930984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
1931984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
1932785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
1933984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
1934984c4197SStefano 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 */
1935785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
1936984c4197SStefano Zampini   /* auxiliary stuff for basis change */
1937785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
19384641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
1939984c4197SStefano Zampini 
1940984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
1941984c4197SStefano Zampini   total_primal_vertices=0;
1942984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
1943674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1944984c4197SStefano Zampini     if (size_of_constraint == 1) {
19454641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
1946984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
1947984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
1948984c4197SStefano Zampini       total_primal_vertices++;
19494641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
1950984c4197SStefano Zampini       PetscInt min_loc,min_index;
1951984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
1952984c4197SStefano Zampini       /* find first untouched local node */
1953674ae819SStefano Zampini       k = 0;
19544641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
1955984c4197SStefano Zampini       min_index = global_indices[k];
1956984c4197SStefano Zampini       min_loc = k;
1957984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
1958984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
1959984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
19604641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
1961984c4197SStefano Zampini           min_index = global_indices[k];
1962984c4197SStefano Zampini           min_loc = k;
1963674ae819SStefano Zampini         }
1964674ae819SStefano Zampini       }
19654641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
1966984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
1967984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
1968984c4197SStefano Zampini       total_primal_vertices++;
1969984c4197SStefano Zampini     }
1970984c4197SStefano Zampini   }
1971a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
1972a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
1973a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
1974a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
1975a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
1976fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
1977a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
1978a717540cSStefano Zampini         j = 0;
1979a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
1980a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
1981a717540cSStefano Zampini             j++;
1982a717540cSStefano Zampini           }
1983a717540cSStefano Zampini         }
1984a717540cSStefano Zampini         /* found more than one primal dof on the cc */
1985a717540cSStefano Zampini         if (j > 1) {
1986a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
1987a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
1988a717540cSStefano Zampini         }
1989fa434743SStefano Zampini       } else {
1990fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
1991fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
1992fa434743SStefano Zampini       }
1993a717540cSStefano Zampini     }
1994a717540cSStefano Zampini   }
1995984c4197SStefano Zampini   /* free workspace */
1996984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
199745a1bb75SStefano Zampini 
1998674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
1999a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
2000984c4197SStefano Zampini 
2001984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
2002785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2003984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
2004984c4197SStefano Zampini   j=total_primal_vertices;
2005984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
20064641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2007674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2008674ae819SStefano Zampini       j++;
2009674ae819SStefano Zampini     }
2010674ae819SStefano Zampini   }
2011674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2012674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2013674ae819SStefano Zampini   /* set values in constraint matrix */
2014984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
2015984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2016674ae819SStefano Zampini   }
2017984c4197SStefano Zampini   total_counts = total_primal_vertices;
2018984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
20194641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2020674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2021674ae819SStefano 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);
2022674ae819SStefano Zampini       total_counts++;
2023674ae819SStefano Zampini     }
2024674ae819SStefano Zampini   }
2025674ae819SStefano Zampini   /* assembling */
2026674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2027674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2028984c4197SStefano Zampini   /*
202945a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2030984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2031984c4197SStefano Zampini   */
2032674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2033674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2034026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2035984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2036026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
2037026de310SStefano Zampini     PetscInt     primal_counter;
2038984c4197SStefano Zampini     /* working stuff for GEQRF */
203981d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2040984c4197SStefano Zampini     PetscBLASInt lqr_work;
2041984c4197SStefano Zampini     /* working stuff for UNGQR */
2042984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2043984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2044984c4197SStefano Zampini     /* working stuff for TRTRS */
2045984c4197SStefano Zampini     PetscScalar  *trs_rhs;
20463f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2047984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2048984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2049984c4197SStefano Zampini     PetscScalar  *start_vals;
2050984c4197SStefano Zampini     /* working stuff for values insertion */
20514641a718SStefano Zampini     PetscBT      is_primal;
2052906d46d4SStefano Zampini     /* matrix sizes */
2053906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2054906d46d4SStefano Zampini     /* work array for nonzeros */
2055906d46d4SStefano Zampini     PetscScalar  *nnz_array;
2056906d46d4SStefano Zampini     /* temporary change of basis */
2057906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2058906d46d4SStefano Zampini     /* auxiliary work for global change of basis */
2059906d46d4SStefano Zampini     Vec          nnz_vec;
206022bc73bbSStefano Zampini     PetscInt     *idxs_I,*idxs_B,*idxs_all,*d_nnz,*o_nnz;
2061906d46d4SStefano Zampini     PetscInt     nvtxs,*xadj,*adjncy,*idxs_mapped;
2062906d46d4SStefano Zampini     PetscScalar  *vals;
2063906d46d4SStefano Zampini     PetscBool    done;
2064984c4197SStefano Zampini 
2065906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2066906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
2067906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2068906d46d4SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2069906d46d4SStefano Zampini 
2070906d46d4SStefano Zampini     /* nonzeros for local mat */
2071785e854fSJed Brown     ierr = PetscMalloc1(pcis->n_B,&nnz);CHKERRQ(ierr);
2072a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) nnz[i]=1;
2073a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2074a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2075a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2076a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2077a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2078a717540cSStefano Zampini         } else {
2079a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = 2;
2080a717540cSStefano Zampini           /* get local primal index on the cc */
2081a717540cSStefano Zampini           j = 0;
2082a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2083a717540cSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2084a717540cSStefano Zampini         }
2085a717540cSStefano Zampini       }
2086a717540cSStefano Zampini     }
2087906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2088a717540cSStefano Zampini     /* Set initial identity in the matrix */
2089a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2090906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2091a717540cSStefano Zampini     }
2092a717540cSStefano Zampini 
2093a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2094a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2095a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2096a717540cSStefano Zampini     }
2097a717540cSStefano Zampini 
2098a717540cSStefano Zampini 
2099a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2100a717540cSStefano Zampini     /*
2101a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2102a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2103a717540cSStefano Zampini 
2104a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2105a717540cSStefano Zampini 
2106a6b551f4SStefano Zampini           - Using the following block transformation if there is only a primal dof on the cc (and -pc_bddc_use_qr_single is not specified)
2107a6b551f4SStefano Zampini 
2108a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2109a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2110a717540cSStefano Zampini             |              ...                        |
2111a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2112a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2113a717540cSStefano Zampini 
2114a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2115a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2116a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2117a6b551f4SStefano Zampini 
2118a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2119a717540cSStefano Zampini     */
2120a717540cSStefano Zampini     if (qr_needed) {
2121984c4197SStefano Zampini       /* space to store Q */
2122854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2123984c4197SStefano Zampini       /* first we issue queries for optimal work */
21243f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
21253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
21263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2127984c4197SStefano Zampini       lqr_work = -1;
21283f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2129984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2130984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2131785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2132984c4197SStefano Zampini       lgqr_work = -1;
21333f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
21343f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
21353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
21363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
21373f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
21383f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2139984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2140984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2141785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2142984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2143785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2144984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2145785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2146a717540cSStefano Zampini       /* allocating workspace for check */
2147a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2148785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2149a717540cSStefano Zampini       }
2150a717540cSStefano Zampini     }
2151984c4197SStefano Zampini     /* array to store whether a node is primal or not */
21524641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2153473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
21545e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
215539e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
215639e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
21574641a718SStefano Zampini     }
215839e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
215939e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
216039e2fb2aSStefano Zampini     }
216139e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2162984c4197SStefano Zampini 
2163a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2164026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2165026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2166026de310SStefano Zampini     primal_counter = total_counts;
2167026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2168026de310SStefano Zampini       primal_dofs = 1;
21694641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2170026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2171026de310SStefano 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]]) {
2172026de310SStefano Zampini           primal_dofs++;
2173674ae819SStefano Zampini         }
2174984c4197SStefano Zampini         /* get constraint info */
2175026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2176984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2177984c4197SStefano Zampini 
2178984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2179a717540cSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Constraints %d to %d (incl) need a change of basis (size %d)\n",total_counts,total_counts+primal_dofs-1,size_of_constraint);CHKERRQ(ierr);
2180674ae819SStefano Zampini         }
2181984c4197SStefano Zampini 
2182fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2183a717540cSStefano Zampini 
2184a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2185a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2186a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2187a717540cSStefano Zampini           }
2188984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2189026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2190984c4197SStefano Zampini 
2191984c4197SStefano Zampini           /* compute QR decomposition of constraints */
21923f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
21933f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
21943f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2195674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21963f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2197984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2198674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2199984c4197SStefano Zampini 
2200984c4197SStefano Zampini           /* explictly compute R^-T */
2201984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2202984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
22033f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
22043f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
22053f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
22063f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2207984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
22083f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2209984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2210984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2211984c4197SStefano Zampini 
2212a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
22133f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
22143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
22153f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
22163f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2217984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
22183f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2219984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2220984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2221984c4197SStefano Zampini 
2222984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2223984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2224984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
22253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
22263f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
22273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
22283f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
22293f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
22303f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2231984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2232c4303822SStefano 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));
2233984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2234026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2235984c4197SStefano Zampini 
2236984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2237026de310SStefano Zampini           start_rows = &temp_indices_to_constraint_B[temp_indices[total_counts]];
2238984c4197SStefano Zampini           /* insert cols for primal dofs */
2239984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2240984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2241026de310SStefano Zampini             start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2242906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2243984c4197SStefano Zampini           }
2244984c4197SStefano Zampini           /* insert cols for dual dofs */
2245984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
22464641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2247984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2248026de310SStefano Zampini               start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2249906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2250984c4197SStefano Zampini               j++;
2251674ae819SStefano Zampini             }
2252674ae819SStefano Zampini           }
2253984c4197SStefano Zampini 
2254984c4197SStefano Zampini           /* check change of basis */
2255984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2256984c4197SStefano Zampini             PetscInt   ii,jj;
2257984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2258c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2259c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2260c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2261c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2262c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2263c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2264984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2265c4303822SStefano 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));
2266984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2267984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2268984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2269984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2270984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2271674ae819SStefano Zampini               }
2272674ae819SStefano Zampini             }
2273984c4197SStefano Zampini             if (!valid_qr) {
227422d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2275984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2276984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2277984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2278984c4197SStefano 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]));
2279674ae819SStefano Zampini                   }
2280984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2281984c4197SStefano 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]));
2282984c4197SStefano Zampini                   }
2283984c4197SStefano Zampini                 }
2284984c4197SStefano Zampini               }
2285674ae819SStefano Zampini             } else {
228622d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2287674ae819SStefano Zampini             }
2288674ae819SStefano Zampini           }
2289a717540cSStefano Zampini         } else { /* simple transformation block */
2290a717540cSStefano Zampini           PetscInt    row,col;
2291a6b551f4SStefano Zampini           PetscScalar val,norm;
2292a6b551f4SStefano Zampini 
2293a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2294a6b551f4SStefano Zampini           PetscStackCallBLAS("BLASdot",norm = BLASdot_(&Blas_N,temp_quadrature_constraint+temp_indices[total_counts],&Blas_one,temp_quadrature_constraint+temp_indices[total_counts],&Blas_one));
2295a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2296a717540cSStefano Zampini             row = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2297a717540cSStefano Zampini             if (!PetscBTLookup(is_primal,row)) {
2298a717540cSStefano Zampini               col = temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2299906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2300a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2301a717540cSStefano Zampini             } else {
2302a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2303a717540cSStefano Zampini                 col = temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2304a717540cSStefano Zampini                 if (row != col) {
2305a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2306a717540cSStefano Zampini                 } else {
2307a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2308a717540cSStefano Zampini                 }
2309906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2310a717540cSStefano Zampini               }
2311a717540cSStefano Zampini             }
2312a717540cSStefano Zampini           }
231398a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
231422d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2315a717540cSStefano Zampini           }
2316674ae819SStefano Zampini         }
2317026de310SStefano Zampini         /* increment primal counter */
2318026de310SStefano Zampini         primal_counter += primal_dofs;
2319984c4197SStefano Zampini       } else {
2320984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2321026de310SStefano 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);
2322674ae819SStefano Zampini         }
2323674ae819SStefano Zampini       }
2324026de310SStefano Zampini       /* increment constraint counter total_counts */
2325026de310SStefano Zampini       total_counts += primal_dofs;
2326674ae819SStefano Zampini     }
2327a717540cSStefano Zampini 
2328a717540cSStefano Zampini     /* free workspace */
2329a717540cSStefano Zampini     if (qr_needed) {
2330984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2331984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2332984c4197SStefano Zampini       }
2333984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2334984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2335984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2336984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2337984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2338674ae819SStefano Zampini     }
2339a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2340906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2341906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2342906d46d4SStefano Zampini 
2343906d46d4SStefano Zampini     /* assembling of global change of variable */
2344906d46d4SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2345906d46d4SStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2346906d46d4SStefano Zampini     ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2347906d46d4SStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2348906d46d4SStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2349906d46d4SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->ChangeOfBasisMatrix,matis->mapping,matis->mapping);CHKERRQ(ierr);
2350906d46d4SStefano Zampini 
2351906d46d4SStefano Zampini     /* nonzeros (overestimated) */
2352906d46d4SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nnz_vec);CHKERRQ(ierr);
2353906d46d4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(nnz_vec,matis->mapping);CHKERRQ(ierr);
2354906d46d4SStefano Zampini     ierr = PetscMalloc2(pcis->n,&nnz_array,pcis->n,&idxs_all);CHKERRQ(ierr);
2355906d46d4SStefano Zampini     for (i=0;i<pcis->n;i++) {
2356906d46d4SStefano Zampini       nnz_array[i] = 1.0;
2357906d46d4SStefano Zampini       idxs_all[i] = i;
2358906d46d4SStefano Zampini     }
2359906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2360906d46d4SStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2361906d46d4SStefano Zampini       nnz_array[idxs_B[i]] = nnz[i];
2362906d46d4SStefano Zampini     }
2363a5187659SStefano Zampini     if (pcis->n) {
2364906d46d4SStefano Zampini       ierr = VecSetValuesLocal(nnz_vec,pcis->n,idxs_all,nnz_array,INSERT_VALUES);CHKERRQ(ierr);
2365a5187659SStefano Zampini     }
2366906d46d4SStefano Zampini     ierr = VecAssemblyBegin(nnz_vec);CHKERRQ(ierr);
2367906d46d4SStefano Zampini     ierr = VecAssemblyEnd(nnz_vec);CHKERRQ(ierr);
2368906d46d4SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2369906d46d4SStefano Zampini     ierr = PetscFree2(nnz_array,idxs_all);CHKERRQ(ierr);
237022bc73bbSStefano Zampini     ierr = PetscMalloc2(local_size,&d_nnz,local_size,&o_nnz);CHKERRQ(ierr);
2371906d46d4SStefano Zampini     ierr = VecGetArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2372906d46d4SStefano Zampini     for (i=0;i<local_size;i++) {
237322bc73bbSStefano Zampini       d_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),local_size);
237422bc73bbSStefano Zampini       o_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),global_size-local_size);
2375906d46d4SStefano Zampini     }
2376906d46d4SStefano Zampini     ierr = VecRestoreArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2377906d46d4SStefano Zampini     ierr = VecDestroy(&nnz_vec);CHKERRQ(ierr);
237822bc73bbSStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,d_nnz,0,o_nnz);CHKERRQ(ierr);
237922bc73bbSStefano Zampini     ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
2380906d46d4SStefano Zampini 
2381906d46d4SStefano Zampini     /* Set identity on dirichlet dofs */
2382906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2383906d46d4SStefano Zampini     for (i=0;i<pcis->n-pcis->n_B;i++) {
2384906d46d4SStefano Zampini       PetscScalar one=1.0;
2385906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,idxs_I+i,1,idxs_I+i,&one,INSERT_VALUES);CHKERRQ(ierr);
2386906d46d4SStefano Zampini     }
2387906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2388906d46d4SStefano Zampini 
2389906d46d4SStefano Zampini     /* Set values at interface dofs */
2390906d46d4SStefano Zampini     done = PETSC_TRUE;
2391906d46d4SStefano Zampini     ierr = MatGetRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2392906d46d4SStefano Zampini     if (!done) {
2393906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2394906d46d4SStefano Zampini     }
2395906d46d4SStefano Zampini     ierr = MatSeqAIJGetArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2396906d46d4SStefano Zampini     ierr = PetscMalloc1(xadj[nvtxs],&idxs_mapped);CHKERRQ(ierr);
23975e8657edSStefano Zampini     ierr = ISLocalToGlobalMappingApply(pcis->BtoNmap,xadj[nvtxs],adjncy,idxs_mapped);CHKERRQ(ierr);
2398906d46d4SStefano Zampini     for (i=0;i<nvtxs;i++) {
2399906d46d4SStefano Zampini       PetscInt    row,*cols,ncols;
2400906d46d4SStefano Zampini       PetscScalar *mat_vals;
2401906d46d4SStefano Zampini 
2402906d46d4SStefano Zampini       row = idxs_B[i];
2403906d46d4SStefano Zampini       ncols = xadj[i+1]-xadj[i];
2404906d46d4SStefano Zampini       cols = idxs_mapped+xadj[i];
2405906d46d4SStefano Zampini       mat_vals = vals+xadj[i];
2406906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,&row,ncols,cols,mat_vals,INSERT_VALUES);CHKERRQ(ierr);
2407906d46d4SStefano Zampini     }
2408906d46d4SStefano Zampini     ierr = MatRestoreRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2409906d46d4SStefano Zampini     if (!done) {
2410906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2411906d46d4SStefano Zampini     }
2412906d46d4SStefano Zampini     ierr = MatSeqAIJRestoreArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2413906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2414906d46d4SStefano Zampini     ierr = PetscFree(idxs_mapped);CHKERRQ(ierr);
2415674ae819SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2416674ae819SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2417906d46d4SStefano Zampini 
2418906d46d4SStefano Zampini     /* check */
2419906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2420906d46d4SStefano Zampini       PetscReal error;
2421906d46d4SStefano Zampini       Vec       x,x_change;
2422906d46d4SStefano Zampini 
2423906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2424906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2425906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2426906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2427906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2428906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2429906d46d4SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
2430906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2431906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2432906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2433906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2434906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2435906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2436906d46d4SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on B: %1.6e\n",error);CHKERRQ(ierr);
2437906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2438906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2439906d46d4SStefano Zampini     }
2440b96c3477SStefano Zampini 
2441b96c3477SStefano Zampini     /* adapt sub_schurs computed (if any) */
2442b96c3477SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
2443b96c3477SStefano Zampini       PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
2444b96c3477SStefano Zampini       if (sub_schurs->n_subs_par_g) {
2445*b7eb3628SStefano Zampini         SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Change of basis with deluxe scaling and parallel problems still needs to be implemented");
2446b96c3477SStefano Zampini       }
2447b96c3477SStefano Zampini       if (sub_schurs->S_Ej_all) {
2448b96c3477SStefano Zampini         Mat S_1,S_2,tmat;
2449b96c3477SStefano Zampini         ierr = MatGetSubMatrixUnsorted(localChangeOfBasisMatrix,sub_schurs->is_Ej_all,sub_schurs->is_Ej_all,MAT_INITIAL_MATRIX,&tmat);CHKERRQ(ierr);
2450b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_1);CHKERRQ(ierr);
2451b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->S_Ej_all);CHKERRQ(ierr);
2452b96c3477SStefano Zampini         sub_schurs->S_Ej_all = S_1;
2453b96c3477SStefano Zampini         ierr = MatPtAP(sub_schurs->sum_S_Ej_all,tmat,MAT_INITIAL_MATRIX,1.0,&S_2);CHKERRQ(ierr);
2454b96c3477SStefano Zampini         ierr = MatDestroy(&sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
2455b96c3477SStefano Zampini         sub_schurs->sum_S_Ej_all = S_2;
2456b96c3477SStefano Zampini         ierr = MatDestroy(&tmat);CHKERRQ(ierr);
2457b96c3477SStefano Zampini       }
2458b96c3477SStefano Zampini     }
2459906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2460906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2461b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2462b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2463b9b85e73SStefano Zampini   }
2464906d46d4SStefano Zampini 
2465906d46d4SStefano Zampini   /* set up change of basis context */
2466906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2467906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2468906d46d4SStefano Zampini 
2469906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2470906d46d4SStefano Zampini       PetscInt global_size,local_size;
2471906d46d4SStefano Zampini 
2472906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2473906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2474906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2475906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2476906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2477906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2478906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2479906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2480906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2481906d46d4SStefano Zampini     } else {
2482906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2483906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2484906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2485906d46d4SStefano Zampini     }
2486906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2487906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2488906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2489906d46d4SStefano Zampini     } else {
2490906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2491906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2492906d46d4SStefano Zampini     }
2493906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2494906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2495906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2496906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2497b9b85e73SStefano Zampini   }
2498a717540cSStefano Zampini 
2499727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2500727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) { /* if this is true, I need to check if a new primal space has been introduced */
2501473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2502727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2503727cdba6SStefano Zampini   }
2504727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2505f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2506473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2507727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2508727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2509727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2510727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2511727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2512727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2513e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2514e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2515727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2516727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2517727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2518727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2519c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2520727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2521727cdba6SStefano Zampini   }
2522727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2523727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2524727cdba6SStefano Zampini 
2525a717540cSStefano Zampini   /* flush dbg viewer */
2526b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2527b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2528b8ffe317SStefano Zampini   }
2529a717540cSStefano Zampini 
2530e310c8b4SStefano Zampini   /* free workspace */
2531a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2532a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2533984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
25344641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
2535906d46d4SStefano Zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2536906d46d4SStefano Zampini   ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
2537674ae819SStefano Zampini   PetscFunctionReturn(0);
2538674ae819SStefano Zampini }
2539674ae819SStefano Zampini 
2540674ae819SStefano Zampini #undef __FUNCT__
2541674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2542674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2543674ae819SStefano Zampini {
2544674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2545674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2546674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
254763602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2548674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2549674ae819SStefano Zampini 
2550674ae819SStefano Zampini   PetscFunctionBegin;
25518e61c736SStefano Zampini   /* Reset previously computed graph */
25528e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2553674ae819SStefano Zampini   /* Init local Graph struct */
2554674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2555674ae819SStefano Zampini 
2556575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2557575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2558575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2559575ad6abSStefano Zampini   }
25609577ea80SStefano Zampini 
2561674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
25624d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2563674ae819SStefano Zampini     Mat       mat_adj;
25644d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
25654d379d7bSStefano Zampini     PetscInt  nvtxs;
2566674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2567674ae819SStefano Zampini 
2568674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
25694d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2570674ae819SStefano Zampini     if (!flg_row) {
2571674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2572674ae819SStefano Zampini     }
25734d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
25744d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
2575b96c3477SStefano Zampini       pcbddc->computed_rowadj = PETSC_TRUE;
25764d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
25774d379d7bSStefano Zampini       IS                     is_dummy;
25784d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
25794d379d7bSStefano Zampini       PetscInt               j,sum;
25804d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
25814d379d7bSStefano Zampini       const PetscInt         *idxs;
25824d379d7bSStefano Zampini       PCBDDCGraph            graph;
25834d379d7bSStefano Zampini       PetscBT                is_on_boundary;
25844d379d7bSStefano Zampini 
25854d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
25864d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
25874d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25884d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
25894d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
25904d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
25914d379d7bSStefano Zampini       graph->xadj = xadj;
25924d379d7bSStefano Zampini       graph->adjncy = adjncy;
25934d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
25944d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
25954d379d7bSStefano Zampini 
25964d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
25974d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
25984d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
25994d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
26004d379d7bSStefano Zampini         }
26014d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
26024d379d7bSStefano Zampini       }
26034d379d7bSStefano Zampini 
26044d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
26054d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
26064d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
26074d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
26084d379d7bSStefano Zampini       }
26094d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
26104d379d7bSStefano Zampini 
26114d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
26124d379d7bSStefano Zampini       sum = 0;
26134d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
26144d379d7bSStefano Zampini         PetscInt sizecc = 0;
26154d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
26164d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
26174d379d7bSStefano Zampini             sizecc++;
26184d379d7bSStefano Zampini           }
26194d379d7bSStefano Zampini         }
26204d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
26214d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
26224d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
26234d379d7bSStefano Zampini           }
26244d379d7bSStefano Zampini         }
26254d379d7bSStefano Zampini         sum += sizecc*sizecc;
26264d379d7bSStefano Zampini       }
26274d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
26284d379d7bSStefano Zampini       sum = 0;
26294d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
26304d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
26314d379d7bSStefano Zampini         cxadj[i] = sum;
26324d379d7bSStefano Zampini         sum += temp;
26334d379d7bSStefano Zampini       }
26344d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
26354d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
26364d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
26374d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
26384d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
26394d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
26404d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
26414d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
26424d379d7bSStefano Zampini                 sizecc++;
26434d379d7bSStefano Zampini               }
26444d379d7bSStefano Zampini             }
26454d379d7bSStefano Zampini           }
26464d379d7bSStefano Zampini         }
26474d379d7bSStefano Zampini       }
26484d379d7bSStefano Zampini       if (nvtxs) {
26494d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
26504d379d7bSStefano Zampini       } else {
26514d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
26524d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
26534d379d7bSStefano Zampini       }
26544d379d7bSStefano Zampini       graph->xadj = 0;
26554d379d7bSStefano Zampini       graph->adjncy = 0;
26564d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
26574d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
26584d379d7bSStefano Zampini     }
26594d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2660674ae819SStefano Zampini     if (!flg_row) {
2661674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2662674ae819SStefano Zampini     }
2663674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2664674ae819SStefano Zampini   }
2665674ae819SStefano Zampini 
266663602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2667674ae819SStefano Zampini   vertex_size = 1;
266863602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
266963602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
267095ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
267163602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2672a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
267363602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2674674ae819SStefano Zampini       }
267563602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
267663602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
267763602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2678674ae819SStefano Zampini     }
267963602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2680674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
268163602bcaSStefano Zampini   } else {
268263602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
268363602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2684854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
268563602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
268663602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
268763602bcaSStefano Zampini       }
268863602bcaSStefano Zampini     }
2689674ae819SStefano Zampini   }
2690674ae819SStefano Zampini 
2691674ae819SStefano Zampini   /* Setup of Graph */
2692785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2693a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2694785d1243SStefano Zampini   }
2695785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2696a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2697785d1243SStefano Zampini   }
269863602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2699674ae819SStefano Zampini 
2700674ae819SStefano Zampini   /* Graph's connected components analysis */
2701674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2702674ae819SStefano Zampini 
2703674ae819SStefano Zampini   /* print some info to stdout */
2704674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
2705e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
2706674ae819SStefano Zampini   }
2707fb180af4SStefano Zampini 
2708fb180af4SStefano Zampini   /* mark topography has done */
2709fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
2710674ae819SStefano Zampini   PetscFunctionReturn(0);
2711674ae819SStefano Zampini }
2712674ae819SStefano Zampini 
2713674ae819SStefano Zampini #undef __FUNCT__
2714674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
2715f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
2716674ae819SStefano Zampini {
2717674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2718674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
2719674ae819SStefano Zampini   PetscErrorCode ierr;
2720674ae819SStefano Zampini 
2721674ae819SStefano Zampini   PetscFunctionBegin;
2722674ae819SStefano Zampini   n = 0;
2723674ae819SStefano Zampini   vertices = 0;
2724674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2725674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
2726b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2727b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2728b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
2729b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2730b120a5c6SStefano Zampini     }
2731811e8ca2SStefano Zampini     if (vertices_idx) {
2732785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
2733b120a5c6SStefano Zampini       n = 0;
2734674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2735674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2736674ae819SStefano Zampini         if (size_of_constraint == 1) {
2737674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
2738674ae819SStefano Zampini         }
2739674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2740674ae819SStefano Zampini       }
2741674ae819SStefano Zampini     }
2742811e8ca2SStefano Zampini   }
2743674ae819SStefano Zampini   *n_vertices = n;
2744811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
2745674ae819SStefano Zampini   PetscFunctionReturn(0);
2746674ae819SStefano Zampini }
2747674ae819SStefano Zampini 
2748674ae819SStefano Zampini #undef __FUNCT__
2749674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
2750f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
2751674ae819SStefano Zampini {
2752674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2753674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
2754674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
27554641a718SStefano Zampini   PetscBT        touched;
2756674ae819SStefano Zampini   PetscErrorCode ierr;
2757674ae819SStefano Zampini 
2758f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
2759f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
2760f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2761674ae819SStefano Zampini   PetscFunctionBegin;
2762674ae819SStefano Zampini   n = 0;
2763674ae819SStefano Zampini   constraints_index = 0;
2764674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2765674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
2766674ae819SStefano Zampini     max_size_of_constraint = 0;
2767674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2768674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2769674ae819SStefano Zampini       if (size_of_constraint > 1) {
2770674ae819SStefano Zampini         n++;
2771674ae819SStefano Zampini       }
2772674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
2773674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2774674ae819SStefano Zampini     }
2775811e8ca2SStefano Zampini     if (constraints_idx) {
2776785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
2777785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
27784641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
2779674ae819SStefano Zampini       n = 0;
2780674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2781674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2782674ae819SStefano Zampini         if (size_of_constraint > 1) {
2783674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
278482d3d8afSStefano Zampini           /* find first untouched local node */
278582d3d8afSStefano Zampini           j = 0;
27864641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
278782d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
278882d3d8afSStefano Zampini           min_loc = j;
278982d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
279082d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
2791674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
27924641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
2793674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
2794674ae819SStefano Zampini               min_loc = j;
2795674ae819SStefano Zampini             }
2796674ae819SStefano Zampini           }
27974641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
2798674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
2799674ae819SStefano Zampini         }
2800674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2801674ae819SStefano Zampini       }
28024641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2803674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
2804811e8ca2SStefano Zampini     }
2805811e8ca2SStefano Zampini   }
2806674ae819SStefano Zampini   *n_constraints = n;
2807811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
2808674ae819SStefano Zampini   PetscFunctionReturn(0);
2809674ae819SStefano Zampini }
2810674ae819SStefano Zampini 
2811674ae819SStefano Zampini #undef __FUNCT__
2812674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
2813674ae819SStefano 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[])
2814674ae819SStefano Zampini {
2815674ae819SStefano Zampini   Vec            local_vec,global_vec;
2816674ae819SStefano Zampini   IS             seqis,paris;
2817674ae819SStefano Zampini   VecScatter     scatter_ctx;
2818674ae819SStefano Zampini   PetscScalar    *array;
2819674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
2820674ae819SStefano Zampini   PetscScalar    globalsum;
2821674ae819SStefano Zampini   PetscInt       i,j,s;
2822674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
2823674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
2824674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
2825674ae819SStefano Zampini   PetscBool      first_found;
2826674ae819SStefano Zampini   PetscErrorCode ierr;
2827674ae819SStefano Zampini 
2828674ae819SStefano Zampini   PetscFunctionBegin;
2829674ae819SStefano Zampini   /* mpi buffers */
2830b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
2831b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
2832674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
2833785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
2834785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
2835674ae819SStefano Zampini   /* get maximum size of subset */
2836785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
2837674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
2838674ae819SStefano Zampini   max_local = 0;
2839b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2840674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
2841674ae819SStefano Zampini       max_local = temp_global_dofs[i];
2842674ae819SStefano Zampini     }
2843674ae819SStefano Zampini   }
2844b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
2845674ae819SStefano Zampini   max_global++;
2846674ae819SStefano Zampini   max_local = 0;
2847b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2848674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
2849674ae819SStefano Zampini       max_local = local_dofs[i];
2850674ae819SStefano Zampini     }
2851674ae819SStefano Zampini   }
2852674ae819SStefano Zampini   max_local++;
2853674ae819SStefano Zampini   /* allocate workspace */
2854674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
2855674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
2856674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
2857674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
2858674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
2859674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
2860674ae819SStefano Zampini   /* create scatter */
2861674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
2862674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
2863674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
2864674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
2865674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
2866674ae819SStefano Zampini   /* init array */
2867674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
2868674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2869674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2870674ae819SStefano Zampini   if (local_dofs_mult) {
2871674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2872674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
2873674ae819SStefano Zampini     }
2874674ae819SStefano Zampini   } else {
2875674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2876674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
2877674ae819SStefano Zampini     }
2878674ae819SStefano Zampini   }
2879674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2880674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
2881674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2882674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2883674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
28845b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
2885674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
2886674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
2887674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
2888674ae819SStefano Zampini   nlocals = 0;
2889674ae819SStefano Zampini   first_index = -1;
2890674ae819SStefano Zampini   first_found = PETSC_FALSE;
2891674ae819SStefano Zampini   for (i=0;i<s;i++) {
2892b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
2893674ae819SStefano Zampini       first_found = PETSC_TRUE;
2894674ae819SStefano Zampini       first_index = i;
2895674ae819SStefano Zampini     }
28965b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
2897674ae819SStefano Zampini   }
2898674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2899674ae819SStefano Zampini   if (!rank_prec_comm) {
2900674ae819SStefano Zampini     dof_displs[0]=0;
2901674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
2902674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
2903674ae819SStefano Zampini     }
2904674ae819SStefano Zampini   }
2905674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2906674ae819SStefano Zampini   if (first_found) {
2907674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
2908674ae819SStefano Zampini     old_index = first_index;
2909674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
2910b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
2911674ae819SStefano Zampini         array[i] += array[old_index];
2912674ae819SStefano Zampini         old_index = i;
2913674ae819SStefano Zampini       }
2914674ae819SStefano Zampini     }
2915674ae819SStefano Zampini   }
2916674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
2917674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2918674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2919674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2920674ae819SStefano Zampini   /* get global ordering of local dofs */
2921674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2922674ae819SStefano Zampini   if (local_dofs_mult) {
2923674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
29245b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
2925674ae819SStefano Zampini     }
2926674ae819SStefano Zampini   } else {
2927674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
29285b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
2929674ae819SStefano Zampini     }
2930674ae819SStefano Zampini   }
2931674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2932674ae819SStefano Zampini   /* free workspace */
2933674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
2934674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
2935674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
2936674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
2937674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
2938674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
2939674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
2940674ae819SStefano Zampini   PetscFunctionReturn(0);
2941674ae819SStefano Zampini }
29429a7d3425SStefano Zampini 
29439a7d3425SStefano Zampini #undef __FUNCT__
29449a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
29459a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
29469a7d3425SStefano Zampini {
29479a7d3425SStefano Zampini   PetscInt       i,j;
29489a7d3425SStefano Zampini   PetscScalar    *alphas;
29499a7d3425SStefano Zampini   PetscErrorCode ierr;
29509a7d3425SStefano Zampini 
29519a7d3425SStefano Zampini   PetscFunctionBegin;
29529a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
2953785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
29549a7d3425SStefano Zampini   for (i=0;i<n;i++) {
29559a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
29569a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
29579a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
29589a7d3425SStefano Zampini   }
29599a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
29609a7d3425SStefano Zampini   PetscFunctionReturn(0);
29619a7d3425SStefano Zampini }
29629a7d3425SStefano Zampini 
2963e7931f94SStefano Zampini #undef __FUNCT__
296470cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
296528143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
2966e7931f94SStefano Zampini {
2967e7931f94SStefano Zampini   Mat             subdomain_adj;
2968e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
2969e7931f94SStefano Zampini   MatPartitioning partitioner;
2970e7931f94SStefano Zampini   Mat_IS          *matis;
2971e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
2972e7931f94SStefano Zampini   PetscInt        prank;
2973e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
2974e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
2975e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
29763837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
2977e7931f94SStefano Zampini   PetscErrorCode  ierr;
29782b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
2979e7931f94SStefano Zampini   PetscSubcomm    subcomm;
2980a57a6d2fSStefano Zampini 
2981e7931f94SStefano Zampini   PetscFunctionBegin;
29822b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
29832b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
29842b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
2985e7931f94SStefano Zampini 
2986e7931f94SStefano Zampini   /* Get info on mapping */
2987e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
2988e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
2989e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
2990e7931f94SStefano Zampini 
2991e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
2992785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
2993e7931f94SStefano Zampini   xadj[0] = 0;
2994e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
2995785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
2996785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
2997e7931f94SStefano Zampini 
29982b510759SStefano Zampini   if (threshold) {
2999d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
30002b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
3001d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
3002d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
3003d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
3004d023bfaeSStefano Zampini         xadj_count++;
3005e7931f94SStefano Zampini       }
3006e7931f94SStefano Zampini     }
3007d023bfaeSStefano Zampini     xadj[1] = xadj_count;
3008c8587f34SStefano Zampini   } else {
3009e7931f94SStefano Zampini     if (xadj[1]) {
3010e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
3011e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
3012c8587f34SStefano Zampini     }
3013e7931f94SStefano Zampini   }
3014e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
3015e7931f94SStefano Zampini   if (use_square) {
3016e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3017e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3018e7931f94SStefano Zampini     }
3019e7931f94SStefano Zampini   }
3020e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3021e7931f94SStefano Zampini 
30223837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3023e7931f94SStefano Zampini 
3024e7931f94SStefano Zampini   /*
3025e7931f94SStefano Zampini     Restrict work on active processes only.
3026e7931f94SStefano Zampini   */
3027e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3028e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3029e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
30302b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3031d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3032e7931f94SStefano Zampini   if (color) {
3033e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3034e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3035e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3036c8587f34SStefano Zampini   } else {
303728143c3dSStefano Zampini     PetscInt coarsening_ratio;
3038e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
3039785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3040e7931f94SStefano Zampini     prank = rank;
3041e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
30428002ef2cSStefano Zampini     /*
3043e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3044e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3045c8587f34SStefano Zampini     }
30468002ef2cSStefano Zampini     */
3047e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3048e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3049c8587f34SStefano Zampini     }
3050e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3051e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
305222b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3053e7931f94SStefano Zampini 
3054e7931f94SStefano Zampini     /* Partition */
3055e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
3056e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3057e7931f94SStefano Zampini     if (use_vwgt) {
30583837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3059e7931f94SStefano Zampini       v_wgt[0] = local_size;
3060e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3061c8587f34SStefano Zampini     }
306228143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
306328143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
306428143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3065e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3066e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
306722b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3068e7931f94SStefano Zampini 
3069e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
307028143c3dSStefano Zampini     if (contiguous) {
307128143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
307228143c3dSStefano Zampini     } else {
307384ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
307428143c3dSStefano Zampini     }
3075e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3076e7931f94SStefano Zampini     /* clean up */
3077e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
3078e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
3079e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3080e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3081e7931f94SStefano Zampini   }
3082e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3083e7931f94SStefano Zampini 
3084e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3085e7931f94SStefano Zampini   i = 1;
3086e7931f94SStefano Zampini   if (color) i=0;
3087e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3088e7931f94SStefano Zampini 
3089e7931f94SStefano Zampini   /* get back IS */
3090e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3091e7931f94SStefano Zampini   PetscFunctionReturn(0);
3092e7931f94SStefano Zampini }
3093e7931f94SStefano Zampini 
3094e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3095e7931f94SStefano Zampini 
3096e7931f94SStefano Zampini #undef __FUNCT__
3097e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
309828143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3099e7931f94SStefano Zampini {
310070cf5478SStefano Zampini   Mat                    local_mat;
3101e7931f94SStefano Zampini   Mat_IS                 *matis;
3102e7931f94SStefano Zampini   IS                     is_sends_internal;
31039d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
310428143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
31059d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3106e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3107e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3108e7931f94SStefano Zampini   const PetscInt*        is_indices;
3109e7931f94SStefano Zampini   MatType                new_local_type;
3110e7931f94SStefano Zampini   /* buffers */
3111e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
311228143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
31139d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3114e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3115e7931f94SStefano Zampini   /* MPI */
311628143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
311728143c3dSStefano Zampini   PetscSubcomm           subcomm;
3118e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
311928143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
312028143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
312128143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
312228143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
312328143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3124e7931f94SStefano Zampini   PetscErrorCode         ierr;
3125e7931f94SStefano Zampini 
3126e7931f94SStefano Zampini   PetscFunctionBegin;
312728143c3dSStefano Zampini   /* TODO: add missing checks */
312828143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
312928143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
313028143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
313128143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3132e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
313328143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3134e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3135e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3136e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3137e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3138e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
313928143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
314070cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
314170cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
314228143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
314370cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
314470cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
314570cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
314670cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
314770cf5478SStefano Zampini   }
3148e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3149e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3150e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3151e7931f94SStefano Zampini   if (!is_sends) {
315228143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
315328143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
315428143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3155c8587f34SStefano Zampini   } else {
3156e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3157e7931f94SStefano Zampini     is_sends_internal = is_sends;
3158c8587f34SStefano Zampini   }
3159e7931f94SStefano Zampini 
3160e7931f94SStefano Zampini   /* get pointer of MATIS data */
3161e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3162e7931f94SStefano Zampini 
3163e7931f94SStefano Zampini   /* get comm */
3164a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3165e7931f94SStefano Zampini 
3166e7931f94SStefano Zampini   /* compute number of sends */
3167e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3168e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3169e7931f94SStefano Zampini 
3170e7931f94SStefano Zampini   /* compute number of receives */
3171e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3172785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3173e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3174e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3175e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3176e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3177e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3178e7931f94SStefano Zampini 
317928143c3dSStefano Zampini   /* restrict comm if requested */
318028143c3dSStefano Zampini   subcomm = 0;
318128143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
318228143c3dSStefano Zampini   if (restrict_comm) {
318328143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
318428143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
318528143c3dSStefano Zampini     color = 0;
318628143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
318728143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
318828143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
318928143c3dSStefano Zampini     /* check if reuse has been requested */
319028143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
319128143c3dSStefano Zampini       if (*mat_n) {
319228143c3dSStefano Zampini         PetscMPIInt subcommsize2;
319328143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
319428143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
319528143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
319628143c3dSStefano Zampini       } else {
319728143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
319828143c3dSStefano Zampini       }
319928143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
320028143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
320128143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
320228143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
320328143c3dSStefano Zampini       comm_n = subcomm->comm;
320428143c3dSStefano Zampini     }
320528143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
320628143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
320728143c3dSStefano Zampini   } else {
320828143c3dSStefano Zampini     comm_n = comm;
320928143c3dSStefano Zampini   }
321028143c3dSStefano Zampini 
3211e7931f94SStefano Zampini   /* prepare send/receive buffers */
3212785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3213e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3214785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3215e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
321628143c3dSStefano Zampini   if (nis) {
3217854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
321828143c3dSStefano Zampini   }
3219e7931f94SStefano Zampini 
322028143c3dSStefano Zampini   /* Get data from local matrices */
3221e7931f94SStefano Zampini   if (!isdense) {
3222a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3223e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3224e7931f94SStefano Zampini     /*
3225e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3226e7931f94SStefano Zampini        send_buffer_idxs should contain:
3227e7931f94SStefano Zampini        - MatType_PRIVATE type
3228e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3229e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3230e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3231e7931f94SStefano Zampini     */
3232e7931f94SStefano Zampini   } else {
3233e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3234e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3235854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3236e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3237e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3238e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3239e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3240e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3241e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3242e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3243e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3244e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3245c8587f34SStefano Zampini     }
3246c8587f34SStefano Zampini   }
3247e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
324828143c3dSStefano Zampini   /* additional is (if any) */
324928143c3dSStefano Zampini   if (nis) {
325028143c3dSStefano Zampini     PetscMPIInt psum;
325128143c3dSStefano Zampini     PetscInt j;
325228143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
325328143c3dSStefano Zampini       PetscInt plen;
325428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
325528143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
325628143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
325728143c3dSStefano Zampini     }
3258854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
325928143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
326028143c3dSStefano Zampini       PetscInt plen;
326128143c3dSStefano Zampini       const PetscInt *is_array_idxs;
326228143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
326328143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
326428143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
326528143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
326628143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
326728143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
326828143c3dSStefano Zampini     }
326928143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
327028143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
327128143c3dSStefano Zampini     }
327228143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
327328143c3dSStefano Zampini   }
327428143c3dSStefano Zampini 
3275e7931f94SStefano Zampini   buf_size_idxs = 0;
3276e7931f94SStefano Zampini   buf_size_vals = 0;
327728143c3dSStefano Zampini   buf_size_idxs_is = 0;
3278e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3279e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3280e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
328128143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3282e7931f94SStefano Zampini   }
3283785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3284785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
328595ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3286e7931f94SStefano Zampini 
3287e7931f94SStefano Zampini   /* get new tags for clean communications */
3288e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3289e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
329028143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3291e7931f94SStefano Zampini 
3292e7931f94SStefano Zampini   /* allocate for requests */
3293785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3294785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
329595ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3296785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3297785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
329895ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3299e7931f94SStefano Zampini 
3300e7931f94SStefano Zampini   /* communications */
3301e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3302e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
330328143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3304e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3305e7931f94SStefano Zampini     source_dest = onodes[i];
3306e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3307e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3308e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3309e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
331028143c3dSStefano Zampini     if (nis) {
331128143c3dSStefano Zampini       ierr = MPI_Irecv(ptr_idxs_is,olengths_idxs_is[i],MPIU_INT,source_dest,tag_idxs_is,comm,&recv_req_idxs_is[i]);CHKERRQ(ierr);
331228143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
331328143c3dSStefano Zampini     }
3314e7931f94SStefano Zampini   }
3315e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3316e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3317e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3318e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
331928143c3dSStefano Zampini     if (nis) {
332028143c3dSStefano Zampini       ierr = MPI_Isend(send_buffer_idxs_is,ilengths_idxs_is[source_dest],MPIU_INT,source_dest,tag_idxs_is,comm,&send_req_idxs_is[i]);CHKERRQ(ierr);
332128143c3dSStefano Zampini     }
3322e7931f94SStefano Zampini   }
3323e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3324e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3325e7931f94SStefano Zampini 
3326e7931f94SStefano Zampini   /* assemble new l2g map */
3327e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3328e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
33299d30be91SStefano Zampini   new_local_rows = 0;
3330e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
33319d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3332e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3333e7931f94SStefano Zampini   }
33349d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3335e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
33369d30be91SStefano Zampini   new_local_rows = 0;
3337e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
33389d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
33399d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3340e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3341e7931f94SStefano Zampini   }
33429d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
33439d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3344e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3345e7931f94SStefano Zampini 
3346e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3347e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3348e7931f94SStefano Zampini   /* it also assumes that if the block size is set, than it is the same among all local matrices (see checks at the beginning of the function) */
3349e7931f94SStefano Zampini   if (n_recvs) {
335028143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3351e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3352e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3353e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3354e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3355e7931f94SStefano Zampini         break;
3356e7931f94SStefano Zampini       }
3357e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3358e7931f94SStefano Zampini     }
3359e7931f94SStefano Zampini     switch (new_local_type_private) {
336028143c3dSStefano Zampini       case MATDENSE_PRIVATE:
336128143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3362e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3363e7931f94SStefano Zampini           bs = 1;
336428143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
336528143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
336628143c3dSStefano Zampini           bs = 1;
336728143c3dSStefano Zampini         }
3368e7931f94SStefano Zampini         break;
3369e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3370e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3371e7931f94SStefano Zampini         bs = 1;
3372e7931f94SStefano Zampini         break;
3373e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3374e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3375e7931f94SStefano Zampini         break;
3376e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3377e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3378e7931f94SStefano Zampini         break;
3379e7931f94SStefano Zampini       default:
33809d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3381e7931f94SStefano Zampini         break;
3382e7931f94SStefano Zampini     }
338328143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
338428143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
338528143c3dSStefano Zampini     bs = 1;
3386e7931f94SStefano Zampini   }
3387e7931f94SStefano Zampini 
338870cf5478SStefano Zampini   /* create MATIS object if needed */
338970cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3390e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
339128143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
339270cf5478SStefano Zampini   } else {
339370cf5478SStefano Zampini     /* it also destroys the local matrices */
339470cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
339570cf5478SStefano Zampini   }
339670cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3397e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
33989d30be91SStefano Zampini 
33999d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
34009d30be91SStefano Zampini 
34019d30be91SStefano Zampini   /* Global to local map of received indices */
34029d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
34039d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
34049d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
34059d30be91SStefano Zampini 
34069d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
34079d30be91SStefano Zampini   buf_size_idxs = 0;
34089d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
34099d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
34109d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
34119d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
34129d30be91SStefano Zampini   }
34139d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
34149d30be91SStefano Zampini 
34159d30be91SStefano Zampini   /* set preallocation */
34169d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
34179d30be91SStefano Zampini   if (!newisdense) {
34189d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
34199d30be91SStefano Zampini 
34209d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
34219d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
34229d30be91SStefano Zampini     if (n_recvs) {
34239d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
34249d30be91SStefano Zampini     }
34259d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
34269d30be91SStefano Zampini       PetscInt j;
34279d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
34289d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
34299d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
34309d30be91SStefano Zampini         }
34319d30be91SStefano Zampini       } else {
34329d30be91SStefano Zampini         /* TODO */
34339d30be91SStefano Zampini       }
34349d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
34359d30be91SStefano Zampini     }
34369d30be91SStefano Zampini     if (new_local_nnz) {
34379d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
34389d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
34399d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
34409d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
34419d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
34429d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
34439d30be91SStefano Zampini     } else {
34449d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
34459d30be91SStefano Zampini     }
34469d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
34479d30be91SStefano Zampini   } else {
34489d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
34499d30be91SStefano Zampini   }
3450e7931f94SStefano Zampini 
3451e7931f94SStefano Zampini   /* set values */
3452e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
34539d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3454e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3455e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3456e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
34579d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3458e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3459e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3460e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
346128143c3dSStefano Zampini     } else {
346228143c3dSStefano Zampini       /* TODO */
3463e7931f94SStefano Zampini     }
3464e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3465e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3466e7931f94SStefano Zampini   }
3467e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3468e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
346970cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
347070cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34719d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
34729d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3473e7931f94SStefano Zampini 
3474dfd14d43SStefano Zampini #if 0
347528143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3476e7931f94SStefano Zampini     Vec       lvec,rvec;
3477e7931f94SStefano Zampini     PetscReal infty_error;
3478e7931f94SStefano Zampini 
34792a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3480e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3481e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3482e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
348370cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3484e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3485e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3486e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3487e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3488e7931f94SStefano Zampini   }
348928143c3dSStefano Zampini #endif
3490e7931f94SStefano Zampini 
349128143c3dSStefano Zampini   /* assemble new additional is (if any) */
349228143c3dSStefano Zampini   if (nis) {
349328143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
349428143c3dSStefano Zampini 
349528143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3496854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
349728143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
349828143c3dSStefano Zampini     psum = 0;
349928143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
350028143c3dSStefano Zampini       for (j=0;j<nis;j++) {
350128143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
350228143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
350328143c3dSStefano Zampini         psum += plen;
350428143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
350528143c3dSStefano Zampini       }
350628143c3dSStefano Zampini     }
3507854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3508854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
350928143c3dSStefano Zampini     for (i=1;i<nis;i++) {
351028143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
351128143c3dSStefano Zampini     }
351228143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
351328143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
351428143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
351528143c3dSStefano Zampini       for (j=0;j<nis;j++) {
351628143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
351728143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
351828143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
351928143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
352028143c3dSStefano Zampini       }
352128143c3dSStefano Zampini     }
352228143c3dSStefano Zampini     for (i=0;i<nis;i++) {
352328143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
352428143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
352528143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
352628143c3dSStefano Zampini     }
352728143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
352828143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
352928143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
353028143c3dSStefano Zampini   }
3531e7931f94SStefano Zampini   /* free workspace */
353228143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3533e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3534e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3535e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3536e7931f94SStefano Zampini   if (isdense) {
3537e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3538e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3539e7931f94SStefano Zampini   } else {
3540e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3541e7931f94SStefano Zampini   }
354228143c3dSStefano Zampini   if (nis) {
354328143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
354428143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
354528143c3dSStefano Zampini   }
3546e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3547e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
354828143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3549e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3550e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
355128143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3552e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3553e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3554e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3555e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3556e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
355728143c3dSStefano Zampini   if (nis) {
355828143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
355928143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
356028143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
356128143c3dSStefano Zampini   }
356228143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
356328143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
356428143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
356528143c3dSStefano Zampini     for (i=0;i<nis;i++) {
356628143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
356728143c3dSStefano Zampini     }
356828143c3dSStefano Zampini   }
3569e7931f94SStefano Zampini   PetscFunctionReturn(0);
3570e7931f94SStefano Zampini }
3571a57a6d2fSStefano Zampini 
357212edc857SStefano Zampini /* temporary hack into ksp private data structure */
357312edc857SStefano Zampini #include <petsc-private/kspimpl.h>
357412edc857SStefano Zampini 
3575c8587f34SStefano Zampini #undef __FUNCT__
3576c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3577c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3578c8587f34SStefano Zampini {
3579c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3580c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
358120a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
35829881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
358320a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
35846e683305SStefano Zampini   IS                     coarse_is,*isarray;
35856e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
35866e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3587f9eb5b7dSStefano Zampini   PC                     pc_temp;
3588c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3589c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3590f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
35914f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
35926e683305SStefano Zampini   Mat                    t_coarse_mat_is;
35936e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
35946e683305SStefano Zampini   PetscMPIInt            all_procs;
359574e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
359668457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
359722bc73bbSStefano Zampini   PetscScalar            *array;
35989881197aSStefano Zampini   PetscErrorCode         ierr;
3599fdc09c96SStefano Zampini 
3600c8587f34SStefano Zampini   PetscFunctionBegin;
3601c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
360268457ee5SStefano Zampini   if (pcbddc->new_primal_space || pcbddc->coarse_size == -1) { /* a new primal space is present or it is the first initialization, so recompute global numbering */
360368457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3604fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3605fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3606f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3607f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3608f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3609fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3610fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3611727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3612fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3613fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3614fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3615f4ddd8eeSStefano Zampini       }
3616fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3617fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3618f4ddd8eeSStefano Zampini     }
361970cf5478SStefano Zampini     /* reset any subassembling information */
362070cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
36216e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
36226e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3623fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3624f4ddd8eeSStefano Zampini   }
3625c8587f34SStefano Zampini 
36266e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
36272b510759SStefano Zampini   im_active = !!(pcis->n);
36282b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
36296e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
36306e683305SStefano Zampini   void_procs = all_procs-active_procs;
36316e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
363274e2c79eSStefano Zampini   redist = PETSC_FALSE;
363322bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
36346e683305SStefano Zampini     csin_ml = PETSC_TRUE;
36356e683305SStefano Zampini     ncoarse_ml = void_procs;
36366e683305SStefano Zampini     csin_ds = PETSC_TRUE;
36376e683305SStefano Zampini     ncoarse_ds = void_procs;
36386e683305SStefano Zampini   } else {
36396e683305SStefano Zampini     csin_ml = PETSC_FALSE;
36406e683305SStefano Zampini     ncoarse_ml = all_procs;
36416e683305SStefano Zampini     if (void_procs) {
36426e683305SStefano Zampini       csin_ds = PETSC_TRUE;
36436e683305SStefano Zampini       ncoarse_ds = void_procs;
36446e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
36456e683305SStefano Zampini     } else {
364674e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
364774e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
364874e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
364974e2c79eSStefano Zampini         redist = PETSC_TRUE;
365074e2c79eSStefano Zampini       } else {
36516e683305SStefano Zampini         csin_ds = PETSC_FALSE;
36526e683305SStefano Zampini         ncoarse_ds = all_procs;
36536e683305SStefano Zampini       }
36546e683305SStefano Zampini     }
365574e2c79eSStefano Zampini   }
36566e683305SStefano Zampini 
36576e683305SStefano Zampini   /*
36586e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
36596e683305SStefano Zampini     - we have not exceeded the number of levels requested
36606e683305SStefano Zampini     - we can actually subassemble the active processes
36616e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
36626e683305SStefano Zampini   */
36636e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
36646e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
36656e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
36666e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
36676e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3668f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
36692b510759SStefano Zampini     } else {
3670f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3671c8587f34SStefano Zampini     }
3672c8587f34SStefano Zampini   }
36736e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
36746e683305SStefano Zampini   if (multilevel_allowed) {
36756e683305SStefano Zampini     ncoarse = ncoarse_ml;
36766e683305SStefano Zampini     csin = csin_ml;
36776e683305SStefano Zampini   } else {
36786e683305SStefano Zampini     ncoarse = ncoarse_ds;
36796e683305SStefano Zampini     csin = csin_ds;
36806e683305SStefano Zampini   }
3681e7931f94SStefano Zampini 
3682abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3683abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3684abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3685abbbba34SStefano Zampini 
3686abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
368722bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
368822bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
368922bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
369022bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3691b9b85e73SStefano Zampini #if 0
3692b9b85e73SStefano Zampini   {
3693b9b85e73SStefano Zampini     PetscViewer viewer;
3694b9b85e73SStefano Zampini     char filename[256];
3695b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3696b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3697b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3698b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3699b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3700b9b85e73SStefano Zampini   }
3701b9b85e73SStefano Zampini #endif
37026e683305SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)pc),1,PETSC_DECIDE,PETSC_DECIDE,pcbddc->coarse_size,pcbddc->coarse_size,coarse_islg,&t_coarse_mat_is);CHKERRQ(ierr);
37036e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
37046e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
37056e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3706abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
3707abbbba34SStefano Zampini 
37086e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
37096e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
37106e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
37116e683305SStefano Zampini     const PetscInt         *idxs;
37126e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
37136e683305SStefano Zampini 
37146e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
37150be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
37166e683305SStefano Zampini     /* allocate space for temporary storage */
3717854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
3718854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
37196e683305SStefano Zampini     /* allocate for IS array */
37206e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
37216e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
37226e683305SStefano Zampini     nis = nisdofs + nisneu;
3723854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
37246e683305SStefano Zampini     /* dofs splitting */
37256e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
37266e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
37276e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
37286e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
37296e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
37306e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
37316e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
37326e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
37336e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
37346e683305SStefano Zampini     }
37356e683305SStefano Zampini     /* neumann boundaries */
37366e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
37376e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
37386e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
37396e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
37406e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
37416e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
37426e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
37436e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
37446e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
37456e683305SStefano Zampini     }
37466e683305SStefano Zampini     /* free memory */
37476e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
37486e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
37496e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
37506e683305SStefano Zampini   } else {
37516e683305SStefano Zampini     nis = 0;
37526e683305SStefano Zampini     nisdofs = 0;
37536e683305SStefano Zampini     nisneu = 0;
37546e683305SStefano Zampini     isarray = NULL;
37556e683305SStefano Zampini   }
37566e683305SStefano Zampini   /* destroy no longer needed map */
37576e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
37586e683305SStefano Zampini 
37596e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
37606e683305SStefano Zampini   coarse_mat_is = NULL;
37616e683305SStefano Zampini   if (csin) {
37626e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
376374e2c79eSStefano Zampini       if (redist) {
376474e2c79eSStefano Zampini         PetscMPIInt rank;
376574e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
376674e2c79eSStefano Zampini 
376774e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
376874e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
376974e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
377074e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
377174e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
377274e2c79eSStefano Zampini         } else {
377374e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
377474e2c79eSStefano Zampini         }
377574e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
377674e2c79eSStefano Zampini       } else {
37776e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
37786e683305SStefano Zampini         PetscInt *coarse_candidates;
37796e683305SStefano Zampini         const PetscInt* tisindices;
37806e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
3781854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
37826e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
37836e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
37846e683305SStefano Zampini           if (!coarse_candidates[i]) {
37856e683305SStefano Zampini             coarse_candidates[j]=i;
37866e683305SStefano Zampini             j++;
37876e683305SStefano Zampini           }
37886e683305SStefano Zampini         }
37896e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
37906e683305SStefano Zampini         /* get a suitable subassembling pattern */
37916e683305SStefano Zampini         if (csin_type_simple) {
37926e683305SStefano Zampini           PetscMPIInt rank;
37936e683305SStefano Zampini           PetscInt    issize,isidx;
37946e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
37956e683305SStefano Zampini           if (im_active) {
37966e683305SStefano Zampini             issize = 1;
37976e683305SStefano Zampini             isidx = (PetscInt)rank;
37986e683305SStefano Zampini           } else {
37996e683305SStefano Zampini             issize = 0;
38006e683305SStefano Zampini             isidx = -1;
38016e683305SStefano Zampini           }
38026e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
38036e683305SStefano Zampini         } else {
38046e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
38056e683305SStefano Zampini         }
38066e683305SStefano Zampini         if (pcbddc->dbg_flag) {
38076e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38086e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
38096e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
38106e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
38116e683305SStefano Zampini           for (i=0;i<j;i++) {
38126e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
38136e683305SStefano Zampini           }
38146e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
38156e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38166e683305SStefano Zampini         }
38176e683305SStefano Zampini         /* shift the pattern on coarse candidates */
38186e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
38196e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
3820854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
38216e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
38226e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
38236e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
38246e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
38256e683305SStefano Zampini       }
382674e2c79eSStefano Zampini     }
38276e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38286e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38296e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
38306e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
38316e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38326e683305SStefano Zampini     }
38336e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
38346e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
38356e683305SStefano Zampini   } else {
38366e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38376e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38386e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
38396e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38406e683305SStefano Zampini     }
38416e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
38426e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
38436e683305SStefano Zampini   }
38446e683305SStefano Zampini 
38456e683305SStefano Zampini   /* create local to global scatters for coarse problem */
384668457ee5SStefano Zampini   if (compute_vecs) {
38476e683305SStefano Zampini     PetscInt lrows;
38486e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
38496e683305SStefano Zampini     if (coarse_mat_is) {
38506e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
38516e683305SStefano Zampini     } else {
38526e683305SStefano Zampini       lrows = 0;
38536e683305SStefano Zampini     }
38546e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
38556e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
38566e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
38576e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38586e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38596e683305SStefano Zampini   }
38606e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
38616e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
3862c8587f34SStefano Zampini 
3863f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
3864f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
3865f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
3866f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
3867f9eb5b7dSStefano Zampini   } else {
3868f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
3869f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
3870c8587f34SStefano Zampini   }
3871c8587f34SStefano Zampini 
38726e683305SStefano Zampini   /* print some info if requested */
38736e683305SStefano Zampini   if (pcbddc->dbg_flag) {
38746e683305SStefano Zampini     if (!multilevel_allowed) {
38756e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38766e683305SStefano Zampini       if (multilevel_requested) {
38776e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Not enough active processes on level %d (active processes %d, coarsening ratio %d)\n",pcbddc->current_level,active_procs,pcbddc->coarsening_ratio);CHKERRQ(ierr);
38786e683305SStefano Zampini       } else if (pcbddc->max_levels) {
38796e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
38806e683305SStefano Zampini       }
38816e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38826e683305SStefano Zampini     }
38836e683305SStefano Zampini   }
38846e683305SStefano Zampini 
3885f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
38866e683305SStefano Zampini   if (coarse_mat_is) {
38876e683305SStefano Zampini     MatReuse coarse_mat_reuse;
38886a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
38896e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38906e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
38916e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
38926e683305SStefano Zampini     }
3893f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
3894312be037SStefano Zampini       char prefix[256],str_level[16];
3895e604994aSStefano Zampini       size_t len;
38966e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
3897c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3898f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
38995f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
3900c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
39016e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
3902c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3903c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3904e604994aSStefano Zampini       /* prefix */
3905e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
3906e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3907e604994aSStefano Zampini       if (!pcbddc->current_level) {
3908e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3909e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
3910c8587f34SStefano Zampini       } else {
3911e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3912312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3913312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
391434d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3915312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3916e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
3917e604994aSStefano Zampini       }
3918e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
3919f9eb5b7dSStefano Zampini       /* allow user customization */
3920f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
39217e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3922312be037SStefano Zampini     }
3923f9eb5b7dSStefano Zampini 
3924f9eb5b7dSStefano Zampini     /* get some info after set from options */
3925f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3926f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
3927f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
39284f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
39296e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
3930f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3931f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
3932f9eb5b7dSStefano Zampini     }
39334f3a063dSStefano Zampini     if (isredundant) {
39344f3a063dSStefano Zampini       KSP inner_ksp;
39354f3a063dSStefano Zampini       PC inner_pc;
39364f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
39374f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
39384f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
39394f3a063dSStefano Zampini     }
3940f9eb5b7dSStefano Zampini 
39416e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
3942f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
3943f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
3944f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
39456e683305SStefano Zampini     if (nisdofs) {
39466e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
39476e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
39486e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
39491035eff8SStefano Zampini       }
39501035eff8SStefano Zampini     }
39516e683305SStefano Zampini     if (nisneu) {
39526e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
39536e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
39541035eff8SStefano Zampini     }
3955fdc09c96SStefano Zampini 
3956f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
3957fa7f1dd8SStefano Zampini     if (coarse_reuse) {
395881d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
3959fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
39606e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
3961fa7f1dd8SStefano Zampini     } else {
39626e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
3963fa7f1dd8SStefano Zampini     }
3964c8587f34SStefano Zampini     if (isbddc || isnn) {
396522bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
396670cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
396728143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
396822b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
39696e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
39706e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
39716e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
39726e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
397322b6e8a2SStefano Zampini           }
397470cf5478SStefano Zampini         }
39756e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
397670cf5478SStefano Zampini       } else {
397722bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
397822bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
397922bc73bbSStefano Zampini       }
398022bc73bbSStefano Zampini     } else {
39812e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
3982c8587f34SStefano Zampini     }
3983c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
3984c8587f34SStefano Zampini 
3985c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
3986b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
39875a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
3988c8587f34SStefano Zampini 
39896e683305SStefano Zampini     /* set operators */
39905f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
39916e683305SStefano Zampini     if (pcbddc->dbg_flag) {
39926e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
39936e683305SStefano Zampini     }
39946e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
39956e683305SStefano Zampini     coarse_mat = 0;
39966e683305SStefano Zampini   }
39976e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
3998b9b85e73SStefano Zampini #if 0
3999b9b85e73SStefano Zampini   {
4000b9b85e73SStefano Zampini     PetscViewer viewer;
4001b9b85e73SStefano Zampini     char filename[256];
4002b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
4003b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
4004b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
4005b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
4006b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
4007b9b85e73SStefano Zampini   }
4008b9b85e73SStefano Zampini #endif
4009c8587f34SStefano Zampini 
4010c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
4011c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
4012c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
401398a51de6SStefano Zampini   }
401498a51de6SStefano Zampini 
401598a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
401698a51de6SStefano Zampini     Vec crhs,csol;
401798a51de6SStefano Zampini     PetscBool ispreonly;
401898a51de6SStefano Zampini     if (CoarseNullSpace) {
4019c8587f34SStefano Zampini       if (isbddc) {
4020c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4021c8587f34SStefano Zampini       } else {
4022c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
4023c8587f34SStefano Zampini       }
4024c8587f34SStefano Zampini     }
4025f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4026f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4027f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4028f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
40296e683305SStefano Zampini     /* hack */
4030f347579bSStefano Zampini     if (!csol) {
40312a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4032f9eb5b7dSStefano Zampini     }
4033f347579bSStefano Zampini     if (!crhs) {
40342a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4035f347579bSStefano Zampini     }
4036cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4037cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
40386e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4039c8587f34SStefano Zampini       KSP       check_ksp;
40402b510759SStefano Zampini       KSPType   check_ksp_type;
4041c8587f34SStefano Zampini       PC        check_pc;
40426e683305SStefano Zampini       Vec       check_vec,coarse_vec;
40436a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
40442b510759SStefano Zampini       PetscInt  its;
40456e683305SStefano Zampini       PetscBool compute_eigs;
40466e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
40476e683305SStefano Zampini       PetscInt  neigs;
40488e185a42SStefano Zampini       const char *prefix;
4049c8587f34SStefano Zampini 
40502b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
40516e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
405223ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4053f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
40542b510759SStefano Zampini       if (ispreonly) {
40552b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
40566e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
40572b510759SStefano Zampini       } else {
4058cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
40596e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4060c8587f34SStefano Zampini       }
4061c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
40626e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
40636e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
40646e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4065a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4066a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4067a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4068a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4069c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4070c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4071c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4072c8587f34SStefano Zampini       /* create random vec */
40736e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
40746e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4075c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4076c8587f34SStefano Zampini       if (CoarseNullSpace) {
4077c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4078c8587f34SStefano Zampini       }
40796e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4080c8587f34SStefano Zampini       /* solve coarse problem */
40816e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4082c8587f34SStefano Zampini       if (CoarseNullSpace) {
40836e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4084c8587f34SStefano Zampini       }
4085cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
40866e683305SStefano Zampini       if (compute_eigs) {
4087854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4088854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
40896e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
40906e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
40916e683305SStefano Zampini         lambda_min = eigs_r[0];
40926e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
40936e683305SStefano Zampini           if (lambda_max>lambda_min) {
4094cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4095cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4096cbcc2c2aSStefano Zampini           }
4097c8587f34SStefano Zampini         }
4098c8587f34SStefano Zampini       }
4099cbcc2c2aSStefano Zampini 
4100c8587f34SStefano Zampini       /* check coarse problem residual error */
41016e683305SStefano Zampini       if (pcbddc->dbg_flag) {
41026e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
41036e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
41046e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4105c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
41066e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
41076e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4108c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
41096e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
41106e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
41116e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
41126e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
41136e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
41146e683305SStefano Zampini         if (compute_eigs) {
41156e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4116deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4117c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
41186e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
41196e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem eigenvalues (estimated with %d iterations of %s): %1.6e %1.6e (%1.6e %1.6e)\n",its,check_ksp_type,lambda_min,lambda_max,lambda_min_s,lambda_max_s);CHKERRQ(ierr);
41206e683305SStefano Zampini           for (i=0;i<neigs;i++) {
41216e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4122c8587f34SStefano Zampini           }
41236e683305SStefano Zampini         }
41246e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
41256e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
41266e683305SStefano Zampini       }
4127c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
41286e683305SStefano Zampini       if (compute_eigs) {
41296e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
41306e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4131c8587f34SStefano Zampini       }
41326e683305SStefano Zampini     }
41336e683305SStefano Zampini   }
4134cbcc2c2aSStefano Zampini   /* print additional info */
4135cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
41366e683305SStefano Zampini     /* waits until all processes reaches this point */
41376e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4138cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4139cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4140cbcc2c2aSStefano Zampini   }
4141cbcc2c2aSStefano Zampini 
41422b510759SStefano Zampini   /* free memory */
4143c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4144fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4145c8587f34SStefano Zampini   PetscFunctionReturn(0);
4146c8587f34SStefano Zampini }
4147674ae819SStefano Zampini 
4148f34684f1SStefano Zampini #undef __FUNCT__
4149f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4150f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4151f34684f1SStefano Zampini {
4152f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4153f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4154f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4155727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4156727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4157f34684f1SStefano Zampini   PetscErrorCode ierr;
4158f34684f1SStefano Zampini 
4159f34684f1SStefano Zampini   PetscFunctionBegin;
4160f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
416189c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
416289c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4163727cdba6SStefano Zampini   }
4164727cdba6SStefano Zampini   ierr = PCBDDCSubsetNumbering(PetscObjectComm((PetscObject)(pc->pmat)),matis->mapping,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,NULL,&coarse_size,&local_primal_indices);CHKERRQ(ierr);
4165f34684f1SStefano Zampini 
4166f34684f1SStefano Zampini   /* check numbering */
4167f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4168f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4169b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4170f34684f1SStefano Zampini 
4171f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4172f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4173f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
41740fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4175f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4176f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4177727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4178f34684f1SStefano Zampini     }
4179f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4180f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4181f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4182f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4183f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4184f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4185f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4186f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4187f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4188f34684f1SStefano Zampini       if (array[i] == 1.0) {
4189b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4190f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4191f34684f1SStefano Zampini       }
4192f34684f1SStefano Zampini     }
4193b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4194f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4195f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4196f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4197f34684f1SStefano Zampini     }
4198f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4199f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4200f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4201f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4202f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4203f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4204b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4205f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4206f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4207f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4208f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4209727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4210f34684f1SStefano Zampini       }
4211f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4212f34684f1SStefano Zampini     }
4213f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4214b9b85e73SStefano Zampini     if (set_error_reduced) {
4215b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4216b9b85e73SStefano Zampini     }
4217f34684f1SStefano Zampini   }
4218f34684f1SStefano Zampini   /* get back data */
4219f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4220f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4221674ae819SStefano Zampini   PetscFunctionReturn(0);
4222674ae819SStefano Zampini }
4223674ae819SStefano Zampini 
4224e456f2a8SStefano Zampini #undef __FUNCT__
4225e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4226a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4227e456f2a8SStefano Zampini {
4228e456f2a8SStefano Zampini   IS             localis_t;
4229a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4230e456f2a8SStefano Zampini   PetscScalar    *vals;
4231e456f2a8SStefano Zampini   PetscErrorCode ierr;
4232e456f2a8SStefano Zampini 
4233e456f2a8SStefano Zampini   PetscFunctionBegin;
4234a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4235e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4236854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4237e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4238e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4239a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4240a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
42411035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4242a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
42431035eff8SStefano Zampini   }
4244a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4245e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4246e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4247a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4248a7dc3881SStefano Zampini   /* now compute set in local ordering */
4249a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4250a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4251a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4252a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4253a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4254ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4255e456f2a8SStefano Zampini       lsize++;
4256e456f2a8SStefano Zampini     }
4257e456f2a8SStefano Zampini   }
4258854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4259a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4260ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4261e456f2a8SStefano Zampini       idxs[lsize++] = i;
4262e456f2a8SStefano Zampini     }
4263e456f2a8SStefano Zampini   }
4264a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4265a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4266e456f2a8SStefano Zampini   *localis = localis_t;
4267e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4268e456f2a8SStefano Zampini }
4269906d46d4SStefano Zampini 
4270906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4271906d46d4SStefano Zampini #undef __FUNCT__
4272906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4273906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4274906d46d4SStefano Zampini {
4275906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4276906d46d4SStefano Zampini   PetscErrorCode   ierr;
4277906d46d4SStefano Zampini 
4278906d46d4SStefano Zampini   PetscFunctionBegin;
4279906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4280906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4281906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4282906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4283906d46d4SStefano Zampini   PetscFunctionReturn(0);
4284906d46d4SStefano Zampini }
4285906d46d4SStefano Zampini 
4286906d46d4SStefano Zampini #undef __FUNCT__
4287906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4288906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4289906d46d4SStefano Zampini {
4290906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4291906d46d4SStefano Zampini   PetscErrorCode   ierr;
4292906d46d4SStefano Zampini 
4293906d46d4SStefano Zampini   PetscFunctionBegin;
4294906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4295906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4296906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4297906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4298906d46d4SStefano Zampini   PetscFunctionReturn(0);
4299906d46d4SStefano Zampini }
4300b96c3477SStefano Zampini 
4301b96c3477SStefano Zampini #undef __FUNCT__
4302b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSubSchurs"
4303*b7eb3628SStefano Zampini PetscErrorCode PCBDDCSetUpSubSchurs(PC pc, PetscInt layers, PetscBool use_useradj, PetscBool compute_Stilda)
4304b96c3477SStefano Zampini {
4305b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4306b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4307b96c3477SStefano Zampini   PetscInt            *used_xadj,*used_adjncy;
4308b96c3477SStefano Zampini   PetscBool           free_used_adj;
4309b96c3477SStefano Zampini   PetscErrorCode      ierr;
4310b96c3477SStefano Zampini 
4311b96c3477SStefano Zampini   PetscFunctionBegin;
4312b96c3477SStefano Zampini   /* decide the adjacency to be used for determining internal problems for local schur on subsets */
4313b96c3477SStefano Zampini   free_used_adj = PETSC_FALSE;
4314b96c3477SStefano Zampini   if (layers == -1) {
4315b96c3477SStefano Zampini     used_xadj = NULL;
4316b96c3477SStefano Zampini     used_adjncy = NULL;
4317b96c3477SStefano Zampini   } else {
4318b96c3477SStefano Zampini     if ( (use_useradj && pcbddc->mat_graph->xadj) || pcbddc->computed_rowadj) {
4319b96c3477SStefano Zampini       used_xadj = pcbddc->mat_graph->xadj;
4320b96c3477SStefano Zampini       used_adjncy = pcbddc->mat_graph->adjncy;
4321b96c3477SStefano Zampini     } else {
4322b96c3477SStefano Zampini       Mat            mat_adj;
4323b96c3477SStefano Zampini       PetscBool      flg_row=PETSC_TRUE;
4324b96c3477SStefano Zampini       const PetscInt *xadj,*adjncy;
4325b96c3477SStefano Zampini       PetscInt       nvtxs;
4326b96c3477SStefano Zampini 
4327b96c3477SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
4328b96c3477SStefano Zampini       ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4329b96c3477SStefano Zampini       if (!flg_row) {
4330b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
4331b96c3477SStefano Zampini       }
4332b96c3477SStefano Zampini       ierr = PetscMalloc2(nvtxs+1,&used_xadj,xadj[nvtxs],&used_adjncy);CHKERRQ(ierr);
4333b96c3477SStefano Zampini       ierr = PetscMemcpy(used_xadj,xadj,(nvtxs+1)*sizeof(*xadj));CHKERRQ(ierr);
4334b96c3477SStefano Zampini       ierr = PetscMemcpy(used_adjncy,adjncy,(xadj[nvtxs])*sizeof(*adjncy));CHKERRQ(ierr);
4335b96c3477SStefano Zampini       ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,&xadj,&adjncy,&flg_row);CHKERRQ(ierr);
4336b96c3477SStefano Zampini       if (!flg_row) {
4337b96c3477SStefano Zampini         SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
4338b96c3477SStefano Zampini       }
4339b96c3477SStefano Zampini       ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
4340b96c3477SStefano Zampini       free_used_adj = PETSC_TRUE;
4341b96c3477SStefano Zampini     }
4342b96c3477SStefano Zampini   }
4343*b7eb3628SStefano Zampini   ierr = PCBDDCSubSchursSetUp(sub_schurs,used_xadj,used_adjncy,layers,compute_Stilda);CHKERRQ(ierr);
4344b96c3477SStefano Zampini 
4345b96c3477SStefano Zampini   /* free adjacency */
4346b96c3477SStefano Zampini   if (free_used_adj) {
4347b96c3477SStefano Zampini     ierr = PetscFree2(used_xadj,used_adjncy);CHKERRQ(ierr);
4348b96c3477SStefano Zampini   }
4349b96c3477SStefano Zampini   PetscFunctionReturn(0);
4350b96c3477SStefano Zampini }
4351b96c3477SStefano Zampini 
4352b96c3477SStefano Zampini #undef __FUNCT__
4353b96c3477SStefano Zampini #define __FUNCT__ "PCBDDCInitSubSchurs"
4354b96c3477SStefano Zampini PetscErrorCode PCBDDCInitSubSchurs(PC pc, PetscBool rebuild, PetscInt threshold)
4355b96c3477SStefano Zampini {
4356b96c3477SStefano Zampini   PC_IS               *pcis=(PC_IS*)pc->data;
4357b96c3477SStefano Zampini   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
4358b96c3477SStefano Zampini   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
4359b96c3477SStefano Zampini   PCBDDCGraph         graph;
4360b96c3477SStefano Zampini   Mat                 S_j;
4361b96c3477SStefano Zampini   PetscErrorCode      ierr;
4362b96c3477SStefano Zampini 
4363b96c3477SStefano Zampini   PetscFunctionBegin;
4364b96c3477SStefano Zampini   /* attach interface graph for determining subsets */
4365b96c3477SStefano Zampini   if (rebuild) { /* in case rebuild has been requested, it uses a graph generated only by the neighbouring information */
4366b96c3477SStefano Zampini     IS verticesIS;
4367b96c3477SStefano Zampini 
4368b96c3477SStefano Zampini     ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,NULL,NULL,NULL,NULL,&verticesIS);CHKERRQ(ierr);
4369b96c3477SStefano Zampini     ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
4370b96c3477SStefano Zampini     ierr = PCBDDCGraphInit(graph,pcbddc->mat_graph->l2gmap);CHKERRQ(ierr);
4371b96c3477SStefano Zampini     ierr = PCBDDCGraphSetUp(graph,0,NULL,pcbddc->DirichletBoundariesLocal,0,NULL,verticesIS);CHKERRQ(ierr);
4372b96c3477SStefano Zampini     ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
4373b96c3477SStefano Zampini     ierr = ISDestroy(&verticesIS);CHKERRQ(ierr);
4374b96c3477SStefano Zampini /*
4375b96c3477SStefano Zampini     if (pcbddc->dbg_flag) {
4376b96c3477SStefano Zampini       ierr = PCBDDCGraphASCIIView(graph,pcbddc->dbg_flag,pcbddc->dbg_viewer);CHKERRQ(ierr);
4377b96c3477SStefano Zampini     }
4378b96c3477SStefano Zampini */
4379b96c3477SStefano Zampini   } else {
4380b96c3477SStefano Zampini     graph = pcbddc->mat_graph;
4381b96c3477SStefano Zampini   }
4382b96c3477SStefano Zampini 
4383b96c3477SStefano Zampini   /* Create Schur complement matrix */
4384b96c3477SStefano Zampini   ierr = MatCreateSchurComplement(pcis->A_II,pcis->A_II,pcis->A_IB,pcis->A_BI,pcis->A_BB,&S_j);CHKERRQ(ierr);
4385b96c3477SStefano Zampini   ierr = MatSchurComplementSetKSP(S_j,pcbddc->ksp_D);CHKERRQ(ierr);
4386b96c3477SStefano Zampini 
4387b96c3477SStefano Zampini   /* sub_schurs init */
4388b96c3477SStefano Zampini   ierr = PCBDDCSubSchursInit(sub_schurs,pcbddc->local_mat,S_j,pcis->is_I_local,pcis->is_B_local,graph,pcis->BtoNmap,threshold);CHKERRQ(ierr);
4389b96c3477SStefano Zampini   ierr = MatDestroy(&S_j);CHKERRQ(ierr);
4390b96c3477SStefano Zampini   /* free graph struct */
4391b96c3477SStefano Zampini   if (rebuild) {
4392b96c3477SStefano Zampini     ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
4393b96c3477SStefano Zampini   }
4394b96c3477SStefano Zampini   PetscFunctionReturn(0);
4395b96c3477SStefano Zampini }
4396