xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision b1b3d7a2dc467bc01d0ce7eb62bfacc6b4178a73)
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 
8*b1b3d7a2SStefano Zampini #if 0
9*b1b3d7a2SStefano Zampini #undef __FUNCT__
10*b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
11*b1b3d7a2SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc, MatNullSpace* adapt_nnsp)
12*b1b3d7a2SStefano Zampini {
13*b1b3d7a2SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14*b1b3d7a2SStefano Zampini   PetscErrorCode ierr;
15*b1b3d7a2SStefano Zampini 
16*b1b3d7a2SStefano Zampini   PetscFunctionBegin;
17*b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs[0],pcbddc->mat_graph,...);CHKERRQ(ierr);
18*b1b3d7a2SStefano Zampini   PetscFunctionReturn(0);
19*b1b3d7a2SStefano Zampini }
20*b1b3d7a2SStefano Zampini #endif
21*b1b3d7a2SStefano 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);
92*b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs[0]);CHKERRQ(ierr);
93*b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs[1]);CHKERRQ(ierr);
94674ae819SStefano Zampini   PetscFunctionReturn(0);
95674ae819SStefano Zampini }
96674ae819SStefano Zampini 
97674ae819SStefano Zampini #undef __FUNCT__
98674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetSolvers"
99674ae819SStefano Zampini PetscErrorCode PCBDDCResetSolvers(PC pc)
100674ae819SStefano Zampini {
101674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
102674ae819SStefano Zampini   PetscErrorCode ierr;
103674ae819SStefano Zampini 
104674ae819SStefano Zampini   PetscFunctionBegin;
105674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
106674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->coarse_rhs);CHKERRQ(ierr);
107674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
108674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
10915aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
11015aaf578SStefano Zampini   ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
111674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
112674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
113674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
114674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
115674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
116674ae819SStefano Zampini   ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1178ce42a96SStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
118674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
119674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
120674ae819SStefano Zampini   ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
121f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_D);CHKERRQ(ierr);
122f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->ksp_R);CHKERRQ(ierr);
123f4ddd8eeSStefano Zampini   ierr = KSPDestroy(&pcbddc->coarse_ksp);CHKERRQ(ierr);
124f4ddd8eeSStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
125727cdba6SStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
126f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
12770cf5478SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
1286e683305SStefano Zampini   ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
129674ae819SStefano Zampini   PetscFunctionReturn(0);
130674ae819SStefano Zampini }
131674ae819SStefano Zampini 
132674ae819SStefano Zampini #undef __FUNCT__
133f4ddd8eeSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalWorkVectors"
134f4ddd8eeSStefano Zampini PetscErrorCode PCBDDCSetUpLocalWorkVectors(PC pc)
1356bfb1811SStefano Zampini {
1366bfb1811SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1376bfb1811SStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1386bfb1811SStefano Zampini   VecType        impVecType;
139e9189074SStefano Zampini   PetscInt       n_constraints,n_R,old_size;
1406bfb1811SStefano Zampini   PetscErrorCode ierr;
1416bfb1811SStefano Zampini 
1426bfb1811SStefano Zampini   PetscFunctionBegin;
143f4ddd8eeSStefano Zampini   if (!pcbddc->ConstraintMatrix) {
144f4ddd8eeSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Constraint matrix has not been created");
145f4ddd8eeSStefano Zampini   }
146e7b262bdSStefano Zampini   /* get sizes */
147e9189074SStefano Zampini   n_constraints = pcbddc->local_primal_size - pcbddc->n_actual_vertices;
148e9189074SStefano Zampini   n_R = pcis->n-pcbddc->n_actual_vertices;
1496bfb1811SStefano Zampini   ierr = VecGetType(pcis->vec1_N,&impVecType);CHKERRQ(ierr);
150e7b262bdSStefano Zampini   /* local work vectors (try to avoid unneeded work)*/
151e7b262bdSStefano Zampini   /* R nodes */
152e7b262bdSStefano Zampini   old_size = -1;
153e7b262bdSStefano Zampini   if (pcbddc->vec1_R) {
154e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_R,&old_size);CHKERRQ(ierr);
155e7b262bdSStefano Zampini   }
156e7b262bdSStefano Zampini   if (n_R != old_size) {
157e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_R);CHKERRQ(ierr);
158e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec2_R);CHKERRQ(ierr);
1596bfb1811SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_R);CHKERRQ(ierr);
1606bfb1811SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_R,PETSC_DECIDE,n_R);CHKERRQ(ierr);
1616bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_R,impVecType);CHKERRQ(ierr);
1626bfb1811SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_R,&pcbddc->vec2_R);CHKERRQ(ierr);
163e7b262bdSStefano Zampini   }
164e7b262bdSStefano Zampini   /* local primal dofs */
165e7b262bdSStefano Zampini   old_size = -1;
166e7b262bdSStefano Zampini   if (pcbddc->vec1_P) {
167e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_P,&old_size);CHKERRQ(ierr);
168e7b262bdSStefano Zampini   }
169e9189074SStefano Zampini   if (pcbddc->local_primal_size != old_size) {
170e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_P);CHKERRQ(ierr);
17183b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_P);CHKERRQ(ierr);
172e9189074SStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_P,PETSC_DECIDE,pcbddc->local_primal_size);CHKERRQ(ierr);
1736bfb1811SStefano Zampini     ierr = VecSetType(pcbddc->vec1_P,impVecType);CHKERRQ(ierr);
174e7b262bdSStefano Zampini   }
175e7b262bdSStefano Zampini   /* local explicit constraints */
176e7b262bdSStefano Zampini   old_size = -1;
177e7b262bdSStefano Zampini   if (pcbddc->vec1_C) {
178e7b262bdSStefano Zampini     ierr = VecGetSize(pcbddc->vec1_C,&old_size);CHKERRQ(ierr);
179e7b262bdSStefano Zampini   }
180e7b262bdSStefano Zampini   if (n_constraints && n_constraints != old_size) {
181e7b262bdSStefano Zampini     ierr = VecDestroy(&pcbddc->vec1_C);CHKERRQ(ierr);
18283b7ccabSStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pcis->vec1_N),&pcbddc->vec1_C);CHKERRQ(ierr);
18383b7ccabSStefano Zampini     ierr = VecSetSizes(pcbddc->vec1_C,PETSC_DECIDE,n_constraints);CHKERRQ(ierr);
18483b7ccabSStefano Zampini     ierr = VecSetType(pcbddc->vec1_C,impVecType);CHKERRQ(ierr);
18583b7ccabSStefano Zampini   }
1866bfb1811SStefano Zampini   PetscFunctionReturn(0);
1876bfb1811SStefano Zampini }
1886bfb1811SStefano Zampini 
1896bfb1811SStefano Zampini #undef __FUNCT__
19047f4ddc3SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCorrection"
19147f4ddc3SStefano Zampini PetscErrorCode PCBDDCSetUpCorrection(PC pc, PetscScalar **coarse_submat_vals_n)
19288ebb749SStefano Zampini {
19325084f0cSStefano Zampini   PetscErrorCode         ierr;
19425084f0cSStefano Zampini   /* pointers to pcis and pcbddc */
19588ebb749SStefano Zampini   PC_IS*                 pcis = (PC_IS*)pc->data;
19688ebb749SStefano Zampini   PC_BDDC*               pcbddc = (PC_BDDC*)pc->data;
19725084f0cSStefano Zampini   /* submatrices of local problem */
19888ebb749SStefano Zampini   Mat                    A_RV,A_VR,A_VV;
19925084f0cSStefano Zampini   /* working matrices */
20025084f0cSStefano Zampini   Mat                    M1,M2,M3,C_CR;
20125084f0cSStefano Zampini   /* working vectors */
20225084f0cSStefano Zampini   Vec                    vec1_C,vec2_C,vec1_V,vec2_V;
20325084f0cSStefano Zampini   /* additional working stuff */
20425084f0cSStefano Zampini   IS                     is_aux;
20525084f0cSStefano Zampini   PetscScalar            *coarse_submat_vals; /* TODO: use a PETSc matrix */
20625084f0cSStefano Zampini   const PetscScalar      *array,*row_cmat_values;
20725084f0cSStefano Zampini   const PetscInt         *row_cmat_indices,*idx_R_local;
208e9189074SStefano Zampini   PetscInt               *idx_V_B,*auxindices;
20925084f0cSStefano Zampini   PetscInt               n_vertices,n_constraints,size_of_constraint;
21025084f0cSStefano Zampini   PetscInt               i,j,n_R,n_D,n_B;
211b9d89cd5SStefano Zampini   PetscBool              unsymmetric_check;
21245a1bb75SStefano Zampini   /* matrix type (vector type propagated downstream from vec1_C and local matrix type) */
21388ebb749SStefano Zampini   MatType                impMatType;
21425084f0cSStefano Zampini   /* some shortcuts to scalars */
21525084f0cSStefano Zampini   PetscScalar            zero=0.0,one=1.0,m_one=-1.0;
21625084f0cSStefano Zampini   /* for debugging purposes */
21788ebb749SStefano Zampini   PetscReal              *coarsefunctions_errors,*constraints_errors;
21888ebb749SStefano Zampini 
21988ebb749SStefano Zampini   PetscFunctionBegin;
220e9189074SStefano Zampini   /* get number of vertices (corners plus constraints with change of basis)
221e9189074SStefano Zampini      pcbddc->n_actual_vertices stores the actual number of vertices, pcbddc->n_vertices the number of corners computed */
222e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
22388ebb749SStefano Zampini   n_constraints = pcbddc->local_primal_size-n_vertices;
22488ebb749SStefano Zampini   /* Set Non-overlapping dimensions */
22588ebb749SStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
22688ebb749SStefano Zampini   n_R = pcis->n-n_vertices;
22788ebb749SStefano Zampini 
22888ebb749SStefano Zampini   /* Set types for local objects needed by BDDC precondtioner */
22988ebb749SStefano Zampini   impMatType = MATSEQDENSE;
23088ebb749SStefano Zampini 
23188ebb749SStefano Zampini   /* Allocating some extra storage just to be safe */
23288ebb749SStefano Zampini   ierr = PetscMalloc (pcis->n*sizeof(PetscInt),&auxindices);CHKERRQ(ierr);
23388ebb749SStefano Zampini   for (i=0;i<pcis->n;i++) auxindices[i]=i;
23488ebb749SStefano Zampini 
23588ebb749SStefano Zampini   /* vertices in boundary numbering */
236785e854fSJed Brown   ierr = PetscMalloc1(n_vertices,&idx_V_B);CHKERRQ(ierr);
2375e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_vertices,pcbddc->primal_indices_local_idxs,&i,idx_V_B);CHKERRQ(ierr);
23888ebb749SStefano Zampini   if (i != n_vertices) {
23922d5777bSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in boundary numbering for BDDC vertices! %d != %d\n",n_vertices,i);
24088ebb749SStefano Zampini   }
24188ebb749SStefano Zampini 
24288ebb749SStefano Zampini   /* Precompute stuffs needed for preprocessing and application of BDDC*/
24388ebb749SStefano Zampini   if (n_constraints) {
244f4ddd8eeSStefano Zampini     /* see if we can save some allocations */
245f4ddd8eeSStefano Zampini     if (pcbddc->local_auxmat2) {
246f4ddd8eeSStefano Zampini       PetscInt on_R,on_constraints;
247f4ddd8eeSStefano Zampini       ierr = MatGetSize(pcbddc->local_auxmat2,&on_R,&on_constraints);CHKERRQ(ierr);
248f4ddd8eeSStefano Zampini       if (on_R != n_R || on_constraints != n_constraints) {
249f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat2);CHKERRQ(ierr);
250f4ddd8eeSStefano Zampini         ierr = MatDestroy(&pcbddc->local_auxmat1);CHKERRQ(ierr);
251f4ddd8eeSStefano Zampini       }
252f4ddd8eeSStefano Zampini     }
25345a1bb75SStefano Zampini     /* work vectors */
25445a1bb75SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec1_C);CHKERRQ(ierr);
25545a1bb75SStefano Zampini     ierr = VecDuplicate(pcbddc->vec1_C,&vec2_C);CHKERRQ(ierr);
25645a1bb75SStefano Zampini     /* auxiliary matrices */
257f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat2) {
25888ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->local_auxmat2);CHKERRQ(ierr);
25925084f0cSStefano Zampini       ierr = MatSetSizes(pcbddc->local_auxmat2,n_R,n_constraints,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
26088ebb749SStefano Zampini       ierr = MatSetType(pcbddc->local_auxmat2,impMatType);CHKERRQ(ierr);
26125084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->local_auxmat2);CHKERRQ(ierr);
262f4ddd8eeSStefano Zampini     }
26388ebb749SStefano Zampini 
26425084f0cSStefano Zampini     /* Extract constraints on R nodes: C_{CR}  */
26525084f0cSStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,n_constraints,n_vertices,1,&is_aux);CHKERRQ(ierr);
2668ce42a96SStefano Zampini     ierr = MatGetSubMatrix(pcbddc->ConstraintMatrix,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&C_CR);CHKERRQ(ierr);
26725084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
26888ebb749SStefano Zampini 
26988ebb749SStefano Zampini     /* Assemble local_auxmat2 = - A_{RR}^{-1} C^T_{CR} needed by BDDC application */
27088ebb749SStefano Zampini     for (i=0;i<n_constraints;i++) {
27188ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
27288ebb749SStefano Zampini       /* Get row of constraint matrix in R numbering */
27325084f0cSStefano Zampini       ierr = MatGetRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
27425084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_R,size_of_constraint,row_cmat_indices,row_cmat_values,INSERT_VALUES);CHKERRQ(ierr);
27525084f0cSStefano Zampini       ierr = MatRestoreRow(C_CR,i,&size_of_constraint,&row_cmat_indices,&row_cmat_values);CHKERRQ(ierr);
27625084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_R);CHKERRQ(ierr);
27725084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_R);CHKERRQ(ierr);
27888ebb749SStefano Zampini       /* Solve for row of constraint matrix in R numbering */
27988ebb749SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
28025084f0cSStefano Zampini       /* Set values in local_auxmat2 */
28125084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
28288ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->local_auxmat2,n_R,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
28325084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec2_R,&array);CHKERRQ(ierr);
28488ebb749SStefano Zampini     }
28588ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28688ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->local_auxmat2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28725084f0cSStefano Zampini     ierr = MatScale(pcbddc->local_auxmat2,m_one);CHKERRQ(ierr);
28888ebb749SStefano Zampini 
28988ebb749SStefano Zampini     /* Assemble explicitly M1 = ( C_{CR} A_{RR}^{-1} C^T_{CR} )^{-1} needed in preproc  */
29025084f0cSStefano Zampini     ierr = MatMatMult(C_CR,pcbddc->local_auxmat2,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&M3);CHKERRQ(ierr);
29125084f0cSStefano Zampini     ierr = MatLUFactor(M3,NULL,NULL,NULL);CHKERRQ(ierr);
29288ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&M1);CHKERRQ(ierr);
29388ebb749SStefano Zampini     ierr = MatSetSizes(M1,n_constraints,n_constraints,n_constraints,n_constraints);CHKERRQ(ierr);
29488ebb749SStefano Zampini     ierr = MatSetType(M1,impMatType);CHKERRQ(ierr);
29525084f0cSStefano Zampini     ierr = MatSetUp(M1);CHKERRQ(ierr);
29625084f0cSStefano Zampini     ierr = MatDuplicate(M1,MAT_DO_NOT_COPY_VALUES,&M2);CHKERRQ(ierr);
29725084f0cSStefano Zampini     ierr = MatZeroEntries(M2);CHKERRQ(ierr);
29825084f0cSStefano Zampini     ierr = VecSet(vec1_C,m_one);CHKERRQ(ierr);
29925084f0cSStefano Zampini     ierr = MatDiagonalSet(M2,vec1_C,INSERT_VALUES);CHKERRQ(ierr);
30025084f0cSStefano Zampini     ierr = MatMatSolve(M3,M2,M1);CHKERRQ(ierr);
30125084f0cSStefano Zampini     ierr = MatDestroy(&M2);CHKERRQ(ierr);
30225084f0cSStefano Zampini     ierr = MatDestroy(&M3);CHKERRQ(ierr);
30388ebb749SStefano Zampini     /* Assemble local_auxmat1 = M1*C_{CR} needed by BDDC application in KSP and in preproc */
304f4ddd8eeSStefano Zampini     if (!pcbddc->local_auxmat1) {
30588ebb749SStefano Zampini       ierr = MatMatMult(M1,C_CR,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
306f4ddd8eeSStefano Zampini     } else {
307f4ddd8eeSStefano Zampini       ierr = MatMatMult(M1,C_CR,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pcbddc->local_auxmat1);CHKERRQ(ierr);
308f4ddd8eeSStefano Zampini     }
30988ebb749SStefano Zampini   }
31088ebb749SStefano Zampini 
31188ebb749SStefano Zampini   /* Get submatrices from subdomain matrix */
31288ebb749SStefano Zampini   if (n_vertices) {
3133a50541eSStefano Zampini     PetscInt ibs,mbs;
3143a50541eSStefano Zampini     PetscBool issbaij;
315af732b37SStefano Zampini     Mat newmat;
3163a50541eSStefano Zampini 
3173a50541eSStefano Zampini     ierr = ISComplement(pcbddc->is_R_local,0,pcis->n,&is_aux);CHKERRQ(ierr);
3189577ea80SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
3199577ea80SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
3203a50541eSStefano Zampini     if (ibs != mbs) { /* need to convert to SEQAIJ */
3219577ea80SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
3229577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3239577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3249577ea80SStefano Zampini       ierr = MatGetSubMatrix(newmat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
3259577ea80SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
3269577ea80SStefano Zampini     } else {
3273a50541eSStefano Zampini       /* this is safe */
3289577ea80SStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,is_aux,MAT_INITIAL_MATRIX,&A_VV);CHKERRQ(ierr);
3293a50541eSStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcbddc->local_mat,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
3303a50541eSStefano Zampini       if (issbaij) { /* need to convert to BAIJ to get offdiagonal blocks */
3313a50541eSStefano Zampini         ierr = MatConvert(pcbddc->local_mat,MATSEQBAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
33245a1bb75SStefano Zampini         /* which of the two approaches is faster? */
3333a50541eSStefano Zampini         /* ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3343a50541eSStefano Zampini         ierr = MatCreateTranspose(A_RV,&A_VR);CHKERRQ(ierr);*/
3353a50541eSStefano Zampini         ierr = MatGetSubMatrix(newmat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3363a50541eSStefano Zampini         ierr = MatCreateTranspose(A_VR,&A_RV);CHKERRQ(ierr);
3373a50541eSStefano Zampini         ierr = MatDestroy(&newmat);CHKERRQ(ierr);
3383a50541eSStefano Zampini       } else {
3399577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,is_aux,MAT_INITIAL_MATRIX,&A_RV);CHKERRQ(ierr);
3409577ea80SStefano Zampini         ierr = MatGetSubMatrix(pcbddc->local_mat,is_aux,pcbddc->is_R_local,MAT_INITIAL_MATRIX,&A_VR);CHKERRQ(ierr);
3419577ea80SStefano Zampini       }
3423a50541eSStefano Zampini     }
3432a7a6963SBarry Smith     ierr = MatCreateVecs(A_RV,&vec1_V,NULL);CHKERRQ(ierr);
34445a1bb75SStefano Zampini     ierr = VecDuplicate(vec1_V,&vec2_V);CHKERRQ(ierr);
34525084f0cSStefano Zampini     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
34688ebb749SStefano Zampini   }
34788ebb749SStefano Zampini 
34888ebb749SStefano Zampini   /* Matrix of coarse basis functions (local) */
349f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_B) {
350f4ddd8eeSStefano Zampini     PetscInt on_B,on_primal;
351f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_B,&on_B,&on_primal);CHKERRQ(ierr);
352f4ddd8eeSStefano Zampini     if (on_B != n_B || on_primal != pcbddc->local_primal_size) {
353f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_B);CHKERRQ(ierr);
354f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_B);CHKERRQ(ierr);
355f4ddd8eeSStefano Zampini     }
356f4ddd8eeSStefano Zampini   }
357f4ddd8eeSStefano Zampini   if (pcbddc->coarse_phi_D) {
358f4ddd8eeSStefano Zampini     PetscInt on_D,on_primal;
359f4ddd8eeSStefano Zampini     ierr = MatGetSize(pcbddc->coarse_phi_D,&on_D,&on_primal);CHKERRQ(ierr);
360f4ddd8eeSStefano Zampini     if (on_D != n_D || on_primal != pcbddc->local_primal_size) {
361f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_phi_D);CHKERRQ(ierr);
362f4ddd8eeSStefano Zampini       ierr = MatDestroy(&pcbddc->coarse_psi_D);CHKERRQ(ierr);
363f4ddd8eeSStefano Zampini     }
364f4ddd8eeSStefano Zampini   }
365f4ddd8eeSStefano Zampini   if (!pcbddc->coarse_phi_B) {
36688ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_B);CHKERRQ(ierr);
36788ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_phi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
36888ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_phi_B,impMatType);CHKERRQ(ierr);
36925084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_phi_B);CHKERRQ(ierr);
370f4ddd8eeSStefano Zampini   }
371f4ddd8eeSStefano Zampini   if ( (pcbddc->switch_static || pcbddc->dbg_flag) && !pcbddc->coarse_phi_D ) {
37288ebb749SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_phi_D);CHKERRQ(ierr);
37388ebb749SStefano Zampini     ierr = MatSetSizes(pcbddc->coarse_phi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
37488ebb749SStefano Zampini     ierr = MatSetType(pcbddc->coarse_phi_D,impMatType);CHKERRQ(ierr);
37525084f0cSStefano Zampini     ierr = MatSetUp(pcbddc->coarse_phi_D);CHKERRQ(ierr);
37688ebb749SStefano Zampini   }
37788ebb749SStefano Zampini 
37825084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
3798ce42a96SStefano Zampini     ierr = ISGetIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
380785e854fSJed Brown     ierr = PetscMalloc1(2*pcbddc->local_primal_size,&coarsefunctions_errors);CHKERRQ(ierr);
381785e854fSJed Brown     ierr = PetscMalloc1(2*pcbddc->local_primal_size,&constraints_errors);CHKERRQ(ierr);
38288ebb749SStefano Zampini   }
38388ebb749SStefano Zampini   /* Subdomain contribution (Non-overlapping) to coarse matrix  */
384854ce69bSBarry Smith   ierr = PetscMalloc1(pcbddc->local_primal_size*pcbddc->local_primal_size,&coarse_submat_vals);CHKERRQ(ierr);
38588ebb749SStefano Zampini 
38688ebb749SStefano Zampini   /* We are now ready to evaluate coarse basis functions and subdomain contribution to coarse problem */
38725084f0cSStefano Zampini 
38825084f0cSStefano Zampini   /* vertices */
38988ebb749SStefano Zampini   for (i=0;i<n_vertices;i++) {
39045a1bb75SStefano Zampini     /* this should not be needed, but MatMult_BAIJ is broken when using compressed row routines */
391f4ddd8eeSStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr); /* TODO: REMOVE IT */
39288ebb749SStefano Zampini     ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
39388ebb749SStefano Zampini     ierr = VecSetValue(vec1_V,i,one,INSERT_VALUES);CHKERRQ(ierr);
39488ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
39588ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
39625084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on constraints multipliers */
39788ebb749SStefano Zampini     ierr = MatMult(A_RV,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
39888ebb749SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
39988ebb749SStefano Zampini     ierr = VecScale(pcbddc->vec1_R,m_one);CHKERRQ(ierr);
40088ebb749SStefano Zampini     if (n_constraints) {
40188ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,pcbddc->vec1_R,vec1_C);CHKERRQ(ierr);
40288ebb749SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
40388ebb749SStefano Zampini       ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
40488ebb749SStefano Zampini     }
40588ebb749SStefano Zampini     ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
40688ebb749SStefano Zampini     ierr = MatMultAdd(A_VV,vec1_V,vec2_V,vec2_V);CHKERRQ(ierr);
40788ebb749SStefano Zampini 
40888ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
40988ebb749SStefano Zampini     /* coarse basis functions */
41088ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
41188ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41288ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41325084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
41488ebb749SStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
41525084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
41688ebb749SStefano Zampini     ierr = MatSetValue(pcbddc->coarse_phi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
4178eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
41888ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
41988ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
42025084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
42188ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
42225084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
42388ebb749SStefano Zampini     }
42425084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
42525084f0cSStefano Zampini     ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
42625084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
42725084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
42888ebb749SStefano Zampini     if (n_constraints) {
42925084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
43025084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[i*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
43125084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
43288ebb749SStefano Zampini     }
43388ebb749SStefano Zampini 
43425084f0cSStefano Zampini     /* check */
43525084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
43625084f0cSStefano Zampini       /* assemble subdomain vector on local nodes */
43788ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
43825084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
4399f00e9b4SStefano Zampini       if (n_R) {
44025084f0cSStefano Zampini         ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
4419f00e9b4SStefano Zampini       }
44225084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
443e9189074SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],one,INSERT_VALUES);CHKERRQ(ierr);
44425084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
44525084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
44688ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers (i.e. primal nodes) */
44788ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
44825084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
44925084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
45025084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
45188ebb749SStefano Zampini       if (n_constraints) {
45225084f0cSStefano Zampini         ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
45325084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
45425084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
45588ebb749SStefano Zampini       }
45625084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
45725084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
45888ebb749SStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
45988ebb749SStefano Zampini       /* check saddle point solution */
46088ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
46188ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
46288ebb749SStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i]);CHKERRQ(ierr);
46388ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
46425084f0cSStefano Zampini       /* shift by the identity matrix */
46525084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
46625084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
46725084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
46888ebb749SStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i]);CHKERRQ(ierr);
46988ebb749SStefano Zampini     }
47088ebb749SStefano Zampini   }
47188ebb749SStefano Zampini 
47225084f0cSStefano Zampini   /* constraints */
47388ebb749SStefano Zampini   for (i=0;i<n_constraints;i++) {
47488ebb749SStefano Zampini     ierr = VecSet(vec2_C,zero);CHKERRQ(ierr);
47588ebb749SStefano Zampini     ierr = VecSetValue(vec2_C,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
47688ebb749SStefano Zampini     ierr = VecAssemblyBegin(vec2_C);CHKERRQ(ierr);
47788ebb749SStefano Zampini     ierr = VecAssemblyEnd(vec2_C);CHKERRQ(ierr);
47825084f0cSStefano Zampini     /* simplified solution of saddle point problem with null rhs on vertices multipliers */
47988ebb749SStefano Zampini     ierr = MatMult(M1,vec2_C,vec1_C);CHKERRQ(ierr);
48088ebb749SStefano Zampini     ierr = MatMult(pcbddc->local_auxmat2,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
48188ebb749SStefano Zampini     ierr = VecScale(vec1_C,m_one);CHKERRQ(ierr);
48225084f0cSStefano Zampini     if (n_vertices) {
48325084f0cSStefano Zampini       ierr = MatMult(A_VR,pcbddc->vec1_R,vec2_V);CHKERRQ(ierr);
48425084f0cSStefano Zampini     }
48588ebb749SStefano Zampini     /* Set values in coarse basis function and subdomain part of coarse_mat */
48688ebb749SStefano Zampini     /* coarse basis functions */
48725084f0cSStefano Zampini     j = i+n_vertices; /* don't touch this! */
48888ebb749SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
48988ebb749SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49088ebb749SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49125084f0cSStefano Zampini     ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
49225084f0cSStefano Zampini     ierr = MatSetValues(pcbddc->coarse_phi_B,n_B,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
49325084f0cSStefano Zampini     ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
4948eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
49588ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49688ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
49725084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
49825084f0cSStefano Zampini       ierr = MatSetValues(pcbddc->coarse_phi_D,n_D,auxindices,1,&j,array,INSERT_VALUES);CHKERRQ(ierr);
49925084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
50088ebb749SStefano Zampini     }
50125084f0cSStefano Zampini     /* subdomain contribution to coarse matrix. WARNING -> column major ordering */
50288ebb749SStefano Zampini     if (n_vertices) {
50325084f0cSStefano Zampini       ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
50425084f0cSStefano Zampini       ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size],array,n_vertices*sizeof(PetscScalar));CHKERRQ(ierr);
50525084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
50688ebb749SStefano Zampini     }
50725084f0cSStefano Zampini     ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
50825084f0cSStefano Zampini     ierr = PetscMemcpy(&coarse_submat_vals[j*pcbddc->local_primal_size+n_vertices],array,n_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
50925084f0cSStefano Zampini     ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
51088ebb749SStefano Zampini 
51125084f0cSStefano Zampini     if (pcbddc->dbg_flag) {
51288ebb749SStefano Zampini       /* assemble subdomain vector on nodes */
51388ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
51425084f0cSStefano Zampini       ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
5159f00e9b4SStefano Zampini       if (n_R) {
51625084f0cSStefano Zampini         ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
5179f00e9b4SStefano Zampini       }
51825084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
51925084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
52025084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
52188ebb749SStefano Zampini       /* assemble subdomain vector of lagrange multipliers */
52288ebb749SStefano Zampini       ierr = VecSet(pcbddc->vec1_P,zero);CHKERRQ(ierr);
52388ebb749SStefano Zampini       if (n_vertices) {
52425084f0cSStefano Zampini         ierr = VecGetArrayRead(vec2_V,&array);CHKERRQ(ierr);
52525084f0cSStefano Zampini         ierr = VecSetValues(pcbddc->vec1_P,n_vertices,auxindices,array,INSERT_VALUES);CHKERRQ(ierr);
52625084f0cSStefano Zampini         ierr = VecRestoreArrayRead(vec2_V,&array);CHKERRQ(ierr);
52788ebb749SStefano Zampini       }
52825084f0cSStefano Zampini       ierr = VecGetArrayRead(vec1_C,&array);CHKERRQ(ierr);
52925084f0cSStefano Zampini       ierr = VecSetValues(pcbddc->vec1_P,n_constraints,&auxindices[n_vertices],array,INSERT_VALUES);CHKERRQ(ierr);
53025084f0cSStefano Zampini       ierr = VecRestoreArrayRead(vec1_C,&array);CHKERRQ(ierr);
53125084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
53225084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
53325084f0cSStefano Zampini       ierr = VecScale(pcbddc->vec1_P,m_one);CHKERRQ(ierr);
53488ebb749SStefano Zampini       /* check saddle point solution */
53588ebb749SStefano Zampini       ierr = MatMult(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
53688ebb749SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
53725084f0cSStefano Zampini       ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[j]);CHKERRQ(ierr);
53888ebb749SStefano Zampini       ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
53925084f0cSStefano Zampini       /* shift by the identity matrix */
54025084f0cSStefano Zampini       ierr = VecSetValue(pcbddc->vec1_P,j,m_one,ADD_VALUES);CHKERRQ(ierr);
54125084f0cSStefano Zampini       ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
54225084f0cSStefano Zampini       ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
54325084f0cSStefano Zampini       ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[j]);CHKERRQ(ierr);
54488ebb749SStefano Zampini     }
54588ebb749SStefano Zampini   }
54625084f0cSStefano Zampini   /* call assembling routines for local coarse basis */
54788ebb749SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
54888ebb749SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->coarse_phi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5498eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
55088ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55188ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_phi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
55288ebb749SStefano Zampini   }
55325084f0cSStefano Zampini 
55488ebb749SStefano Zampini   /* compute other basis functions for non-symmetric problems */
55551cb09feSStefano Zampini   /*ierr = MatIsSymmetric(pc->pmat,0.,&pcbddc->issym);CHKERRQ(ierr);*/
55651cb09feSStefano Zampini   { /* this is a temporary workaround since seqbaij matrices does not have support for symmetry checking */
55751cb09feSStefano Zampini     PetscBool setsym;
55851cb09feSStefano Zampini     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&pcbddc->issym);CHKERRQ(ierr);
55951cb09feSStefano Zampini     if (!setsym) pcbddc->issym = PETSC_FALSE;
56051cb09feSStefano Zampini   }
56151cb09feSStefano Zampini 
562b9d89cd5SStefano Zampini   if (!pcbddc->issym) {
563f4ddd8eeSStefano Zampini     if (!pcbddc->coarse_psi_B) {
56488ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
56588ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
56688ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
56725084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_B);CHKERRQ(ierr);
568f4ddd8eeSStefano Zampini     }
569f4ddd8eeSStefano Zampini     if ( (pcbddc->switch_static || pcbddc->dbg_flag) && !pcbddc->coarse_psi_D) {
57088ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
57188ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
57288ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
57325084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_D);CHKERRQ(ierr);
57488ebb749SStefano Zampini     }
57588ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
57688ebb749SStefano Zampini       if (n_constraints) {
57788ebb749SStefano Zampini         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
57888ebb749SStefano Zampini         for (j=0;j<n_constraints;j++) {
57925084f0cSStefano Zampini           ierr = VecSetValue(vec1_C,j,coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
58088ebb749SStefano Zampini         }
58125084f0cSStefano Zampini         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
58225084f0cSStefano Zampini         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
58388ebb749SStefano Zampini       }
58488ebb749SStefano Zampini       if (i<n_vertices) {
58588ebb749SStefano Zampini         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
58688ebb749SStefano Zampini         ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
58788ebb749SStefano Zampini         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
58888ebb749SStefano Zampini         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
58988ebb749SStefano Zampini         ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
59088ebb749SStefano Zampini         if (n_constraints) {
59188ebb749SStefano Zampini           ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
59288ebb749SStefano Zampini         }
59388ebb749SStefano Zampini       } else {
59488ebb749SStefano Zampini         ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
59588ebb749SStefano Zampini       }
59688ebb749SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
59788ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
59888ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
59988ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60025084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
60188ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
60225084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
60388ebb749SStefano Zampini       if (i<n_vertices) {
60488ebb749SStefano Zampini         ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
60588ebb749SStefano Zampini       }
6068eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
60788ebb749SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60888ebb749SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60925084f0cSStefano Zampini         ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
61088ebb749SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
61125084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
61288ebb749SStefano Zampini       }
61388ebb749SStefano Zampini 
61425084f0cSStefano Zampini       if (pcbddc->dbg_flag) {
61588ebb749SStefano Zampini         /* assemble subdomain vector on nodes */
61688ebb749SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
61725084f0cSStefano Zampini         ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
6189f00e9b4SStefano Zampini         if (n_R) {
61925084f0cSStefano Zampini           ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
6209f00e9b4SStefano Zampini         }
62125084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
62225084f0cSStefano Zampini         if (i<n_vertices) {
623e9189074SStefano Zampini           ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],one,INSERT_VALUES);CHKERRQ(ierr);
62488ebb749SStefano Zampini         }
62525084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
62625084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
62725084f0cSStefano Zampini         /* assemble subdomain vector of lagrange multipliers */
62825084f0cSStefano Zampini         for (j=0;j<pcbddc->local_primal_size;j++) {
62925084f0cSStefano Zampini           ierr = VecSetValue(pcbddc->vec1_P,j,-coarse_submat_vals[j*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
63025084f0cSStefano Zampini         }
63125084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
63225084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
63388ebb749SStefano Zampini         /* check saddle point solution */
63488ebb749SStefano Zampini         ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
63588ebb749SStefano Zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
63688ebb749SStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
63788ebb749SStefano Zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
63825084f0cSStefano Zampini         /* shift by the identity matrix */
63925084f0cSStefano Zampini         ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
64025084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
64125084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
64288ebb749SStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
64388ebb749SStefano Zampini       }
64488ebb749SStefano Zampini     }
64588ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64688ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6478eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
64888ebb749SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64988ebb749SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
65088ebb749SStefano Zampini     }
651c0553b1fSStefano Zampini     unsymmetric_check = PETSC_TRUE;
652c0553b1fSStefano Zampini   } else { /* take references to already computed coarse basis */
653c0553b1fSStefano Zampini     unsymmetric_check = PETSC_FALSE;
654c0553b1fSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
655c0553b1fSStefano Zampini     pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
656c0553b1fSStefano Zampini     if (pcbddc->coarse_phi_D) {
657c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
658c0553b1fSStefano Zampini       pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
659c0553b1fSStefano Zampini     }
66088ebb749SStefano Zampini   }
66188ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
66288ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
66388ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
66488ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
66525084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
66688ebb749SStefano Zampini     Mat         coarse_sub_mat;
66725084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
66888ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
66988ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
67088ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
67188ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
67288ebb749SStefano Zampini     PetscReal   real_value;
67388ebb749SStefano Zampini 
67488ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
67588ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
67688ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
67788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
67888ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
67988ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
680c0553b1fSStefano Zampini     if (unsymmetric_check) {
68188ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
68288ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
68388ebb749SStefano Zampini     }
68488ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
68588ebb749SStefano Zampini 
68625084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
68725084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
68825084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
689c0553b1fSStefano Zampini     if (unsymmetric_check) {
69088ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69188ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
69288ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69388ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
69588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69688ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
69888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69988ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
70088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
70188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70288ebb749SStefano Zampini     } else {
70388ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
70488ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
70588ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
70688ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
70788ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70888ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
70988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
71088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
71188ebb749SStefano Zampini     }
71288ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
71388ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
71488ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
71588ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
71681d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
71788ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
7180fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
71925084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"----------------------------------\n");CHKERRQ(ierr);
72025084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
72125084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
72225084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
72388ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
72425084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
72588ebb749SStefano Zampini     }
72625084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
72788ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
72825084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
72988ebb749SStefano Zampini     }
730c0553b1fSStefano Zampini     if (unsymmetric_check) {
73125084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
73288ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
73325084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
73488ebb749SStefano Zampini       }
73525084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
73688ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
73725084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
73888ebb749SStefano Zampini       }
73988ebb749SStefano Zampini     }
74025084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
74188ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
74288ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
74388ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
74488ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
74588ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
74688ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
74788ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
74888ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
74988ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
75088ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
751c0553b1fSStefano Zampini     if (unsymmetric_check) {
75288ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
75388ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
75488ebb749SStefano Zampini     }
75588ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
7568ce42a96SStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
75788ebb749SStefano Zampini     ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
75888ebb749SStefano Zampini     ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
75988ebb749SStefano Zampini   }
76088ebb749SStefano Zampini   /* free memory */
76188ebb749SStefano Zampini   if (n_vertices) {
76288ebb749SStefano Zampini     ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
76388ebb749SStefano Zampini     ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
76488ebb749SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
76588ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
76688ebb749SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
76788ebb749SStefano Zampini   }
76888ebb749SStefano Zampini   if (n_constraints) {
76988ebb749SStefano Zampini     ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
77088ebb749SStefano Zampini     ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
77188ebb749SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
77288ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
77388ebb749SStefano Zampini   }
77488ebb749SStefano Zampini   ierr = PetscFree(auxindices);CHKERRQ(ierr);
7758629588bSStefano Zampini   /* get back data */
7768629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
77788ebb749SStefano Zampini   PetscFunctionReturn(0);
77888ebb749SStefano Zampini }
77988ebb749SStefano Zampini 
78088ebb749SStefano Zampini #undef __FUNCT__
7815e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
7825e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
783aa0d41d4SStefano Zampini {
784aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
7855e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
7865e8657edSStefano Zampini   Mat            *change_mat_all;
7875e8657edSStefano Zampini   IS             is_local,is_global;
7885e8657edSStefano Zampini   PetscBool      sorted,isseqaij;
7895e8657edSStefano Zampini   PetscInt       local_size,*idxs_perm;
790aa0d41d4SStefano Zampini   PetscErrorCode ierr;
791aa0d41d4SStefano Zampini 
792aa0d41d4SStefano Zampini   PetscFunctionBegin;
793aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
7945e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
7955e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
796906d46d4SStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(matis->mapping,is_local,&is_global);CHKERRQ(ierr);
797906d46d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
798906d46d4SStefano Zampini   ierr = ISSorted(is_global,&sorted);CHKERRQ(ierr);
799906d46d4SStefano Zampini   if (!sorted) {
800906d46d4SStefano Zampini     const PetscInt *idxs;
801906d46d4SStefano Zampini     PetscInt *idxs_sorted,i;
802aa0d41d4SStefano Zampini 
8035e8657edSStefano Zampini     ierr = PetscMalloc1(local_size,&idxs_perm);CHKERRQ(ierr);
8045e8657edSStefano Zampini     ierr = PetscMalloc1(local_size,&idxs_sorted);CHKERRQ(ierr);
8055e8657edSStefano Zampini     for (i=0;i<local_size;i++) {
806906d46d4SStefano Zampini       idxs_perm[i] = i;
807aa0d41d4SStefano Zampini     }
808906d46d4SStefano Zampini     ierr = ISGetIndices(is_global,&idxs);CHKERRQ(ierr);
8095e8657edSStefano Zampini     ierr = PetscSortIntWithPermutation(local_size,idxs,idxs_perm);CHKERRQ(ierr);
8105e8657edSStefano Zampini     for (i=0;i<local_size;i++) {
811906d46d4SStefano Zampini       idxs_sorted[i] = idxs[idxs_perm[i]];
812aa0d41d4SStefano Zampini     }
813906d46d4SStefano Zampini     ierr = ISRestoreIndices(is_global,&idxs);CHKERRQ(ierr);
814906d46d4SStefano Zampini     ierr = ISDestroy(&is_global);CHKERRQ(ierr);
8155e8657edSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,local_size,idxs_sorted,PETSC_OWN_POINTER,&is_global);CHKERRQ(ierr);
816aa0d41d4SStefano Zampini   }
817906d46d4SStefano Zampini 
818906d46d4SStefano Zampini   /* get change of basis on the whole set of local dofs */
8195e8657edSStefano Zampini   ierr = MatGetSubMatrices(ChangeOfBasisMatrix,1,&is_global,&is_global,MAT_INITIAL_MATRIX,&change_mat_all);CHKERRQ(ierr);
820906d46d4SStefano Zampini 
821906d46d4SStefano Zampini   if (!sorted) {
822906d46d4SStefano Zampini     Mat      new_mat;
823906d46d4SStefano Zampini     IS       is_perm;
824906d46d4SStefano Zampini     PetscInt *idxs,i;
825906d46d4SStefano Zampini 
8265e8657edSStefano Zampini     ierr = PetscMalloc1(local_size,&idxs);CHKERRQ(ierr);
8275e8657edSStefano Zampini     for (i=0;i<local_size;i++) {
828906d46d4SStefano Zampini       idxs[idxs_perm[i]] = i;
829906d46d4SStefano Zampini     }
830906d46d4SStefano Zampini     ierr = PetscFree(idxs_perm);CHKERRQ(ierr);
8315e8657edSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,local_size,idxs,PETSC_OWN_POINTER,&is_perm);CHKERRQ(ierr);
832906d46d4SStefano Zampini     ierr = ISSetPermutation(is_perm);CHKERRQ(ierr);
833906d46d4SStefano Zampini     ierr = MatPermute(change_mat_all[0],is_perm,is_perm,&new_mat);CHKERRQ(ierr);
834906d46d4SStefano Zampini     ierr = MatDestroy(&change_mat_all[0]);CHKERRQ(ierr);
835906d46d4SStefano Zampini     change_mat_all[0] = new_mat;
836906d46d4SStefano Zampini     ierr = ISDestroy(&is_perm);CHKERRQ(ierr);
837906d46d4SStefano Zampini   }
838906d46d4SStefano Zampini 
839906d46d4SStefano Zampini   /* check */
840906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
841906d46d4SStefano Zampini     Vec       x,x_change;
842906d46d4SStefano Zampini     PetscReal error;
843906d46d4SStefano Zampini 
8445e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
845906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
8465e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
8475e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8485e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
8495e8657edSStefano Zampini     ierr = MatMult(change_mat_all[0],matis->x,matis->y);CHKERRQ(ierr);
8505e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
8515e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
852906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
853906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
854906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
855906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
856906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
857906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
858906d46d4SStefano Zampini   }
859906d46d4SStefano Zampini 
86022d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
8619b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
86222d5777bSStefano Zampini   if (isseqaij) {
8635e8657edSStefano Zampini     ierr = MatPtAP(matis->A,change_mat_all[0],MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
864aa0d41d4SStefano Zampini   } else {
865aa0d41d4SStefano Zampini     Mat work_mat;
866aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
8675e8657edSStefano Zampini     ierr = MatPtAP(work_mat,change_mat_all[0],MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
868aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
869aa0d41d4SStefano Zampini   }
87045a1bb75SStefano Zampini   /*
87145a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
87245a1bb75SStefano Zampini   ierr = MatView(change_mat_all,(PetscViewer)0);CHKERRQ(ierr);
87345a1bb75SStefano Zampini   */
874906d46d4SStefano Zampini   ierr = MatDestroyMatrices(1,&change_mat_all);CHKERRQ(ierr);
875906d46d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
876aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
877aa0d41d4SStefano Zampini }
878aa0d41d4SStefano Zampini 
879aa0d41d4SStefano Zampini #undef __FUNCT__
880a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
8818ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
882a64d13efSStefano Zampini {
883a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
884a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
8858ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
886e9189074SStefano Zampini   PetscInt       *aux_array1,*aux_array2,*is_indices,*idx_R_local;
8873a50541eSStefano Zampini   PetscInt       n_vertices,i,j,n_R,n_D,n_B;
8883a50541eSStefano Zampini   PetscInt       vbs,bs;
8894641a718SStefano Zampini   PetscBT        bitmask;
890a64d13efSStefano Zampini   PetscErrorCode ierr;
891a64d13efSStefano Zampini 
892a64d13efSStefano Zampini   PetscFunctionBegin;
893b23d619eSStefano Zampini   /*
894b23d619eSStefano Zampini     No need to setup local scatters if
895b23d619eSStefano Zampini       - primal space is unchanged
896b23d619eSStefano Zampini         AND
897b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
898b23d619eSStefano Zampini         AND
899b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
900b23d619eSStefano Zampini   */
901b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
902f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
903f4ddd8eeSStefano Zampini   }
904f4ddd8eeSStefano Zampini   /* destroy old objects */
905f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
906f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
907f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
908a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
909a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
910e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
9114641a718SStefano Zampini   /* create auxiliary bitmask */
9124641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
9134641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
914e9189074SStefano Zampini     ierr = PetscBTSet(bitmask,pcbddc->primal_indices_local_idxs[i]);CHKERRQ(ierr);
9154641a718SStefano Zampini   }
9163a50541eSStefano Zampini 
917a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
918854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
919a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
9204641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
921a64d13efSStefano Zampini       idx_R_local[n_R] = i;
922a64d13efSStefano Zampini       n_R++;
923a64d13efSStefano Zampini     }
924a64d13efSStefano Zampini   }
9253a50541eSStefano Zampini 
9263a50541eSStefano Zampini   /* Block code */
9273a50541eSStefano Zampini   vbs = 1;
9283a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
9293a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
9303a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
9313a50541eSStefano Zampini     PetscInt  *vary;
9323a50541eSStefano Zampini     /* Verify if the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
933785e854fSJed Brown     ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
9343a50541eSStefano Zampini     ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
935e9189074SStefano Zampini     for (i=0; i<n_vertices; i++) vary[pcbddc->primal_indices_local_idxs[i]/bs]++;
9363a50541eSStefano Zampini     for (i=0; i<n_vertices; i++) {
9373a50541eSStefano Zampini       if (vary[i]!=0 && vary[i]!=bs) {
9383a50541eSStefano Zampini         is_blocked = PETSC_FALSE;
9393a50541eSStefano Zampini         break;
9403a50541eSStefano Zampini       }
9413a50541eSStefano Zampini     }
9423a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
9433a50541eSStefano Zampini       vbs = bs;
9443a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
9453a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
9463a50541eSStefano Zampini       }
9473a50541eSStefano Zampini     }
9483a50541eSStefano Zampini     ierr = PetscFree(vary);CHKERRQ(ierr);
9493a50541eSStefano Zampini   }
9503a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
9513a50541eSStefano Zampini   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
952a64d13efSStefano Zampini 
953a64d13efSStefano Zampini   /* print some info if requested */
954a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
955a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
956a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
9570fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
958a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
959a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
9603a50541eSStefano 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);
961a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
962a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
963a64d13efSStefano Zampini   }
964a64d13efSStefano Zampini 
965a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
9663a50541eSStefano Zampini   ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
967854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
968854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
969a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
9704641a718SStefano Zampini   for (i=0; i<n_D; i++) {
9714641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
9724641a718SStefano Zampini   }
973a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
974a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
9754641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
9764641a718SStefano Zampini       aux_array1[j++] = i;
977a64d13efSStefano Zampini     }
978a64d13efSStefano Zampini   }
979a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
980a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
981a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
9824641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
9834641a718SStefano Zampini       aux_array2[j++] = i;
984a64d13efSStefano Zampini     }
985a64d13efSStefano Zampini   }
986a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
987a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
988a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
989a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
990a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
991a64d13efSStefano Zampini 
9928eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
993785e854fSJed Brown     ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
994a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
9954641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
9964641a718SStefano Zampini         aux_array1[j++] = i;
997a64d13efSStefano Zampini       }
998a64d13efSStefano Zampini     }
999a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1000a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1001a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1002a64d13efSStefano Zampini   }
10034641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
10043a50541eSStefano Zampini   ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1005a64d13efSStefano Zampini   PetscFunctionReturn(0);
1006a64d13efSStefano Zampini }
1007a64d13efSStefano Zampini 
1008304d26faSStefano Zampini 
1009304d26faSStefano Zampini #undef __FUNCT__
1010304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1011684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1012304d26faSStefano Zampini {
1013304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1014304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1015304d26faSStefano Zampini   PC             pc_temp;
1016304d26faSStefano Zampini   Mat            A_RR;
1017f4ddd8eeSStefano Zampini   MatReuse       reuse;
1018304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1019304d26faSStefano Zampini   PetscReal      value;
1020af732b37SStefano Zampini   PetscInt       n_D,n_R,ibs,mbs;
10219577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1022304d26faSStefano Zampini   PetscErrorCode ierr;
1023e604994aSStefano Zampini   /* prefixes stuff */
1024312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1025e604994aSStefano Zampini   size_t         len;
1026304d26faSStefano Zampini 
1027304d26faSStefano Zampini   PetscFunctionBegin;
1028304d26faSStefano Zampini 
1029e604994aSStefano Zampini   /* compute prefixes */
1030e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1031e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1032e604994aSStefano Zampini   if (!pcbddc->current_level) {
1033e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1034e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1035e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1036e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1037e604994aSStefano Zampini   } else {
1038e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1039312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1040e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1041e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1042312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1043312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
104434d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
104534d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1046e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1047e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1048e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1049e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1050e604994aSStefano Zampini   }
1051e604994aSStefano Zampini 
1052304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1053684f6988SStefano Zampini   if (dirichlet) {
1054ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
10558ce42a96SStefano Zampini     ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
1056304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1057304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1058304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1059304d26faSStefano Zampini       /* default */
1060304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1061e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
10629577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1063304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
10649577ea80SStefano Zampini       if (issbaij) {
10659577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
10669577ea80SStefano Zampini       } else {
1067304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
10689577ea80SStefano Zampini       }
1069304d26faSStefano Zampini       /* Allow user's customization */
1070304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1071304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1072304d26faSStefano Zampini     }
1073d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1074304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1075304d26faSStefano Zampini     if (!n_D) {
1076304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1077304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1078304d26faSStefano Zampini     }
1079304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1080304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1081304d26faSStefano Zampini     /* set ksp_D into pcis data */
1082304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1083304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1084304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1085684f6988SStefano Zampini   }
1086304d26faSStefano Zampini 
1087304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1088684f6988SStefano Zampini   A_RR = 0;
1089684f6988SStefano Zampini   if (neumann) {
1090f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
10918ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1092f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1093f4ddd8eeSStefano Zampini       PetscInt nn_R;
109481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1095f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1096f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1097f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1098f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1099f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1100f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1101f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1102727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1103f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1104f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1105f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1106f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1107f4ddd8eeSStefano Zampini         }
1108f4ddd8eeSStefano Zampini       }
1109f4ddd8eeSStefano Zampini       /* last check */
1110d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1111f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1112f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1113f4ddd8eeSStefano Zampini       }
1114f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1115f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1116f4ddd8eeSStefano Zampini     }
1117f4ddd8eeSStefano Zampini     /* extract A_RR */
1118af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1119af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
11203a50541eSStefano Zampini     if (ibs != mbs) {
1121af732b37SStefano Zampini       Mat newmat;
1122af732b37SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
1123f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1124af732b37SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
1125af732b37SStefano Zampini     } else {
1126f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1127af732b37SStefano Zampini     }
1128f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1129304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1130304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1131304d26faSStefano Zampini       /* default */
1132304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1133e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1134304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
11359577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
11369577ea80SStefano Zampini       if (issbaij) {
11379577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
11389577ea80SStefano Zampini       } else {
1139304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
11409577ea80SStefano Zampini       }
1141304d26faSStefano Zampini       /* Allow user's customization */
1142304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1143304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1144304d26faSStefano Zampini     }
1145d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1146304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1147304d26faSStefano Zampini     if (!n_R) {
1148304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1149304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1150304d26faSStefano Zampini     }
1151304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1152304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1153684f6988SStefano Zampini   }
1154304d26faSStefano Zampini 
1155304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
11560fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1157684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1158684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1159684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1160684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1161684f6988SStefano Zampini     }
1162684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
11630fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
11640fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
11650fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
11660fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
11670fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1168304d26faSStefano Zampini       /* need to be adapted? */
1169b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1170b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1171b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1172304d26faSStefano Zampini       /* print info */
1173304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1174e604994aSStefano 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);
1175304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1176304d26faSStefano Zampini       }
1177b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
11788ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
1179304d26faSStefano Zampini       }
1180684f6988SStefano Zampini     }
1181684f6988SStefano Zampini     if (neumann) { /* Neumann */
11820fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
11830fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
11840fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
11850fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
11860fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1187304d26faSStefano Zampini       /* need to be adapted? */
1188b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1189b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1190304d26faSStefano Zampini       /* print info */
1191304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1192e604994aSStefano 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);
1193304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1194304d26faSStefano Zampini       }
1195b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
11968ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
1197304d26faSStefano Zampini       }
11980fccc4e9SStefano Zampini     }
1199684f6988SStefano Zampini   }
1200304d26faSStefano Zampini   /* free Neumann problem's matrix */
1201304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1202304d26faSStefano Zampini   PetscFunctionReturn(0);
1203304d26faSStefano Zampini }
1204304d26faSStefano Zampini 
1205304d26faSStefano Zampini #undef __FUNCT__
1206ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
120720c7b377SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec rhs, Vec sol, Vec work, PetscBool applytranspose)
1208674ae819SStefano Zampini {
1209674ae819SStefano Zampini   PetscErrorCode ierr;
1210674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1211674ae819SStefano Zampini 
1212674ae819SStefano Zampini   PetscFunctionBegin;
121320c7b377SStefano Zampini   if (applytranspose) {
1214674ae819SStefano Zampini     if (pcbddc->local_auxmat1) {
121520c7b377SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,rhs,work);CHKERRQ(ierr);
121620c7b377SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,work,rhs,rhs);CHKERRQ(ierr);
121720c7b377SStefano Zampini     }
121820c7b377SStefano Zampini     ierr = KSPSolveTranspose(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
121920c7b377SStefano Zampini   } else {
122020c7b377SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
122120c7b377SStefano Zampini     if (pcbddc->local_auxmat1) {
122220c7b377SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,sol,work);CHKERRQ(ierr);
122320c7b377SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,work,sol,sol);CHKERRQ(ierr);
122420c7b377SStefano Zampini     }
1225674ae819SStefano Zampini   }
1226674ae819SStefano Zampini   PetscFunctionReturn(0);
1227674ae819SStefano Zampini }
1228674ae819SStefano Zampini 
1229dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1230674ae819SStefano Zampini #undef __FUNCT__
1231674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1232dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1233674ae819SStefano Zampini {
1234674ae819SStefano Zampini   PetscErrorCode ierr;
1235674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1236674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1237674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1238674ae819SStefano Zampini 
1239674ae819SStefano Zampini   PetscFunctionBegin;
1240dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1241dc359a40SStefano Zampini   if (applytranspose) {
1242674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
12438eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1244dc359a40SStefano Zampini   } else {
1245674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1246674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
124715aaf578SStefano Zampini   }
124812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
124912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
125012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
125112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
125212edc857SStefano Zampini 
12539f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
125412edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
125512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
125612edc857SStefano Zampini     if (applytranspose) {
125712edc857SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
125812edc857SStefano Zampini     } else {
125912edc857SStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
126012edc857SStefano Zampini     }
126112edc857SStefano Zampini   }
1262674ae819SStefano Zampini 
1263674ae819SStefano Zampini   /* Local solution on R nodes */
12649f00e9b4SStefano Zampini   if (pcis->n) {
1265674ae819SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1266674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1267674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12688eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1269674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1270674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1271674ae819SStefano Zampini     }
127220c7b377SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcbddc->vec1_R,pcbddc->vec2_R,pcbddc->vec1_C,applytranspose);CHKERRQ(ierr);
1273674ae819SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1274674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1275674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12768eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1277674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1278674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1279674ae819SStefano Zampini     }
12809f00e9b4SStefano Zampini   }
1281674ae819SStefano Zampini 
12829f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
12839f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
128412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1285674ae819SStefano Zampini 
1286674ae819SStefano Zampini   /* Sum contributions from two levels */
1287dc359a40SStefano Zampini   if (applytranspose) {
1288dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1289dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1290dc359a40SStefano Zampini   } else {
1291674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
12928eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1293dc359a40SStefano Zampini   }
1294674ae819SStefano Zampini   PetscFunctionReturn(0);
1295674ae819SStefano Zampini }
1296674ae819SStefano Zampini 
129712edc857SStefano Zampini /* TODO: the following two function can be optimized using VecPlaceArray whenever possible and using overlap flag */
1298674ae819SStefano Zampini #undef __FUNCT__
1299674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
130012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1301674ae819SStefano Zampini {
1302674ae819SStefano Zampini   PetscErrorCode ierr;
1303674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
130412edc857SStefano Zampini   PetscScalar    *array,*array2;
130512edc857SStefano Zampini   Vec            from,to;
1306674ae819SStefano Zampini 
1307674ae819SStefano Zampini   PetscFunctionBegin;
130812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
130912edc857SStefano Zampini     from = pcbddc->coarse_vec;
131012edc857SStefano Zampini     to = pcbddc->vec1_P;
131112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
131212edc857SStefano Zampini       Vec tvec;
131312edc857SStefano Zampini       PetscInt lsize;
131412edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
131512edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
131612edc857SStefano Zampini       ierr = VecGetArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
131712edc857SStefano Zampini       ierr = VecGetArray(from,&array2);CHKERRQ(ierr);
131812edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
131912edc857SStefano Zampini       ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
132012edc857SStefano Zampini       ierr = VecRestoreArray(from,&array2);CHKERRQ(ierr);
132112edc857SStefano Zampini     }
132212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
132312edc857SStefano Zampini     from = pcbddc->vec1_P;
132412edc857SStefano Zampini     to = pcbddc->coarse_vec;
132512edc857SStefano Zampini   }
132612edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1327674ae819SStefano Zampini   PetscFunctionReturn(0);
1328674ae819SStefano Zampini }
1329674ae819SStefano Zampini 
1330674ae819SStefano Zampini #undef __FUNCT__
1331674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
133212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1333674ae819SStefano Zampini {
1334674ae819SStefano Zampini   PetscErrorCode ierr;
1335674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
133612edc857SStefano Zampini   PetscScalar    *array,*array2;
133712edc857SStefano Zampini   Vec            from,to;
1338674ae819SStefano Zampini 
1339674ae819SStefano Zampini   PetscFunctionBegin;
134012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
134112edc857SStefano Zampini     from = pcbddc->coarse_vec;
134212edc857SStefano Zampini     to = pcbddc->vec1_P;
134312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
134412edc857SStefano Zampini     from = pcbddc->vec1_P;
134512edc857SStefano Zampini     to = pcbddc->coarse_vec;
134612edc857SStefano Zampini   }
134712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
134812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
134912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
135012edc857SStefano Zampini       Vec tvec;
135112edc857SStefano Zampini       PetscInt lsize;
135212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
135312edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
135412edc857SStefano Zampini       ierr = VecGetArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
135512edc857SStefano Zampini       ierr = VecGetArray(tvec,&array2);CHKERRQ(ierr);
135612edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
135712edc857SStefano Zampini       ierr = VecRestoreArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
135812edc857SStefano Zampini       ierr = VecRestoreArray(tvec,&array2);CHKERRQ(ierr);
135912edc857SStefano Zampini     }
136012edc857SStefano Zampini   }
1361674ae819SStefano Zampini   PetscFunctionReturn(0);
1362674ae819SStefano Zampini }
1363674ae819SStefano Zampini 
1364984c4197SStefano Zampini /* uncomment for testing purposes */
1365984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1366674ae819SStefano Zampini #undef __FUNCT__
1367674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1368674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1369674ae819SStefano Zampini {
1370674ae819SStefano Zampini   PetscErrorCode    ierr;
1371674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1372674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1373674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1374984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1375674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1376984c4197SStefano Zampini   /* one and zero */
1377984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1378984c4197SStefano Zampini   /* space to store constraints and their local indices */
1379984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1380984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1381984c4197SStefano Zampini   /* iterators */
1382984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1383984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1384984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1385984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1386984c4197SStefano Zampini   /* near null space stuff */
1387674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1388674ae819SStefano Zampini   const Vec         *nearnullvecs;
1389674ae819SStefano Zampini   Vec               *localnearnullsp;
1390984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1391984c4197SStefano Zampini   PetscInt          nnsp_size;
1392984c4197SStefano Zampini   PetscScalar       *array;
1393984c4197SStefano Zampini   /* BLAS integers */
1394e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1395e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1396c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1397984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1398242a89d7SStefano Zampini   PetscBool         skip_lapack;
1399984c4197SStefano Zampini   PetscScalar       *work;
1400984c4197SStefano Zampini   PetscReal         *singular_vals;
1401984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1402984c4197SStefano Zampini   PetscReal         *rwork;
1403674ae819SStefano Zampini #endif
1404984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1405e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1406984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1407b7d8b9f8SStefano Zampini #else
1408b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1409b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1410984c4197SStefano Zampini #endif
1411727cdba6SStefano Zampini   /* reuse */
1412727cdba6SStefano Zampini   PetscInt          olocal_primal_size;
1413727cdba6SStefano Zampini   PetscInt          *oprimal_indices_local_idxs;
1414984c4197SStefano Zampini   /* change of basis */
1415984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
1416a717540cSStefano Zampini   PetscBool         boolforchange,qr_needed;
1417a717540cSStefano Zampini   PetscBT           touched,change_basis,qr_needed_idx;
1418984c4197SStefano Zampini   /* auxiliary stuff */
141939e2fb2aSStefano Zampini   PetscInt          *nnz,*is_indices,*aux_primal_numbering_B;
1420911cabfeSStefano Zampini   PetscInt          ncc,*gidxs,*permutation,*temp_indices_to_constraint_work;
1421911cabfeSStefano Zampini   PetscScalar       *temp_quadrature_constraint_work;
1422984c4197SStefano Zampini   /* some quantities */
142345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
1424984c4197SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint,max_constraints,temp_constraints;
1425984c4197SStefano Zampini 
1426674ae819SStefano Zampini 
1427674ae819SStefano Zampini   PetscFunctionBegin;
14288e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
14298e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
14308e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1431674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
1432d06fc5fdSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
1433d06fc5fdSStefano Zampini   /* free unneeded index sets */
1434d06fc5fdSStefano Zampini   if (!pcbddc->use_vertices) {
1435d06fc5fdSStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1436674ae819SStefano Zampini   }
1437d06fc5fdSStefano Zampini   if (!pcbddc->use_edges) {
1438d06fc5fdSStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
1439d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1440d06fc5fdSStefano Zampini     }
1441d06fc5fdSStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1442d06fc5fdSStefano Zampini     n_ISForEdges = 0;
1443d06fc5fdSStefano Zampini   }
1444d06fc5fdSStefano Zampini   if (!pcbddc->use_faces) {
1445d06fc5fdSStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
1446d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1447d06fc5fdSStefano Zampini     }
1448d06fc5fdSStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1449d06fc5fdSStefano Zampini     n_ISForFaces = 0;
1450d06fc5fdSStefano Zampini   }
1451d06fc5fdSStefano Zampini   /* HACKS (the following two blocks of code) */
1452b9b85e73SStefano Zampini   if (!ISForVertices && pcbddc->NullSpace && !pcbddc->user_ChangeOfBasisMatrix) {
1453b8ffe317SStefano Zampini     pcbddc->use_change_of_basis = PETSC_TRUE;
1454d06fc5fdSStefano Zampini     if (!ISForEdges) {
1455d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = PETSC_TRUE;
1456d06fc5fdSStefano Zampini     }
1457b8ffe317SStefano Zampini   }
145898a51de6SStefano Zampini   if (pcbddc->NullSpace) {
145998a51de6SStefano Zampini     /* use_change_of_basis should be consistent among processors */
1460d06fc5fdSStefano Zampini     PetscBool tbool[2],gbool[2];
1461d06fc5fdSStefano Zampini     tbool [0] = pcbddc->use_change_of_basis;
1462d06fc5fdSStefano Zampini     tbool [1] = pcbddc->use_change_on_faces;
1463d06fc5fdSStefano Zampini     ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1464d06fc5fdSStefano Zampini     pcbddc->use_change_of_basis = gbool[0];
1465d06fc5fdSStefano Zampini     pcbddc->use_change_on_faces = gbool[1];
146698a51de6SStefano Zampini   }
1467984c4197SStefano Zampini   /* print some info */
1468674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
14690fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1470674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1471674ae819SStefano Zampini     i = 0;
1472674ae819SStefano Zampini     if (ISForVertices) {
1473674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1474674ae819SStefano Zampini     }
1475674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1476674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
147715aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1478674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1479674ae819SStefano Zampini   }
1480674ae819SStefano Zampini   /* check if near null space is attached to global mat */
1481674ae819SStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1482674ae819SStefano Zampini   if (nearnullsp) {
1483674ae819SStefano Zampini     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1484f4ddd8eeSStefano Zampini     /* remove any stored info */
1485f4ddd8eeSStefano Zampini     ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1486f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1487f4ddd8eeSStefano Zampini     /* store information for BDDC solver reuse */
1488f4ddd8eeSStefano Zampini     ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
1489f4ddd8eeSStefano Zampini     pcbddc->onearnullspace = nearnullsp;
1490473ba861SJed Brown     ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1491f4ddd8eeSStefano Zampini     for (i=0;i<nnsp_size;i++) {
1492f4ddd8eeSStefano Zampini       ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
1493f4ddd8eeSStefano Zampini     }
1494984c4197SStefano Zampini   } else { /* if near null space is not provided BDDC uses constants by default */
1495984c4197SStefano Zampini     nnsp_size = 0;
1496674ae819SStefano Zampini     nnsp_has_cnst = PETSC_TRUE;
1497674ae819SStefano Zampini   }
1498984c4197SStefano Zampini   /* get max number of constraints on a single cc */
1499984c4197SStefano Zampini   max_constraints = nnsp_size;
1500984c4197SStefano Zampini   if (nnsp_has_cnst) max_constraints++;
1501984c4197SStefano Zampini 
1502674ae819SStefano Zampini   /*
1503674ae819SStefano Zampini        Evaluate maximum storage size needed by the procedure
1504674ae819SStefano Zampini        - temp_indices will contain start index of each constraint stored as follows
1505911cabfeSStefano 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
1506911cabfeSStefano 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
1507911cabfeSStefano Zampini        - temp_quadrature_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the scalars representing the constraint itself
1508674ae819SStefano Zampini                                                                                                                                                          */
1509674ae819SStefano Zampini   total_counts = n_ISForFaces+n_ISForEdges;
1510984c4197SStefano Zampini   total_counts *= max_constraints;
1511674ae819SStefano Zampini   n_vertices = 0;
1512674ae819SStefano Zampini   if (ISForVertices) {
1513674ae819SStefano Zampini     ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1514674ae819SStefano Zampini   }
1515674ae819SStefano Zampini   total_counts += n_vertices;
1516854ce69bSBarry Smith   ierr = PetscMalloc1(total_counts+1,&temp_indices);CHKERRQ(ierr);
15174641a718SStefano Zampini   ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1518674ae819SStefano Zampini   total_counts = 0;
1519674ae819SStefano Zampini   max_size_of_constraint = 0;
1520674ae819SStefano Zampini   for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1521674ae819SStefano Zampini     if (i<n_ISForEdges) {
1522674ae819SStefano Zampini       used_IS = &ISForEdges[i];
1523674ae819SStefano Zampini     } else {
1524674ae819SStefano Zampini       used_IS = &ISForFaces[i-n_ISForEdges];
1525674ae819SStefano Zampini     }
1526674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1527674ae819SStefano Zampini     total_counts += j;
1528674ae819SStefano Zampini     max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1529674ae819SStefano Zampini   }
1530984c4197SStefano Zampini   total_counts *= max_constraints;
1531674ae819SStefano Zampini   total_counts += n_vertices;
1532906d46d4SStefano Zampini   ierr = PetscMalloc3(total_counts,&temp_quadrature_constraint,total_counts,&temp_indices_to_constraint,total_counts,&temp_indices_to_constraint_B);CHKERRQ(ierr);
1533984c4197SStefano Zampini   /* get local part of global near null space vectors */
1534785e854fSJed Brown   ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
1535984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1536984c4197SStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1537984c4197SStefano Zampini     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1538984c4197SStefano Zampini     ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1539984c4197SStefano Zampini   }
1540674ae819SStefano Zampini 
1541242a89d7SStefano Zampini   /* whether or not to skip lapack calls */
1542242a89d7SStefano Zampini   skip_lapack = PETSC_TRUE;
1543a773dcb8SStefano Zampini   if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
1544242a89d7SStefano Zampini 
15458f1c130eSStefano Zampini   /* allocate some auxiliary stuff */
15468f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
15478f1c130eSStefano 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);
15488f1c130eSStefano Zampini   }
15498f1c130eSStefano Zampini 
1550984c4197SStefano Zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1551a773dcb8SStefano Zampini   if (!skip_lapack) {
1552674ae819SStefano Zampini     PetscScalar temp_work;
1553911cabfeSStefano Zampini 
1554674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1555984c4197SStefano Zampini     /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1556785e854fSJed Brown     ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
1557785e854fSJed Brown     ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
1558785e854fSJed Brown     ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
1559674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1560785e854fSJed Brown     ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
1561674ae819SStefano Zampini #endif
1562674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1563c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1564c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1565674ae819SStefano Zampini     lwork = -1;
1566674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1567674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1568c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1569674ae819SStefano Zampini #else
1570c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1571674ae819SStefano Zampini #endif
1572674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1573984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1574674ae819SStefano Zampini #else /* on missing GESVD */
1575674ae819SStefano Zampini     /* SVD */
1576674ae819SStefano Zampini     PetscInt max_n,min_n;
1577674ae819SStefano Zampini     max_n = max_size_of_constraint;
1578984c4197SStefano Zampini     min_n = max_constraints;
1579984c4197SStefano Zampini     if (max_size_of_constraint < max_constraints) {
1580674ae819SStefano Zampini       min_n = max_size_of_constraint;
1581984c4197SStefano Zampini       max_n = max_constraints;
1582674ae819SStefano Zampini     }
1583785e854fSJed Brown     ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
1584674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1585785e854fSJed Brown     ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
1586674ae819SStefano Zampini #endif
1587674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1588674ae819SStefano Zampini     lwork = -1;
1589e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1590e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1591b7d8b9f8SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1592674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1593674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1594e310c8b4SStefano 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));
1595674ae819SStefano Zampini #else
1596e310c8b4SStefano 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));
1597674ae819SStefano Zampini #endif
1598674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1599984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1600984c4197SStefano Zampini #endif /* on missing GESVD */
1601674ae819SStefano Zampini     /* Allocate optimal workspace */
1602674ae819SStefano Zampini     ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1603854ce69bSBarry Smith     ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
1604674ae819SStefano Zampini   }
1605674ae819SStefano Zampini   /* Now we can loop on constraining sets */
1606674ae819SStefano Zampini   total_counts = 0;
1607674ae819SStefano Zampini   temp_indices[0] = 0;
1608674ae819SStefano Zampini   /* vertices */
1609674ae819SStefano Zampini   if (ISForVertices) {
1610674ae819SStefano Zampini     ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1611674ae819SStefano Zampini     if (nnsp_has_cnst) { /* consider all vertices */
161239e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
1613674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1614674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1615674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1616674ae819SStefano Zampini         total_counts++;
1617674ae819SStefano Zampini       }
1618674ae819SStefano Zampini     } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1619984c4197SStefano Zampini       PetscBool used_vertex;
1620674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1621674ae819SStefano Zampini         used_vertex = PETSC_FALSE;
1622674ae819SStefano Zampini         k = 0;
1623674ae819SStefano Zampini         while (!used_vertex && k<nnsp_size) {
1624984c4197SStefano Zampini           ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1625984c4197SStefano Zampini           if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1626674ae819SStefano Zampini             temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1627674ae819SStefano Zampini             temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1628674ae819SStefano Zampini             temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1629674ae819SStefano Zampini             total_counts++;
1630674ae819SStefano Zampini             used_vertex = PETSC_TRUE;
1631674ae819SStefano Zampini           }
1632984c4197SStefano Zampini           ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1633674ae819SStefano Zampini           k++;
1634674ae819SStefano Zampini         }
1635674ae819SStefano Zampini       }
1636674ae819SStefano Zampini     }
1637674ae819SStefano Zampini     ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1638674ae819SStefano Zampini     n_vertices = total_counts;
1639674ae819SStefano Zampini   }
1640984c4197SStefano Zampini 
1641674ae819SStefano Zampini   /* edges and faces */
1642911cabfeSStefano Zampini   for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
1643911cabfeSStefano Zampini     if (ncc<n_ISForEdges) {
1644911cabfeSStefano Zampini       used_IS = &ISForEdges[ncc];
1645984c4197SStefano Zampini       boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1646674ae819SStefano Zampini     } else {
1647911cabfeSStefano Zampini       used_IS = &ISForFaces[ncc-n_ISForEdges];
1648984c4197SStefano Zampini       boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1649674ae819SStefano Zampini     }
1650674ae819SStefano Zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1651674ae819SStefano Zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1652674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1653674ae819SStefano Zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1654984c4197SStefano Zampini     /* change of basis should not be performed on local periodic nodes */
1655984c4197SStefano Zampini     if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1656674ae819SStefano Zampini     if (nnsp_has_cnst) {
16575b08dc53SStefano Zampini       PetscScalar quad_value;
1658674ae819SStefano Zampini       temp_constraints++;
1659a773dcb8SStefano Zampini       if (!pcbddc->use_nnsp_true) {
1660674ae819SStefano Zampini         quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1661a773dcb8SStefano Zampini       } else {
1662a773dcb8SStefano Zampini         quad_value = 1.0;
1663a773dcb8SStefano Zampini       }
166439e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1665674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1666674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1667674ae819SStefano Zampini       }
1668911cabfeSStefano Zampini       /* sort by global ordering if using lapack subroutines */
16698f1c130eSStefano Zampini       if (!skip_lapack || pcbddc->use_qr_single) {
1670911cabfeSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1671911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1672911cabfeSStefano Zampini           permutation[j]=j;
1673911cabfeSStefano Zampini         }
1674911cabfeSStefano Zampini         ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1675911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1676911cabfeSStefano Zampini           temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1677911cabfeSStefano Zampini           temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1678911cabfeSStefano Zampini         }
1679911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1680911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1681911cabfeSStefano Zampini       }
1682674ae819SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1683674ae819SStefano Zampini       total_counts++;
1684674ae819SStefano Zampini     }
1685674ae819SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1686984c4197SStefano Zampini       PetscReal real_value;
1687984c4197SStefano Zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
168839e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1689674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1690984c4197SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
1691674ae819SStefano Zampini       }
1692984c4197SStefano Zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1693984c4197SStefano Zampini       /* check if array is null on the connected component */
1694e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1695e310c8b4SStefano Zampini       PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
16965b08dc53SStefano Zampini       if (real_value > 0.0) { /* keep indices and values */
1697911cabfeSStefano Zampini         /* sort by global ordering if using lapack subroutines */
16988f1c130eSStefano Zampini         if (!skip_lapack || pcbddc->use_qr_single) {
1699911cabfeSStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1700911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1701911cabfeSStefano Zampini             permutation[j]=j;
1702911cabfeSStefano Zampini           }
1703911cabfeSStefano Zampini           ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1704911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1705911cabfeSStefano Zampini             temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1706911cabfeSStefano Zampini             temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1707911cabfeSStefano Zampini           }
1708911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1709911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1710911cabfeSStefano Zampini         }
1711674ae819SStefano Zampini         temp_constraints++;
1712674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1713674ae819SStefano Zampini         total_counts++;
1714674ae819SStefano Zampini       }
1715674ae819SStefano Zampini     }
1716674ae819SStefano Zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
171745a1bb75SStefano Zampini     valid_constraints = temp_constraints;
1718eb97c9d2SStefano Zampini     if (!pcbddc->use_nnsp_true && temp_constraints) {
1719a773dcb8SStefano Zampini       if (temp_constraints == 1) { /* just normalize the constraint */
1720a773dcb8SStefano Zampini         PetscScalar norm;
1721a773dcb8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1722a773dcb8SStefano 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));
1723a773dcb8SStefano Zampini         norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
1724a773dcb8SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
1725a773dcb8SStefano Zampini       } else { /* perform SVD */
1726984c4197SStefano Zampini         PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
1727674ae819SStefano Zampini 
1728674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1729984c4197SStefano Zampini         /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
1730984c4197SStefano Zampini            POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
1731984c4197SStefano Zampini            -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
1732984c4197SStefano Zampini               the constraints basis will differ (by a complex factor with absolute value equal to 1)
1733984c4197SStefano Zampini               from that computed using LAPACKgesvd
1734984c4197SStefano Zampini            -> This is due to a different computation of eigenvectors in LAPACKheev
1735984c4197SStefano Zampini            -> The quality of the POD-computed basis will be the same */
1736984c4197SStefano Zampini         ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
1737674ae819SStefano Zampini         /* Store upper triangular part of correlation matrix */
1738e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1739984c4197SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1740674ae819SStefano Zampini         for (j=0;j<temp_constraints;j++) {
1741674ae819SStefano Zampini           for (k=0;k<j+1;k++) {
1742e310c8b4SStefano 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));
1743674ae819SStefano Zampini           }
1744674ae819SStefano Zampini         }
1745e310c8b4SStefano Zampini         /* compute eigenvalues and eigenvectors of correlation matrix */
1746e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1747e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
1748674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1749c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
1750674ae819SStefano Zampini #else
1751c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
1752674ae819SStefano Zampini #endif
1753674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1754984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
1755984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
1756674ae819SStefano Zampini         j = 0;
1757984c4197SStefano Zampini         while (j < temp_constraints && singular_vals[j] < tol) j++;
1758674ae819SStefano Zampini         total_counts = total_counts-j;
175945a1bb75SStefano Zampini         valid_constraints = temp_constraints-j;
1760e310c8b4SStefano Zampini         /* scale and copy POD basis into used quadrature memory */
1761c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1762c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1763c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
1764c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1765c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
1766c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
1767674ae819SStefano Zampini         if (j<temp_constraints) {
1768984c4197SStefano Zampini           PetscInt ii;
1769984c4197SStefano Zampini           for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
1770674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1771c4303822SStefano 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));
1772674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1773984c4197SStefano Zampini           for (k=0;k<temp_constraints-j;k++) {
1774674ae819SStefano Zampini             for (ii=0;ii<size_of_constraint;ii++) {
1775984c4197SStefano 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];
1776674ae819SStefano Zampini             }
1777674ae819SStefano Zampini           }
1778674ae819SStefano Zampini         }
1779674ae819SStefano Zampini #else  /* on missing GESVD */
1780e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1781e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1782b7d8b9f8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1783674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1784674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1785e310c8b4SStefano 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));
1786674ae819SStefano Zampini #else
1787e310c8b4SStefano 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));
1788674ae819SStefano Zampini #endif
1789984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
1790674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1791984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
1792e310c8b4SStefano Zampini         k = temp_constraints;
1793e310c8b4SStefano Zampini         if (k > size_of_constraint) k = size_of_constraint;
1794674ae819SStefano Zampini         j = 0;
1795e310c8b4SStefano Zampini         while (j < k && singular_vals[k-j-1] < tol) j++;
179645a1bb75SStefano Zampini         valid_constraints = k-j;
1797911cabfeSStefano Zampini         total_counts = total_counts-temp_constraints+valid_constraints;
1798984c4197SStefano Zampini #endif /* on missing GESVD */
1799674ae819SStefano Zampini       }
1800a773dcb8SStefano Zampini     }
180145a1bb75SStefano Zampini     /* setting change_of_basis flag is safe now */
180245a1bb75SStefano Zampini     if (boolforchange) {
180345a1bb75SStefano Zampini       for (j=0;j<valid_constraints;j++) {
180445a1bb75SStefano Zampini         PetscBTSet(change_basis,total_counts-j-1);
180545a1bb75SStefano Zampini       }
180645a1bb75SStefano Zampini     }
1807674ae819SStefano Zampini   }
1808674ae819SStefano Zampini   /* free index sets of faces, edges and vertices */
1809674ae819SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
1810674ae819SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1811674ae819SStefano Zampini   }
1812d06fc5fdSStefano Zampini   if (n_ISForFaces) {
1813674ae819SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1814d06fc5fdSStefano Zampini   }
1815674ae819SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
1816674ae819SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1817674ae819SStefano Zampini   }
1818d06fc5fdSStefano Zampini   if (n_ISForEdges) {
1819674ae819SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1820d06fc5fdSStefano Zampini   }
1821674ae819SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
182239e2fb2aSStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
18235e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
182439e2fb2aSStefano Zampini   if (i != temp_indices[total_counts]) {
182539e2fb2aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
182639e2fb2aSStefano Zampini   }
1827674ae819SStefano Zampini 
1828984c4197SStefano Zampini   /* free workspace */
18298f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
1830911cabfeSStefano Zampini     ierr = PetscFree4(gidxs,permutation,temp_indices_to_constraint_work,temp_quadrature_constraint_work);CHKERRQ(ierr);
18318f1c130eSStefano Zampini   }
18328f1c130eSStefano Zampini   if (!skip_lapack) {
1833984c4197SStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
1834984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1835984c4197SStefano Zampini     ierr = PetscFree(rwork);CHKERRQ(ierr);
1836984c4197SStefano Zampini #endif
1837984c4197SStefano Zampini     ierr = PetscFree(singular_vals);CHKERRQ(ierr);
1838984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1839984c4197SStefano Zampini     ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
1840984c4197SStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
1841984c4197SStefano Zampini #endif
1842984c4197SStefano Zampini   }
1843984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1844984c4197SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1845984c4197SStefano Zampini   }
1846984c4197SStefano Zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
1847984c4197SStefano Zampini 
1848727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
1849984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
1850674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
1851727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
1852984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
1853674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
1854984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
1855674ae819SStefano Zampini 
1856674ae819SStefano Zampini   /* Create constraint matrix */
1857674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
1858674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
1859674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1860674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
1861984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
1862984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
1863785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
1864984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
1865984c4197SStefano 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 */
1866785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
1867984c4197SStefano Zampini   /* auxiliary stuff for basis change */
1868785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
18694641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
1870984c4197SStefano Zampini 
1871984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
1872984c4197SStefano Zampini   total_primal_vertices=0;
1873984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
1874674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1875984c4197SStefano Zampini     if (size_of_constraint == 1) {
18764641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
1877984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
1878984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
1879984c4197SStefano Zampini       total_primal_vertices++;
18804641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
1881984c4197SStefano Zampini       PetscInt min_loc,min_index;
1882984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
1883984c4197SStefano Zampini       /* find first untouched local node */
1884674ae819SStefano Zampini       k = 0;
18854641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
1886984c4197SStefano Zampini       min_index = global_indices[k];
1887984c4197SStefano Zampini       min_loc = k;
1888984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
1889984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
1890984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
18914641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
1892984c4197SStefano Zampini           min_index = global_indices[k];
1893984c4197SStefano Zampini           min_loc = k;
1894674ae819SStefano Zampini         }
1895674ae819SStefano Zampini       }
18964641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
1897984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
1898984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
1899984c4197SStefano Zampini       total_primal_vertices++;
1900984c4197SStefano Zampini     }
1901984c4197SStefano Zampini   }
1902a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
1903a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
1904a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
1905a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
1906a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
1907fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
1908a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
1909a717540cSStefano Zampini         j = 0;
1910a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
1911a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
1912a717540cSStefano Zampini             j++;
1913a717540cSStefano Zampini           }
1914a717540cSStefano Zampini         }
1915a717540cSStefano Zampini         /* found more than one primal dof on the cc */
1916a717540cSStefano Zampini         if (j > 1) {
1917a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
1918a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
1919a717540cSStefano Zampini         }
1920fa434743SStefano Zampini       } else {
1921fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
1922fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
1923fa434743SStefano Zampini       }
1924a717540cSStefano Zampini     }
1925a717540cSStefano Zampini   }
1926984c4197SStefano Zampini   /* free workspace */
1927984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
192845a1bb75SStefano Zampini 
1929674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
1930a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
1931984c4197SStefano Zampini 
1932984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
1933785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
1934984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
1935984c4197SStefano Zampini   j=total_primal_vertices;
1936984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
19374641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
1938674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
1939674ae819SStefano Zampini       j++;
1940674ae819SStefano Zampini     }
1941674ae819SStefano Zampini   }
1942674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
1943674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
1944674ae819SStefano Zampini   /* set values in constraint matrix */
1945984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
1946984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
1947674ae819SStefano Zampini   }
1948984c4197SStefano Zampini   total_counts = total_primal_vertices;
1949984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
19504641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
1951674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
1952674ae819SStefano 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);
1953674ae819SStefano Zampini       total_counts++;
1954674ae819SStefano Zampini     }
1955674ae819SStefano Zampini   }
1956674ae819SStefano Zampini   /* assembling */
1957674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1958674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1959984c4197SStefano Zampini   /*
196045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
1961984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
1962984c4197SStefano Zampini   */
1963674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
1964674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
1965026de310SStefano Zampini     /* dual and primal dofs on a single cc */
1966984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
1967026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
1968026de310SStefano Zampini     PetscInt     primal_counter;
1969984c4197SStefano Zampini     /* working stuff for GEQRF */
197081d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
1971984c4197SStefano Zampini     PetscBLASInt lqr_work;
1972984c4197SStefano Zampini     /* working stuff for UNGQR */
1973984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
1974984c4197SStefano Zampini     PetscBLASInt lgqr_work;
1975984c4197SStefano Zampini     /* working stuff for TRTRS */
1976984c4197SStefano Zampini     PetscScalar  *trs_rhs;
19773f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
1978984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
1979984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
1980984c4197SStefano Zampini     PetscScalar  *start_vals;
1981984c4197SStefano Zampini     /* working stuff for values insertion */
19824641a718SStefano Zampini     PetscBT      is_primal;
1983906d46d4SStefano Zampini     /* matrix sizes */
1984906d46d4SStefano Zampini     PetscInt     global_size,local_size;
1985906d46d4SStefano Zampini     /* work array for nonzeros */
1986906d46d4SStefano Zampini     PetscScalar  *nnz_array;
1987906d46d4SStefano Zampini     /* temporary change of basis */
1988906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
1989906d46d4SStefano Zampini     /* auxiliary work for global change of basis */
1990906d46d4SStefano Zampini     Vec          nnz_vec;
199122bc73bbSStefano Zampini     PetscInt     *idxs_I,*idxs_B,*idxs_all,*d_nnz,*o_nnz;
1992906d46d4SStefano Zampini     PetscInt     nvtxs,*xadj,*adjncy,*idxs_mapped;
1993906d46d4SStefano Zampini     PetscScalar  *vals;
1994906d46d4SStefano Zampini     PetscBool    done;
1995984c4197SStefano Zampini 
1996906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
1997906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
1998906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
1999906d46d4SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2000906d46d4SStefano Zampini 
2001906d46d4SStefano Zampini     /* nonzeros for local mat */
2002785e854fSJed Brown     ierr = PetscMalloc1(pcis->n_B,&nnz);CHKERRQ(ierr);
2003a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) nnz[i]=1;
2004a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2005a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2006a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2007a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2008a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2009a717540cSStefano Zampini         } else {
2010a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = 2;
2011a717540cSStefano Zampini           /* get local primal index on the cc */
2012a717540cSStefano Zampini           j = 0;
2013a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2014a717540cSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2015a717540cSStefano Zampini         }
2016a717540cSStefano Zampini       }
2017a717540cSStefano Zampini     }
2018906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2019a717540cSStefano Zampini     /* Set initial identity in the matrix */
2020a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2021906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2022a717540cSStefano Zampini     }
2023a717540cSStefano Zampini 
2024a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2025a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2026a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2027a717540cSStefano Zampini     }
2028a717540cSStefano Zampini 
2029a717540cSStefano Zampini 
2030a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2031a717540cSStefano Zampini     /*
2032a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2033a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2034a717540cSStefano Zampini 
2035a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2036a717540cSStefano Zampini 
2037a6b551f4SStefano 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)
2038a6b551f4SStefano Zampini 
2039a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2040a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2041a717540cSStefano Zampini             |              ...                        |
2042a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2043a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2044a717540cSStefano Zampini 
2045a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2046a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2047a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2048a6b551f4SStefano Zampini 
2049a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2050a717540cSStefano Zampini     */
2051a717540cSStefano Zampini     if (qr_needed) {
2052984c4197SStefano Zampini       /* space to store Q */
2053854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2054984c4197SStefano Zampini       /* first we issue queries for optimal work */
20553f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
20563f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
20573f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2058984c4197SStefano Zampini       lqr_work = -1;
20593f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2060984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2061984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2062785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2063984c4197SStefano Zampini       lgqr_work = -1;
20643f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
20653f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
20663f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
20673f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
20683f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
20693f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2070984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2071984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2072785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2073984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2074785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2075984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2076785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2077a717540cSStefano Zampini       /* allocating workspace for check */
2078a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2079785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2080a717540cSStefano Zampini       }
2081a717540cSStefano Zampini     }
2082984c4197SStefano Zampini     /* array to store whether a node is primal or not */
20834641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2084473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
20855e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
208639e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
208739e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
20884641a718SStefano Zampini     }
208939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
209039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
209139e2fb2aSStefano Zampini     }
209239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2093984c4197SStefano Zampini 
2094a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2095026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2096026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2097026de310SStefano Zampini     primal_counter = total_counts;
2098026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2099026de310SStefano Zampini       primal_dofs = 1;
21004641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2101026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2102026de310SStefano 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]]) {
2103026de310SStefano Zampini           primal_dofs++;
2104674ae819SStefano Zampini         }
2105984c4197SStefano Zampini         /* get constraint info */
2106026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2107984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2108984c4197SStefano Zampini 
2109984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2110a717540cSStefano 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);
2111674ae819SStefano Zampini         }
2112984c4197SStefano Zampini 
2113fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2114a717540cSStefano Zampini 
2115a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2116a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2117a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2118a717540cSStefano Zampini           }
2119984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2120026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2121984c4197SStefano Zampini 
2122984c4197SStefano Zampini           /* compute QR decomposition of constraints */
21233f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
21243f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
21253f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2126674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21273f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2128984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2129674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2130984c4197SStefano Zampini 
2131984c4197SStefano Zampini           /* explictly compute R^-T */
2132984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2133984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
21343f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
21353f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
21363f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
21373f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2138984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21393f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2140984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2141984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2142984c4197SStefano Zampini 
2143a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
21443f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
21453f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
21463f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
21473f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2148984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21493f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2150984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2151984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2152984c4197SStefano Zampini 
2153984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2154984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2155984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
21563f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
21573f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
21583f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
21593f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
21603f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
21613f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2162984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2163c4303822SStefano 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));
2164984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2165026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2166984c4197SStefano Zampini 
2167984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2168026de310SStefano Zampini           start_rows = &temp_indices_to_constraint_B[temp_indices[total_counts]];
2169984c4197SStefano Zampini           /* insert cols for primal dofs */
2170984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2171984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2172026de310SStefano Zampini             start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2173906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2174984c4197SStefano Zampini           }
2175984c4197SStefano Zampini           /* insert cols for dual dofs */
2176984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
21774641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2178984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2179026de310SStefano Zampini               start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2180906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2181984c4197SStefano Zampini               j++;
2182674ae819SStefano Zampini             }
2183674ae819SStefano Zampini           }
2184984c4197SStefano Zampini 
2185984c4197SStefano Zampini           /* check change of basis */
2186984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2187984c4197SStefano Zampini             PetscInt   ii,jj;
2188984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2189c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2190c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2191c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2192c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2193c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2194c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2195984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2196c4303822SStefano 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));
2197984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2198984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2199984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2200984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2201984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2202674ae819SStefano Zampini               }
2203674ae819SStefano Zampini             }
2204984c4197SStefano Zampini             if (!valid_qr) {
220522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2206984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2207984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2208984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2209984c4197SStefano 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]));
2210674ae819SStefano Zampini                   }
2211984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2212984c4197SStefano 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]));
2213984c4197SStefano Zampini                   }
2214984c4197SStefano Zampini                 }
2215984c4197SStefano Zampini               }
2216674ae819SStefano Zampini             } else {
221722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2218674ae819SStefano Zampini             }
2219674ae819SStefano Zampini           }
2220a717540cSStefano Zampini         } else { /* simple transformation block */
2221a717540cSStefano Zampini           PetscInt    row,col;
2222a6b551f4SStefano Zampini           PetscScalar val,norm;
2223a6b551f4SStefano Zampini 
2224a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2225a6b551f4SStefano 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));
2226a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2227a717540cSStefano Zampini             row = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2228a717540cSStefano Zampini             if (!PetscBTLookup(is_primal,row)) {
2229a717540cSStefano Zampini               col = temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2230906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2231a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2232a717540cSStefano Zampini             } else {
2233a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2234a717540cSStefano Zampini                 col = temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2235a717540cSStefano Zampini                 if (row != col) {
2236a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2237a717540cSStefano Zampini                 } else {
2238a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2239a717540cSStefano Zampini                 }
2240906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2241a717540cSStefano Zampini               }
2242a717540cSStefano Zampini             }
2243a717540cSStefano Zampini           }
224498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
224522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2246a717540cSStefano Zampini           }
2247674ae819SStefano Zampini         }
2248026de310SStefano Zampini         /* increment primal counter */
2249026de310SStefano Zampini         primal_counter += primal_dofs;
2250984c4197SStefano Zampini       } else {
2251984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2252026de310SStefano 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);
2253674ae819SStefano Zampini         }
2254674ae819SStefano Zampini       }
2255026de310SStefano Zampini       /* increment constraint counter total_counts */
2256026de310SStefano Zampini       total_counts += primal_dofs;
2257674ae819SStefano Zampini     }
2258a717540cSStefano Zampini 
2259a717540cSStefano Zampini     /* free workspace */
2260a717540cSStefano Zampini     if (qr_needed) {
2261984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2262984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2263984c4197SStefano Zampini       }
2264984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2265984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2266984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2267984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2268984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2269674ae819SStefano Zampini     }
2270a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2271906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2272906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2273906d46d4SStefano Zampini 
2274906d46d4SStefano Zampini     /* assembling of global change of variable */
2275906d46d4SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2276906d46d4SStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2277906d46d4SStefano Zampini     ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2278906d46d4SStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2279906d46d4SStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2280906d46d4SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->ChangeOfBasisMatrix,matis->mapping,matis->mapping);CHKERRQ(ierr);
2281906d46d4SStefano Zampini 
2282906d46d4SStefano Zampini     /* nonzeros (overestimated) */
2283906d46d4SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nnz_vec);CHKERRQ(ierr);
2284906d46d4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(nnz_vec,matis->mapping);CHKERRQ(ierr);
2285906d46d4SStefano Zampini     ierr = PetscMalloc2(pcis->n,&nnz_array,pcis->n,&idxs_all);CHKERRQ(ierr);
2286906d46d4SStefano Zampini     for (i=0;i<pcis->n;i++) {
2287906d46d4SStefano Zampini       nnz_array[i] = 1.0;
2288906d46d4SStefano Zampini       idxs_all[i] = i;
2289906d46d4SStefano Zampini     }
2290906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2291906d46d4SStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2292906d46d4SStefano Zampini       nnz_array[idxs_B[i]] = nnz[i];
2293906d46d4SStefano Zampini     }
2294a5187659SStefano Zampini     if (pcis->n) {
2295906d46d4SStefano Zampini       ierr = VecSetValuesLocal(nnz_vec,pcis->n,idxs_all,nnz_array,INSERT_VALUES);CHKERRQ(ierr);
2296a5187659SStefano Zampini     }
2297906d46d4SStefano Zampini     ierr = VecAssemblyBegin(nnz_vec);CHKERRQ(ierr);
2298906d46d4SStefano Zampini     ierr = VecAssemblyEnd(nnz_vec);CHKERRQ(ierr);
2299906d46d4SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2300906d46d4SStefano Zampini     ierr = PetscFree2(nnz_array,idxs_all);CHKERRQ(ierr);
230122bc73bbSStefano Zampini     ierr = PetscMalloc2(local_size,&d_nnz,local_size,&o_nnz);CHKERRQ(ierr);
2302906d46d4SStefano Zampini     ierr = VecGetArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2303906d46d4SStefano Zampini     for (i=0;i<local_size;i++) {
230422bc73bbSStefano Zampini       d_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),local_size);
230522bc73bbSStefano Zampini       o_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),global_size-local_size);
2306906d46d4SStefano Zampini     }
2307906d46d4SStefano Zampini     ierr = VecRestoreArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2308906d46d4SStefano Zampini     ierr = VecDestroy(&nnz_vec);CHKERRQ(ierr);
230922bc73bbSStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,d_nnz,0,o_nnz);CHKERRQ(ierr);
231022bc73bbSStefano Zampini     ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
2311906d46d4SStefano Zampini 
2312906d46d4SStefano Zampini     /* Set identity on dirichlet dofs */
2313906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2314906d46d4SStefano Zampini     for (i=0;i<pcis->n-pcis->n_B;i++) {
2315906d46d4SStefano Zampini       PetscScalar one=1.0;
2316906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,idxs_I+i,1,idxs_I+i,&one,INSERT_VALUES);CHKERRQ(ierr);
2317906d46d4SStefano Zampini     }
2318906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2319906d46d4SStefano Zampini 
2320906d46d4SStefano Zampini     /* Set values at interface dofs */
2321906d46d4SStefano Zampini     done = PETSC_TRUE;
2322906d46d4SStefano Zampini     ierr = MatGetRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2323906d46d4SStefano Zampini     if (!done) {
2324906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2325906d46d4SStefano Zampini     }
2326906d46d4SStefano Zampini     ierr = MatSeqAIJGetArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2327906d46d4SStefano Zampini     ierr = PetscMalloc1(xadj[nvtxs],&idxs_mapped);CHKERRQ(ierr);
23285e8657edSStefano Zampini     ierr = ISLocalToGlobalMappingApply(pcis->BtoNmap,xadj[nvtxs],adjncy,idxs_mapped);CHKERRQ(ierr);
2329906d46d4SStefano Zampini     for (i=0;i<nvtxs;i++) {
2330906d46d4SStefano Zampini       PetscInt    row,*cols,ncols;
2331906d46d4SStefano Zampini       PetscScalar *mat_vals;
2332906d46d4SStefano Zampini 
2333906d46d4SStefano Zampini       row = idxs_B[i];
2334906d46d4SStefano Zampini       ncols = xadj[i+1]-xadj[i];
2335906d46d4SStefano Zampini       cols = idxs_mapped+xadj[i];
2336906d46d4SStefano Zampini       mat_vals = vals+xadj[i];
2337906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,&row,ncols,cols,mat_vals,INSERT_VALUES);CHKERRQ(ierr);
2338906d46d4SStefano Zampini     }
2339906d46d4SStefano Zampini     ierr = MatRestoreRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2340906d46d4SStefano Zampini     if (!done) {
2341906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2342906d46d4SStefano Zampini     }
2343906d46d4SStefano Zampini     ierr = MatSeqAIJRestoreArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2344906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2345906d46d4SStefano Zampini     ierr = PetscFree(idxs_mapped);CHKERRQ(ierr);
2346674ae819SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2347674ae819SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2348906d46d4SStefano Zampini 
2349906d46d4SStefano Zampini     /* check */
2350906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2351906d46d4SStefano Zampini       PetscReal error;
2352906d46d4SStefano Zampini       Vec       x,x_change;
2353906d46d4SStefano Zampini 
2354906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2355906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2356906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2357906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2358906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2359906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2360906d46d4SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
2361906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2362906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2363906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2364906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2365906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2366906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2367906d46d4SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on B: %1.6e\n",error);CHKERRQ(ierr);
2368906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2369906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2370906d46d4SStefano Zampini     }
2371906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2372906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2373b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2374b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2375b9b85e73SStefano Zampini   }
2376906d46d4SStefano Zampini 
2377906d46d4SStefano Zampini   /* set up change of basis context */
2378906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2379906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2380906d46d4SStefano Zampini 
2381906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2382906d46d4SStefano Zampini       PetscInt global_size,local_size;
2383906d46d4SStefano Zampini 
2384906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2385906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2386906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2387906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2388906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2389906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2390906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2391906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2392906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2393906d46d4SStefano Zampini     } else {
2394906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2395906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2396906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2397906d46d4SStefano Zampini     }
2398906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2399906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2400906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2401906d46d4SStefano Zampini     } else {
2402906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2403906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2404906d46d4SStefano Zampini     }
2405906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2406906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2407906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2408906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2409b9b85e73SStefano Zampini   }
2410a717540cSStefano Zampini 
2411727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2412727cdba6SStefano 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 */
2413473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2414727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2415727cdba6SStefano Zampini   }
2416727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2417f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2418473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2419727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2420727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2421727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2422727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2423727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2424727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2425e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2426e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2427727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2428727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2429727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2430727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2431c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2432727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2433727cdba6SStefano Zampini   }
2434727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2435727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2436727cdba6SStefano Zampini 
2437a717540cSStefano Zampini   /* flush dbg viewer */
2438b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2439b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2440b8ffe317SStefano Zampini   }
2441a717540cSStefano Zampini 
2442e310c8b4SStefano Zampini   /* free workspace */
2443a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2444a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2445984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
24464641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
2447906d46d4SStefano Zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2448906d46d4SStefano Zampini   ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
2449674ae819SStefano Zampini   PetscFunctionReturn(0);
2450674ae819SStefano Zampini }
2451674ae819SStefano Zampini 
2452674ae819SStefano Zampini #undef __FUNCT__
2453674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2454674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2455674ae819SStefano Zampini {
2456674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2457674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2458674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
245963602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2460674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2461674ae819SStefano Zampini 
2462674ae819SStefano Zampini   PetscFunctionBegin;
24638e61c736SStefano Zampini   /* Reset previously computed graph */
24648e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2465674ae819SStefano Zampini   /* Init local Graph struct */
2466674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2467674ae819SStefano Zampini 
2468575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2469575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2470575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2471575ad6abSStefano Zampini   }
24729577ea80SStefano Zampini 
2473674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
24744d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2475674ae819SStefano Zampini     Mat       mat_adj;
24764d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
24774d379d7bSStefano Zampini     PetscInt  nvtxs;
2478674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2479674ae819SStefano Zampini 
2480674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
24814d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2482674ae819SStefano Zampini     if (!flg_row) {
2483674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2484674ae819SStefano Zampini     }
24854d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
24864d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
24874d379d7bSStefano Zampini       pcbddc->deluxe_compute_rowadj = PETSC_FALSE;
24884d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
24894d379d7bSStefano Zampini       IS                     is_dummy;
24904d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
24914d379d7bSStefano Zampini       PetscInt               j,sum;
24924d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
24934d379d7bSStefano Zampini       const PetscInt         *idxs;
24944d379d7bSStefano Zampini       PCBDDCGraph            graph;
24954d379d7bSStefano Zampini       PetscBT                is_on_boundary;
24964d379d7bSStefano Zampini 
24974d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
24984d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
24994d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25004d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
25014d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
25024d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
25034d379d7bSStefano Zampini       graph->xadj = xadj;
25044d379d7bSStefano Zampini       graph->adjncy = adjncy;
25054d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
25064d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
25074d379d7bSStefano Zampini 
25084d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
25094d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
25104d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
25114d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
25124d379d7bSStefano Zampini         }
25134d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
25144d379d7bSStefano Zampini       }
25154d379d7bSStefano Zampini 
25164d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
25174d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
25184d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
25194d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
25204d379d7bSStefano Zampini       }
25214d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
25224d379d7bSStefano Zampini 
25234d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
25244d379d7bSStefano Zampini       sum = 0;
25254d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
25264d379d7bSStefano Zampini         PetscInt sizecc = 0;
25274d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
25284d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
25294d379d7bSStefano Zampini             sizecc++;
25304d379d7bSStefano Zampini           }
25314d379d7bSStefano Zampini         }
25324d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
25334d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
25344d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
25354d379d7bSStefano Zampini           }
25364d379d7bSStefano Zampini         }
25374d379d7bSStefano Zampini         sum += sizecc*sizecc;
25384d379d7bSStefano Zampini       }
25394d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
25404d379d7bSStefano Zampini       sum = 0;
25414d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
25424d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
25434d379d7bSStefano Zampini         cxadj[i] = sum;
25444d379d7bSStefano Zampini         sum += temp;
25454d379d7bSStefano Zampini       }
25464d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
25474d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
25484d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
25494d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
25504d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
25514d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
25524d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
25534d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
25544d379d7bSStefano Zampini                 sizecc++;
25554d379d7bSStefano Zampini               }
25564d379d7bSStefano Zampini             }
25574d379d7bSStefano Zampini           }
25584d379d7bSStefano Zampini         }
25594d379d7bSStefano Zampini       }
25604d379d7bSStefano Zampini       if (nvtxs) {
25614d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
25624d379d7bSStefano Zampini       } else {
25634d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
25644d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
25654d379d7bSStefano Zampini       }
25664d379d7bSStefano Zampini       graph->xadj = 0;
25674d379d7bSStefano Zampini       graph->adjncy = 0;
25684d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
25694d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
25704d379d7bSStefano Zampini     }
25714d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2572674ae819SStefano Zampini     if (!flg_row) {
2573674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2574674ae819SStefano Zampini     }
2575674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2576674ae819SStefano Zampini   }
2577674ae819SStefano Zampini 
257863602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2579674ae819SStefano Zampini   vertex_size = 1;
258063602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
258163602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
258295ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
258363602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2584a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
258563602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2586674ae819SStefano Zampini       }
258763602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
258863602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
258963602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2590674ae819SStefano Zampini     }
259163602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2592674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
259363602bcaSStefano Zampini   } else {
259463602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
259563602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2596854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
259763602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
259863602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
259963602bcaSStefano Zampini       }
260063602bcaSStefano Zampini     }
2601674ae819SStefano Zampini   }
2602674ae819SStefano Zampini 
2603674ae819SStefano Zampini   /* Setup of Graph */
2604785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2605a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2606785d1243SStefano Zampini   }
2607785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2608a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2609785d1243SStefano Zampini   }
261063602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2611674ae819SStefano Zampini 
2612674ae819SStefano Zampini   /* Graph's connected components analysis */
2613674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2614674ae819SStefano Zampini 
2615674ae819SStefano Zampini   /* print some info to stdout */
2616674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
2617e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
2618674ae819SStefano Zampini   }
2619fb180af4SStefano Zampini 
2620fb180af4SStefano Zampini   /* mark topography has done */
2621fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
2622674ae819SStefano Zampini   PetscFunctionReturn(0);
2623674ae819SStefano Zampini }
2624674ae819SStefano Zampini 
2625674ae819SStefano Zampini #undef __FUNCT__
2626674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
2627f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
2628674ae819SStefano Zampini {
2629674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2630674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
2631674ae819SStefano Zampini   PetscErrorCode ierr;
2632674ae819SStefano Zampini 
2633674ae819SStefano Zampini   PetscFunctionBegin;
2634674ae819SStefano Zampini   n = 0;
2635674ae819SStefano Zampini   vertices = 0;
2636674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2637674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
2638b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2639b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2640b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
2641b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2642b120a5c6SStefano Zampini     }
2643811e8ca2SStefano Zampini     if (vertices_idx) {
2644785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
2645b120a5c6SStefano Zampini       n = 0;
2646674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2647674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2648674ae819SStefano Zampini         if (size_of_constraint == 1) {
2649674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
2650674ae819SStefano Zampini         }
2651674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2652674ae819SStefano Zampini       }
2653674ae819SStefano Zampini     }
2654811e8ca2SStefano Zampini   }
2655674ae819SStefano Zampini   *n_vertices = n;
2656811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
2657674ae819SStefano Zampini   PetscFunctionReturn(0);
2658674ae819SStefano Zampini }
2659674ae819SStefano Zampini 
2660674ae819SStefano Zampini #undef __FUNCT__
2661674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
2662f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
2663674ae819SStefano Zampini {
2664674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2665674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
2666674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
26674641a718SStefano Zampini   PetscBT        touched;
2668674ae819SStefano Zampini   PetscErrorCode ierr;
2669674ae819SStefano Zampini 
2670f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
2671f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
2672f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2673674ae819SStefano Zampini   PetscFunctionBegin;
2674674ae819SStefano Zampini   n = 0;
2675674ae819SStefano Zampini   constraints_index = 0;
2676674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2677674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
2678674ae819SStefano Zampini     max_size_of_constraint = 0;
2679674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2680674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2681674ae819SStefano Zampini       if (size_of_constraint > 1) {
2682674ae819SStefano Zampini         n++;
2683674ae819SStefano Zampini       }
2684674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
2685674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2686674ae819SStefano Zampini     }
2687811e8ca2SStefano Zampini     if (constraints_idx) {
2688785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
2689785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
26904641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
2691674ae819SStefano Zampini       n = 0;
2692674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2693674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2694674ae819SStefano Zampini         if (size_of_constraint > 1) {
2695674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
269682d3d8afSStefano Zampini           /* find first untouched local node */
269782d3d8afSStefano Zampini           j = 0;
26984641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
269982d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
270082d3d8afSStefano Zampini           min_loc = j;
270182d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
270282d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
2703674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
27044641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
2705674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
2706674ae819SStefano Zampini               min_loc = j;
2707674ae819SStefano Zampini             }
2708674ae819SStefano Zampini           }
27094641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
2710674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
2711674ae819SStefano Zampini         }
2712674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2713674ae819SStefano Zampini       }
27144641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2715674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
2716811e8ca2SStefano Zampini     }
2717811e8ca2SStefano Zampini   }
2718674ae819SStefano Zampini   *n_constraints = n;
2719811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
2720674ae819SStefano Zampini   PetscFunctionReturn(0);
2721674ae819SStefano Zampini }
2722674ae819SStefano Zampini 
2723674ae819SStefano Zampini #undef __FUNCT__
2724674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
2725674ae819SStefano 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[])
2726674ae819SStefano Zampini {
2727674ae819SStefano Zampini   Vec            local_vec,global_vec;
2728674ae819SStefano Zampini   IS             seqis,paris;
2729674ae819SStefano Zampini   VecScatter     scatter_ctx;
2730674ae819SStefano Zampini   PetscScalar    *array;
2731674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
2732674ae819SStefano Zampini   PetscScalar    globalsum;
2733674ae819SStefano Zampini   PetscInt       i,j,s;
2734674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
2735674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
2736674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
2737674ae819SStefano Zampini   PetscBool      first_found;
2738674ae819SStefano Zampini   PetscErrorCode ierr;
2739674ae819SStefano Zampini 
2740674ae819SStefano Zampini   PetscFunctionBegin;
2741674ae819SStefano Zampini   /* mpi buffers */
2742b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
2743b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
2744674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
2745785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
2746785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
2747674ae819SStefano Zampini   /* get maximum size of subset */
2748785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
2749674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
2750674ae819SStefano Zampini   max_local = 0;
2751b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2752674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
2753674ae819SStefano Zampini       max_local = temp_global_dofs[i];
2754674ae819SStefano Zampini     }
2755674ae819SStefano Zampini   }
2756b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
2757674ae819SStefano Zampini   max_global++;
2758674ae819SStefano Zampini   max_local = 0;
2759b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2760674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
2761674ae819SStefano Zampini       max_local = local_dofs[i];
2762674ae819SStefano Zampini     }
2763674ae819SStefano Zampini   }
2764674ae819SStefano Zampini   max_local++;
2765674ae819SStefano Zampini   /* allocate workspace */
2766674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
2767674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
2768674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
2769674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
2770674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
2771674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
2772674ae819SStefano Zampini   /* create scatter */
2773674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
2774674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
2775674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
2776674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
2777674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
2778674ae819SStefano Zampini   /* init array */
2779674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
2780674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2781674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2782674ae819SStefano Zampini   if (local_dofs_mult) {
2783674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2784674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
2785674ae819SStefano Zampini     }
2786674ae819SStefano Zampini   } else {
2787674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2788674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
2789674ae819SStefano Zampini     }
2790674ae819SStefano Zampini   }
2791674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2792674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
2793674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2794674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2795674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
27965b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
2797674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
2798674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
2799674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
2800674ae819SStefano Zampini   nlocals = 0;
2801674ae819SStefano Zampini   first_index = -1;
2802674ae819SStefano Zampini   first_found = PETSC_FALSE;
2803674ae819SStefano Zampini   for (i=0;i<s;i++) {
2804b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
2805674ae819SStefano Zampini       first_found = PETSC_TRUE;
2806674ae819SStefano Zampini       first_index = i;
2807674ae819SStefano Zampini     }
28085b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
2809674ae819SStefano Zampini   }
2810674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2811674ae819SStefano Zampini   if (!rank_prec_comm) {
2812674ae819SStefano Zampini     dof_displs[0]=0;
2813674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
2814674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
2815674ae819SStefano Zampini     }
2816674ae819SStefano Zampini   }
2817674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2818674ae819SStefano Zampini   if (first_found) {
2819674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
2820674ae819SStefano Zampini     old_index = first_index;
2821674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
2822b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
2823674ae819SStefano Zampini         array[i] += array[old_index];
2824674ae819SStefano Zampini         old_index = i;
2825674ae819SStefano Zampini       }
2826674ae819SStefano Zampini     }
2827674ae819SStefano Zampini   }
2828674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
2829674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2830674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2831674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2832674ae819SStefano Zampini   /* get global ordering of local dofs */
2833674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2834674ae819SStefano Zampini   if (local_dofs_mult) {
2835674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
28365b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
2837674ae819SStefano Zampini     }
2838674ae819SStefano Zampini   } else {
2839674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
28405b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
2841674ae819SStefano Zampini     }
2842674ae819SStefano Zampini   }
2843674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2844674ae819SStefano Zampini   /* free workspace */
2845674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
2846674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
2847674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
2848674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
2849674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
2850674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
2851674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
2852674ae819SStefano Zampini   PetscFunctionReturn(0);
2853674ae819SStefano Zampini }
28549a7d3425SStefano Zampini 
28559a7d3425SStefano Zampini #undef __FUNCT__
28569a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
28579a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
28589a7d3425SStefano Zampini {
28599a7d3425SStefano Zampini   PetscInt       i,j;
28609a7d3425SStefano Zampini   PetscScalar    *alphas;
28619a7d3425SStefano Zampini   PetscErrorCode ierr;
28629a7d3425SStefano Zampini 
28639a7d3425SStefano Zampini   PetscFunctionBegin;
28649a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
2865785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
28669a7d3425SStefano Zampini   for (i=0;i<n;i++) {
28679a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
28689a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
28699a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
28709a7d3425SStefano Zampini   }
28719a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
28729a7d3425SStefano Zampini   PetscFunctionReturn(0);
28739a7d3425SStefano Zampini }
28749a7d3425SStefano Zampini 
2875e7931f94SStefano Zampini #undef __FUNCT__
287670cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
287728143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
2878e7931f94SStefano Zampini {
2879e7931f94SStefano Zampini   Mat             subdomain_adj;
2880e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
2881e7931f94SStefano Zampini   MatPartitioning partitioner;
2882e7931f94SStefano Zampini   Mat_IS          *matis;
2883e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
2884e7931f94SStefano Zampini   PetscInt        prank;
2885e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
2886e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
2887e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
28883837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
2889e7931f94SStefano Zampini   PetscErrorCode  ierr;
28902b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
2891e7931f94SStefano Zampini   PetscSubcomm    subcomm;
2892a57a6d2fSStefano Zampini 
2893e7931f94SStefano Zampini   PetscFunctionBegin;
28942b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
28952b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
28962b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
2897e7931f94SStefano Zampini 
2898e7931f94SStefano Zampini   /* Get info on mapping */
2899e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
2900e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
2901e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
2902e7931f94SStefano Zampini 
2903e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
2904785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
2905e7931f94SStefano Zampini   xadj[0] = 0;
2906e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
2907785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
2908785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
2909e7931f94SStefano Zampini 
29102b510759SStefano Zampini   if (threshold) {
2911d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
29122b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
2913d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
2914d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
2915d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
2916d023bfaeSStefano Zampini         xadj_count++;
2917e7931f94SStefano Zampini       }
2918e7931f94SStefano Zampini     }
2919d023bfaeSStefano Zampini     xadj[1] = xadj_count;
2920c8587f34SStefano Zampini   } else {
2921e7931f94SStefano Zampini     if (xadj[1]) {
2922e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
2923e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
2924c8587f34SStefano Zampini     }
2925e7931f94SStefano Zampini   }
2926e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
2927e7931f94SStefano Zampini   if (use_square) {
2928e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
2929e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
2930e7931f94SStefano Zampini     }
2931e7931f94SStefano Zampini   }
2932e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
2933e7931f94SStefano Zampini 
29343837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
2935e7931f94SStefano Zampini 
2936e7931f94SStefano Zampini   /*
2937e7931f94SStefano Zampini     Restrict work on active processes only.
2938e7931f94SStefano Zampini   */
2939e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
2940e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
2941e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
29422b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
2943d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
2944e7931f94SStefano Zampini   if (color) {
2945e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
2946e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
2947e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
2948c8587f34SStefano Zampini   } else {
294928143c3dSStefano Zampini     PetscInt coarsening_ratio;
2950e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
2951785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
2952e7931f94SStefano Zampini     prank = rank;
2953e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
29548002ef2cSStefano Zampini     /*
2955e7931f94SStefano Zampini     for (i=0;i<size;i++) {
2956e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
2957c8587f34SStefano Zampini     }
29588002ef2cSStefano Zampini     */
2959e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
2960e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
2961c8587f34SStefano Zampini     }
2962e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
2963e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
296422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
2965e7931f94SStefano Zampini 
2966e7931f94SStefano Zampini     /* Partition */
2967e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
2968e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
2969e7931f94SStefano Zampini     if (use_vwgt) {
29703837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
2971e7931f94SStefano Zampini       v_wgt[0] = local_size;
2972e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
2973c8587f34SStefano Zampini     }
297428143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
297528143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
297628143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
2977e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
2978e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
297922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
2980e7931f94SStefano Zampini 
2981e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
298228143c3dSStefano Zampini     if (contiguous) {
298328143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
298428143c3dSStefano Zampini     } else {
298584ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
298628143c3dSStefano Zampini     }
2987e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
2988e7931f94SStefano Zampini     /* clean up */
2989e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
2990e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
2991e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
2992e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
2993e7931f94SStefano Zampini   }
2994e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
2995e7931f94SStefano Zampini 
2996e7931f94SStefano Zampini   /* assemble parallel IS for sends */
2997e7931f94SStefano Zampini   i = 1;
2998e7931f94SStefano Zampini   if (color) i=0;
2999e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3000e7931f94SStefano Zampini 
3001e7931f94SStefano Zampini   /* get back IS */
3002e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3003e7931f94SStefano Zampini   PetscFunctionReturn(0);
3004e7931f94SStefano Zampini }
3005e7931f94SStefano Zampini 
3006e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3007e7931f94SStefano Zampini 
3008e7931f94SStefano Zampini #undef __FUNCT__
3009e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
301028143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3011e7931f94SStefano Zampini {
301270cf5478SStefano Zampini   Mat                    local_mat;
3013e7931f94SStefano Zampini   Mat_IS                 *matis;
3014e7931f94SStefano Zampini   IS                     is_sends_internal;
30159d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
301628143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
30179d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3018e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3019e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3020e7931f94SStefano Zampini   const PetscInt*        is_indices;
3021e7931f94SStefano Zampini   MatType                new_local_type;
3022e7931f94SStefano Zampini   /* buffers */
3023e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
302428143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
30259d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3026e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3027e7931f94SStefano Zampini   /* MPI */
302828143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
302928143c3dSStefano Zampini   PetscSubcomm           subcomm;
3030e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
303128143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
303228143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
303328143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
303428143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
303528143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3036e7931f94SStefano Zampini   PetscErrorCode         ierr;
3037e7931f94SStefano Zampini 
3038e7931f94SStefano Zampini   PetscFunctionBegin;
303928143c3dSStefano Zampini   /* TODO: add missing checks */
304028143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
304128143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
304228143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
304328143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3044e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
304528143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3046e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3047e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3048e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3049e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3050e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
305128143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
305270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
305370cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
305428143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
305570cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
305670cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
305770cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
305870cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
305970cf5478SStefano Zampini   }
3060e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3061e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3062e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3063e7931f94SStefano Zampini   if (!is_sends) {
306428143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
306528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
306628143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3067c8587f34SStefano Zampini   } else {
3068e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3069e7931f94SStefano Zampini     is_sends_internal = is_sends;
3070c8587f34SStefano Zampini   }
3071e7931f94SStefano Zampini 
3072e7931f94SStefano Zampini   /* get pointer of MATIS data */
3073e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3074e7931f94SStefano Zampini 
3075e7931f94SStefano Zampini   /* get comm */
3076a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3077e7931f94SStefano Zampini 
3078e7931f94SStefano Zampini   /* compute number of sends */
3079e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3080e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3081e7931f94SStefano Zampini 
3082e7931f94SStefano Zampini   /* compute number of receives */
3083e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3084785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3085e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3086e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3087e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3088e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3089e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3090e7931f94SStefano Zampini 
309128143c3dSStefano Zampini   /* restrict comm if requested */
309228143c3dSStefano Zampini   subcomm = 0;
309328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
309428143c3dSStefano Zampini   if (restrict_comm) {
309528143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
309628143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
309728143c3dSStefano Zampini     color = 0;
309828143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
309928143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
310028143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
310128143c3dSStefano Zampini     /* check if reuse has been requested */
310228143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
310328143c3dSStefano Zampini       if (*mat_n) {
310428143c3dSStefano Zampini         PetscMPIInt subcommsize2;
310528143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
310628143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
310728143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
310828143c3dSStefano Zampini       } else {
310928143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
311028143c3dSStefano Zampini       }
311128143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
311228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
311328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
311428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
311528143c3dSStefano Zampini       comm_n = subcomm->comm;
311628143c3dSStefano Zampini     }
311728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
311828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
311928143c3dSStefano Zampini   } else {
312028143c3dSStefano Zampini     comm_n = comm;
312128143c3dSStefano Zampini   }
312228143c3dSStefano Zampini 
3123e7931f94SStefano Zampini   /* prepare send/receive buffers */
3124785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3125e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3126785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3127e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
312828143c3dSStefano Zampini   if (nis) {
3129854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
313028143c3dSStefano Zampini   }
3131e7931f94SStefano Zampini 
313228143c3dSStefano Zampini   /* Get data from local matrices */
3133e7931f94SStefano Zampini   if (!isdense) {
3134a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3135e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3136e7931f94SStefano Zampini     /*
3137e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3138e7931f94SStefano Zampini        send_buffer_idxs should contain:
3139e7931f94SStefano Zampini        - MatType_PRIVATE type
3140e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3141e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3142e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3143e7931f94SStefano Zampini     */
3144e7931f94SStefano Zampini   } else {
3145e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3146e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3147854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3148e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3149e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3150e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3151e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3152e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3153e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3154e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3155e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3156e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3157c8587f34SStefano Zampini     }
3158c8587f34SStefano Zampini   }
3159e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
316028143c3dSStefano Zampini   /* additional is (if any) */
316128143c3dSStefano Zampini   if (nis) {
316228143c3dSStefano Zampini     PetscMPIInt psum;
316328143c3dSStefano Zampini     PetscInt j;
316428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
316528143c3dSStefano Zampini       PetscInt plen;
316628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
316728143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
316828143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
316928143c3dSStefano Zampini     }
3170854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
317128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
317228143c3dSStefano Zampini       PetscInt plen;
317328143c3dSStefano Zampini       const PetscInt *is_array_idxs;
317428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
317528143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
317628143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
317728143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
317828143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
317928143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
318028143c3dSStefano Zampini     }
318128143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
318228143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
318328143c3dSStefano Zampini     }
318428143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
318528143c3dSStefano Zampini   }
318628143c3dSStefano Zampini 
3187e7931f94SStefano Zampini   buf_size_idxs = 0;
3188e7931f94SStefano Zampini   buf_size_vals = 0;
318928143c3dSStefano Zampini   buf_size_idxs_is = 0;
3190e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3191e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3192e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
319328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3194e7931f94SStefano Zampini   }
3195785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3196785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
319795ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3198e7931f94SStefano Zampini 
3199e7931f94SStefano Zampini   /* get new tags for clean communications */
3200e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3201e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
320228143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3203e7931f94SStefano Zampini 
3204e7931f94SStefano Zampini   /* allocate for requests */
3205785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3206785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
320795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3208785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3209785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
321095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3211e7931f94SStefano Zampini 
3212e7931f94SStefano Zampini   /* communications */
3213e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3214e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
321528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3216e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3217e7931f94SStefano Zampini     source_dest = onodes[i];
3218e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3219e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3220e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3221e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
322228143c3dSStefano Zampini     if (nis) {
322328143c3dSStefano 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);
322428143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
322528143c3dSStefano Zampini     }
3226e7931f94SStefano Zampini   }
3227e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3228e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3229e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3230e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
323128143c3dSStefano Zampini     if (nis) {
323228143c3dSStefano 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);
323328143c3dSStefano Zampini     }
3234e7931f94SStefano Zampini   }
3235e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3236e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3237e7931f94SStefano Zampini 
3238e7931f94SStefano Zampini   /* assemble new l2g map */
3239e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3240e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
32419d30be91SStefano Zampini   new_local_rows = 0;
3242e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
32439d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3244e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3245e7931f94SStefano Zampini   }
32469d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3247e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
32489d30be91SStefano Zampini   new_local_rows = 0;
3249e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
32509d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
32519d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3252e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3253e7931f94SStefano Zampini   }
32549d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
32559d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3256e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3257e7931f94SStefano Zampini 
3258e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3259e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3260e7931f94SStefano 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) */
3261e7931f94SStefano Zampini   if (n_recvs) {
326228143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3263e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3264e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3265e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3266e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3267e7931f94SStefano Zampini         break;
3268e7931f94SStefano Zampini       }
3269e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3270e7931f94SStefano Zampini     }
3271e7931f94SStefano Zampini     switch (new_local_type_private) {
327228143c3dSStefano Zampini       case MATDENSE_PRIVATE:
327328143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3274e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3275e7931f94SStefano Zampini           bs = 1;
327628143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
327728143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
327828143c3dSStefano Zampini           bs = 1;
327928143c3dSStefano Zampini         }
3280e7931f94SStefano Zampini         break;
3281e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3282e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3283e7931f94SStefano Zampini         bs = 1;
3284e7931f94SStefano Zampini         break;
3285e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3286e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3287e7931f94SStefano Zampini         break;
3288e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3289e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3290e7931f94SStefano Zampini         break;
3291e7931f94SStefano Zampini       default:
32929d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3293e7931f94SStefano Zampini         break;
3294e7931f94SStefano Zampini     }
329528143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
329628143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
329728143c3dSStefano Zampini     bs = 1;
3298e7931f94SStefano Zampini   }
3299e7931f94SStefano Zampini 
330070cf5478SStefano Zampini   /* create MATIS object if needed */
330170cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3302e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
330328143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
330470cf5478SStefano Zampini   } else {
330570cf5478SStefano Zampini     /* it also destroys the local matrices */
330670cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
330770cf5478SStefano Zampini   }
330870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3309e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
33109d30be91SStefano Zampini 
33119d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
33129d30be91SStefano Zampini 
33139d30be91SStefano Zampini   /* Global to local map of received indices */
33149d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
33159d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
33169d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
33179d30be91SStefano Zampini 
33189d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
33199d30be91SStefano Zampini   buf_size_idxs = 0;
33209d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
33219d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
33229d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
33239d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
33249d30be91SStefano Zampini   }
33259d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
33269d30be91SStefano Zampini 
33279d30be91SStefano Zampini   /* set preallocation */
33289d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
33299d30be91SStefano Zampini   if (!newisdense) {
33309d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
33319d30be91SStefano Zampini 
33329d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
33339d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
33349d30be91SStefano Zampini     if (n_recvs) {
33359d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
33369d30be91SStefano Zampini     }
33379d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
33389d30be91SStefano Zampini       PetscInt j;
33399d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
33409d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
33419d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
33429d30be91SStefano Zampini         }
33439d30be91SStefano Zampini       } else {
33449d30be91SStefano Zampini         /* TODO */
33459d30be91SStefano Zampini       }
33469d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
33479d30be91SStefano Zampini     }
33489d30be91SStefano Zampini     if (new_local_nnz) {
33499d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
33509d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
33519d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
33529d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
33539d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
33549d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
33559d30be91SStefano Zampini     } else {
33569d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
33579d30be91SStefano Zampini     }
33589d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
33599d30be91SStefano Zampini   } else {
33609d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
33619d30be91SStefano Zampini   }
3362e7931f94SStefano Zampini 
3363e7931f94SStefano Zampini   /* set values */
3364e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
33659d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3366e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3367e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3368e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
33699d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3370e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3371e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3372e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
337328143c3dSStefano Zampini     } else {
337428143c3dSStefano Zampini       /* TODO */
3375e7931f94SStefano Zampini     }
3376e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3377e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3378e7931f94SStefano Zampini   }
3379e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3380e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
338170cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
338270cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
33839d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
33849d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3385e7931f94SStefano Zampini 
3386dfd14d43SStefano Zampini #if 0
338728143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3388e7931f94SStefano Zampini     Vec       lvec,rvec;
3389e7931f94SStefano Zampini     PetscReal infty_error;
3390e7931f94SStefano Zampini 
33912a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3392e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3393e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3394e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
339570cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3396e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3397e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3398e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3399e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3400e7931f94SStefano Zampini   }
340128143c3dSStefano Zampini #endif
3402e7931f94SStefano Zampini 
340328143c3dSStefano Zampini   /* assemble new additional is (if any) */
340428143c3dSStefano Zampini   if (nis) {
340528143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
340628143c3dSStefano Zampini 
340728143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3408854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
340928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
341028143c3dSStefano Zampini     psum = 0;
341128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
341228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
341328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
341428143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
341528143c3dSStefano Zampini         psum += plen;
341628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
341728143c3dSStefano Zampini       }
341828143c3dSStefano Zampini     }
3419854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3420854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
342128143c3dSStefano Zampini     for (i=1;i<nis;i++) {
342228143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
342328143c3dSStefano Zampini     }
342428143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
342528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
342628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
342728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
342828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
342928143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
343028143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
343128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
343228143c3dSStefano Zampini       }
343328143c3dSStefano Zampini     }
343428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
343528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
343628143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
343728143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
343828143c3dSStefano Zampini     }
343928143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
344028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
344128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
344228143c3dSStefano Zampini   }
3443e7931f94SStefano Zampini   /* free workspace */
344428143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3445e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3446e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3447e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3448e7931f94SStefano Zampini   if (isdense) {
3449e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3450e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3451e7931f94SStefano Zampini   } else {
3452e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3453e7931f94SStefano Zampini   }
345428143c3dSStefano Zampini   if (nis) {
345528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
345628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
345728143c3dSStefano Zampini   }
3458e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3459e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
346028143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3461e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3462e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
346328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3464e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3465e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3466e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3467e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3468e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
346928143c3dSStefano Zampini   if (nis) {
347028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
347128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
347228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
347328143c3dSStefano Zampini   }
347428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
347528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
347628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
347728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
347828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
347928143c3dSStefano Zampini     }
348028143c3dSStefano Zampini   }
3481e7931f94SStefano Zampini   PetscFunctionReturn(0);
3482e7931f94SStefano Zampini }
3483a57a6d2fSStefano Zampini 
348412edc857SStefano Zampini /* temporary hack into ksp private data structure */
348512edc857SStefano Zampini #include <petsc-private/kspimpl.h>
348612edc857SStefano Zampini 
3487c8587f34SStefano Zampini #undef __FUNCT__
3488c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3489c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3490c8587f34SStefano Zampini {
3491c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3492c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
349320a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
34949881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
349520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
34966e683305SStefano Zampini   IS                     coarse_is,*isarray;
34976e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
34986e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3499f9eb5b7dSStefano Zampini   PC                     pc_temp;
3500c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3501c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3502f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
35034f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
35046e683305SStefano Zampini   Mat                    t_coarse_mat_is;
35056e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
35066e683305SStefano Zampini   PetscMPIInt            all_procs;
350774e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
350868457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
350922bc73bbSStefano Zampini   PetscScalar            *array;
35109881197aSStefano Zampini   PetscErrorCode         ierr;
3511fdc09c96SStefano Zampini 
3512c8587f34SStefano Zampini   PetscFunctionBegin;
3513c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
351468457ee5SStefano 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 */
351568457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3516fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3517fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3518f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3519f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3520f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3521fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3522fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3523727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3524fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3525fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3526fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3527f4ddd8eeSStefano Zampini       }
3528fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3529fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3530f4ddd8eeSStefano Zampini     }
353170cf5478SStefano Zampini     /* reset any subassembling information */
353270cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
35336e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
35346e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3535fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3536f4ddd8eeSStefano Zampini   }
3537c8587f34SStefano Zampini 
35386e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
35392b510759SStefano Zampini   im_active = !!(pcis->n);
35402b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
35416e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
35426e683305SStefano Zampini   void_procs = all_procs-active_procs;
35436e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
354474e2c79eSStefano Zampini   redist = PETSC_FALSE;
354522bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
35466e683305SStefano Zampini     csin_ml = PETSC_TRUE;
35476e683305SStefano Zampini     ncoarse_ml = void_procs;
35486e683305SStefano Zampini     csin_ds = PETSC_TRUE;
35496e683305SStefano Zampini     ncoarse_ds = void_procs;
35506e683305SStefano Zampini   } else {
35516e683305SStefano Zampini     csin_ml = PETSC_FALSE;
35526e683305SStefano Zampini     ncoarse_ml = all_procs;
35536e683305SStefano Zampini     if (void_procs) {
35546e683305SStefano Zampini       csin_ds = PETSC_TRUE;
35556e683305SStefano Zampini       ncoarse_ds = void_procs;
35566e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
35576e683305SStefano Zampini     } else {
355874e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
355974e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
356074e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
356174e2c79eSStefano Zampini         redist = PETSC_TRUE;
356274e2c79eSStefano Zampini       } else {
35636e683305SStefano Zampini         csin_ds = PETSC_FALSE;
35646e683305SStefano Zampini         ncoarse_ds = all_procs;
35656e683305SStefano Zampini       }
35666e683305SStefano Zampini     }
356774e2c79eSStefano Zampini   }
35686e683305SStefano Zampini 
35696e683305SStefano Zampini   /*
35706e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
35716e683305SStefano Zampini     - we have not exceeded the number of levels requested
35726e683305SStefano Zampini     - we can actually subassemble the active processes
35736e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
35746e683305SStefano Zampini   */
35756e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
35766e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
35776e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
35786e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
35796e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3580f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
35812b510759SStefano Zampini     } else {
3582f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3583c8587f34SStefano Zampini     }
3584c8587f34SStefano Zampini   }
35856e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
35866e683305SStefano Zampini   if (multilevel_allowed) {
35876e683305SStefano Zampini     ncoarse = ncoarse_ml;
35886e683305SStefano Zampini     csin = csin_ml;
35896e683305SStefano Zampini   } else {
35906e683305SStefano Zampini     ncoarse = ncoarse_ds;
35916e683305SStefano Zampini     csin = csin_ds;
35926e683305SStefano Zampini   }
3593e7931f94SStefano Zampini 
3594abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3595abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3596abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3597abbbba34SStefano Zampini 
3598abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
359922bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
360022bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
360122bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
360222bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3603b9b85e73SStefano Zampini #if 0
3604b9b85e73SStefano Zampini   {
3605b9b85e73SStefano Zampini     PetscViewer viewer;
3606b9b85e73SStefano Zampini     char filename[256];
3607b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3608b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3609b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3610b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3611b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3612b9b85e73SStefano Zampini   }
3613b9b85e73SStefano Zampini #endif
36146e683305SStefano 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);
36156e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
36166e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36176e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3618abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
3619abbbba34SStefano Zampini 
36206e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
36216e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
36226e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
36236e683305SStefano Zampini     const PetscInt         *idxs;
36246e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
36256e683305SStefano Zampini 
36266e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
36270be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
36286e683305SStefano Zampini     /* allocate space for temporary storage */
3629854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
3630854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
36316e683305SStefano Zampini     /* allocate for IS array */
36326e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
36336e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
36346e683305SStefano Zampini     nis = nisdofs + nisneu;
3635854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
36366e683305SStefano Zampini     /* dofs splitting */
36376e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
36386e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
36396e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
36406e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
36416e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
36426e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
36436e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
36446e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
36456e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
36466e683305SStefano Zampini     }
36476e683305SStefano Zampini     /* neumann boundaries */
36486e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
36496e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
36506e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
36516e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
36526e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
36536e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
36546e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
36556e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
36566e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
36576e683305SStefano Zampini     }
36586e683305SStefano Zampini     /* free memory */
36596e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
36606e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
36616e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
36626e683305SStefano Zampini   } else {
36636e683305SStefano Zampini     nis = 0;
36646e683305SStefano Zampini     nisdofs = 0;
36656e683305SStefano Zampini     nisneu = 0;
36666e683305SStefano Zampini     isarray = NULL;
36676e683305SStefano Zampini   }
36686e683305SStefano Zampini   /* destroy no longer needed map */
36696e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
36706e683305SStefano Zampini 
36716e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
36726e683305SStefano Zampini   coarse_mat_is = NULL;
36736e683305SStefano Zampini   if (csin) {
36746e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
367574e2c79eSStefano Zampini       if (redist) {
367674e2c79eSStefano Zampini         PetscMPIInt rank;
367774e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
367874e2c79eSStefano Zampini 
367974e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
368074e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
368174e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
368274e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
368374e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
368474e2c79eSStefano Zampini         } else {
368574e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
368674e2c79eSStefano Zampini         }
368774e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
368874e2c79eSStefano Zampini       } else {
36896e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
36906e683305SStefano Zampini         PetscInt *coarse_candidates;
36916e683305SStefano Zampini         const PetscInt* tisindices;
36926e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
3693854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
36946e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
36956e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
36966e683305SStefano Zampini           if (!coarse_candidates[i]) {
36976e683305SStefano Zampini             coarse_candidates[j]=i;
36986e683305SStefano Zampini             j++;
36996e683305SStefano Zampini           }
37006e683305SStefano Zampini         }
37016e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
37026e683305SStefano Zampini         /* get a suitable subassembling pattern */
37036e683305SStefano Zampini         if (csin_type_simple) {
37046e683305SStefano Zampini           PetscMPIInt rank;
37056e683305SStefano Zampini           PetscInt    issize,isidx;
37066e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
37076e683305SStefano Zampini           if (im_active) {
37086e683305SStefano Zampini             issize = 1;
37096e683305SStefano Zampini             isidx = (PetscInt)rank;
37106e683305SStefano Zampini           } else {
37116e683305SStefano Zampini             issize = 0;
37126e683305SStefano Zampini             isidx = -1;
37136e683305SStefano Zampini           }
37146e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
37156e683305SStefano Zampini         } else {
37166e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
37176e683305SStefano Zampini         }
37186e683305SStefano Zampini         if (pcbddc->dbg_flag) {
37196e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
37206e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
37216e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
37226e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
37236e683305SStefano Zampini           for (i=0;i<j;i++) {
37246e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
37256e683305SStefano Zampini           }
37266e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
37276e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
37286e683305SStefano Zampini         }
37296e683305SStefano Zampini         /* shift the pattern on coarse candidates */
37306e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
37316e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
3732854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
37336e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
37346e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
37356e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
37366e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
37376e683305SStefano Zampini       }
373874e2c79eSStefano Zampini     }
37396e683305SStefano Zampini     if (pcbddc->dbg_flag) {
37406e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
37416e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
37426e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
37436e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
37446e683305SStefano Zampini     }
37456e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
37466e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
37476e683305SStefano Zampini   } else {
37486e683305SStefano Zampini     if (pcbddc->dbg_flag) {
37496e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
37506e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
37516e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
37526e683305SStefano Zampini     }
37536e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
37546e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
37556e683305SStefano Zampini   }
37566e683305SStefano Zampini 
37576e683305SStefano Zampini   /* create local to global scatters for coarse problem */
375868457ee5SStefano Zampini   if (compute_vecs) {
37596e683305SStefano Zampini     PetscInt lrows;
37606e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
37616e683305SStefano Zampini     if (coarse_mat_is) {
37626e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
37636e683305SStefano Zampini     } else {
37646e683305SStefano Zampini       lrows = 0;
37656e683305SStefano Zampini     }
37666e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
37676e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
37686e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
37696e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
37706e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
37716e683305SStefano Zampini   }
37726e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
37736e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
3774c8587f34SStefano Zampini 
3775f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
3776f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
3777f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
3778f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
3779f9eb5b7dSStefano Zampini   } else {
3780f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
3781f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
3782c8587f34SStefano Zampini   }
3783c8587f34SStefano Zampini 
37846e683305SStefano Zampini   /* print some info if requested */
37856e683305SStefano Zampini   if (pcbddc->dbg_flag) {
37866e683305SStefano Zampini     if (!multilevel_allowed) {
37876e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
37886e683305SStefano Zampini       if (multilevel_requested) {
37896e683305SStefano 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);
37906e683305SStefano Zampini       } else if (pcbddc->max_levels) {
37916e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
37926e683305SStefano Zampini       }
37936e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
37946e683305SStefano Zampini     }
37956e683305SStefano Zampini   }
37966e683305SStefano Zampini 
3797f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
37986e683305SStefano Zampini   if (coarse_mat_is) {
37996e683305SStefano Zampini     MatReuse coarse_mat_reuse;
38006a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
38016e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38026e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
38036e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
38046e683305SStefano Zampini     }
3805f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
3806312be037SStefano Zampini       char prefix[256],str_level[16];
3807e604994aSStefano Zampini       size_t len;
38086e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
3809c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3810f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
38115f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
3812c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
38136e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
3814c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3815c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3816e604994aSStefano Zampini       /* prefix */
3817e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
3818e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3819e604994aSStefano Zampini       if (!pcbddc->current_level) {
3820e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3821e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
3822c8587f34SStefano Zampini       } else {
3823e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3824312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3825312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
382634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3827312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3828e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
3829e604994aSStefano Zampini       }
3830e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
3831f9eb5b7dSStefano Zampini       /* allow user customization */
3832f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
38337e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3834312be037SStefano Zampini     }
3835f9eb5b7dSStefano Zampini 
3836f9eb5b7dSStefano Zampini     /* get some info after set from options */
3837f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3838f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
3839f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
38404f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
38416e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
3842f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3843f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
3844f9eb5b7dSStefano Zampini     }
38454f3a063dSStefano Zampini     if (isredundant) {
38464f3a063dSStefano Zampini       KSP inner_ksp;
38474f3a063dSStefano Zampini       PC inner_pc;
38484f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
38494f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
38504f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
38514f3a063dSStefano Zampini     }
3852f9eb5b7dSStefano Zampini 
38536e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
3854f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
3855f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
3856f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
38576e683305SStefano Zampini     if (nisdofs) {
38586e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
38596e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
38606e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
38611035eff8SStefano Zampini       }
38621035eff8SStefano Zampini     }
38636e683305SStefano Zampini     if (nisneu) {
38646e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
38656e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
38661035eff8SStefano Zampini     }
3867fdc09c96SStefano Zampini 
3868f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
3869fa7f1dd8SStefano Zampini     if (coarse_reuse) {
387081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
3871fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
38726e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
3873fa7f1dd8SStefano Zampini     } else {
38746e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
3875fa7f1dd8SStefano Zampini     }
3876c8587f34SStefano Zampini     if (isbddc || isnn) {
387722bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
387870cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
387928143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
388022b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
38816e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38826e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
38836e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
38846e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
388522b6e8a2SStefano Zampini           }
388670cf5478SStefano Zampini         }
38876e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
388870cf5478SStefano Zampini       } else {
388922bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
389022bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
389122bc73bbSStefano Zampini       }
389222bc73bbSStefano Zampini     } else {
38932e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
3894c8587f34SStefano Zampini     }
3895c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
3896c8587f34SStefano Zampini 
3897c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
3898b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
38995a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
3900c8587f34SStefano Zampini 
39016e683305SStefano Zampini     /* set operators */
39025f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
39036e683305SStefano Zampini     if (pcbddc->dbg_flag) {
39046e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
39056e683305SStefano Zampini     }
39066e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
39076e683305SStefano Zampini     coarse_mat = 0;
39086e683305SStefano Zampini   }
39096e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
3910b9b85e73SStefano Zampini #if 0
3911b9b85e73SStefano Zampini   {
3912b9b85e73SStefano Zampini     PetscViewer viewer;
3913b9b85e73SStefano Zampini     char filename[256];
3914b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
3915b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
3916b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3917b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
3918b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3919b9b85e73SStefano Zampini   }
3920b9b85e73SStefano Zampini #endif
3921c8587f34SStefano Zampini 
3922c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
3923c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
3924c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
392598a51de6SStefano Zampini   }
392698a51de6SStefano Zampini 
392798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
392898a51de6SStefano Zampini     Vec crhs,csol;
392998a51de6SStefano Zampini     PetscBool ispreonly;
393098a51de6SStefano Zampini     if (CoarseNullSpace) {
3931c8587f34SStefano Zampini       if (isbddc) {
3932c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
3933c8587f34SStefano Zampini       } else {
3934c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
3935c8587f34SStefano Zampini       }
3936c8587f34SStefano Zampini     }
3937f9eb5b7dSStefano Zampini     /* setup coarse ksp */
3938f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
3939f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
3940f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
39416e683305SStefano Zampini     /* hack */
3942f347579bSStefano Zampini     if (!csol) {
39432a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
3944f9eb5b7dSStefano Zampini     }
3945f347579bSStefano Zampini     if (!crhs) {
39462a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
3947f347579bSStefano Zampini     }
3948cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
3949cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
39506e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
3951c8587f34SStefano Zampini       KSP       check_ksp;
39522b510759SStefano Zampini       KSPType   check_ksp_type;
3953c8587f34SStefano Zampini       PC        check_pc;
39546e683305SStefano Zampini       Vec       check_vec,coarse_vec;
39556a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
39562b510759SStefano Zampini       PetscInt  its;
39576e683305SStefano Zampini       PetscBool compute_eigs;
39586e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
39596e683305SStefano Zampini       PetscInt  neigs;
39608e185a42SStefano Zampini       const char *prefix;
3961c8587f34SStefano Zampini 
39622b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
39636e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
396423ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
3965f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
39662b510759SStefano Zampini       if (ispreonly) {
39672b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
39686e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
39692b510759SStefano Zampini       } else {
3970cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
39716e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
3972c8587f34SStefano Zampini       }
3973c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
39746e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
39756e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
39766e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
3977a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
3978a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
3979a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
3980a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
3981c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
3982c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
3983c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
3984c8587f34SStefano Zampini       /* create random vec */
39856e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
39866e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
3987c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
3988c8587f34SStefano Zampini       if (CoarseNullSpace) {
3989c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
3990c8587f34SStefano Zampini       }
39916e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
3992c8587f34SStefano Zampini       /* solve coarse problem */
39936e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
3994c8587f34SStefano Zampini       if (CoarseNullSpace) {
39956e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
3996c8587f34SStefano Zampini       }
3997cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
39986e683305SStefano Zampini       if (compute_eigs) {
3999854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4000854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
40016e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
40026e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
40036e683305SStefano Zampini         lambda_min = eigs_r[0];
40046e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
40056e683305SStefano Zampini           if (lambda_max>lambda_min) {
4006cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4007cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4008cbcc2c2aSStefano Zampini           }
4009c8587f34SStefano Zampini         }
4010c8587f34SStefano Zampini       }
4011cbcc2c2aSStefano Zampini 
4012c8587f34SStefano Zampini       /* check coarse problem residual error */
40136e683305SStefano Zampini       if (pcbddc->dbg_flag) {
40146e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
40156e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
40166e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4017c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
40186e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
40196e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4020c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
40216e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
40226e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
40236e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
40246e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
40256e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
40266e683305SStefano Zampini         if (compute_eigs) {
40276e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4028deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4029c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
40306e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
40316e683305SStefano 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);
40326e683305SStefano Zampini           for (i=0;i<neigs;i++) {
40336e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4034c8587f34SStefano Zampini           }
40356e683305SStefano Zampini         }
40366e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
40376e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
40386e683305SStefano Zampini       }
4039c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
40406e683305SStefano Zampini       if (compute_eigs) {
40416e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
40426e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4043c8587f34SStefano Zampini       }
40446e683305SStefano Zampini     }
40456e683305SStefano Zampini   }
4046cbcc2c2aSStefano Zampini   /* print additional info */
4047cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
40486e683305SStefano Zampini     /* waits until all processes reaches this point */
40496e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4050cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4051cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4052cbcc2c2aSStefano Zampini   }
4053cbcc2c2aSStefano Zampini 
40542b510759SStefano Zampini   /* free memory */
4055c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4056fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4057c8587f34SStefano Zampini   PetscFunctionReturn(0);
4058c8587f34SStefano Zampini }
4059674ae819SStefano Zampini 
4060f34684f1SStefano Zampini #undef __FUNCT__
4061f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4062f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4063f34684f1SStefano Zampini {
4064f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4065f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4066f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4067727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4068727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4069f34684f1SStefano Zampini   PetscErrorCode ierr;
4070f34684f1SStefano Zampini 
4071f34684f1SStefano Zampini   PetscFunctionBegin;
4072f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
407389c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
407489c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4075727cdba6SStefano Zampini   }
4076727cdba6SStefano 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);
4077f34684f1SStefano Zampini 
4078f34684f1SStefano Zampini   /* check numbering */
4079f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4080f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4081b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4082f34684f1SStefano Zampini 
4083f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4084f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4085f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
40860fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4087f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4088f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4089727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4090f34684f1SStefano Zampini     }
4091f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4092f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4093f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4094f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4095f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4096f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4097f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4098f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4099f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4100f34684f1SStefano Zampini       if (array[i] == 1.0) {
4101b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4102f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4103f34684f1SStefano Zampini       }
4104f34684f1SStefano Zampini     }
4105b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4106f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4107f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4108f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4109f34684f1SStefano Zampini     }
4110f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4111f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4112f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4113f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4114f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4115f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4116b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4117f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4118f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4119f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4120f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4121727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4122f34684f1SStefano Zampini       }
4123f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4124f34684f1SStefano Zampini     }
4125f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4126b9b85e73SStefano Zampini     if (set_error_reduced) {
4127b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4128b9b85e73SStefano Zampini     }
4129f34684f1SStefano Zampini   }
4130f34684f1SStefano Zampini   /* get back data */
4131f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4132f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4133674ae819SStefano Zampini   PetscFunctionReturn(0);
4134674ae819SStefano Zampini }
4135674ae819SStefano Zampini 
4136e456f2a8SStefano Zampini #undef __FUNCT__
4137e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4138a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4139e456f2a8SStefano Zampini {
4140e456f2a8SStefano Zampini   IS             localis_t;
4141a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4142e456f2a8SStefano Zampini   PetscScalar    *vals;
4143e456f2a8SStefano Zampini   PetscErrorCode ierr;
4144e456f2a8SStefano Zampini 
4145e456f2a8SStefano Zampini   PetscFunctionBegin;
4146a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4147e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4148854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4149e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4150e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4151a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4152a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
41531035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4154a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
41551035eff8SStefano Zampini   }
4156a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4157e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4158e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4159a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4160a7dc3881SStefano Zampini   /* now compute set in local ordering */
4161a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4162a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4163a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4164a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4165a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4166ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4167e456f2a8SStefano Zampini       lsize++;
4168e456f2a8SStefano Zampini     }
4169e456f2a8SStefano Zampini   }
4170854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4171a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4172ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4173e456f2a8SStefano Zampini       idxs[lsize++] = i;
4174e456f2a8SStefano Zampini     }
4175e456f2a8SStefano Zampini   }
4176a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4177a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4178e456f2a8SStefano Zampini   *localis = localis_t;
4179e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4180e456f2a8SStefano Zampini }
4181906d46d4SStefano Zampini 
4182906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4183906d46d4SStefano Zampini #undef __FUNCT__
4184906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4185906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4186906d46d4SStefano Zampini {
4187906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4188906d46d4SStefano Zampini   PetscErrorCode   ierr;
4189906d46d4SStefano Zampini 
4190906d46d4SStefano Zampini   PetscFunctionBegin;
4191906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4192906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4193906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4194906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4195906d46d4SStefano Zampini   PetscFunctionReturn(0);
4196906d46d4SStefano Zampini }
4197906d46d4SStefano Zampini 
4198906d46d4SStefano Zampini #undef __FUNCT__
4199906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4200906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4201906d46d4SStefano Zampini {
4202906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4203906d46d4SStefano Zampini   PetscErrorCode   ierr;
4204906d46d4SStefano Zampini 
4205906d46d4SStefano Zampini   PetscFunctionBegin;
4206906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4207906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4208906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4209906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4210906d46d4SStefano Zampini   PetscFunctionReturn(0);
4211906d46d4SStefano Zampini }
4212