xref: /petsc/src/ksp/pc/impls/bddc/bddcprivate.c (revision d65f70fd938573fec9f4e0f30225958f4666553f)
1ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h>
2ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3674ae819SStefano Zampini #include <petscblaslapack.h>
4674ae819SStefano Zampini 
5906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y);
6906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y);
7906d46d4SStefano Zampini 
8b1b3d7a2SStefano Zampini #if 0
9b1b3d7a2SStefano Zampini #undef __FUNCT__
10b1b3d7a2SStefano Zampini #define __FUNCT__ "PCBDDCAdaptiveSelection"
11b1b3d7a2SStefano Zampini PetscErrorCode PCBDDCAdaptiveSelection(PC pc, MatNullSpace* adapt_nnsp)
12b1b3d7a2SStefano Zampini {
13b1b3d7a2SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14b1b3d7a2SStefano Zampini   PetscErrorCode ierr;
15b1b3d7a2SStefano Zampini 
16b1b3d7a2SStefano Zampini   PetscFunctionBegin;
17b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursInit(pcbddc->sub_schurs[0],pcbddc->mat_graph,...);CHKERRQ(ierr);
18b1b3d7a2SStefano Zampini   PetscFunctionReturn(0);
19b1b3d7a2SStefano Zampini }
20b1b3d7a2SStefano Zampini #endif
21b1b3d7a2SStefano Zampini 
22674ae819SStefano Zampini #undef __FUNCT__
23c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpSolvers"
24c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpSolvers(PC pc)
25c8587f34SStefano Zampini {
26c8587f34SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
278629588bSStefano Zampini   PetscScalar    *coarse_submat_vals;
28c8587f34SStefano Zampini   PetscErrorCode ierr;
29c8587f34SStefano Zampini 
30c8587f34SStefano Zampini   PetscFunctionBegin;
31f4ddd8eeSStefano Zampini   /* Setup local scatters R_to_B and (optionally) R_to_D */
325e8657edSStefano Zampini   /* PCBDDCSetUpLocalWorkVectors should be called first! */
33c8587f34SStefano Zampini   ierr = PCBDDCSetUpLocalScatters(pc);CHKERRQ(ierr);
34c8587f34SStefano Zampini 
35684f6988SStefano Zampini   /* Setup local neumann solver ksp_R */
360fccc4e9SStefano Zampini   /* PCBDDCSetUpLocalScatters should be called first! */
37684f6988SStefano Zampini   ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_FALSE,PETSC_TRUE);CHKERRQ(ierr);
38c8587f34SStefano Zampini 
39c8587f34SStefano Zampini   /* Change global null space passed in by the user if change of basis has been requested */
40b9b85e73SStefano Zampini   if (pcbddc->NullSpace && pcbddc->ChangeOfBasisMatrix) {
41c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAdaptGlobal(pc);CHKERRQ(ierr);
42c8587f34SStefano Zampini   }
43c8587f34SStefano Zampini 
448629588bSStefano Zampini   /*
458629588bSStefano Zampini      Setup local correction and local part of coarse basis.
468629588bSStefano Zampini      Gives back the dense local part of the coarse matrix in column major ordering
478629588bSStefano Zampini   */
4847f4ddc3SStefano Zampini   ierr = PCBDDCSetUpCorrection(pc,&coarse_submat_vals);CHKERRQ(ierr);
498629588bSStefano Zampini 
508629588bSStefano Zampini   /* Compute total number of coarse nodes and setup coarse solver */
518629588bSStefano Zampini   ierr = PCBDDCSetUpCoarseSolver(pc,coarse_submat_vals);CHKERRQ(ierr);
528629588bSStefano Zampini 
538629588bSStefano Zampini   /* free */
548629588bSStefano Zampini   ierr = PetscFree(coarse_submat_vals);CHKERRQ(ierr);
55c8587f34SStefano Zampini   PetscFunctionReturn(0);
56c8587f34SStefano Zampini }
57c8587f34SStefano Zampini 
58c8587f34SStefano Zampini #undef __FUNCT__
59674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetCustomization"
60674ae819SStefano Zampini PetscErrorCode PCBDDCResetCustomization(PC pc)
61674ae819SStefano Zampini {
62674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
63674ae819SStefano Zampini   PetscErrorCode ierr;
64674ae819SStefano Zampini 
65674ae819SStefano Zampini   PetscFunctionBegin;
66674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
67674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
68674ae819SStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
69674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
70785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
71674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
72f4ddd8eeSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
73f4ddd8eeSStefano Zampini   ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
74785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
7563602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplitting(pc,0,NULL);CHKERRQ(ierr);
7663602bcaSStefano Zampini   ierr = PCBDDCSetDofsSplittingLocal(pc,0,NULL);CHKERRQ(ierr);
77674ae819SStefano Zampini   PetscFunctionReturn(0);
78674ae819SStefano Zampini }
79674ae819SStefano Zampini 
80674ae819SStefano Zampini #undef __FUNCT__
81674ae819SStefano Zampini #define __FUNCT__ "PCBDDCResetTopography"
82674ae819SStefano Zampini PetscErrorCode PCBDDCResetTopography(PC pc)
83674ae819SStefano Zampini {
84674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
85674ae819SStefano Zampini   PetscErrorCode ierr;
86674ae819SStefano Zampini 
87674ae819SStefano Zampini   PetscFunctionBegin;
88b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
89674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
90674ae819SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
91674ae819SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
92b1b3d7a2SStefano Zampini   ierr = PCBDDCSubSchursReset(pcbddc->sub_schurs[0]);CHKERRQ(ierr);
93b1b3d7a2SStefano 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 */
555b9d89cd5SStefano Zampini   if (!pcbddc->issym) {
556f4ddd8eeSStefano Zampini     if (!pcbddc->coarse_psi_B) {
55788ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_B);CHKERRQ(ierr);
55888ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_B,n_B,pcbddc->local_primal_size,n_B,pcbddc->local_primal_size);CHKERRQ(ierr);
55988ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_B,impMatType);CHKERRQ(ierr);
56025084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_B);CHKERRQ(ierr);
561f4ddd8eeSStefano Zampini     }
562f4ddd8eeSStefano Zampini     if ( (pcbddc->switch_static || pcbddc->dbg_flag) && !pcbddc->coarse_psi_D) {
56388ebb749SStefano Zampini       ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->coarse_psi_D);CHKERRQ(ierr);
56488ebb749SStefano Zampini       ierr = MatSetSizes(pcbddc->coarse_psi_D,n_D,pcbddc->local_primal_size,n_D,pcbddc->local_primal_size);CHKERRQ(ierr);
56588ebb749SStefano Zampini       ierr = MatSetType(pcbddc->coarse_psi_D,impMatType);CHKERRQ(ierr);
56625084f0cSStefano Zampini       ierr = MatSetUp(pcbddc->coarse_psi_D);CHKERRQ(ierr);
56788ebb749SStefano Zampini     }
56888ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
56988ebb749SStefano Zampini       if (n_constraints) {
57088ebb749SStefano Zampini         ierr = VecSet(vec1_C,zero);CHKERRQ(ierr);
57188ebb749SStefano Zampini         for (j=0;j<n_constraints;j++) {
57225084f0cSStefano Zampini           ierr = VecSetValue(vec1_C,j,coarse_submat_vals[(j+n_vertices)*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
57388ebb749SStefano Zampini         }
57425084f0cSStefano Zampini         ierr = VecAssemblyBegin(vec1_C);CHKERRQ(ierr);
57525084f0cSStefano Zampini         ierr = VecAssemblyEnd(vec1_C);CHKERRQ(ierr);
57688ebb749SStefano Zampini       }
57788ebb749SStefano Zampini       if (i<n_vertices) {
57888ebb749SStefano Zampini         ierr = VecSet(vec1_V,zero);CHKERRQ(ierr);
57988ebb749SStefano Zampini         ierr = VecSetValue(vec1_V,i,m_one,INSERT_VALUES);CHKERRQ(ierr);
58088ebb749SStefano Zampini         ierr = VecAssemblyBegin(vec1_V);CHKERRQ(ierr);
58188ebb749SStefano Zampini         ierr = VecAssemblyEnd(vec1_V);CHKERRQ(ierr);
58288ebb749SStefano Zampini         ierr = MatMultTranspose(A_VR,vec1_V,pcbddc->vec1_R);CHKERRQ(ierr);
58388ebb749SStefano Zampini         if (n_constraints) {
58488ebb749SStefano Zampini           ierr = MatMultTransposeAdd(C_CR,vec1_C,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
58588ebb749SStefano Zampini         }
58688ebb749SStefano Zampini       } else {
58788ebb749SStefano Zampini         ierr = MatMultTranspose(C_CR,vec1_C,pcbddc->vec1_R);CHKERRQ(ierr);
58888ebb749SStefano Zampini       }
58988ebb749SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_R,pcbddc->vec1_R,pcbddc->vec1_R);CHKERRQ(ierr);
59088ebb749SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
59188ebb749SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
59288ebb749SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec1_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
59325084f0cSStefano Zampini       ierr = VecGetArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
59488ebb749SStefano Zampini       ierr = MatSetValues(pcbddc->coarse_psi_B,n_B,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
59525084f0cSStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec1_B,&array);CHKERRQ(ierr);
59688ebb749SStefano Zampini       if (i<n_vertices) {
59788ebb749SStefano Zampini         ierr = MatSetValue(pcbddc->coarse_psi_B,idx_V_B[i],i,one,INSERT_VALUES);CHKERRQ(ierr);
59888ebb749SStefano Zampini       }
5998eeda7d8SStefano Zampini       if (pcbddc->switch_static || pcbddc->dbg_flag) {
60088ebb749SStefano Zampini         ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60188ebb749SStefano Zampini         ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec1_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60225084f0cSStefano Zampini         ierr = VecGetArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
60388ebb749SStefano Zampini         ierr = MatSetValues(pcbddc->coarse_psi_D,n_D,auxindices,1,&i,array,INSERT_VALUES);CHKERRQ(ierr);
60425084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcis->vec1_D,&array);CHKERRQ(ierr);
60588ebb749SStefano Zampini       }
60688ebb749SStefano Zampini 
60725084f0cSStefano Zampini       if (pcbddc->dbg_flag) {
60888ebb749SStefano Zampini         /* assemble subdomain vector on nodes */
60988ebb749SStefano Zampini         ierr = VecSet(pcis->vec1_N,zero);CHKERRQ(ierr);
61025084f0cSStefano Zampini         ierr = VecGetArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
6119f00e9b4SStefano Zampini         if (n_R) {
61225084f0cSStefano Zampini           ierr = VecSetValues(pcis->vec1_N,n_R,idx_R_local,array,INSERT_VALUES);CHKERRQ(ierr);
6139f00e9b4SStefano Zampini         }
61425084f0cSStefano Zampini         ierr = VecRestoreArrayRead(pcbddc->vec1_R,&array);CHKERRQ(ierr);
61525084f0cSStefano Zampini         if (i<n_vertices) {
616e9189074SStefano Zampini           ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],one,INSERT_VALUES);CHKERRQ(ierr);
61788ebb749SStefano Zampini         }
61825084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
61925084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
62025084f0cSStefano Zampini         /* assemble subdomain vector of lagrange multipliers */
62125084f0cSStefano Zampini         for (j=0;j<pcbddc->local_primal_size;j++) {
62225084f0cSStefano Zampini           ierr = VecSetValue(pcbddc->vec1_P,j,-coarse_submat_vals[j*pcbddc->local_primal_size+i],INSERT_VALUES);CHKERRQ(ierr);
62325084f0cSStefano Zampini         }
62425084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
62525084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
62688ebb749SStefano Zampini         /* check saddle point solution */
62788ebb749SStefano Zampini         ierr = MatMultTranspose(pcbddc->local_mat,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
62888ebb749SStefano Zampini         ierr = MatMultTransposeAdd(pcbddc->ConstraintMatrix,pcbddc->vec1_P,pcis->vec2_N,pcis->vec2_N);CHKERRQ(ierr);
62988ebb749SStefano Zampini         ierr = VecNorm(pcis->vec2_N,NORM_INFINITY,&coarsefunctions_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
63088ebb749SStefano Zampini         ierr = MatMult(pcbddc->ConstraintMatrix,pcis->vec1_N,pcbddc->vec1_P);CHKERRQ(ierr);
63125084f0cSStefano Zampini         /* shift by the identity matrix */
63225084f0cSStefano Zampini         ierr = VecSetValue(pcbddc->vec1_P,i,m_one,ADD_VALUES);CHKERRQ(ierr);
63325084f0cSStefano Zampini         ierr = VecAssemblyBegin(pcbddc->vec1_P);CHKERRQ(ierr);
63425084f0cSStefano Zampini         ierr = VecAssemblyEnd(pcbddc->vec1_P);CHKERRQ(ierr);
63588ebb749SStefano Zampini         ierr = VecNorm(pcbddc->vec1_P,NORM_INFINITY,&constraints_errors[i+pcbddc->local_primal_size]);CHKERRQ(ierr);
63688ebb749SStefano Zampini       }
63788ebb749SStefano Zampini     }
63888ebb749SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
63988ebb749SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->coarse_psi_B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6408eeda7d8SStefano Zampini     if (pcbddc->switch_static || pcbddc->dbg_flag) {
64188ebb749SStefano Zampini       ierr = MatAssemblyBegin(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64288ebb749SStefano Zampini       ierr = MatAssemblyEnd(pcbddc->coarse_psi_D,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
64388ebb749SStefano Zampini     }
644c0553b1fSStefano Zampini     unsymmetric_check = PETSC_TRUE;
645c0553b1fSStefano Zampini   } else { /* take references to already computed coarse basis */
646c0553b1fSStefano Zampini     unsymmetric_check = PETSC_FALSE;
647c0553b1fSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_B);CHKERRQ(ierr);
648c0553b1fSStefano Zampini     pcbddc->coarse_psi_B = pcbddc->coarse_phi_B;
649c0553b1fSStefano Zampini     if (pcbddc->coarse_phi_D) {
650c0553b1fSStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->coarse_phi_D);CHKERRQ(ierr);
651c0553b1fSStefano Zampini       pcbddc->coarse_psi_D = pcbddc->coarse_phi_D;
652c0553b1fSStefano Zampini     }
65388ebb749SStefano Zampini   }
65488ebb749SStefano Zampini   ierr = PetscFree(idx_V_B);CHKERRQ(ierr);
65588ebb749SStefano Zampini   /* Checking coarse_sub_mat and coarse basis functios */
65688ebb749SStefano Zampini   /* Symmetric case     : It should be \Phi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
65788ebb749SStefano Zampini   /* Non-symmetric case : It should be \Psi^{(j)^T} A^{(j)} \Phi^{(j)}=coarse_sub_mat */
65825084f0cSStefano Zampini   if (pcbddc->dbg_flag) {
65988ebb749SStefano Zampini     Mat         coarse_sub_mat;
66025084f0cSStefano Zampini     Mat         AUXMAT,TM1,TM2,TM3,TM4;
66188ebb749SStefano Zampini     Mat         coarse_phi_D,coarse_phi_B;
66288ebb749SStefano Zampini     Mat         coarse_psi_D,coarse_psi_B;
66388ebb749SStefano Zampini     Mat         A_II,A_BB,A_IB,A_BI;
66488ebb749SStefano Zampini     MatType     checkmattype=MATSEQAIJ;
66588ebb749SStefano Zampini     PetscReal   real_value;
66688ebb749SStefano Zampini 
66788ebb749SStefano Zampini     ierr = MatConvert(pcis->A_II,checkmattype,MAT_INITIAL_MATRIX,&A_II);CHKERRQ(ierr);
66888ebb749SStefano Zampini     ierr = MatConvert(pcis->A_IB,checkmattype,MAT_INITIAL_MATRIX,&A_IB);CHKERRQ(ierr);
66988ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BI,checkmattype,MAT_INITIAL_MATRIX,&A_BI);CHKERRQ(ierr);
67088ebb749SStefano Zampini     ierr = MatConvert(pcis->A_BB,checkmattype,MAT_INITIAL_MATRIX,&A_BB);CHKERRQ(ierr);
67188ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_D);CHKERRQ(ierr);
67288ebb749SStefano Zampini     ierr = MatConvert(pcbddc->coarse_phi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_phi_B);CHKERRQ(ierr);
673c0553b1fSStefano Zampini     if (unsymmetric_check) {
67488ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_D,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_D);CHKERRQ(ierr);
67588ebb749SStefano Zampini       ierr = MatConvert(pcbddc->coarse_psi_B,checkmattype,MAT_INITIAL_MATRIX,&coarse_psi_B);CHKERRQ(ierr);
67688ebb749SStefano Zampini     }
67788ebb749SStefano Zampini     ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,coarse_submat_vals,&coarse_sub_mat);CHKERRQ(ierr);
67888ebb749SStefano Zampini 
67925084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
68025084f0cSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse sub mat and local basis functions\n");CHKERRQ(ierr);
68125084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
682c0553b1fSStefano Zampini     if (unsymmetric_check) {
68388ebb749SStefano Zampini       ierr = MatMatMult(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
68488ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
68588ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
68688ebb749SStefano Zampini       ierr = MatMatMult(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
68788ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
68888ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
68988ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69088ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
69188ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69288ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69388ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_psi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
69488ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
69588ebb749SStefano Zampini     } else {
69688ebb749SStefano Zampini       ierr = MatPtAP(A_II,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&TM1);CHKERRQ(ierr);
69788ebb749SStefano Zampini       ierr = MatPtAP(A_BB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&TM2);CHKERRQ(ierr);
69888ebb749SStefano Zampini       ierr = MatMatMult(A_IB,coarse_phi_B,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
69988ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_D,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM3);CHKERRQ(ierr);
70088ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70188ebb749SStefano Zampini       ierr = MatMatMult(A_BI,coarse_phi_D,MAT_INITIAL_MATRIX,1.0,&AUXMAT);CHKERRQ(ierr);
70288ebb749SStefano Zampini       ierr = MatTransposeMatMult(coarse_phi_B,AUXMAT,MAT_INITIAL_MATRIX,1.0,&TM4);CHKERRQ(ierr);
70388ebb749SStefano Zampini       ierr = MatDestroy(&AUXMAT);CHKERRQ(ierr);
70488ebb749SStefano Zampini     }
70588ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM2,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70688ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM3,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70788ebb749SStefano Zampini     ierr = MatAXPY(TM1,one,TM4,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
70888ebb749SStefano Zampini     ierr = MatConvert(TM1,MATSEQDENSE,MAT_REUSE_MATRIX,&TM1);CHKERRQ(ierr);
70981d9aea3SBarry Smith     ierr = MatAXPY(TM1,m_one,coarse_sub_mat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
71088ebb749SStefano Zampini     ierr = MatNorm(TM1,NORM_INFINITY,&real_value);CHKERRQ(ierr);
7110fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
71225084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"----------------------------------\n");CHKERRQ(ierr);
71325084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d \n",PetscGlobalRank);CHKERRQ(ierr);
71425084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"matrix error = % 1.14e\n",real_value);CHKERRQ(ierr);
71525084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (phi) errors\n");CHKERRQ(ierr);
71688ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
71725084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,coarsefunctions_errors[i]);CHKERRQ(ierr);
71888ebb749SStefano Zampini     }
71925084f0cSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (phi) errors\n");CHKERRQ(ierr);
72088ebb749SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
72125084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i,constraints_errors[i]);CHKERRQ(ierr);
72288ebb749SStefano Zampini     }
723c0553b1fSStefano Zampini     if (unsymmetric_check) {
72425084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"coarse functions (psi) errors\n");CHKERRQ(ierr);
72588ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
72625084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,coarsefunctions_errors[i]);CHKERRQ(ierr);
72788ebb749SStefano Zampini       }
72825084f0cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"constraints (psi) errors\n");CHKERRQ(ierr);
72988ebb749SStefano Zampini       for (i=pcbddc->local_primal_size;i<2*pcbddc->local_primal_size;i++) {
73025084f0cSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local %02d-th function error = % 1.14e\n",i-pcbddc->local_primal_size,constraints_errors[i]);CHKERRQ(ierr);
73188ebb749SStefano Zampini       }
73288ebb749SStefano Zampini     }
73325084f0cSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
73488ebb749SStefano Zampini     ierr = MatDestroy(&A_II);CHKERRQ(ierr);
73588ebb749SStefano Zampini     ierr = MatDestroy(&A_BB);CHKERRQ(ierr);
73688ebb749SStefano Zampini     ierr = MatDestroy(&A_IB);CHKERRQ(ierr);
73788ebb749SStefano Zampini     ierr = MatDestroy(&A_BI);CHKERRQ(ierr);
73888ebb749SStefano Zampini     ierr = MatDestroy(&TM1);CHKERRQ(ierr);
73988ebb749SStefano Zampini     ierr = MatDestroy(&TM2);CHKERRQ(ierr);
74088ebb749SStefano Zampini     ierr = MatDestroy(&TM3);CHKERRQ(ierr);
74188ebb749SStefano Zampini     ierr = MatDestroy(&TM4);CHKERRQ(ierr);
74288ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_D);CHKERRQ(ierr);
74388ebb749SStefano Zampini     ierr = MatDestroy(&coarse_phi_B);CHKERRQ(ierr);
744c0553b1fSStefano Zampini     if (unsymmetric_check) {
74588ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_D);CHKERRQ(ierr);
74688ebb749SStefano Zampini       ierr = MatDestroy(&coarse_psi_B);CHKERRQ(ierr);
74788ebb749SStefano Zampini     }
74888ebb749SStefano Zampini     ierr = MatDestroy(&coarse_sub_mat);CHKERRQ(ierr);
7498ce42a96SStefano Zampini     ierr = ISRestoreIndices(pcbddc->is_R_local,&idx_R_local);CHKERRQ(ierr);
75088ebb749SStefano Zampini     ierr = PetscFree(coarsefunctions_errors);CHKERRQ(ierr);
75188ebb749SStefano Zampini     ierr = PetscFree(constraints_errors);CHKERRQ(ierr);
75288ebb749SStefano Zampini   }
75388ebb749SStefano Zampini   /* free memory */
75488ebb749SStefano Zampini   if (n_vertices) {
75588ebb749SStefano Zampini     ierr = VecDestroy(&vec1_V);CHKERRQ(ierr);
75688ebb749SStefano Zampini     ierr = VecDestroy(&vec2_V);CHKERRQ(ierr);
75788ebb749SStefano Zampini     ierr = MatDestroy(&A_RV);CHKERRQ(ierr);
75888ebb749SStefano Zampini     ierr = MatDestroy(&A_VR);CHKERRQ(ierr);
75988ebb749SStefano Zampini     ierr = MatDestroy(&A_VV);CHKERRQ(ierr);
76088ebb749SStefano Zampini   }
76188ebb749SStefano Zampini   if (n_constraints) {
76288ebb749SStefano Zampini     ierr = VecDestroy(&vec1_C);CHKERRQ(ierr);
76388ebb749SStefano Zampini     ierr = VecDestroy(&vec2_C);CHKERRQ(ierr);
76488ebb749SStefano Zampini     ierr = MatDestroy(&M1);CHKERRQ(ierr);
76588ebb749SStefano Zampini     ierr = MatDestroy(&C_CR);CHKERRQ(ierr);
76688ebb749SStefano Zampini   }
76788ebb749SStefano Zampini   ierr = PetscFree(auxindices);CHKERRQ(ierr);
7688629588bSStefano Zampini   /* get back data */
7698629588bSStefano Zampini   *coarse_submat_vals_n = coarse_submat_vals;
77088ebb749SStefano Zampini   PetscFunctionReturn(0);
77188ebb749SStefano Zampini }
77288ebb749SStefano Zampini 
77388ebb749SStefano Zampini #undef __FUNCT__
774*d65f70fdSStefano Zampini #define __FUNCT__ "MatGetSubMatrixUnsorted"
775*d65f70fdSStefano Zampini PetscErrorCode MatGetSubMatrixUnsorted(Mat A, IS isrow, IS iscol, Mat* B)
776*d65f70fdSStefano Zampini {
777*d65f70fdSStefano Zampini   Mat            *work_mat;
778*d65f70fdSStefano Zampini   IS             isrow_s,iscol_s;
779*d65f70fdSStefano Zampini   PetscBool      rsorted,csorted;
780*d65f70fdSStefano Zampini   PetscInt       rsize,*idxs_perm_r,csize,*idxs_perm_c;
781*d65f70fdSStefano Zampini   PetscErrorCode ierr;
782*d65f70fdSStefano Zampini 
783*d65f70fdSStefano Zampini   PetscFunctionBegin;
784*d65f70fdSStefano Zampini   ierr = ISSorted(isrow,&rsorted);CHKERRQ(ierr);
785*d65f70fdSStefano Zampini   ierr = ISSorted(iscol,&csorted);CHKERRQ(ierr);
786*d65f70fdSStefano Zampini   ierr = ISGetLocalSize(isrow,&rsize);CHKERRQ(ierr);
787*d65f70fdSStefano Zampini   ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr);
788*d65f70fdSStefano Zampini 
789*d65f70fdSStefano Zampini   if (!rsorted) {
790*d65f70fdSStefano Zampini     const PetscInt *idxs;
791*d65f70fdSStefano Zampini     PetscInt *idxs_sorted,i;
792*d65f70fdSStefano Zampini 
793*d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_perm_r);CHKERRQ(ierr);
794*d65f70fdSStefano Zampini     ierr = PetscMalloc1(rsize,&idxs_sorted);CHKERRQ(ierr);
795*d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
796*d65f70fdSStefano Zampini       idxs_perm_r[i] = i;
797*d65f70fdSStefano Zampini     }
798*d65f70fdSStefano Zampini     ierr = ISGetIndices(isrow,&idxs);CHKERRQ(ierr);
799*d65f70fdSStefano Zampini     ierr = PetscSortIntWithPermutation(rsize,idxs,idxs_perm_r);CHKERRQ(ierr);
800*d65f70fdSStefano Zampini     for (i=0;i<rsize;i++) {
801*d65f70fdSStefano Zampini       idxs_sorted[i] = idxs[idxs_perm_r[i]];
802*d65f70fdSStefano Zampini     }
803*d65f70fdSStefano Zampini     ierr = ISRestoreIndices(isrow,&idxs);CHKERRQ(ierr);
804*d65f70fdSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_sorted,PETSC_OWN_POINTER,&isrow_s);CHKERRQ(ierr);
805*d65f70fdSStefano Zampini   } else {
806*d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)isrow);CHKERRQ(ierr);
807*d65f70fdSStefano Zampini     isrow_s = isrow;
808*d65f70fdSStefano Zampini   }
809*d65f70fdSStefano Zampini 
810*d65f70fdSStefano Zampini   if (!csorted) {
811*d65f70fdSStefano Zampini     if (isrow == iscol) {
812*d65f70fdSStefano Zampini       ierr = PetscObjectReference((PetscObject)isrow_s);CHKERRQ(ierr);
813*d65f70fdSStefano Zampini       iscol_s = isrow_s;
814*d65f70fdSStefano Zampini     } else {
815*d65f70fdSStefano Zampini       const PetscInt *idxs;
816*d65f70fdSStefano Zampini       PetscInt *idxs_sorted,i;
817*d65f70fdSStefano Zampini 
818*d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_perm_c);CHKERRQ(ierr);
819*d65f70fdSStefano Zampini       ierr = PetscMalloc1(csize,&idxs_sorted);CHKERRQ(ierr);
820*d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
821*d65f70fdSStefano Zampini         idxs_perm_c[i] = i;
822*d65f70fdSStefano Zampini       }
823*d65f70fdSStefano Zampini       ierr = ISGetIndices(iscol,&idxs);CHKERRQ(ierr);
824*d65f70fdSStefano Zampini       ierr = PetscSortIntWithPermutation(csize,idxs,idxs_perm_c);CHKERRQ(ierr);
825*d65f70fdSStefano Zampini       for (i=0;i<csize;i++) {
826*d65f70fdSStefano Zampini         idxs_sorted[i] = idxs[idxs_perm_c[i]];
827*d65f70fdSStefano Zampini       }
828*d65f70fdSStefano Zampini       ierr = ISRestoreIndices(iscol,&idxs);CHKERRQ(ierr);
829*d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_sorted,PETSC_OWN_POINTER,&iscol_s);CHKERRQ(ierr);
830*d65f70fdSStefano Zampini     }
831*d65f70fdSStefano Zampini   } else {
832*d65f70fdSStefano Zampini     ierr = PetscObjectReference((PetscObject)iscol);CHKERRQ(ierr);
833*d65f70fdSStefano Zampini     iscol_s = iscol;
834*d65f70fdSStefano Zampini   }
835*d65f70fdSStefano Zampini 
836*d65f70fdSStefano Zampini   ierr = MatGetSubMatrices(A,1,&isrow_s,&iscol_s,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
837*d65f70fdSStefano Zampini 
838*d65f70fdSStefano Zampini   if (!rsorted || !csorted) {
839*d65f70fdSStefano Zampini     Mat      new_mat;
840*d65f70fdSStefano Zampini     IS       is_perm_r,is_perm_c;
841*d65f70fdSStefano Zampini 
842*d65f70fdSStefano Zampini     if (!rsorted) {
843*d65f70fdSStefano Zampini       PetscInt *idxs_r,i;
844*d65f70fdSStefano Zampini       ierr = PetscMalloc1(rsize,&idxs_r);CHKERRQ(ierr);
845*d65f70fdSStefano Zampini       for (i=0;i<rsize;i++) {
846*d65f70fdSStefano Zampini         idxs_r[idxs_perm_r[i]] = i;
847*d65f70fdSStefano Zampini       }
848*d65f70fdSStefano Zampini       ierr = PetscFree(idxs_perm_r);CHKERRQ(ierr);
849*d65f70fdSStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,rsize,idxs_r,PETSC_OWN_POINTER,&is_perm_r);CHKERRQ(ierr);
850*d65f70fdSStefano Zampini     } else {
851*d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,rsize,0,1,&is_perm_r);CHKERRQ(ierr);
852*d65f70fdSStefano Zampini     }
853*d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_r);CHKERRQ(ierr);
854*d65f70fdSStefano Zampini 
855*d65f70fdSStefano Zampini     if (!csorted) {
856*d65f70fdSStefano Zampini       if (isrow_s == iscol_s) {
857*d65f70fdSStefano Zampini         ierr = PetscObjectReference((PetscObject)is_perm_r);CHKERRQ(ierr);
858*d65f70fdSStefano Zampini         is_perm_c = is_perm_r;
859*d65f70fdSStefano Zampini       } else {
860*d65f70fdSStefano Zampini         PetscInt *idxs_c,i;
861*d65f70fdSStefano Zampini         ierr = PetscMalloc1(csize,&idxs_c);CHKERRQ(ierr);
862*d65f70fdSStefano Zampini         for (i=0;i<csize;i++) {
863*d65f70fdSStefano Zampini           idxs_c[idxs_perm_c[i]] = i;
864*d65f70fdSStefano Zampini         }
865*d65f70fdSStefano Zampini         ierr = PetscFree(idxs_perm_c);CHKERRQ(ierr);
866*d65f70fdSStefano Zampini         ierr = ISCreateGeneral(PETSC_COMM_SELF,csize,idxs_c,PETSC_OWN_POINTER,&is_perm_c);CHKERRQ(ierr);
867*d65f70fdSStefano Zampini       }
868*d65f70fdSStefano Zampini     } else {
869*d65f70fdSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,csize,0,1,&is_perm_c);CHKERRQ(ierr);
870*d65f70fdSStefano Zampini     }
871*d65f70fdSStefano Zampini     ierr = ISSetPermutation(is_perm_c);CHKERRQ(ierr);
872*d65f70fdSStefano Zampini 
873*d65f70fdSStefano Zampini     ierr = MatPermute(work_mat[0],is_perm_r,is_perm_c,&new_mat);CHKERRQ(ierr);
874*d65f70fdSStefano Zampini     ierr = MatDestroy(&work_mat[0]);CHKERRQ(ierr);
875*d65f70fdSStefano Zampini     work_mat[0] = new_mat;
876*d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_r);CHKERRQ(ierr);
877*d65f70fdSStefano Zampini     ierr = ISDestroy(&is_perm_c);CHKERRQ(ierr);
878*d65f70fdSStefano Zampini   }
879*d65f70fdSStefano Zampini 
880*d65f70fdSStefano Zampini   ierr = PetscObjectReference((PetscObject)work_mat[0]);CHKERRQ(ierr);
881*d65f70fdSStefano Zampini   *B = work_mat[0];
882*d65f70fdSStefano Zampini   ierr = MatDestroyMatrices(1,&work_mat);CHKERRQ(ierr);
883*d65f70fdSStefano Zampini   ierr = ISDestroy(&isrow_s);CHKERRQ(ierr);
884*d65f70fdSStefano Zampini   ierr = ISDestroy(&iscol_s);CHKERRQ(ierr);
885*d65f70fdSStefano Zampini   PetscFunctionReturn(0);
886*d65f70fdSStefano Zampini }
887*d65f70fdSStefano Zampini 
888*d65f70fdSStefano Zampini #undef __FUNCT__
8895e8657edSStefano Zampini #define __FUNCT__ "PCBDDCComputeLocalMatrix"
8905e8657edSStefano Zampini PetscErrorCode PCBDDCComputeLocalMatrix(PC pc, Mat ChangeOfBasisMatrix)
891aa0d41d4SStefano Zampini {
892aa0d41d4SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
8935e8657edSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
894*d65f70fdSStefano Zampini   Mat            new_mat;
8955e8657edSStefano Zampini   IS             is_local,is_global;
896*d65f70fdSStefano Zampini   PetscInt       local_size;
897*d65f70fdSStefano Zampini   PetscBool      isseqaij;
898aa0d41d4SStefano Zampini   PetscErrorCode ierr;
899aa0d41d4SStefano Zampini 
900aa0d41d4SStefano Zampini   PetscFunctionBegin;
901aa0d41d4SStefano Zampini   ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
9025e8657edSStefano Zampini   ierr = MatGetSize(matis->A,&local_size,NULL);CHKERRQ(ierr);
9035e8657edSStefano Zampini   ierr = ISCreateStride(PetscObjectComm((PetscObject)matis->A),local_size,0,1,&is_local);CHKERRQ(ierr);
904906d46d4SStefano Zampini   ierr = ISLocalToGlobalMappingApplyIS(matis->mapping,is_local,&is_global);CHKERRQ(ierr);
905906d46d4SStefano Zampini   ierr = ISDestroy(&is_local);CHKERRQ(ierr);
906*d65f70fdSStefano Zampini   ierr = MatGetSubMatrixUnsorted(ChangeOfBasisMatrix,is_global,is_global,&new_mat);CHKERRQ(ierr);
907906d46d4SStefano Zampini   ierr = ISDestroy(&is_global);CHKERRQ(ierr);
908906d46d4SStefano Zampini 
909906d46d4SStefano Zampini   /* check */
910906d46d4SStefano Zampini   if (pcbddc->dbg_flag) {
911906d46d4SStefano Zampini     Vec       x,x_change;
912906d46d4SStefano Zampini     PetscReal error;
913906d46d4SStefano Zampini 
9145e8657edSStefano Zampini     ierr = MatCreateVecs(ChangeOfBasisMatrix,&x,&x_change);CHKERRQ(ierr);
915906d46d4SStefano Zampini     ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
9165e8657edSStefano Zampini     ierr = MatMult(ChangeOfBasisMatrix,x,x_change);CHKERRQ(ierr);
9175e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
9185e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,x,matis->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
919*d65f70fdSStefano Zampini     ierr = MatMult(new_mat,matis->x,matis->y);CHKERRQ(ierr);
9205e8657edSStefano Zampini     ierr = VecScatterBegin(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9215e8657edSStefano Zampini     ierr = VecScatterEnd(matis->ctx,matis->y,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
922906d46d4SStefano Zampini     ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
923906d46d4SStefano Zampini     ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
924906d46d4SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
925906d46d4SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on N: %1.6e\n",error);CHKERRQ(ierr);
926906d46d4SStefano Zampini     ierr = VecDestroy(&x);CHKERRQ(ierr);
927906d46d4SStefano Zampini     ierr = VecDestroy(&x_change);CHKERRQ(ierr);
928906d46d4SStefano Zampini   }
929906d46d4SStefano Zampini 
93022d5777bSStefano Zampini   /* TODO: HOW TO WORK WITH BAIJ and SBAIJ and SEQDENSE? */
9319b28b3ffSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
93222d5777bSStefano Zampini   if (isseqaij) {
933*d65f70fdSStefano Zampini     ierr = MatPtAP(matis->A,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
934aa0d41d4SStefano Zampini   } else {
935aa0d41d4SStefano Zampini     Mat work_mat;
936aa0d41d4SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&work_mat);CHKERRQ(ierr);
937*d65f70fdSStefano Zampini     ierr = MatPtAP(work_mat,new_mat,MAT_INITIAL_MATRIX,2.0,&pcbddc->local_mat);CHKERRQ(ierr);
938aa0d41d4SStefano Zampini     ierr = MatDestroy(&work_mat);CHKERRQ(ierr);
939aa0d41d4SStefano Zampini   }
940*d65f70fdSStefano Zampini   ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
94145a1bb75SStefano Zampini   /*
94245a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
943*d65f70fdSStefano Zampini   ierr = MatView(new_mat,(PetscViewer)0);CHKERRQ(ierr);
94445a1bb75SStefano Zampini   */
945*d65f70fdSStefano Zampini   ierr = MatDestroy(&new_mat);CHKERRQ(ierr);
946aa0d41d4SStefano Zampini   PetscFunctionReturn(0);
947aa0d41d4SStefano Zampini }
948aa0d41d4SStefano Zampini 
949aa0d41d4SStefano Zampini #undef __FUNCT__
950a64d13efSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalScatters"
9518ce42a96SStefano Zampini PetscErrorCode PCBDDCSetUpLocalScatters(PC pc)
952a64d13efSStefano Zampini {
953a64d13efSStefano Zampini   PC_IS*         pcis = (PC_IS*)(pc->data);
954a64d13efSStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
9558ce42a96SStefano Zampini   IS             is_aux1,is_aux2;
956e9189074SStefano Zampini   PetscInt       *aux_array1,*aux_array2,*is_indices,*idx_R_local;
9573a50541eSStefano Zampini   PetscInt       n_vertices,i,j,n_R,n_D,n_B;
9583a50541eSStefano Zampini   PetscInt       vbs,bs;
9594641a718SStefano Zampini   PetscBT        bitmask;
960a64d13efSStefano Zampini   PetscErrorCode ierr;
961a64d13efSStefano Zampini 
962a64d13efSStefano Zampini   PetscFunctionBegin;
963b23d619eSStefano Zampini   /*
964b23d619eSStefano Zampini     No need to setup local scatters if
965b23d619eSStefano Zampini       - primal space is unchanged
966b23d619eSStefano Zampini         AND
967b23d619eSStefano Zampini       - we actually have locally some primal dofs (could not be true in multilevel or for isolated subdomains)
968b23d619eSStefano Zampini         AND
969b23d619eSStefano Zampini       - we are not in debugging mode (this is needed since there are Synchronized prints at the end of the subroutine
970b23d619eSStefano Zampini   */
971b23d619eSStefano Zampini   if (!pcbddc->new_primal_space_local && pcbddc->local_primal_size && !pcbddc->dbg_flag) {
972f4ddd8eeSStefano Zampini     PetscFunctionReturn(0);
973f4ddd8eeSStefano Zampini   }
974f4ddd8eeSStefano Zampini   /* destroy old objects */
975f4ddd8eeSStefano Zampini   ierr = ISDestroy(&pcbddc->is_R_local);CHKERRQ(ierr);
976f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_B);CHKERRQ(ierr);
977f4ddd8eeSStefano Zampini   ierr = VecScatterDestroy(&pcbddc->R_to_D);CHKERRQ(ierr);
978a64d13efSStefano Zampini   /* Set Non-overlapping dimensions */
979a64d13efSStefano Zampini   n_B = pcis->n_B; n_D = pcis->n - n_B;
980e9189074SStefano Zampini   n_vertices = pcbddc->n_actual_vertices;
9814641a718SStefano Zampini   /* create auxiliary bitmask */
9824641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n,&bitmask);CHKERRQ(ierr);
9834641a718SStefano Zampini   for (i=0;i<n_vertices;i++) {
984e9189074SStefano Zampini     ierr = PetscBTSet(bitmask,pcbddc->primal_indices_local_idxs[i]);CHKERRQ(ierr);
9854641a718SStefano Zampini   }
9863a50541eSStefano Zampini 
987a64d13efSStefano Zampini   /* Dohrmann's notation: dofs splitted in R (Remaining: all dofs but the vertices) and V (Vertices) */
988854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n-n_vertices,&idx_R_local);CHKERRQ(ierr);
989a64d13efSStefano Zampini   for (i=0, n_R=0; i<pcis->n; i++) {
9904641a718SStefano Zampini     if (!PetscBTLookup(bitmask,i)) {
991a64d13efSStefano Zampini       idx_R_local[n_R] = i;
992a64d13efSStefano Zampini       n_R++;
993a64d13efSStefano Zampini     }
994a64d13efSStefano Zampini   }
9953a50541eSStefano Zampini 
9963a50541eSStefano Zampini   /* Block code */
9973a50541eSStefano Zampini   vbs = 1;
9983a50541eSStefano Zampini   ierr = MatGetBlockSize(pcbddc->local_mat,&bs);CHKERRQ(ierr);
9993a50541eSStefano Zampini   if (bs>1 && !(n_vertices%bs)) {
10003a50541eSStefano Zampini     PetscBool is_blocked = PETSC_TRUE;
10013a50541eSStefano Zampini     PetscInt  *vary;
10023a50541eSStefano Zampini     /* Verify if the vertex indices correspond to each element in a block (code taken from sbaij2.c) */
1003785e854fSJed Brown     ierr = PetscMalloc1(pcis->n/bs,&vary);CHKERRQ(ierr);
10043a50541eSStefano Zampini     ierr = PetscMemzero(vary,pcis->n/bs*sizeof(PetscInt));CHKERRQ(ierr);
1005e9189074SStefano Zampini     for (i=0; i<n_vertices; i++) vary[pcbddc->primal_indices_local_idxs[i]/bs]++;
10063a50541eSStefano Zampini     for (i=0; i<n_vertices; i++) {
10073a50541eSStefano Zampini       if (vary[i]!=0 && vary[i]!=bs) {
10083a50541eSStefano Zampini         is_blocked = PETSC_FALSE;
10093a50541eSStefano Zampini         break;
10103a50541eSStefano Zampini       }
10113a50541eSStefano Zampini     }
10123a50541eSStefano Zampini     if (is_blocked) { /* build compressed IS for R nodes (complement of vertices) */
10133a50541eSStefano Zampini       vbs = bs;
10143a50541eSStefano Zampini       for (i=0;i<n_R/vbs;i++) {
10153a50541eSStefano Zampini         idx_R_local[i] = idx_R_local[vbs*i]/vbs;
10163a50541eSStefano Zampini       }
10173a50541eSStefano Zampini     }
10183a50541eSStefano Zampini     ierr = PetscFree(vary);CHKERRQ(ierr);
10193a50541eSStefano Zampini   }
10203a50541eSStefano Zampini   ierr = ISCreateBlock(PETSC_COMM_SELF,vbs,n_R/vbs,idx_R_local,PETSC_COPY_VALUES,&pcbddc->is_R_local);CHKERRQ(ierr);
10213a50541eSStefano Zampini   ierr = PetscFree(idx_R_local);CHKERRQ(ierr);
1022a64d13efSStefano Zampini 
1023a64d13efSStefano Zampini   /* print some info if requested */
1024a64d13efSStefano Zampini   if (pcbddc->dbg_flag) {
1025a64d13efSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1026a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
10270fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1028a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d local dimensions\n",PetscGlobalRank);CHKERRQ(ierr);
1029a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_size = %d, dirichlet_size = %d, boundary_size = %d\n",pcis->n,n_D,n_B);CHKERRQ(ierr);
10303a50541eSStefano 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);
1031a64d13efSStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"pcbddc->n_vertices = %d, pcbddc->n_constraints = %d\n",pcbddc->n_vertices,pcbddc->n_constraints);CHKERRQ(ierr);
1032a64d13efSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1033a64d13efSStefano Zampini   }
1034a64d13efSStefano Zampini 
1035a64d13efSStefano Zampini   /* VecScatters pcbddc->R_to_B and (optionally) pcbddc->R_to_D */
10363a50541eSStefano Zampini   ierr = ISGetIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1037854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array1);CHKERRQ(ierr);
1038854ce69bSBarry Smith   ierr = PetscMalloc1(pcis->n_B-n_vertices,&aux_array2);CHKERRQ(ierr);
1039a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10404641a718SStefano Zampini   for (i=0; i<n_D; i++) {
10414641a718SStefano Zampini     ierr = PetscBTSet(bitmask,is_indices[i]);CHKERRQ(ierr);
10424641a718SStefano Zampini   }
1043a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1044a64d13efSStefano Zampini   for (i=0, j=0; i<n_R; i++) {
10454641a718SStefano Zampini     if (!PetscBTLookup(bitmask,idx_R_local[i])) {
10464641a718SStefano Zampini       aux_array1[j++] = i;
1047a64d13efSStefano Zampini     }
1048a64d13efSStefano Zampini   }
1049a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1050a64d13efSStefano Zampini   ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1051a64d13efSStefano Zampini   for (i=0, j=0; i<n_B; i++) {
10524641a718SStefano Zampini     if (!PetscBTLookup(bitmask,is_indices[i])) {
10534641a718SStefano Zampini       aux_array2[j++] = i;
1054a64d13efSStefano Zampini     }
1055a64d13efSStefano Zampini   }
1056a64d13efSStefano Zampini   ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1057a64d13efSStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array2,PETSC_OWN_POINTER,&is_aux2);CHKERRQ(ierr);
1058a64d13efSStefano Zampini   ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_B,is_aux2,&pcbddc->R_to_B);CHKERRQ(ierr);
1059a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1060a64d13efSStefano Zampini   ierr = ISDestroy(&is_aux2);CHKERRQ(ierr);
1061a64d13efSStefano Zampini 
10628eeda7d8SStefano Zampini   if (pcbddc->switch_static || pcbddc->dbg_flag) {
1063785e854fSJed Brown     ierr = PetscMalloc1(n_D,&aux_array1);CHKERRQ(ierr);
1064a64d13efSStefano Zampini     for (i=0, j=0; i<n_R; i++) {
10654641a718SStefano Zampini       if (PetscBTLookup(bitmask,idx_R_local[i])) {
10664641a718SStefano Zampini         aux_array1[j++] = i;
1067a64d13efSStefano Zampini       }
1068a64d13efSStefano Zampini     }
1069a64d13efSStefano Zampini     ierr = ISCreateGeneral(PETSC_COMM_SELF,j,aux_array1,PETSC_OWN_POINTER,&is_aux1);CHKERRQ(ierr);
1070a64d13efSStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_R,is_aux1,pcis->vec1_D,(IS)0,&pcbddc->R_to_D);CHKERRQ(ierr);
1071a64d13efSStefano Zampini     ierr = ISDestroy(&is_aux1);CHKERRQ(ierr);
1072a64d13efSStefano Zampini   }
10734641a718SStefano Zampini   ierr = PetscBTDestroy(&bitmask);CHKERRQ(ierr);
10743a50541eSStefano Zampini   ierr = ISRestoreIndices(pcbddc->is_R_local,(const PetscInt**)&idx_R_local);CHKERRQ(ierr);
1075a64d13efSStefano Zampini   PetscFunctionReturn(0);
1076a64d13efSStefano Zampini }
1077a64d13efSStefano Zampini 
1078304d26faSStefano Zampini 
1079304d26faSStefano Zampini #undef __FUNCT__
1080304d26faSStefano Zampini #define __FUNCT__ "PCBDDCSetUpLocalSolvers"
1081684f6988SStefano Zampini PetscErrorCode PCBDDCSetUpLocalSolvers(PC pc, PetscBool dirichlet, PetscBool neumann)
1082304d26faSStefano Zampini {
1083304d26faSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1084304d26faSStefano Zampini   PC_IS          *pcis = (PC_IS*)pc->data;
1085304d26faSStefano Zampini   PC             pc_temp;
1086304d26faSStefano Zampini   Mat            A_RR;
1087f4ddd8eeSStefano Zampini   MatReuse       reuse;
1088304d26faSStefano Zampini   PetscScalar    m_one = -1.0;
1089304d26faSStefano Zampini   PetscReal      value;
1090af732b37SStefano Zampini   PetscInt       n_D,n_R,ibs,mbs;
10919577ea80SStefano Zampini   PetscBool      use_exact,use_exact_reduced,issbaij;
1092304d26faSStefano Zampini   PetscErrorCode ierr;
1093e604994aSStefano Zampini   /* prefixes stuff */
1094312be037SStefano Zampini   char           dir_prefix[256],neu_prefix[256],str_level[16];
1095e604994aSStefano Zampini   size_t         len;
1096304d26faSStefano Zampini 
1097304d26faSStefano Zampini   PetscFunctionBegin;
1098304d26faSStefano Zampini 
1099e604994aSStefano Zampini   /* compute prefixes */
1100e604994aSStefano Zampini   ierr = PetscStrcpy(dir_prefix,"");CHKERRQ(ierr);
1101e604994aSStefano Zampini   ierr = PetscStrcpy(neu_prefix,"");CHKERRQ(ierr);
1102e604994aSStefano Zampini   if (!pcbddc->current_level) {
1103e604994aSStefano Zampini     ierr = PetscStrcpy(dir_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1104e604994aSStefano Zampini     ierr = PetscStrcpy(neu_prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
1105e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1106e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1107e604994aSStefano Zampini   } else {
1108e604994aSStefano Zampini     ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
1109312be037SStefano Zampini     sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
1110e604994aSStefano Zampini     ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
1111e604994aSStefano Zampini     len -= 15; /* remove "pc_bddc_coarse_" */
1112312be037SStefano Zampini     if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
1113312be037SStefano Zampini     if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
111434d6797cSStefano Zampini     ierr = PetscStrncpy(dir_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
111534d6797cSStefano Zampini     ierr = PetscStrncpy(neu_prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
1116e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,"pc_bddc_dirichlet_");CHKERRQ(ierr);
1117e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,"pc_bddc_neumann_");CHKERRQ(ierr);
1118e604994aSStefano Zampini     ierr = PetscStrcat(dir_prefix,str_level);CHKERRQ(ierr);
1119e604994aSStefano Zampini     ierr = PetscStrcat(neu_prefix,str_level);CHKERRQ(ierr);
1120e604994aSStefano Zampini   }
1121e604994aSStefano Zampini 
1122304d26faSStefano Zampini   /* DIRICHLET PROBLEM */
1123684f6988SStefano Zampini   if (dirichlet) {
1124ac78edfcSStefano Zampini     /* Matrix for Dirichlet problem is pcis->A_II */
11258ce42a96SStefano Zampini     ierr = ISGetSize(pcis->is_I_local,&n_D);CHKERRQ(ierr);
1126304d26faSStefano Zampini     if (!pcbddc->ksp_D) { /* create object if not yet build */
1127304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_D);CHKERRQ(ierr);
1128304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr);
1129304d26faSStefano Zampini       /* default */
1130304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_D,KSPPREONLY);CHKERRQ(ierr);
1131e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_D,dir_prefix);CHKERRQ(ierr);
11329577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)pcis->A_II,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1133304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
11349577ea80SStefano Zampini       if (issbaij) {
11359577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
11369577ea80SStefano Zampini       } else {
1137304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
11389577ea80SStefano Zampini       }
1139304d26faSStefano Zampini       /* Allow user's customization */
1140304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_D);CHKERRQ(ierr);
1141304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1142304d26faSStefano Zampini     }
1143d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr);
1144304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1145304d26faSStefano Zampini     if (!n_D) {
1146304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
1147304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1148304d26faSStefano Zampini     }
1149304d26faSStefano Zampini     /* Set Up KSP for Dirichlet problem of BDDC */
1150304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_D);CHKERRQ(ierr);
1151304d26faSStefano Zampini     /* set ksp_D into pcis data */
1152304d26faSStefano Zampini     ierr = KSPDestroy(&pcis->ksp_D);CHKERRQ(ierr);
1153304d26faSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->ksp_D);CHKERRQ(ierr);
1154304d26faSStefano Zampini     pcis->ksp_D = pcbddc->ksp_D;
1155684f6988SStefano Zampini   }
1156304d26faSStefano Zampini 
1157304d26faSStefano Zampini   /* NEUMANN PROBLEM */
1158684f6988SStefano Zampini   A_RR = 0;
1159684f6988SStefano Zampini   if (neumann) {
1160f4ddd8eeSStefano Zampini     /* Matrix for Neumann problem is A_RR -> we need to create/reuse it at this point */
11618ce42a96SStefano Zampini     ierr = ISGetSize(pcbddc->is_R_local,&n_R);CHKERRQ(ierr);
1162f4ddd8eeSStefano Zampini     if (pcbddc->ksp_R) { /* already created ksp */
1163f4ddd8eeSStefano Zampini       PetscInt nn_R;
116481d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->ksp_R,NULL,&A_RR);CHKERRQ(ierr);
1165f4ddd8eeSStefano Zampini       ierr = PetscObjectReference((PetscObject)A_RR);CHKERRQ(ierr);
1166f4ddd8eeSStefano Zampini       ierr = MatGetSize(A_RR,&nn_R,NULL);CHKERRQ(ierr);
1167f4ddd8eeSStefano Zampini       if (nn_R != n_R) { /* old ksp is not reusable, so reset it */
1168f4ddd8eeSStefano Zampini         ierr = KSPReset(pcbddc->ksp_R);CHKERRQ(ierr);
1169f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1170f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1171f4ddd8eeSStefano Zampini       } else { /* same sizes, but nonzero pattern depend on primal vertices so it can be changed */
1172727cdba6SStefano Zampini         if (pcbddc->new_primal_space_local) { /* we are not sure the matrix will have the same nonzero pattern */
1173f4ddd8eeSStefano Zampini           ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1174f4ddd8eeSStefano Zampini           reuse = MAT_INITIAL_MATRIX;
1175f4ddd8eeSStefano Zampini         } else { /* safe to reuse the matrix */
1176f4ddd8eeSStefano Zampini           reuse = MAT_REUSE_MATRIX;
1177f4ddd8eeSStefano Zampini         }
1178f4ddd8eeSStefano Zampini       }
1179f4ddd8eeSStefano Zampini       /* last check */
1180d1e9a80fSBarry Smith       if (pc->flag == DIFFERENT_NONZERO_PATTERN) {
1181f4ddd8eeSStefano Zampini         ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1182f4ddd8eeSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
1183f4ddd8eeSStefano Zampini       }
1184f4ddd8eeSStefano Zampini     } else { /* first time, so we need to create the matrix */
1185f4ddd8eeSStefano Zampini       reuse = MAT_INITIAL_MATRIX;
1186f4ddd8eeSStefano Zampini     }
1187f4ddd8eeSStefano Zampini     /* extract A_RR */
1188af732b37SStefano Zampini     ierr = MatGetBlockSize(pcbddc->local_mat,&mbs);CHKERRQ(ierr);
1189af732b37SStefano Zampini     ierr = ISGetBlockSize(pcbddc->is_R_local,&ibs);CHKERRQ(ierr);
11903a50541eSStefano Zampini     if (ibs != mbs) {
1191af732b37SStefano Zampini       Mat newmat;
1192af732b37SStefano Zampini       ierr = MatConvert(pcbddc->local_mat,MATSEQAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr);
1193f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(newmat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1194af732b37SStefano Zampini       ierr = MatDestroy(&newmat);CHKERRQ(ierr);
1195af732b37SStefano Zampini     } else {
1196f4ddd8eeSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcbddc->is_R_local,pcbddc->is_R_local,reuse,&A_RR);CHKERRQ(ierr);
1197af732b37SStefano Zampini     }
1198f4ddd8eeSStefano Zampini     if (!pcbddc->ksp_R) { /* create object if not present */
1199304d26faSStefano Zampini       ierr = KSPCreate(PETSC_COMM_SELF,&pcbddc->ksp_R);CHKERRQ(ierr);
1200304d26faSStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->ksp_R,(PetscObject)pc,1);CHKERRQ(ierr);
1201304d26faSStefano Zampini       /* default */
1202304d26faSStefano Zampini       ierr = KSPSetType(pcbddc->ksp_R,KSPPREONLY);CHKERRQ(ierr);
1203e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->ksp_R,neu_prefix);CHKERRQ(ierr);
1204304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
12059577ea80SStefano Zampini       ierr = PetscObjectTypeCompare((PetscObject)A_RR,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
12069577ea80SStefano Zampini       if (issbaij) {
12079577ea80SStefano Zampini         ierr = PCSetType(pc_temp,PCCHOLESKY);CHKERRQ(ierr);
12089577ea80SStefano Zampini       } else {
1209304d26faSStefano Zampini         ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
12109577ea80SStefano Zampini       }
1211304d26faSStefano Zampini       /* Allow user's customization */
1212304d26faSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->ksp_R);CHKERRQ(ierr);
1213304d26faSStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
1214304d26faSStefano Zampini     }
1215d1e9a80fSBarry Smith     ierr = KSPSetOperators(pcbddc->ksp_R,A_RR,A_RR);CHKERRQ(ierr);
1216304d26faSStefano Zampini     /* umfpack interface has a bug when matrix dimension is zero. TODO solve from umfpack interface */
1217304d26faSStefano Zampini     if (!n_R) {
1218304d26faSStefano Zampini       ierr = KSPGetPC(pcbddc->ksp_R,&pc_temp);CHKERRQ(ierr);
1219304d26faSStefano Zampini       ierr = PCSetType(pc_temp,PCNONE);CHKERRQ(ierr);
1220304d26faSStefano Zampini     }
1221304d26faSStefano Zampini     /* Set Up KSP for Neumann problem of BDDC */
1222304d26faSStefano Zampini     ierr = KSPSetUp(pcbddc->ksp_R);CHKERRQ(ierr);
1223684f6988SStefano Zampini   }
1224304d26faSStefano Zampini 
1225304d26faSStefano Zampini   /* check Dirichlet and Neumann solvers and adapt them if a nullspace correction is needed */
12260fccc4e9SStefano Zampini   if (pcbddc->NullSpace || pcbddc->dbg_flag) {
1227684f6988SStefano Zampini     if (pcbddc->dbg_flag) {
1228684f6988SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1229684f6988SStefano Zampini       ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1230684f6988SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
1231684f6988SStefano Zampini     }
1232684f6988SStefano Zampini     if (dirichlet) { /* Dirichlet */
12330fccc4e9SStefano Zampini       ierr = VecSetRandom(pcis->vec1_D,NULL);CHKERRQ(ierr);
12340fccc4e9SStefano Zampini       ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
12350fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec2_D,pcis->vec2_D);CHKERRQ(ierr);
12360fccc4e9SStefano Zampini       ierr = VecAXPY(pcis->vec1_D,m_one,pcis->vec2_D);CHKERRQ(ierr);
12370fccc4e9SStefano Zampini       ierr = VecNorm(pcis->vec1_D,NORM_INFINITY,&value);CHKERRQ(ierr);
1238304d26faSStefano Zampini       /* need to be adapted? */
1239b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1240b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1241b8ffe317SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,use_exact_reduced);CHKERRQ(ierr);
1242304d26faSStefano Zampini       /* print info */
1243304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1244e604994aSStefano 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);
1245304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1246304d26faSStefano Zampini       }
1247b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced && !pcbddc->switch_static) {
12488ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcis->is_I_local);CHKERRQ(ierr);
1249304d26faSStefano Zampini       }
1250684f6988SStefano Zampini     }
1251684f6988SStefano Zampini     if (neumann) { /* Neumann */
12520fccc4e9SStefano Zampini       ierr = VecSetRandom(pcbddc->vec1_R,NULL);CHKERRQ(ierr);
12530fccc4e9SStefano Zampini       ierr = MatMult(A_RR,pcbddc->vec1_R,pcbddc->vec2_R);CHKERRQ(ierr);
12540fccc4e9SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_R,pcbddc->vec2_R,pcbddc->vec2_R);CHKERRQ(ierr);
12550fccc4e9SStefano Zampini       ierr = VecAXPY(pcbddc->vec1_R,m_one,pcbddc->vec2_R);CHKERRQ(ierr);
12560fccc4e9SStefano Zampini       ierr = VecNorm(pcbddc->vec1_R,NORM_INFINITY,&value);CHKERRQ(ierr);
1257304d26faSStefano Zampini       /* need to be adapted? */
1258b8ffe317SStefano Zampini       use_exact = (PetscAbsReal(value) > 1.e-4 ? PETSC_FALSE : PETSC_TRUE);
1259b8ffe317SStefano Zampini       ierr = MPI_Allreduce(&use_exact,&use_exact_reduced,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1260304d26faSStefano Zampini       /* print info */
1261304d26faSStefano Zampini       if (pcbddc->dbg_flag) {
1262e604994aSStefano 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);
1263304d26faSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1264304d26faSStefano Zampini       }
1265b8ffe317SStefano Zampini       if (pcbddc->NullSpace && !use_exact_reduced) { /* is it the right logic? */
12668ce42a96SStefano Zampini         ierr = PCBDDCNullSpaceAssembleCorrection(pc,pcbddc->is_R_local);CHKERRQ(ierr);
1267304d26faSStefano Zampini       }
12680fccc4e9SStefano Zampini     }
1269684f6988SStefano Zampini   }
1270304d26faSStefano Zampini   /* free Neumann problem's matrix */
1271304d26faSStefano Zampini   ierr = MatDestroy(&A_RR);CHKERRQ(ierr);
1272304d26faSStefano Zampini   PetscFunctionReturn(0);
1273304d26faSStefano Zampini }
1274304d26faSStefano Zampini 
1275304d26faSStefano Zampini #undef __FUNCT__
1276ba15a52eSStefano Zampini #define __FUNCT__ "PCBDDCSolveSubstructureCorrection"
127720c7b377SStefano Zampini static PetscErrorCode  PCBDDCSolveSubstructureCorrection(PC pc, Vec rhs, Vec sol, Vec work, PetscBool applytranspose)
1278674ae819SStefano Zampini {
1279674ae819SStefano Zampini   PetscErrorCode ierr;
1280674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
1281674ae819SStefano Zampini 
1282674ae819SStefano Zampini   PetscFunctionBegin;
128320c7b377SStefano Zampini   if (applytranspose) {
1284674ae819SStefano Zampini     if (pcbddc->local_auxmat1) {
128520c7b377SStefano Zampini       ierr = MatMultTranspose(pcbddc->local_auxmat2,rhs,work);CHKERRQ(ierr);
128620c7b377SStefano Zampini       ierr = MatMultTransposeAdd(pcbddc->local_auxmat1,work,rhs,rhs);CHKERRQ(ierr);
128720c7b377SStefano Zampini     }
128820c7b377SStefano Zampini     ierr = KSPSolveTranspose(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
128920c7b377SStefano Zampini   } else {
129020c7b377SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_R,rhs,sol);CHKERRQ(ierr);
129120c7b377SStefano Zampini     if (pcbddc->local_auxmat1) {
129220c7b377SStefano Zampini       ierr = MatMult(pcbddc->local_auxmat1,sol,work);CHKERRQ(ierr);
129320c7b377SStefano Zampini       ierr = MatMultAdd(pcbddc->local_auxmat2,work,sol,sol);CHKERRQ(ierr);
129420c7b377SStefano Zampini     }
1295674ae819SStefano Zampini   }
1296674ae819SStefano Zampini   PetscFunctionReturn(0);
1297674ae819SStefano Zampini }
1298674ae819SStefano Zampini 
1299dc359a40SStefano Zampini /* parameter apply transpose determines if the interface preconditioner should be applied transposed or not */
1300674ae819SStefano Zampini #undef __FUNCT__
1301674ae819SStefano Zampini #define __FUNCT__ "PCBDDCApplyInterfacePreconditioner"
1302dc359a40SStefano Zampini PetscErrorCode  PCBDDCApplyInterfacePreconditioner(PC pc, PetscBool applytranspose)
1303674ae819SStefano Zampini {
1304674ae819SStefano Zampini   PetscErrorCode ierr;
1305674ae819SStefano Zampini   PC_BDDC*        pcbddc = (PC_BDDC*)(pc->data);
1306674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)  (pc->data);
1307674ae819SStefano Zampini   const PetscScalar zero = 0.0;
1308674ae819SStefano Zampini 
1309674ae819SStefano Zampini   PetscFunctionBegin;
1310dc359a40SStefano Zampini   /* Application of PSI^T or PHI^T (depending on applytranspose, see comment above) */
1311dc359a40SStefano Zampini   if (applytranspose) {
1312674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_phi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
13138eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_phi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
1314dc359a40SStefano Zampini   } else {
1315674ae819SStefano Zampini     ierr = MatMultTranspose(pcbddc->coarse_psi_B,pcis->vec1_B,pcbddc->vec1_P);CHKERRQ(ierr);
1316674ae819SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcbddc->coarse_psi_D,pcis->vec1_D,pcbddc->vec1_P,pcbddc->vec1_P);CHKERRQ(ierr); }
131715aaf578SStefano Zampini   }
131812edc857SStefano Zampini   /* start communications from local primal nodes to rhs of coarse solver */
131912edc857SStefano Zampini   ierr = VecSet(pcbddc->coarse_vec,zero);CHKERRQ(ierr);
132012edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
132112edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
132212edc857SStefano Zampini 
13239f00e9b4SStefano Zampini   /* Coarse solution -> rhs and sol updated inside PCBDDCScattarCoarseDataBegin/End */
132412edc857SStefano Zampini   /* TODO remove null space when doing multilevel */
132512edc857SStefano Zampini   if (pcbddc->coarse_ksp) {
132612edc857SStefano Zampini     if (applytranspose) {
132712edc857SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
132812edc857SStefano Zampini     } else {
132912edc857SStefano Zampini       ierr = KSPSolve(pcbddc->coarse_ksp,NULL,NULL);CHKERRQ(ierr);
133012edc857SStefano Zampini     }
133112edc857SStefano Zampini   }
1332674ae819SStefano Zampini 
1333674ae819SStefano Zampini   /* Local solution on R nodes */
13349f00e9b4SStefano Zampini   if (pcis->n) {
1335674ae819SStefano Zampini     ierr = VecSet(pcbddc->vec1_R,zero);CHKERRQ(ierr);
1336674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1337674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcis->vec1_B,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13388eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1339674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1340674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcis->vec1_D,pcbddc->vec1_R,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1341674ae819SStefano Zampini     }
134220c7b377SStefano Zampini     ierr = PCBDDCSolveSubstructureCorrection(pc,pcbddc->vec1_R,pcbddc->vec2_R,pcbddc->vec1_C,applytranspose);CHKERRQ(ierr);
1343674ae819SStefano Zampini     ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1344674ae819SStefano Zampini     ierr = VecScatterBegin(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1345674ae819SStefano Zampini     ierr = VecScatterEnd(pcbddc->R_to_B,pcbddc->vec2_R,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13468eeda7d8SStefano Zampini     if (pcbddc->switch_static) {
1347674ae819SStefano Zampini       ierr = VecScatterBegin(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1348674ae819SStefano Zampini       ierr = VecScatterEnd(pcbddc->R_to_D,pcbddc->vec2_R,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1349674ae819SStefano Zampini     }
13509f00e9b4SStefano Zampini   }
1351674ae819SStefano Zampini 
13529f00e9b4SStefano Zampini   /* communications from coarse sol to local primal nodes */
13539f00e9b4SStefano Zampini   ierr = PCBDDCScatterCoarseDataBegin(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
135412edc857SStefano Zampini   ierr = PCBDDCScatterCoarseDataEnd(pc,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1355674ae819SStefano Zampini 
1356674ae819SStefano Zampini   /* Sum contributions from two levels */
1357dc359a40SStefano Zampini   if (applytranspose) {
1358dc359a40SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_psi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
1359dc359a40SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_psi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1360dc359a40SStefano Zampini   } else {
1361674ae819SStefano Zampini     ierr = MatMultAdd(pcbddc->coarse_phi_B,pcbddc->vec1_P,pcis->vec1_B,pcis->vec1_B);CHKERRQ(ierr);
13628eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcbddc->coarse_phi_D,pcbddc->vec1_P,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1363dc359a40SStefano Zampini   }
1364674ae819SStefano Zampini   PetscFunctionReturn(0);
1365674ae819SStefano Zampini }
1366674ae819SStefano Zampini 
136712edc857SStefano Zampini /* TODO: the following two function can be optimized using VecPlaceArray whenever possible and using overlap flag */
1368674ae819SStefano Zampini #undef __FUNCT__
1369674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataBegin"
137012edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataBegin(PC pc,InsertMode imode, ScatterMode smode)
1371674ae819SStefano Zampini {
1372674ae819SStefano Zampini   PetscErrorCode ierr;
1373674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
137412edc857SStefano Zampini   PetscScalar    *array,*array2;
137512edc857SStefano Zampini   Vec            from,to;
1376674ae819SStefano Zampini 
1377674ae819SStefano Zampini   PetscFunctionBegin;
137812edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
137912edc857SStefano Zampini     from = pcbddc->coarse_vec;
138012edc857SStefano Zampini     to = pcbddc->vec1_P;
138112edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
138212edc857SStefano Zampini       Vec tvec;
138312edc857SStefano Zampini       PetscInt lsize;
138412edc857SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
138512edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
138612edc857SStefano Zampini       ierr = VecGetArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
138712edc857SStefano Zampini       ierr = VecGetArray(from,&array2);CHKERRQ(ierr);
138812edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
138912edc857SStefano Zampini       ierr = VecRestoreArrayRead(tvec,(const PetscScalar**)&array);CHKERRQ(ierr);
139012edc857SStefano Zampini       ierr = VecRestoreArray(from,&array2);CHKERRQ(ierr);
139112edc857SStefano Zampini     }
139212edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
139312edc857SStefano Zampini     from = pcbddc->vec1_P;
139412edc857SStefano Zampini     to = pcbddc->coarse_vec;
139512edc857SStefano Zampini   }
139612edc857SStefano Zampini   ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
1397674ae819SStefano Zampini   PetscFunctionReturn(0);
1398674ae819SStefano Zampini }
1399674ae819SStefano Zampini 
1400674ae819SStefano Zampini #undef __FUNCT__
1401674ae819SStefano Zampini #define __FUNCT__ "PCBDDCScatterCoarseDataEnd"
140212edc857SStefano Zampini PetscErrorCode PCBDDCScatterCoarseDataEnd(PC pc, InsertMode imode, ScatterMode smode)
1403674ae819SStefano Zampini {
1404674ae819SStefano Zampini   PetscErrorCode ierr;
1405674ae819SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
140612edc857SStefano Zampini   PetscScalar    *array,*array2;
140712edc857SStefano Zampini   Vec            from,to;
1408674ae819SStefano Zampini 
1409674ae819SStefano Zampini   PetscFunctionBegin;
141012edc857SStefano Zampini   if (smode == SCATTER_REVERSE) { /* from global to local -> get data from coarse solution */
141112edc857SStefano Zampini     from = pcbddc->coarse_vec;
141212edc857SStefano Zampini     to = pcbddc->vec1_P;
141312edc857SStefano Zampini   } else { /* from local to global -> put data in coarse right hand side */
141412edc857SStefano Zampini     from = pcbddc->vec1_P;
141512edc857SStefano Zampini     to = pcbddc->coarse_vec;
141612edc857SStefano Zampini   }
141712edc857SStefano Zampini   ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,from,to,imode,smode);CHKERRQ(ierr);
141812edc857SStefano Zampini   if (smode == SCATTER_FORWARD) {
141912edc857SStefano Zampini     if (pcbddc->coarse_ksp) { /* get array from coarse processes */
142012edc857SStefano Zampini       Vec tvec;
142112edc857SStefano Zampini       PetscInt lsize;
142212edc857SStefano Zampini       ierr = KSPGetRhs(pcbddc->coarse_ksp,&tvec);CHKERRQ(ierr);
142312edc857SStefano Zampini       ierr = VecGetLocalSize(tvec,&lsize);CHKERRQ(ierr);
142412edc857SStefano Zampini       ierr = VecGetArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
142512edc857SStefano Zampini       ierr = VecGetArray(tvec,&array2);CHKERRQ(ierr);
142612edc857SStefano Zampini       ierr = PetscMemcpy(array2,array,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
142712edc857SStefano Zampini       ierr = VecRestoreArrayRead(to,(const PetscScalar**)&array);CHKERRQ(ierr);
142812edc857SStefano Zampini       ierr = VecRestoreArray(tvec,&array2);CHKERRQ(ierr);
142912edc857SStefano Zampini     }
143012edc857SStefano Zampini   }
1431674ae819SStefano Zampini   PetscFunctionReturn(0);
1432674ae819SStefano Zampini }
1433674ae819SStefano Zampini 
1434984c4197SStefano Zampini /* uncomment for testing purposes */
1435984c4197SStefano Zampini /* #define PETSC_MISSING_LAPACK_GESVD 1 */
1436674ae819SStefano Zampini #undef __FUNCT__
1437674ae819SStefano Zampini #define __FUNCT__ "PCBDDCConstraintsSetUp"
1438674ae819SStefano Zampini PetscErrorCode PCBDDCConstraintsSetUp(PC pc)
1439674ae819SStefano Zampini {
1440674ae819SStefano Zampini   PetscErrorCode    ierr;
1441674ae819SStefano Zampini   PC_IS*            pcis = (PC_IS*)(pc->data);
1442674ae819SStefano Zampini   PC_BDDC*          pcbddc = (PC_BDDC*)pc->data;
1443674ae819SStefano Zampini   Mat_IS*           matis = (Mat_IS*)pc->pmat->data;
1444984c4197SStefano Zampini   /* constraint and (optionally) change of basis matrix implemented as SeqAIJ */
1445674ae819SStefano Zampini   MatType           impMatType=MATSEQAIJ;
1446984c4197SStefano Zampini   /* one and zero */
1447984c4197SStefano Zampini   PetscScalar       one=1.0,zero=0.0;
1448984c4197SStefano Zampini   /* space to store constraints and their local indices */
1449984c4197SStefano Zampini   PetscScalar       *temp_quadrature_constraint;
1450984c4197SStefano Zampini   PetscInt          *temp_indices,*temp_indices_to_constraint,*temp_indices_to_constraint_B;
1451984c4197SStefano Zampini   /* iterators */
1452984c4197SStefano Zampini   PetscInt          i,j,k,total_counts,temp_start_ptr;
1453984c4197SStefano Zampini   /* stuff to store connected components stored in pcbddc->mat_graph */
1454984c4197SStefano Zampini   IS                ISForVertices,*ISForFaces,*ISForEdges,*used_IS;
1455984c4197SStefano Zampini   PetscInt          n_ISForFaces,n_ISForEdges;
1456984c4197SStefano Zampini   /* near null space stuff */
1457674ae819SStefano Zampini   MatNullSpace      nearnullsp;
1458674ae819SStefano Zampini   const Vec         *nearnullvecs;
1459674ae819SStefano Zampini   Vec               *localnearnullsp;
1460984c4197SStefano Zampini   PetscBool         nnsp_has_cnst;
1461984c4197SStefano Zampini   PetscInt          nnsp_size;
1462984c4197SStefano Zampini   PetscScalar       *array;
1463984c4197SStefano Zampini   /* BLAS integers */
1464e310c8b4SStefano Zampini   PetscBLASInt      lwork,lierr;
1465e310c8b4SStefano Zampini   PetscBLASInt      Blas_N,Blas_M,Blas_K,Blas_one=1;
1466c4303822SStefano Zampini   PetscBLASInt      Blas_LDA,Blas_LDB,Blas_LDC;
1467984c4197SStefano Zampini   /* LAPACK working arrays for SVD or POD */
1468242a89d7SStefano Zampini   PetscBool         skip_lapack;
1469984c4197SStefano Zampini   PetscScalar       *work;
1470984c4197SStefano Zampini   PetscReal         *singular_vals;
1471984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1472984c4197SStefano Zampini   PetscReal         *rwork;
1473674ae819SStefano Zampini #endif
1474984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1475e310c8b4SStefano Zampini   PetscBLASInt      Blas_one_2=1;
1476984c4197SStefano Zampini   PetscScalar       *temp_basis,*correlation_mat;
1477b7d8b9f8SStefano Zampini #else
1478b7d8b9f8SStefano Zampini   PetscBLASInt      dummy_int_1=1,dummy_int_2=1;
1479b7d8b9f8SStefano Zampini   PetscScalar       dummy_scalar_1=0.0,dummy_scalar_2=0.0;
1480984c4197SStefano Zampini #endif
1481727cdba6SStefano Zampini   /* reuse */
1482727cdba6SStefano Zampini   PetscInt          olocal_primal_size;
1483727cdba6SStefano Zampini   PetscInt          *oprimal_indices_local_idxs;
1484984c4197SStefano Zampini   /* change of basis */
1485984c4197SStefano Zampini   PetscInt          *aux_primal_numbering,*aux_primal_minloc,*global_indices;
1486a717540cSStefano Zampini   PetscBool         boolforchange,qr_needed;
1487a717540cSStefano Zampini   PetscBT           touched,change_basis,qr_needed_idx;
1488984c4197SStefano Zampini   /* auxiliary stuff */
148939e2fb2aSStefano Zampini   PetscInt          *nnz,*is_indices,*aux_primal_numbering_B;
1490911cabfeSStefano Zampini   PetscInt          ncc,*gidxs,*permutation,*temp_indices_to_constraint_work;
1491911cabfeSStefano Zampini   PetscScalar       *temp_quadrature_constraint_work;
1492984c4197SStefano Zampini   /* some quantities */
149345a1bb75SStefano Zampini   PetscInt          n_vertices,total_primal_vertices,valid_constraints;
1494984c4197SStefano Zampini   PetscInt          size_of_constraint,max_size_of_constraint,max_constraints,temp_constraints;
1495984c4197SStefano Zampini 
1496674ae819SStefano Zampini 
1497674ae819SStefano Zampini   PetscFunctionBegin;
14988e61c736SStefano Zampini   /* Destroy Mat objects computed previously */
14998e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
15008e61c736SStefano Zampini   ierr = MatDestroy(&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1501674ae819SStefano Zampini   /* Get index sets for faces, edges and vertices from graph */
1502d06fc5fdSStefano Zampini   ierr = PCBDDCGraphGetCandidatesIS(pcbddc->mat_graph,&n_ISForFaces,&ISForFaces,&n_ISForEdges,&ISForEdges,&ISForVertices);CHKERRQ(ierr);
1503d06fc5fdSStefano Zampini   /* free unneeded index sets */
1504d06fc5fdSStefano Zampini   if (!pcbddc->use_vertices) {
1505d06fc5fdSStefano Zampini     ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
1506674ae819SStefano Zampini   }
1507d06fc5fdSStefano Zampini   if (!pcbddc->use_edges) {
1508d06fc5fdSStefano Zampini     for (i=0;i<n_ISForEdges;i++) {
1509d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1510d06fc5fdSStefano Zampini     }
1511d06fc5fdSStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1512d06fc5fdSStefano Zampini     n_ISForEdges = 0;
1513d06fc5fdSStefano Zampini   }
1514d06fc5fdSStefano Zampini   if (!pcbddc->use_faces) {
1515d06fc5fdSStefano Zampini     for (i=0;i<n_ISForFaces;i++) {
1516d06fc5fdSStefano Zampini       ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1517d06fc5fdSStefano Zampini     }
1518d06fc5fdSStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1519d06fc5fdSStefano Zampini     n_ISForFaces = 0;
1520d06fc5fdSStefano Zampini   }
1521d06fc5fdSStefano Zampini   /* HACKS (the following two blocks of code) */
1522b9b85e73SStefano Zampini   if (!ISForVertices && pcbddc->NullSpace && !pcbddc->user_ChangeOfBasisMatrix) {
1523b8ffe317SStefano Zampini     pcbddc->use_change_of_basis = PETSC_TRUE;
1524d06fc5fdSStefano Zampini     if (!ISForEdges) {
1525d06fc5fdSStefano Zampini       pcbddc->use_change_on_faces = PETSC_TRUE;
1526d06fc5fdSStefano Zampini     }
1527b8ffe317SStefano Zampini   }
152898a51de6SStefano Zampini   if (pcbddc->NullSpace) {
152998a51de6SStefano Zampini     /* use_change_of_basis should be consistent among processors */
1530d06fc5fdSStefano Zampini     PetscBool tbool[2],gbool[2];
1531d06fc5fdSStefano Zampini     tbool [0] = pcbddc->use_change_of_basis;
1532d06fc5fdSStefano Zampini     tbool [1] = pcbddc->use_change_on_faces;
1533d06fc5fdSStefano Zampini     ierr = MPI_Allreduce(tbool,gbool,2,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
1534d06fc5fdSStefano Zampini     pcbddc->use_change_of_basis = gbool[0];
1535d06fc5fdSStefano Zampini     pcbddc->use_change_on_faces = gbool[1];
153698a51de6SStefano Zampini   }
1537984c4197SStefano Zampini   /* print some info */
1538674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
15390fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
1540674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
1541674ae819SStefano Zampini     i = 0;
1542674ae819SStefano Zampini     if (ISForVertices) {
1543674ae819SStefano Zampini       ierr = ISGetSize(ISForVertices,&i);CHKERRQ(ierr);
1544674ae819SStefano Zampini     }
1545674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate vertices\n",PetscGlobalRank,i);CHKERRQ(ierr);
1546674ae819SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate edges\n",PetscGlobalRank,n_ISForEdges);CHKERRQ(ierr);
154715aaf578SStefano Zampini     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d got %02d local candidate faces\n",PetscGlobalRank,n_ISForFaces);CHKERRQ(ierr);
1548674ae819SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
1549674ae819SStefano Zampini   }
1550674ae819SStefano Zampini   /* check if near null space is attached to global mat */
1551674ae819SStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullsp);CHKERRQ(ierr);
1552674ae819SStefano Zampini   if (nearnullsp) {
1553674ae819SStefano Zampini     ierr = MatNullSpaceGetVecs(nearnullsp,&nnsp_has_cnst,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1554f4ddd8eeSStefano Zampini     /* remove any stored info */
1555f4ddd8eeSStefano Zampini     ierr = MatNullSpaceDestroy(&pcbddc->onearnullspace);CHKERRQ(ierr);
1556f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1557f4ddd8eeSStefano Zampini     /* store information for BDDC solver reuse */
1558f4ddd8eeSStefano Zampini     ierr = PetscObjectReference((PetscObject)nearnullsp);CHKERRQ(ierr);
1559f4ddd8eeSStefano Zampini     pcbddc->onearnullspace = nearnullsp;
1560473ba861SJed Brown     ierr = PetscMalloc1(nnsp_size,&pcbddc->onearnullvecs_state);CHKERRQ(ierr);
1561f4ddd8eeSStefano Zampini     for (i=0;i<nnsp_size;i++) {
1562f4ddd8eeSStefano Zampini       ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&pcbddc->onearnullvecs_state[i]);CHKERRQ(ierr);
1563f4ddd8eeSStefano Zampini     }
1564984c4197SStefano Zampini   } else { /* if near null space is not provided BDDC uses constants by default */
1565984c4197SStefano Zampini     nnsp_size = 0;
1566674ae819SStefano Zampini     nnsp_has_cnst = PETSC_TRUE;
1567674ae819SStefano Zampini   }
1568984c4197SStefano Zampini   /* get max number of constraints on a single cc */
1569984c4197SStefano Zampini   max_constraints = nnsp_size;
1570984c4197SStefano Zampini   if (nnsp_has_cnst) max_constraints++;
1571984c4197SStefano Zampini 
1572674ae819SStefano Zampini   /*
1573674ae819SStefano Zampini        Evaluate maximum storage size needed by the procedure
1574674ae819SStefano Zampini        - temp_indices will contain start index of each constraint stored as follows
1575911cabfeSStefano 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
1576911cabfeSStefano 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
1577911cabfeSStefano Zampini        - temp_quadrature_constraint  [temp_indices[i],...,temp_indices[i+1]-1] will contain the scalars representing the constraint itself
1578674ae819SStefano Zampini                                                                                                                                                          */
1579674ae819SStefano Zampini   total_counts = n_ISForFaces+n_ISForEdges;
1580984c4197SStefano Zampini   total_counts *= max_constraints;
1581674ae819SStefano Zampini   n_vertices = 0;
1582674ae819SStefano Zampini   if (ISForVertices) {
1583674ae819SStefano Zampini     ierr = ISGetSize(ISForVertices,&n_vertices);CHKERRQ(ierr);
1584674ae819SStefano Zampini   }
1585674ae819SStefano Zampini   total_counts += n_vertices;
1586854ce69bSBarry Smith   ierr = PetscMalloc1(total_counts+1,&temp_indices);CHKERRQ(ierr);
15874641a718SStefano Zampini   ierr = PetscBTCreate(total_counts,&change_basis);CHKERRQ(ierr);
1588674ae819SStefano Zampini   total_counts = 0;
1589674ae819SStefano Zampini   max_size_of_constraint = 0;
1590674ae819SStefano Zampini   for (i=0;i<n_ISForEdges+n_ISForFaces;i++) {
1591674ae819SStefano Zampini     if (i<n_ISForEdges) {
1592674ae819SStefano Zampini       used_IS = &ISForEdges[i];
1593674ae819SStefano Zampini     } else {
1594674ae819SStefano Zampini       used_IS = &ISForFaces[i-n_ISForEdges];
1595674ae819SStefano Zampini     }
1596674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&j);CHKERRQ(ierr);
1597674ae819SStefano Zampini     total_counts += j;
1598674ae819SStefano Zampini     max_size_of_constraint = PetscMax(j,max_size_of_constraint);
1599674ae819SStefano Zampini   }
1600984c4197SStefano Zampini   total_counts *= max_constraints;
1601674ae819SStefano Zampini   total_counts += n_vertices;
1602906d46d4SStefano Zampini   ierr = PetscMalloc3(total_counts,&temp_quadrature_constraint,total_counts,&temp_indices_to_constraint,total_counts,&temp_indices_to_constraint_B);CHKERRQ(ierr);
1603984c4197SStefano Zampini   /* get local part of global near null space vectors */
1604785e854fSJed Brown   ierr = PetscMalloc1(nnsp_size,&localnearnullsp);CHKERRQ(ierr);
1605984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1606984c4197SStefano Zampini     ierr = VecDuplicate(pcis->vec1_N,&localnearnullsp[k]);CHKERRQ(ierr);
1607984c4197SStefano Zampini     ierr = VecScatterBegin(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1608984c4197SStefano Zampini     ierr = VecScatterEnd(matis->ctx,nearnullvecs[k],localnearnullsp[k],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1609984c4197SStefano Zampini   }
1610674ae819SStefano Zampini 
1611242a89d7SStefano Zampini   /* whether or not to skip lapack calls */
1612242a89d7SStefano Zampini   skip_lapack = PETSC_TRUE;
1613a773dcb8SStefano Zampini   if (n_ISForFaces+n_ISForEdges && max_constraints > 1 && !pcbddc->use_nnsp_true) skip_lapack = PETSC_FALSE;
1614242a89d7SStefano Zampini 
16158f1c130eSStefano Zampini   /* allocate some auxiliary stuff */
16168f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
16178f1c130eSStefano 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);
16188f1c130eSStefano Zampini   }
16198f1c130eSStefano Zampini 
1620984c4197SStefano Zampini   /* First we issue queries to allocate optimal workspace for LAPACKgesvd (or LAPACKsyev if SVD is missing) */
1621a773dcb8SStefano Zampini   if (!skip_lapack) {
1622674ae819SStefano Zampini     PetscScalar temp_work;
1623911cabfeSStefano Zampini 
1624674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1625984c4197SStefano Zampini     /* Proper Orthogonal Decomposition (POD) using the snapshot method */
1626785e854fSJed Brown     ierr = PetscMalloc1(max_constraints*max_constraints,&correlation_mat);CHKERRQ(ierr);
1627785e854fSJed Brown     ierr = PetscMalloc1(max_constraints,&singular_vals);CHKERRQ(ierr);
1628785e854fSJed Brown     ierr = PetscMalloc1(max_size_of_constraint*max_constraints,&temp_basis);CHKERRQ(ierr);
1629674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1630785e854fSJed Brown     ierr = PetscMalloc1(3*max_constraints,&rwork);CHKERRQ(ierr);
1631674ae819SStefano Zampini #endif
1632674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1633c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
1634c8244a33SStefano Zampini     ierr = PetscBLASIntCast(max_constraints,&Blas_LDA);CHKERRQ(ierr);
1635674ae819SStefano Zampini     lwork = -1;
1636674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1637674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1638c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,&lierr));
1639674ae819SStefano Zampini #else
1640c8244a33SStefano Zampini     PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,&temp_work,&lwork,rwork,&lierr));
1641674ae819SStefano Zampini #endif
1642674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1643984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to SYEV Lapack routine %d",(int)lierr);
1644674ae819SStefano Zampini #else /* on missing GESVD */
1645674ae819SStefano Zampini     /* SVD */
1646674ae819SStefano Zampini     PetscInt max_n,min_n;
1647674ae819SStefano Zampini     max_n = max_size_of_constraint;
1648984c4197SStefano Zampini     min_n = max_constraints;
1649984c4197SStefano Zampini     if (max_size_of_constraint < max_constraints) {
1650674ae819SStefano Zampini       min_n = max_size_of_constraint;
1651984c4197SStefano Zampini       max_n = max_constraints;
1652674ae819SStefano Zampini     }
1653785e854fSJed Brown     ierr = PetscMalloc1(min_n,&singular_vals);CHKERRQ(ierr);
1654674ae819SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1655785e854fSJed Brown     ierr = PetscMalloc1(5*min_n,&rwork);CHKERRQ(ierr);
1656674ae819SStefano Zampini #endif
1657674ae819SStefano Zampini     /* now we evaluate the optimal workspace using query with lwork=-1 */
1658674ae819SStefano Zampini     lwork = -1;
1659e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_M);CHKERRQ(ierr);
1660e310c8b4SStefano Zampini     ierr = PetscBLASIntCast(min_n,&Blas_N);CHKERRQ(ierr);
1661b7d8b9f8SStefano Zampini     ierr = PetscBLASIntCast(max_n,&Blas_LDA);CHKERRQ(ierr);
1662674ae819SStefano Zampini     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1663674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1664e310c8b4SStefano 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));
1665674ae819SStefano Zampini #else
1666e310c8b4SStefano 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));
1667674ae819SStefano Zampini #endif
1668674ae819SStefano Zampini     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1669984c4197SStefano Zampini     if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GESVD Lapack routine %d",(int)lierr);
1670984c4197SStefano Zampini #endif /* on missing GESVD */
1671674ae819SStefano Zampini     /* Allocate optimal workspace */
1672674ae819SStefano Zampini     ierr = PetscBLASIntCast((PetscInt)PetscRealPart(temp_work),&lwork);CHKERRQ(ierr);
1673854ce69bSBarry Smith     ierr = PetscMalloc1(lwork,&work);CHKERRQ(ierr);
1674674ae819SStefano Zampini   }
1675674ae819SStefano Zampini   /* Now we can loop on constraining sets */
1676674ae819SStefano Zampini   total_counts = 0;
1677674ae819SStefano Zampini   temp_indices[0] = 0;
1678674ae819SStefano Zampini   /* vertices */
1679674ae819SStefano Zampini   if (ISForVertices) {
1680674ae819SStefano Zampini     ierr = ISGetIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1681674ae819SStefano Zampini     if (nnsp_has_cnst) { /* consider all vertices */
168239e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,n_vertices*sizeof(PetscInt));CHKERRQ(ierr);
1683674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1684674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1685674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1686674ae819SStefano Zampini         total_counts++;
1687674ae819SStefano Zampini       }
1688674ae819SStefano Zampini     } else { /* consider vertices for which exist at least a localnearnullsp which is not null there */
1689984c4197SStefano Zampini       PetscBool used_vertex;
1690674ae819SStefano Zampini       for (i=0;i<n_vertices;i++) {
1691674ae819SStefano Zampini         used_vertex = PETSC_FALSE;
1692674ae819SStefano Zampini         k = 0;
1693674ae819SStefano Zampini         while (!used_vertex && k<nnsp_size) {
1694984c4197SStefano Zampini           ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1695984c4197SStefano Zampini           if (PetscAbsScalar(array[is_indices[i]])>0.0) {
1696674ae819SStefano Zampini             temp_indices_to_constraint[temp_indices[total_counts]]=is_indices[i];
1697674ae819SStefano Zampini             temp_quadrature_constraint[temp_indices[total_counts]]=1.0;
1698674ae819SStefano Zampini             temp_indices[total_counts+1]=temp_indices[total_counts]+1;
1699674ae819SStefano Zampini             total_counts++;
1700674ae819SStefano Zampini             used_vertex = PETSC_TRUE;
1701674ae819SStefano Zampini           }
1702984c4197SStefano Zampini           ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1703674ae819SStefano Zampini           k++;
1704674ae819SStefano Zampini         }
1705674ae819SStefano Zampini       }
1706674ae819SStefano Zampini     }
1707674ae819SStefano Zampini     ierr = ISRestoreIndices(ISForVertices,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1708674ae819SStefano Zampini     n_vertices = total_counts;
1709674ae819SStefano Zampini   }
1710984c4197SStefano Zampini 
1711674ae819SStefano Zampini   /* edges and faces */
1712911cabfeSStefano Zampini   for (ncc=0;ncc<n_ISForEdges+n_ISForFaces;ncc++) {
1713911cabfeSStefano Zampini     if (ncc<n_ISForEdges) {
1714911cabfeSStefano Zampini       used_IS = &ISForEdges[ncc];
1715984c4197SStefano Zampini       boolforchange = pcbddc->use_change_of_basis; /* change or not the basis on the edge */
1716674ae819SStefano Zampini     } else {
1717911cabfeSStefano Zampini       used_IS = &ISForFaces[ncc-n_ISForEdges];
1718984c4197SStefano Zampini       boolforchange = (PetscBool)(pcbddc->use_change_of_basis && pcbddc->use_change_on_faces); /* change or not the basis on the face */
1719674ae819SStefano Zampini     }
1720674ae819SStefano Zampini     temp_constraints = 0;          /* zero the number of constraints I have on this conn comp */
1721674ae819SStefano Zampini     temp_start_ptr = total_counts; /* need to know the starting index of constraints stored */
1722674ae819SStefano Zampini     ierr = ISGetSize(*used_IS,&size_of_constraint);CHKERRQ(ierr);
1723674ae819SStefano Zampini     ierr = ISGetIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
1724984c4197SStefano Zampini     /* change of basis should not be performed on local periodic nodes */
1725984c4197SStefano Zampini     if (pcbddc->mat_graph->mirrors && pcbddc->mat_graph->mirrors[is_indices[0]]) boolforchange = PETSC_FALSE;
1726674ae819SStefano Zampini     if (nnsp_has_cnst) {
17275b08dc53SStefano Zampini       PetscScalar quad_value;
1728674ae819SStefano Zampini       temp_constraints++;
1729a773dcb8SStefano Zampini       if (!pcbddc->use_nnsp_true) {
1730674ae819SStefano Zampini         quad_value = (PetscScalar)(1.0/PetscSqrtReal((PetscReal)size_of_constraint));
1731a773dcb8SStefano Zampini       } else {
1732a773dcb8SStefano Zampini         quad_value = 1.0;
1733a773dcb8SStefano Zampini       }
173439e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1735674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1736674ae819SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=quad_value;
1737674ae819SStefano Zampini       }
1738911cabfeSStefano Zampini       /* sort by global ordering if using lapack subroutines */
17398f1c130eSStefano Zampini       if (!skip_lapack || pcbddc->use_qr_single) {
1740911cabfeSStefano Zampini         ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1741911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1742911cabfeSStefano Zampini           permutation[j]=j;
1743911cabfeSStefano Zampini         }
1744911cabfeSStefano Zampini         ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1745911cabfeSStefano Zampini         for (j=0;j<size_of_constraint;j++) {
1746911cabfeSStefano Zampini           temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1747911cabfeSStefano Zampini           temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1748911cabfeSStefano Zampini         }
1749911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1750911cabfeSStefano Zampini         ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1751911cabfeSStefano Zampini       }
1752674ae819SStefano Zampini       temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1753674ae819SStefano Zampini       total_counts++;
1754674ae819SStefano Zampini     }
1755674ae819SStefano Zampini     for (k=0;k<nnsp_size;k++) {
1756984c4197SStefano Zampini       PetscReal real_value;
1757984c4197SStefano Zampini       ierr = VecGetArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
175839e2fb2aSStefano Zampini       ierr = PetscMemcpy(&temp_indices_to_constraint[temp_indices[total_counts]],is_indices,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1759674ae819SStefano Zampini       for (j=0;j<size_of_constraint;j++) {
1760984c4197SStefano Zampini         temp_quadrature_constraint[temp_indices[total_counts]+j]=array[is_indices[j]];
1761674ae819SStefano Zampini       }
1762984c4197SStefano Zampini       ierr = VecRestoreArrayRead(localnearnullsp[k],(const PetscScalar**)&array);CHKERRQ(ierr);
1763984c4197SStefano Zampini       /* check if array is null on the connected component */
1764e310c8b4SStefano Zampini       ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1765e310c8b4SStefano Zampini       PetscStackCallBLAS("BLASasum",real_value = BLASasum_(&Blas_N,&temp_quadrature_constraint[temp_indices[total_counts]],&Blas_one));
17665b08dc53SStefano Zampini       if (real_value > 0.0) { /* keep indices and values */
1767911cabfeSStefano Zampini         /* sort by global ordering if using lapack subroutines */
17688f1c130eSStefano Zampini         if (!skip_lapack || pcbddc->use_qr_single) {
1769911cabfeSStefano Zampini           ierr = ISLocalToGlobalMappingApply(matis->mapping,size_of_constraint,temp_indices_to_constraint+temp_indices[total_counts],gidxs);CHKERRQ(ierr);
1770911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1771911cabfeSStefano Zampini             permutation[j]=j;
1772911cabfeSStefano Zampini           }
1773911cabfeSStefano Zampini           ierr = PetscSortIntWithPermutation(size_of_constraint,gidxs,permutation);CHKERRQ(ierr);
1774911cabfeSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
1775911cabfeSStefano Zampini             temp_indices_to_constraint_work[j] = temp_indices_to_constraint[temp_indices[total_counts]+permutation[j]];
1776911cabfeSStefano Zampini             temp_quadrature_constraint_work[j] = temp_quadrature_constraint[temp_indices[total_counts]+permutation[j]];
1777911cabfeSStefano Zampini           }
1778911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_indices_to_constraint+temp_indices[total_counts],temp_indices_to_constraint_work,size_of_constraint*sizeof(PetscInt));CHKERRQ(ierr);
1779911cabfeSStefano Zampini           ierr = PetscMemcpy(temp_quadrature_constraint+temp_indices[total_counts],temp_quadrature_constraint_work,size_of_constraint*sizeof(PetscScalar));CHKERRQ(ierr);
1780911cabfeSStefano Zampini         }
1781674ae819SStefano Zampini         temp_constraints++;
1782674ae819SStefano Zampini         temp_indices[total_counts+1]=temp_indices[total_counts]+size_of_constraint;  /* store new starting point */
1783674ae819SStefano Zampini         total_counts++;
1784674ae819SStefano Zampini       }
1785674ae819SStefano Zampini     }
1786674ae819SStefano Zampini     ierr = ISRestoreIndices(*used_IS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
178745a1bb75SStefano Zampini     valid_constraints = temp_constraints;
1788eb97c9d2SStefano Zampini     if (!pcbddc->use_nnsp_true && temp_constraints) {
1789a773dcb8SStefano Zampini       if (temp_constraints == 1) { /* just normalize the constraint */
1790a773dcb8SStefano Zampini         PetscScalar norm;
1791a773dcb8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1792a773dcb8SStefano 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));
1793a773dcb8SStefano Zampini         norm = 1.0/PetscSqrtReal(PetscRealPart(norm));
1794a773dcb8SStefano Zampini         PetscStackCallBLAS("BLASscal",BLASscal_(&Blas_N,&norm,temp_quadrature_constraint+temp_indices[temp_start_ptr],&Blas_one));
1795a773dcb8SStefano Zampini       } else { /* perform SVD */
1796984c4197SStefano Zampini         PetscReal tol = 1.0e-8; /* tolerance for retaining eigenmodes */
1797674ae819SStefano Zampini 
1798674ae819SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1799984c4197SStefano Zampini         /* SVD: Y = U*S*V^H                -> U (eigenvectors of Y*Y^H) = Y*V*(S)^\dag
1800984c4197SStefano Zampini            POD: Y^H*Y = V*D*V^H, D = S^H*S -> U = Y*V*D^(-1/2)
1801984c4197SStefano Zampini            -> When PETSC_USE_COMPLEX and PETSC_MISSING_LAPACK_GESVD are defined
1802984c4197SStefano Zampini               the constraints basis will differ (by a complex factor with absolute value equal to 1)
1803984c4197SStefano Zampini               from that computed using LAPACKgesvd
1804984c4197SStefano Zampini            -> This is due to a different computation of eigenvectors in LAPACKheev
1805984c4197SStefano Zampini            -> The quality of the POD-computed basis will be the same */
1806984c4197SStefano Zampini         ierr = PetscMemzero(correlation_mat,temp_constraints*temp_constraints*sizeof(PetscScalar));CHKERRQ(ierr);
1807674ae819SStefano Zampini         /* Store upper triangular part of correlation matrix */
1808e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
1809984c4197SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1810674ae819SStefano Zampini         for (j=0;j<temp_constraints;j++) {
1811674ae819SStefano Zampini           for (k=0;k<j+1;k++) {
1812e310c8b4SStefano 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));
1813674ae819SStefano Zampini           }
1814674ae819SStefano Zampini         }
1815e310c8b4SStefano Zampini         /* compute eigenvalues and eigenvectors of correlation matrix */
1816e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1817e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDA);CHKERRQ(ierr);
1818674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1819c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,&lierr));
1820674ae819SStefano Zampini #else
1821c8244a33SStefano Zampini         PetscStackCallBLAS("LAPACKsyev",LAPACKsyev_("V","U",&Blas_N,correlation_mat,&Blas_LDA,singular_vals,work,&lwork,rwork,&lierr));
1822674ae819SStefano Zampini #endif
1823674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1824984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in SYEV Lapack routine %d",(int)lierr);
1825984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKsyev gives eigs in ascending order */
1826674ae819SStefano Zampini         j = 0;
1827984c4197SStefano Zampini         while (j < temp_constraints && singular_vals[j] < tol) j++;
1828674ae819SStefano Zampini         total_counts = total_counts-j;
182945a1bb75SStefano Zampini         valid_constraints = temp_constraints-j;
1830e310c8b4SStefano Zampini         /* scale and copy POD basis into used quadrature memory */
1831c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1832c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1833c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_K);CHKERRQ(ierr);
1834c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1835c4303822SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_LDB);CHKERRQ(ierr);
1836c4303822SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
1837674ae819SStefano Zampini         if (j<temp_constraints) {
1838984c4197SStefano Zampini           PetscInt ii;
1839984c4197SStefano Zampini           for (k=j;k<temp_constraints;k++) singular_vals[k]=1.0/PetscSqrtReal(singular_vals[k]);
1840674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1841c4303822SStefano 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));
1842674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
1843984c4197SStefano Zampini           for (k=0;k<temp_constraints-j;k++) {
1844674ae819SStefano Zampini             for (ii=0;ii<size_of_constraint;ii++) {
1845984c4197SStefano 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];
1846674ae819SStefano Zampini             }
1847674ae819SStefano Zampini           }
1848674ae819SStefano Zampini         }
1849674ae819SStefano Zampini #else  /* on missing GESVD */
1850e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
1851e310c8b4SStefano Zampini         ierr = PetscBLASIntCast(temp_constraints,&Blas_N);CHKERRQ(ierr);
1852b7d8b9f8SStefano Zampini         ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
1853674ae819SStefano Zampini         ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1854674ae819SStefano Zampini #if !defined(PETSC_USE_COMPLEX)
1855e310c8b4SStefano 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));
1856674ae819SStefano Zampini #else
1857e310c8b4SStefano 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));
1858674ae819SStefano Zampini #endif
1859984c4197SStefano Zampini         if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GESVD Lapack routine %d",(int)lierr);
1860674ae819SStefano Zampini         ierr = PetscFPTrapPop();CHKERRQ(ierr);
1861984c4197SStefano Zampini         /* retain eigenvalues greater than tol: note that LAPACKgesvd gives eigs in descending order */
1862e310c8b4SStefano Zampini         k = temp_constraints;
1863e310c8b4SStefano Zampini         if (k > size_of_constraint) k = size_of_constraint;
1864674ae819SStefano Zampini         j = 0;
1865e310c8b4SStefano Zampini         while (j < k && singular_vals[k-j-1] < tol) j++;
186645a1bb75SStefano Zampini         valid_constraints = k-j;
1867911cabfeSStefano Zampini         total_counts = total_counts-temp_constraints+valid_constraints;
1868984c4197SStefano Zampini #endif /* on missing GESVD */
1869674ae819SStefano Zampini       }
1870a773dcb8SStefano Zampini     }
187145a1bb75SStefano Zampini     /* setting change_of_basis flag is safe now */
187245a1bb75SStefano Zampini     if (boolforchange) {
187345a1bb75SStefano Zampini       for (j=0;j<valid_constraints;j++) {
187445a1bb75SStefano Zampini         PetscBTSet(change_basis,total_counts-j-1);
187545a1bb75SStefano Zampini       }
187645a1bb75SStefano Zampini     }
1877674ae819SStefano Zampini   }
1878674ae819SStefano Zampini   /* free index sets of faces, edges and vertices */
1879674ae819SStefano Zampini   for (i=0;i<n_ISForFaces;i++) {
1880674ae819SStefano Zampini     ierr = ISDestroy(&ISForFaces[i]);CHKERRQ(ierr);
1881674ae819SStefano Zampini   }
1882d06fc5fdSStefano Zampini   if (n_ISForFaces) {
1883674ae819SStefano Zampini     ierr = PetscFree(ISForFaces);CHKERRQ(ierr);
1884d06fc5fdSStefano Zampini   }
1885674ae819SStefano Zampini   for (i=0;i<n_ISForEdges;i++) {
1886674ae819SStefano Zampini     ierr = ISDestroy(&ISForEdges[i]);CHKERRQ(ierr);
1887674ae819SStefano Zampini   }
1888d06fc5fdSStefano Zampini   if (n_ISForEdges) {
1889674ae819SStefano Zampini     ierr = PetscFree(ISForEdges);CHKERRQ(ierr);
1890d06fc5fdSStefano Zampini   }
1891674ae819SStefano Zampini   ierr = ISDestroy(&ISForVertices);CHKERRQ(ierr);
189239e2fb2aSStefano Zampini   /* map temp_indices_to_constraint in boundary numbering */
18935e8657edSStefano Zampini   ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,temp_indices[total_counts],temp_indices_to_constraint,&i,temp_indices_to_constraint_B);CHKERRQ(ierr);
189439e2fb2aSStefano Zampini   if (i != temp_indices[total_counts]) {
189539e2fb2aSStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for constraints indices %d != %d\n",temp_indices[total_counts],i);
189639e2fb2aSStefano Zampini   }
1897674ae819SStefano Zampini 
1898984c4197SStefano Zampini   /* free workspace */
18998f1c130eSStefano Zampini   if (!skip_lapack || pcbddc->use_qr_single) {
1900911cabfeSStefano Zampini     ierr = PetscFree4(gidxs,permutation,temp_indices_to_constraint_work,temp_quadrature_constraint_work);CHKERRQ(ierr);
19018f1c130eSStefano Zampini   }
19028f1c130eSStefano Zampini   if (!skip_lapack) {
1903984c4197SStefano Zampini     ierr = PetscFree(work);CHKERRQ(ierr);
1904984c4197SStefano Zampini #if defined(PETSC_USE_COMPLEX)
1905984c4197SStefano Zampini     ierr = PetscFree(rwork);CHKERRQ(ierr);
1906984c4197SStefano Zampini #endif
1907984c4197SStefano Zampini     ierr = PetscFree(singular_vals);CHKERRQ(ierr);
1908984c4197SStefano Zampini #if defined(PETSC_MISSING_LAPACK_GESVD)
1909984c4197SStefano Zampini     ierr = PetscFree(correlation_mat);CHKERRQ(ierr);
1910984c4197SStefano Zampini     ierr = PetscFree(temp_basis);CHKERRQ(ierr);
1911984c4197SStefano Zampini #endif
1912984c4197SStefano Zampini   }
1913984c4197SStefano Zampini   for (k=0;k<nnsp_size;k++) {
1914984c4197SStefano Zampini     ierr = VecDestroy(&localnearnullsp[k]);CHKERRQ(ierr);
1915984c4197SStefano Zampini   }
1916984c4197SStefano Zampini   ierr = PetscFree(localnearnullsp);CHKERRQ(ierr);
1917984c4197SStefano Zampini 
1918727cdba6SStefano Zampini   /* set quantities in pcbddc data structure and store previous primal size */
1919984c4197SStefano Zampini   /* n_vertices defines the number of subdomain corners in the primal space */
1920674ae819SStefano Zampini   /* n_constraints defines the number of averages (they can be point primal dofs if change of basis is requested) */
1921727cdba6SStefano Zampini   olocal_primal_size = pcbddc->local_primal_size;
1922984c4197SStefano Zampini   pcbddc->local_primal_size = total_counts;
1923674ae819SStefano Zampini   pcbddc->n_vertices = n_vertices;
1924984c4197SStefano Zampini   pcbddc->n_constraints = pcbddc->local_primal_size-pcbddc->n_vertices;
1925674ae819SStefano Zampini 
1926674ae819SStefano Zampini   /* Create constraint matrix */
1927674ae819SStefano Zampini   /* The constraint matrix is used to compute the l2g map of primal dofs */
1928674ae819SStefano Zampini   /* so we need to set it up properly either with or without change of basis */
1929674ae819SStefano Zampini   ierr = MatCreate(PETSC_COMM_SELF,&pcbddc->ConstraintMatrix);CHKERRQ(ierr);
1930674ae819SStefano Zampini   ierr = MatSetType(pcbddc->ConstraintMatrix,impMatType);CHKERRQ(ierr);
1931984c4197SStefano Zampini   ierr = MatSetSizes(pcbddc->ConstraintMatrix,pcbddc->local_primal_size,pcis->n,pcbddc->local_primal_size,pcis->n);CHKERRQ(ierr);
1932984c4197SStefano Zampini   /* array to compute a local numbering of constraints : vertices first then constraints */
1933785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_numbering);CHKERRQ(ierr);
1934984c4197SStefano Zampini   /* array to select the proper local node (of minimum index with respect to global ordering) when changing the basis */
1935984c4197SStefano 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 */
1936785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&aux_primal_minloc);CHKERRQ(ierr);
1937984c4197SStefano Zampini   /* auxiliary stuff for basis change */
1938785e854fSJed Brown   ierr = PetscMalloc1(max_size_of_constraint,&global_indices);CHKERRQ(ierr);
19394641a718SStefano Zampini   ierr = PetscBTCreate(pcis->n_B,&touched);CHKERRQ(ierr);
1940984c4197SStefano Zampini 
1941984c4197SStefano Zampini   /* find primal_dofs: subdomain corners plus dofs selected as primal after change of basis */
1942984c4197SStefano Zampini   total_primal_vertices=0;
1943984c4197SStefano Zampini   for (i=0;i<pcbddc->local_primal_size;i++) {
1944674ae819SStefano Zampini     size_of_constraint=temp_indices[i+1]-temp_indices[i];
1945984c4197SStefano Zampini     if (size_of_constraint == 1) {
19464641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]]);CHKERRQ(ierr);
1947984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]];
1948984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=0;
1949984c4197SStefano Zampini       total_primal_vertices++;
19504641a718SStefano Zampini     } else if (PetscBTLookup(change_basis,i)) { /* Same procedure used in PCBDDCGetPrimalConstraintsLocalIdx */
1951984c4197SStefano Zampini       PetscInt min_loc,min_index;
1952984c4197SStefano Zampini       ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,&temp_indices_to_constraint[temp_indices[i]],global_indices);CHKERRQ(ierr);
1953984c4197SStefano Zampini       /* find first untouched local node */
1954674ae819SStefano Zampini       k = 0;
19554641a718SStefano Zampini       while (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) k++;
1956984c4197SStefano Zampini       min_index = global_indices[k];
1957984c4197SStefano Zampini       min_loc = k;
1958984c4197SStefano Zampini       /* search the minimum among global nodes already untouched on the cc */
1959984c4197SStefano Zampini       for (k=1;k<size_of_constraint;k++) {
1960984c4197SStefano Zampini         /* there can be more than one constraint on a single connected component */
19614641a718SStefano Zampini         if (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k]) && min_index > global_indices[k]) {
1962984c4197SStefano Zampini           min_index = global_indices[k];
1963984c4197SStefano Zampini           min_loc = k;
1964674ae819SStefano Zampini         }
1965674ae819SStefano Zampini       }
19664641a718SStefano Zampini       ierr = PetscBTSet(touched,temp_indices_to_constraint_B[temp_indices[i]+min_loc]);CHKERRQ(ierr);
1967984c4197SStefano Zampini       aux_primal_numbering[total_primal_vertices]=temp_indices_to_constraint[temp_indices[i]+min_loc];
1968984c4197SStefano Zampini       aux_primal_minloc[total_primal_vertices]=min_loc;
1969984c4197SStefano Zampini       total_primal_vertices++;
1970984c4197SStefano Zampini     }
1971984c4197SStefano Zampini   }
1972a717540cSStefano Zampini   /* determine if a QR strategy is needed for change of basis */
1973a717540cSStefano Zampini   qr_needed = PETSC_FALSE;
1974a717540cSStefano Zampini   ierr = PetscBTCreate(pcbddc->local_primal_size,&qr_needed_idx);CHKERRQ(ierr);
1975a717540cSStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
1976a717540cSStefano Zampini     if (PetscBTLookup(change_basis,i)) {
1977fa434743SStefano Zampini       if (!pcbddc->use_qr_single) {
1978a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
1979a717540cSStefano Zampini         j = 0;
1980a717540cSStefano Zampini         for (k=0;k<size_of_constraint;k++) {
1981a717540cSStefano Zampini           if (PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+k])) {
1982a717540cSStefano Zampini             j++;
1983a717540cSStefano Zampini           }
1984a717540cSStefano Zampini         }
1985a717540cSStefano Zampini         /* found more than one primal dof on the cc */
1986a717540cSStefano Zampini         if (j > 1) {
1987a717540cSStefano Zampini           PetscBTSet(qr_needed_idx,i);
1988a717540cSStefano Zampini           qr_needed = PETSC_TRUE;
1989a717540cSStefano Zampini         }
1990fa434743SStefano Zampini       } else {
1991fa434743SStefano Zampini         PetscBTSet(qr_needed_idx,i);
1992fa434743SStefano Zampini         qr_needed = PETSC_TRUE;
1993fa434743SStefano Zampini       }
1994a717540cSStefano Zampini     }
1995a717540cSStefano Zampini   }
1996984c4197SStefano Zampini   /* free workspace */
1997984c4197SStefano Zampini   ierr = PetscFree(global_indices);CHKERRQ(ierr);
199845a1bb75SStefano Zampini 
1999674ae819SStefano Zampini   /* permute indices in order to have a sorted set of vertices */
2000a717540cSStefano Zampini   ierr = PetscSortInt(total_primal_vertices,aux_primal_numbering);CHKERRQ(ierr);
2001984c4197SStefano Zampini 
2002984c4197SStefano Zampini   /* nonzero structure of constraint matrix */
2003785e854fSJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&nnz);CHKERRQ(ierr);
2004984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) nnz[i]=1;
2005984c4197SStefano Zampini   j=total_primal_vertices;
2006984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
20074641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2008674ae819SStefano Zampini       nnz[j]=temp_indices[i+1]-temp_indices[i];
2009674ae819SStefano Zampini       j++;
2010674ae819SStefano Zampini     }
2011674ae819SStefano Zampini   }
2012674ae819SStefano Zampini   ierr = MatSeqAIJSetPreallocation(pcbddc->ConstraintMatrix,0,nnz);CHKERRQ(ierr);
2013674ae819SStefano Zampini   ierr = PetscFree(nnz);CHKERRQ(ierr);
2014674ae819SStefano Zampini   /* set values in constraint matrix */
2015984c4197SStefano Zampini   for (i=0;i<total_primal_vertices;i++) {
2016984c4197SStefano Zampini     ierr = MatSetValue(pcbddc->ConstraintMatrix,i,aux_primal_numbering[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
2017674ae819SStefano Zampini   }
2018984c4197SStefano Zampini   total_counts = total_primal_vertices;
2019984c4197SStefano Zampini   for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
20204641a718SStefano Zampini     if (!PetscBTLookup(change_basis,i)) {
2021674ae819SStefano Zampini       size_of_constraint=temp_indices[i+1]-temp_indices[i];
2022674ae819SStefano 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);
2023674ae819SStefano Zampini       total_counts++;
2024674ae819SStefano Zampini     }
2025674ae819SStefano Zampini   }
2026674ae819SStefano Zampini   /* assembling */
2027674ae819SStefano Zampini   ierr = MatAssemblyBegin(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2028674ae819SStefano Zampini   ierr = MatAssemblyEnd(pcbddc->ConstraintMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2029984c4197SStefano Zampini   /*
203045a1bb75SStefano Zampini   ierr = PetscViewerSetFormat(PETSC_VIEWER_STDOUT_SELF,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
2031984c4197SStefano Zampini   ierr = MatView(pcbddc->ConstraintMatrix,(PetscViewer)0);CHKERRQ(ierr);
2032984c4197SStefano Zampini   */
2033674ae819SStefano Zampini   /* Create matrix for change of basis. We don't need it in case pcbddc->use_change_of_basis is FALSE */
2034674ae819SStefano Zampini   if (pcbddc->use_change_of_basis) {
2035026de310SStefano Zampini     /* dual and primal dofs on a single cc */
2036984c4197SStefano Zampini     PetscInt     dual_dofs,primal_dofs;
2037026de310SStefano Zampini     /* iterator on aux_primal_minloc (ordered as read from nearnullspace: vertices, edges and then constraints) */
2038026de310SStefano Zampini     PetscInt     primal_counter;
2039984c4197SStefano Zampini     /* working stuff for GEQRF */
204081d9aea3SBarry Smith     PetscScalar  *qr_basis,*qr_tau = NULL,*qr_work,lqr_work_t;
2041984c4197SStefano Zampini     PetscBLASInt lqr_work;
2042984c4197SStefano Zampini     /* working stuff for UNGQR */
2043984c4197SStefano Zampini     PetscScalar  *gqr_work,lgqr_work_t;
2044984c4197SStefano Zampini     PetscBLASInt lgqr_work;
2045984c4197SStefano Zampini     /* working stuff for TRTRS */
2046984c4197SStefano Zampini     PetscScalar  *trs_rhs;
20473f08241aSStefano Zampini     PetscBLASInt Blas_NRHS;
2048984c4197SStefano Zampini     /* pointers for values insertion into change of basis matrix */
2049984c4197SStefano Zampini     PetscInt     *start_rows,*start_cols;
2050984c4197SStefano Zampini     PetscScalar  *start_vals;
2051984c4197SStefano Zampini     /* working stuff for values insertion */
20524641a718SStefano Zampini     PetscBT      is_primal;
2053906d46d4SStefano Zampini     /* matrix sizes */
2054906d46d4SStefano Zampini     PetscInt     global_size,local_size;
2055906d46d4SStefano Zampini     /* work array for nonzeros */
2056906d46d4SStefano Zampini     PetscScalar  *nnz_array;
2057906d46d4SStefano Zampini     /* temporary change of basis */
2058906d46d4SStefano Zampini     Mat          localChangeOfBasisMatrix;
2059906d46d4SStefano Zampini     /* auxiliary work for global change of basis */
2060906d46d4SStefano Zampini     Vec          nnz_vec;
206122bc73bbSStefano Zampini     PetscInt     *idxs_I,*idxs_B,*idxs_all,*d_nnz,*o_nnz;
2062906d46d4SStefano Zampini     PetscInt     nvtxs,*xadj,*adjncy,*idxs_mapped;
2063906d46d4SStefano Zampini     PetscScalar  *vals;
2064906d46d4SStefano Zampini     PetscBool    done;
2065984c4197SStefano Zampini 
2066906d46d4SStefano Zampini     /* local temporary change of basis acts on local interfaces -> dimension is n_B x n_B */
2067906d46d4SStefano Zampini     ierr = MatCreate(PETSC_COMM_SELF,&localChangeOfBasisMatrix);CHKERRQ(ierr);
2068906d46d4SStefano Zampini     ierr = MatSetType(localChangeOfBasisMatrix,impMatType);CHKERRQ(ierr);
2069906d46d4SStefano Zampini     ierr = MatSetSizes(localChangeOfBasisMatrix,pcis->n_B,pcis->n_B,pcis->n_B,pcis->n_B);CHKERRQ(ierr);
2070906d46d4SStefano Zampini 
2071906d46d4SStefano Zampini     /* nonzeros for local mat */
2072785e854fSJed Brown     ierr = PetscMalloc1(pcis->n_B,&nnz);CHKERRQ(ierr);
2073a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) nnz[i]=1;
2074a717540cSStefano Zampini     for (i=pcbddc->n_vertices;i<pcbddc->local_primal_size;i++) {
2075a717540cSStefano Zampini       if (PetscBTLookup(change_basis,i)) {
2076a717540cSStefano Zampini         size_of_constraint = temp_indices[i+1]-temp_indices[i];
2077a717540cSStefano Zampini         if (PetscBTLookup(qr_needed_idx,i)) {
2078a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2079a717540cSStefano Zampini         } else {
2080a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = 2;
2081a717540cSStefano Zampini           /* get local primal index on the cc */
2082a717540cSStefano Zampini           j = 0;
2083a717540cSStefano Zampini           while (!PetscBTLookup(touched,temp_indices_to_constraint_B[temp_indices[i]+j])) j++;
2084a717540cSStefano Zampini           nnz[temp_indices_to_constraint_B[temp_indices[i]+j]] = size_of_constraint;
2085a717540cSStefano Zampini         }
2086a717540cSStefano Zampini       }
2087a717540cSStefano Zampini     }
2088906d46d4SStefano Zampini     ierr = MatSeqAIJSetPreallocation(localChangeOfBasisMatrix,0,nnz);CHKERRQ(ierr);
2089a717540cSStefano Zampini     /* Set initial identity in the matrix */
2090a717540cSStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2091906d46d4SStefano Zampini       ierr = MatSetValue(localChangeOfBasisMatrix,i,i,1.0,INSERT_VALUES);CHKERRQ(ierr);
2092a717540cSStefano Zampini     }
2093a717540cSStefano Zampini 
2094a717540cSStefano Zampini     if (pcbddc->dbg_flag) {
2095a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"--------------------------------------------------------------\n");CHKERRQ(ierr);
2096a717540cSStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Checking change of basis computation for subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
2097a717540cSStefano Zampini     }
2098a717540cSStefano Zampini 
2099a717540cSStefano Zampini 
2100a717540cSStefano Zampini     /* Now we loop on the constraints which need a change of basis */
2101a717540cSStefano Zampini     /*
2102a717540cSStefano Zampini        Change of basis matrix is evaluated similarly to the FIRST APPROACH in
2103a717540cSStefano Zampini        Klawonn and Widlund, Dual-primal FETI-DP methods for linear elasticity, (see Sect 6.2.1)
2104a717540cSStefano Zampini 
2105a6b551f4SStefano Zampini        Basic blocks of change of basis matrix T computed by
2106a717540cSStefano Zampini 
2107a6b551f4SStefano 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)
2108a6b551f4SStefano Zampini 
2109a6b551f4SStefano Zampini             | 1        0   ...        0         s_1/S |
2110a6b551f4SStefano Zampini             | 0        1   ...        0         s_2/S |
2111a717540cSStefano Zampini             |              ...                        |
2112a6b551f4SStefano Zampini             | 0        ...            1     s_{n-1}/S |
2113a6b551f4SStefano Zampini             | -s_1/s_n ...    -s_{n-1}/s_n      s_n/S |
2114a717540cSStefano Zampini 
2115a6b551f4SStefano Zampini             with S = \sum_{i=1}^n s_i^2
2116a6b551f4SStefano Zampini             NOTE: in the above example, the primal dof is the last one of the edge in LOCAL ordering
2117a6b551f4SStefano Zampini                   in the current implementation, the primal dof is the first one of the edge in GLOBAL ordering
2118a6b551f4SStefano Zampini 
2119a6b551f4SStefano Zampini           - QR decomposition of constraints otherwise
2120a717540cSStefano Zampini     */
2121a717540cSStefano Zampini     if (qr_needed) {
2122984c4197SStefano Zampini       /* space to store Q */
2123854ce69bSBarry Smith       ierr = PetscMalloc1(max_size_of_constraint*max_size_of_constraint,&qr_basis);CHKERRQ(ierr);
2124984c4197SStefano Zampini       /* first we issue queries for optimal work */
21253f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
21263f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_N);CHKERRQ(ierr);
21273f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2128984c4197SStefano Zampini       lqr_work = -1;
21293f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,&lqr_work_t,&lqr_work,&lierr));
2130984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to GEQRF Lapack routine %d",(int)lierr);
2131984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lqr_work_t),&lqr_work);CHKERRQ(ierr);
2132785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lqr_work_t),&qr_work);CHKERRQ(ierr);
2133984c4197SStefano Zampini       lgqr_work = -1;
21343f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_M);CHKERRQ(ierr);
21353f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_N);CHKERRQ(ierr);
21363f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_constraints,&Blas_K);CHKERRQ(ierr);
21373f08241aSStefano Zampini       ierr = PetscBLASIntCast(max_size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
21383f08241aSStefano Zampini       if (Blas_K>Blas_M) Blas_K=Blas_M; /* adjust just for computing optimal work */
21393f08241aSStefano Zampini       PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,&lgqr_work_t,&lgqr_work,&lierr));
2140984c4197SStefano Zampini       if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in query to UNGQR Lapack routine %d",(int)lierr);
2141984c4197SStefano Zampini       ierr = PetscBLASIntCast((PetscInt)PetscRealPart(lgqr_work_t),&lgqr_work);CHKERRQ(ierr);
2142785e854fSJed Brown       ierr = PetscMalloc1((PetscInt)PetscRealPart(lgqr_work_t),&gqr_work);CHKERRQ(ierr);
2143984c4197SStefano Zampini       /* array to store scaling factors for reflectors */
2144785e854fSJed Brown       ierr = PetscMalloc1(max_constraints,&qr_tau);CHKERRQ(ierr);
2145984c4197SStefano Zampini       /* array to store rhs and solution of triangular solver */
2146785e854fSJed Brown       ierr = PetscMalloc1(max_constraints*max_constraints,&trs_rhs);CHKERRQ(ierr);
2147a717540cSStefano Zampini       /* allocating workspace for check */
2148a717540cSStefano Zampini       if (pcbddc->dbg_flag) {
2149785e854fSJed Brown         ierr = PetscMalloc1(max_size_of_constraint*(max_constraints+max_size_of_constraint),&work);CHKERRQ(ierr);
2150a717540cSStefano Zampini       }
2151a717540cSStefano Zampini     }
2152984c4197SStefano Zampini     /* array to store whether a node is primal or not */
21534641a718SStefano Zampini     ierr = PetscBTCreate(pcis->n_B,&is_primal);CHKERRQ(ierr);
2154473ba861SJed Brown     ierr = PetscMalloc1(total_primal_vertices,&aux_primal_numbering_B);CHKERRQ(ierr);
21555e8657edSStefano Zampini     ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,total_primal_vertices,aux_primal_numbering,&i,aux_primal_numbering_B);CHKERRQ(ierr);
215639e2fb2aSStefano Zampini     if (i != total_primal_vertices) {
215739e2fb2aSStefano Zampini       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Error in boundary numbering for BDDC vertices! %d != %d\n",total_primal_vertices,i);
21584641a718SStefano Zampini     }
215939e2fb2aSStefano Zampini     for (i=0;i<total_primal_vertices;i++) {
216039e2fb2aSStefano Zampini       ierr = PetscBTSet(is_primal,aux_primal_numbering_B[i]);CHKERRQ(ierr);
216139e2fb2aSStefano Zampini     }
216239e2fb2aSStefano Zampini     ierr = PetscFree(aux_primal_numbering_B);CHKERRQ(ierr);
2163984c4197SStefano Zampini 
2164a717540cSStefano Zampini     /* loop on constraints and see whether or not they need a change of basis and compute it */
2165026de310SStefano Zampini     /* -> using implicit ordering contained in temp_indices data */
2166026de310SStefano Zampini     total_counts = pcbddc->n_vertices;
2167026de310SStefano Zampini     primal_counter = total_counts;
2168026de310SStefano Zampini     while (total_counts<pcbddc->local_primal_size) {
2169026de310SStefano Zampini       primal_dofs = 1;
21704641a718SStefano Zampini       if (PetscBTLookup(change_basis,total_counts)) {
2171026de310SStefano Zampini         /* get all constraints with same support: if more then one constraint is present on the cc then surely indices are stored contiguosly */
2172026de310SStefano 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]]) {
2173026de310SStefano Zampini           primal_dofs++;
2174674ae819SStefano Zampini         }
2175984c4197SStefano Zampini         /* get constraint info */
2176026de310SStefano Zampini         size_of_constraint = temp_indices[total_counts+1]-temp_indices[total_counts];
2177984c4197SStefano Zampini         dual_dofs = size_of_constraint-primal_dofs;
2178984c4197SStefano Zampini 
2179984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2180a717540cSStefano 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);
2181674ae819SStefano Zampini         }
2182984c4197SStefano Zampini 
2183fa434743SStefano Zampini         if (PetscBTLookup(qr_needed_idx,total_counts)) { /* QR */
2184a717540cSStefano Zampini 
2185a717540cSStefano Zampini           /* copy quadrature constraints for change of basis check */
2186a717540cSStefano Zampini           if (pcbddc->dbg_flag) {
2187a717540cSStefano Zampini             ierr = PetscMemcpy(work,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2188a717540cSStefano Zampini           }
2189984c4197SStefano Zampini           /* copy temporary constraints into larger work vector (in order to store all columns of Q) */
2190026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2191984c4197SStefano Zampini 
2192984c4197SStefano Zampini           /* compute QR decomposition of constraints */
21933f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
21943f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
21953f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2196674ae819SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
21973f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&Blas_M,&Blas_N,qr_basis,&Blas_LDA,qr_tau,qr_work,&lqr_work,&lierr));
2198984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in GEQRF Lapack routine %d",(int)lierr);
2199674ae819SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2200984c4197SStefano Zampini 
2201984c4197SStefano Zampini           /* explictly compute R^-T */
2202984c4197SStefano Zampini           ierr = PetscMemzero(trs_rhs,primal_dofs*primal_dofs*sizeof(*trs_rhs));CHKERRQ(ierr);
2203984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) trs_rhs[j*(primal_dofs+1)] = 1.0;
22043f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
22053f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_NRHS);CHKERRQ(ierr);
22063f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
22073f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
2208984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
22093f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U","T","N",&Blas_N,&Blas_NRHS,qr_basis,&Blas_LDA,trs_rhs,&Blas_LDB,&lierr));
2210984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TRTRS Lapack routine %d",(int)lierr);
2211984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2212984c4197SStefano Zampini 
2213a717540cSStefano Zampini           /* explicitly compute all columns of Q (Q = [Q1 | Q2] ) overwriting QR factorization in qr_basis */
22143f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
22153f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
22163f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
22173f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2218984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
22193f08241aSStefano Zampini           PetscStackCallBLAS("LAPACKungqr",LAPACKungqr_(&Blas_M,&Blas_N,&Blas_K,qr_basis,&Blas_LDA,qr_tau,gqr_work,&lgqr_work,&lierr));
2220984c4197SStefano Zampini           if (lierr) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in UNGQR Lapack routine %d",(int)lierr);
2221984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2222984c4197SStefano Zampini 
2223984c4197SStefano Zampini           /* first primal_dofs columns of Q need to be re-scaled in order to be unitary w.r.t constraints
2224984c4197SStefano Zampini              i.e. C_{pxn}*Q_{nxn} should be equal to [I_pxp | 0_pxd] (see check below)
2225984c4197SStefano Zampini              where n=size_of_constraint, p=primal_dofs, d=dual_dofs (n=p+d), I and 0 identity and null matrix resp. */
22263f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_M);CHKERRQ(ierr);
22273f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_N);CHKERRQ(ierr);
22283f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_K);CHKERRQ(ierr);
22293f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
22303f08241aSStefano Zampini           ierr = PetscBLASIntCast(primal_dofs,&Blas_LDB);CHKERRQ(ierr);
22313f08241aSStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDC);CHKERRQ(ierr);
2232984c4197SStefano Zampini           ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2233c4303822SStefano 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));
2234984c4197SStefano Zampini           ierr = PetscFPTrapPop();CHKERRQ(ierr);
2235026de310SStefano Zampini           ierr = PetscMemcpy(qr_basis,&temp_quadrature_constraint[temp_indices[total_counts]],size_of_constraint*primal_dofs*sizeof(PetscScalar));CHKERRQ(ierr);
2236984c4197SStefano Zampini 
2237984c4197SStefano Zampini           /* insert values in change of basis matrix respecting global ordering of new primal dofs */
2238026de310SStefano Zampini           start_rows = &temp_indices_to_constraint_B[temp_indices[total_counts]];
2239984c4197SStefano Zampini           /* insert cols for primal dofs */
2240984c4197SStefano Zampini           for (j=0;j<primal_dofs;j++) {
2241984c4197SStefano Zampini             start_vals = &qr_basis[j*size_of_constraint];
2242026de310SStefano Zampini             start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter+j]];
2243906d46d4SStefano Zampini             ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2244984c4197SStefano Zampini           }
2245984c4197SStefano Zampini           /* insert cols for dual dofs */
2246984c4197SStefano Zampini           for (j=0,k=0;j<dual_dofs;k++) {
22474641a718SStefano Zampini             if (!PetscBTLookup(is_primal,temp_indices_to_constraint_B[temp_indices[total_counts]+k])) {
2248984c4197SStefano Zampini               start_vals = &qr_basis[(primal_dofs+j)*size_of_constraint];
2249026de310SStefano Zampini               start_cols = &temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2250906d46d4SStefano Zampini               ierr = MatSetValues(localChangeOfBasisMatrix,size_of_constraint,start_rows,1,start_cols,start_vals,INSERT_VALUES);CHKERRQ(ierr);
2251984c4197SStefano Zampini               j++;
2252674ae819SStefano Zampini             }
2253674ae819SStefano Zampini           }
2254984c4197SStefano Zampini 
2255984c4197SStefano Zampini           /* check change of basis */
2256984c4197SStefano Zampini           if (pcbddc->dbg_flag) {
2257984c4197SStefano Zampini             PetscInt   ii,jj;
2258984c4197SStefano Zampini             PetscBool valid_qr=PETSC_TRUE;
2259c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_M);CHKERRQ(ierr);
2260c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2261c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_K);CHKERRQ(ierr);
2262c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDA);CHKERRQ(ierr);
2263c4303822SStefano Zampini             ierr = PetscBLASIntCast(size_of_constraint,&Blas_LDB);CHKERRQ(ierr);
2264c4303822SStefano Zampini             ierr = PetscBLASIntCast(primal_dofs,&Blas_LDC);CHKERRQ(ierr);
2265984c4197SStefano Zampini             ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
2266c4303822SStefano 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));
2267984c4197SStefano Zampini             ierr = PetscFPTrapPop();CHKERRQ(ierr);
2268984c4197SStefano Zampini             for (jj=0;jj<size_of_constraint;jj++) {
2269984c4197SStefano Zampini               for (ii=0;ii<primal_dofs;ii++) {
2270984c4197SStefano Zampini                 if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) valid_qr = PETSC_FALSE;
2271984c4197SStefano Zampini                 if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) valid_qr = PETSC_FALSE;
2272674ae819SStefano Zampini               }
2273674ae819SStefano Zampini             }
2274984c4197SStefano Zampini             if (!valid_qr) {
227522d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> wrong change of basis!\n");CHKERRQ(ierr);
2276984c4197SStefano Zampini               for (jj=0;jj<size_of_constraint;jj++) {
2277984c4197SStefano Zampini                 for (ii=0;ii<primal_dofs;ii++) {
2278984c4197SStefano Zampini                   if (ii != jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]) > 1.e-12) {
2279984c4197SStefano 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]));
2280674ae819SStefano Zampini                   }
2281984c4197SStefano Zampini                   if (ii == jj && PetscAbsScalar(work[size_of_constraint*primal_dofs+jj*primal_dofs+ii]-1.0) > 1.e-12) {
2282984c4197SStefano 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]));
2283984c4197SStefano Zampini                   }
2284984c4197SStefano Zampini                 }
2285984c4197SStefano Zampini               }
2286674ae819SStefano Zampini             } else {
228722d5777bSStefano Zampini               ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> right change of basis!\n");CHKERRQ(ierr);
2288674ae819SStefano Zampini             }
2289674ae819SStefano Zampini           }
2290a717540cSStefano Zampini         } else { /* simple transformation block */
2291a717540cSStefano Zampini           PetscInt    row,col;
2292a6b551f4SStefano Zampini           PetscScalar val,norm;
2293a6b551f4SStefano Zampini 
2294a6b551f4SStefano Zampini           ierr = PetscBLASIntCast(size_of_constraint,&Blas_N);CHKERRQ(ierr);
2295a6b551f4SStefano 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));
2296a717540cSStefano Zampini           for (j=0;j<size_of_constraint;j++) {
2297a717540cSStefano Zampini             row = temp_indices_to_constraint_B[temp_indices[total_counts]+j];
2298a717540cSStefano Zampini             if (!PetscBTLookup(is_primal,row)) {
2299a717540cSStefano Zampini               col = temp_indices_to_constraint_B[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2300906d46d4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,row,1.0,INSERT_VALUES);CHKERRQ(ierr);
2301a6b551f4SStefano Zampini               ierr = MatSetValue(localChangeOfBasisMatrix,row,col,temp_quadrature_constraint[temp_indices[total_counts]+j]/norm,INSERT_VALUES);CHKERRQ(ierr);
2302a717540cSStefano Zampini             } else {
2303a717540cSStefano Zampini               for (k=0;k<size_of_constraint;k++) {
2304a717540cSStefano Zampini                 col = temp_indices_to_constraint_B[temp_indices[total_counts]+k];
2305a717540cSStefano Zampini                 if (row != col) {
2306a717540cSStefano Zampini                   val = -temp_quadrature_constraint[temp_indices[total_counts]+k]/temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]];
2307a717540cSStefano Zampini                 } else {
2308a6b551f4SStefano Zampini                   val = temp_quadrature_constraint[temp_indices[total_counts]+aux_primal_minloc[primal_counter]]/norm;
2309a717540cSStefano Zampini                 }
2310906d46d4SStefano Zampini                 ierr = MatSetValue(localChangeOfBasisMatrix,row,col,val,INSERT_VALUES);CHKERRQ(ierr);
2311a717540cSStefano Zampini               }
2312a717540cSStefano Zampini             }
2313a717540cSStefano Zampini           }
231498a51de6SStefano Zampini           if (pcbddc->dbg_flag) {
231522d5777bSStefano Zampini             ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"\t-> using standard change of basis\n");CHKERRQ(ierr);
2316a717540cSStefano Zampini           }
2317674ae819SStefano Zampini         }
2318026de310SStefano Zampini         /* increment primal counter */
2319026de310SStefano Zampini         primal_counter += primal_dofs;
2320984c4197SStefano Zampini       } else {
2321984c4197SStefano Zampini         if (pcbddc->dbg_flag) {
2322026de310SStefano 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);
2323674ae819SStefano Zampini         }
2324674ae819SStefano Zampini       }
2325026de310SStefano Zampini       /* increment constraint counter total_counts */
2326026de310SStefano Zampini       total_counts += primal_dofs;
2327674ae819SStefano Zampini     }
2328a717540cSStefano Zampini 
2329a717540cSStefano Zampini     /* free workspace */
2330a717540cSStefano Zampini     if (qr_needed) {
2331984c4197SStefano Zampini       if (pcbddc->dbg_flag) {
2332984c4197SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
2333984c4197SStefano Zampini       }
2334984c4197SStefano Zampini       ierr = PetscFree(trs_rhs);CHKERRQ(ierr);
2335984c4197SStefano Zampini       ierr = PetscFree(qr_tau);CHKERRQ(ierr);
2336984c4197SStefano Zampini       ierr = PetscFree(qr_work);CHKERRQ(ierr);
2337984c4197SStefano Zampini       ierr = PetscFree(gqr_work);CHKERRQ(ierr);
2338984c4197SStefano Zampini       ierr = PetscFree(qr_basis);CHKERRQ(ierr);
2339674ae819SStefano Zampini     }
2340a717540cSStefano Zampini     ierr = PetscBTDestroy(&is_primal);CHKERRQ(ierr);
2341906d46d4SStefano Zampini     ierr = MatAssemblyBegin(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2342906d46d4SStefano Zampini     ierr = MatAssemblyEnd(localChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2343906d46d4SStefano Zampini 
2344906d46d4SStefano Zampini     /* assembling of global change of variable */
2345906d46d4SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2346906d46d4SStefano Zampini     ierr = MatSetType(pcbddc->ChangeOfBasisMatrix,MATAIJ);CHKERRQ(ierr);
2347906d46d4SStefano Zampini     ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2348906d46d4SStefano Zampini     ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2349906d46d4SStefano Zampini     ierr = MatSetSizes(pcbddc->ChangeOfBasisMatrix,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2350906d46d4SStefano Zampini     ierr = MatSetLocalToGlobalMapping(pcbddc->ChangeOfBasisMatrix,matis->mapping,matis->mapping);CHKERRQ(ierr);
2351906d46d4SStefano Zampini 
2352906d46d4SStefano Zampini     /* nonzeros (overestimated) */
2353906d46d4SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nnz_vec);CHKERRQ(ierr);
2354906d46d4SStefano Zampini     ierr = VecSetLocalToGlobalMapping(nnz_vec,matis->mapping);CHKERRQ(ierr);
2355906d46d4SStefano Zampini     ierr = PetscMalloc2(pcis->n,&nnz_array,pcis->n,&idxs_all);CHKERRQ(ierr);
2356906d46d4SStefano Zampini     for (i=0;i<pcis->n;i++) {
2357906d46d4SStefano Zampini       nnz_array[i] = 1.0;
2358906d46d4SStefano Zampini       idxs_all[i] = i;
2359906d46d4SStefano Zampini     }
2360906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2361906d46d4SStefano Zampini     for (i=0;i<pcis->n_B;i++) {
2362906d46d4SStefano Zampini       nnz_array[idxs_B[i]] = nnz[i];
2363906d46d4SStefano Zampini     }
2364a5187659SStefano Zampini     if (pcis->n) {
2365906d46d4SStefano Zampini       ierr = VecSetValuesLocal(nnz_vec,pcis->n,idxs_all,nnz_array,INSERT_VALUES);CHKERRQ(ierr);
2366a5187659SStefano Zampini     }
2367906d46d4SStefano Zampini     ierr = VecAssemblyBegin(nnz_vec);CHKERRQ(ierr);
2368906d46d4SStefano Zampini     ierr = VecAssemblyEnd(nnz_vec);CHKERRQ(ierr);
2369906d46d4SStefano Zampini     ierr = PetscFree(nnz);CHKERRQ(ierr);
2370906d46d4SStefano Zampini     ierr = PetscFree2(nnz_array,idxs_all);CHKERRQ(ierr);
237122bc73bbSStefano Zampini     ierr = PetscMalloc2(local_size,&d_nnz,local_size,&o_nnz);CHKERRQ(ierr);
2372906d46d4SStefano Zampini     ierr = VecGetArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2373906d46d4SStefano Zampini     for (i=0;i<local_size;i++) {
237422bc73bbSStefano Zampini       d_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),local_size);
237522bc73bbSStefano Zampini       o_nnz[i] = PetscMin((PetscInt)(PetscRealPart(nnz_array[i])),global_size-local_size);
2376906d46d4SStefano Zampini     }
2377906d46d4SStefano Zampini     ierr = VecRestoreArray(nnz_vec,&nnz_array);CHKERRQ(ierr);
2378906d46d4SStefano Zampini     ierr = VecDestroy(&nnz_vec);CHKERRQ(ierr);
237922bc73bbSStefano Zampini     ierr = MatMPIAIJSetPreallocation(pcbddc->ChangeOfBasisMatrix,0,d_nnz,0,o_nnz);CHKERRQ(ierr);
238022bc73bbSStefano Zampini     ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr);
2381906d46d4SStefano Zampini 
2382906d46d4SStefano Zampini     /* Set identity on dirichlet dofs */
2383906d46d4SStefano Zampini     ierr = ISGetIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2384906d46d4SStefano Zampini     for (i=0;i<pcis->n-pcis->n_B;i++) {
2385906d46d4SStefano Zampini       PetscScalar one=1.0;
2386906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,idxs_I+i,1,idxs_I+i,&one,INSERT_VALUES);CHKERRQ(ierr);
2387906d46d4SStefano Zampini     }
2388906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_I_local,(const PetscInt**)&idxs_I);CHKERRQ(ierr);
2389906d46d4SStefano Zampini 
2390906d46d4SStefano Zampini     /* Set values at interface dofs */
2391906d46d4SStefano Zampini     done = PETSC_TRUE;
2392906d46d4SStefano Zampini     ierr = MatGetRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2393906d46d4SStefano Zampini     if (!done) {
2394906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2395906d46d4SStefano Zampini     }
2396906d46d4SStefano Zampini     ierr = MatSeqAIJGetArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2397906d46d4SStefano Zampini     ierr = PetscMalloc1(xadj[nvtxs],&idxs_mapped);CHKERRQ(ierr);
23985e8657edSStefano Zampini     ierr = ISLocalToGlobalMappingApply(pcis->BtoNmap,xadj[nvtxs],adjncy,idxs_mapped);CHKERRQ(ierr);
2399906d46d4SStefano Zampini     for (i=0;i<nvtxs;i++) {
2400906d46d4SStefano Zampini       PetscInt    row,*cols,ncols;
2401906d46d4SStefano Zampini       PetscScalar *mat_vals;
2402906d46d4SStefano Zampini 
2403906d46d4SStefano Zampini       row = idxs_B[i];
2404906d46d4SStefano Zampini       ncols = xadj[i+1]-xadj[i];
2405906d46d4SStefano Zampini       cols = idxs_mapped+xadj[i];
2406906d46d4SStefano Zampini       mat_vals = vals+xadj[i];
2407906d46d4SStefano Zampini       ierr = MatSetValuesLocal(pcbddc->ChangeOfBasisMatrix,1,&row,ncols,cols,mat_vals,INSERT_VALUES);CHKERRQ(ierr);
2408906d46d4SStefano Zampini     }
2409906d46d4SStefano Zampini     ierr = MatRestoreRowIJ(localChangeOfBasisMatrix,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2410906d46d4SStefano Zampini     if (!done) {
2411906d46d4SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2412906d46d4SStefano Zampini     }
2413906d46d4SStefano Zampini     ierr = MatSeqAIJRestoreArray(localChangeOfBasisMatrix,&vals);CHKERRQ(ierr);
2414906d46d4SStefano Zampini     ierr = ISRestoreIndices(pcis->is_B_local,(const PetscInt**)&idxs_B);CHKERRQ(ierr);
2415906d46d4SStefano Zampini     ierr = PetscFree(idxs_mapped);CHKERRQ(ierr);
2416674ae819SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2417674ae819SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->ChangeOfBasisMatrix,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2418906d46d4SStefano Zampini 
2419906d46d4SStefano Zampini     /* check */
2420906d46d4SStefano Zampini     if (pcbddc->dbg_flag) {
2421906d46d4SStefano Zampini       PetscReal error;
2422906d46d4SStefano Zampini       Vec       x,x_change;
2423906d46d4SStefano Zampini 
2424906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x);CHKERRQ(ierr);
2425906d46d4SStefano Zampini       ierr = VecDuplicate(pcis->vec1_global,&x_change);CHKERRQ(ierr);
2426906d46d4SStefano Zampini       ierr = VecSetRandom(x,NULL);CHKERRQ(ierr);
2427906d46d4SStefano Zampini       ierr = VecCopy(x,pcis->vec1_global);CHKERRQ(ierr);
2428906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2429906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,x,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2430906d46d4SStefano Zampini       ierr = MatMult(localChangeOfBasisMatrix,pcis->vec1_B,pcis->vec2_B);CHKERRQ(ierr);
2431906d46d4SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2432906d46d4SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_B,pcis->vec2_B,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2433906d46d4SStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x_change);CHKERRQ(ierr);
2434906d46d4SStefano Zampini       ierr = VecAXPY(x,-1.0,x_change);CHKERRQ(ierr);
2435906d46d4SStefano Zampini       ierr = VecNorm(x,NORM_INFINITY,&error);CHKERRQ(ierr);
2436906d46d4SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2437906d46d4SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Error global vs local change on B: %1.6e\n",error);CHKERRQ(ierr);
2438906d46d4SStefano Zampini       ierr = VecDestroy(&x);CHKERRQ(ierr);
2439906d46d4SStefano Zampini       ierr = VecDestroy(&x_change);CHKERRQ(ierr);
2440906d46d4SStefano Zampini     }
2441906d46d4SStefano Zampini     ierr = MatDestroy(&localChangeOfBasisMatrix);CHKERRQ(ierr);
2442906d46d4SStefano Zampini   } else if (pcbddc->user_ChangeOfBasisMatrix) {
2443b9b85e73SStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2444b9b85e73SStefano Zampini     pcbddc->ChangeOfBasisMatrix = pcbddc->user_ChangeOfBasisMatrix;
2445b9b85e73SStefano Zampini   }
2446906d46d4SStefano Zampini 
2447906d46d4SStefano Zampini   /* set up change of basis context */
2448906d46d4SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
2449906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
2450906d46d4SStefano Zampini 
2451906d46d4SStefano Zampini     if (!pcbddc->new_global_mat) {
2452906d46d4SStefano Zampini       PetscInt global_size,local_size;
2453906d46d4SStefano Zampini 
2454906d46d4SStefano Zampini       ierr = VecGetSize(pcis->vec1_global,&global_size);CHKERRQ(ierr);
2455906d46d4SStefano Zampini       ierr = VecGetLocalSize(pcis->vec1_global,&local_size);CHKERRQ(ierr);
2456906d46d4SStefano Zampini       ierr = MatCreate(PetscObjectComm((PetscObject)pc),&pcbddc->new_global_mat);CHKERRQ(ierr);
2457906d46d4SStefano Zampini       ierr = MatSetSizes(pcbddc->new_global_mat,local_size,local_size,global_size,global_size);CHKERRQ(ierr);
2458906d46d4SStefano Zampini       ierr = MatSetType(pcbddc->new_global_mat,MATSHELL);CHKERRQ(ierr);
2459906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT,(void (*)(void))PCBDDCMatMult_Private);CHKERRQ(ierr);
2460906d46d4SStefano Zampini       ierr = MatShellSetOperation(pcbddc->new_global_mat,MATOP_MULT_TRANSPOSE,(void (*)(void))PCBDDCMatMultTranspose_Private);CHKERRQ(ierr);
2461906d46d4SStefano Zampini       ierr = PetscNew(&change_ctx);CHKERRQ(ierr);
2462906d46d4SStefano Zampini       ierr = MatShellSetContext(pcbddc->new_global_mat,change_ctx);CHKERRQ(ierr);
2463906d46d4SStefano Zampini     } else {
2464906d46d4SStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
2465906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
2466906d46d4SStefano Zampini       ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
2467906d46d4SStefano Zampini     }
2468906d46d4SStefano Zampini     if (!pcbddc->user_ChangeOfBasisMatrix) {
2469906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
2470906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->ChangeOfBasisMatrix;
2471906d46d4SStefano Zampini     } else {
2472906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
2473906d46d4SStefano Zampini       change_ctx->global_change = pcbddc->user_ChangeOfBasisMatrix;
2474906d46d4SStefano Zampini     }
2475906d46d4SStefano Zampini     ierr = VecDuplicateVecs(pcis->vec1_global,2,&change_ctx->work);CHKERRQ(ierr);
2476906d46d4SStefano Zampini     ierr = MatSetUp(pcbddc->new_global_mat);CHKERRQ(ierr);
2477906d46d4SStefano Zampini     ierr = MatAssemblyBegin(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2478906d46d4SStefano Zampini     ierr = MatAssemblyEnd(pcbddc->new_global_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2479b9b85e73SStefano Zampini   }
2480a717540cSStefano Zampini 
2481727cdba6SStefano Zampini   /* get indices in local ordering for vertices and constraints */
2482727cdba6SStefano 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 */
2483473ba861SJed Brown     ierr = PetscMalloc1(olocal_primal_size,&oprimal_indices_local_idxs);CHKERRQ(ierr);
2484727cdba6SStefano Zampini     ierr = PetscMemcpy(oprimal_indices_local_idxs,pcbddc->primal_indices_local_idxs,olocal_primal_size*sizeof(PetscInt));CHKERRQ(ierr);
2485727cdba6SStefano Zampini   }
2486727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2487f347579bSStefano Zampini   ierr = PetscFree(pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2488473ba861SJed Brown   ierr = PetscMalloc1(pcbddc->local_primal_size,&pcbddc->primal_indices_local_idxs);CHKERRQ(ierr);
2489727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalVerticesLocalIdx(pc,&i,&aux_primal_numbering);CHKERRQ(ierr);
2490727cdba6SStefano Zampini   ierr = PetscMemcpy(pcbddc->primal_indices_local_idxs,aux_primal_numbering,i*sizeof(PetscInt));CHKERRQ(ierr);
2491727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2492727cdba6SStefano Zampini   ierr = PCBDDCGetPrimalConstraintsLocalIdx(pc,&j,&aux_primal_numbering);CHKERRQ(ierr);
2493727cdba6SStefano Zampini   ierr = PetscMemcpy(&pcbddc->primal_indices_local_idxs[i],aux_primal_numbering,j*sizeof(PetscInt));CHKERRQ(ierr);
2494727cdba6SStefano Zampini   ierr = PetscFree(aux_primal_numbering);CHKERRQ(ierr);
2495e9189074SStefano Zampini   /* set quantities in PCBDDC data struct */
2496e9189074SStefano Zampini   pcbddc->n_actual_vertices = i;
2497727cdba6SStefano Zampini   /* check if a new primal space has been introduced */
2498727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_TRUE;
2499727cdba6SStefano Zampini   if (olocal_primal_size == pcbddc->local_primal_size) {
2500727cdba6SStefano Zampini     ierr = PetscMemcmp(pcbddc->primal_indices_local_idxs,oprimal_indices_local_idxs,olocal_primal_size,&pcbddc->new_primal_space_local);CHKERRQ(ierr);
2501c1c8e736SStefano Zampini     pcbddc->new_primal_space_local = (PetscBool)(!pcbddc->new_primal_space_local);
2502727cdba6SStefano Zampini     ierr = PetscFree(oprimal_indices_local_idxs);CHKERRQ(ierr);
2503727cdba6SStefano Zampini   }
2504727cdba6SStefano Zampini   /* new_primal_space will be used for numbering of coarse dofs, so it should be the same across all subdomains */
2505727cdba6SStefano Zampini   ierr = MPI_Allreduce(&pcbddc->new_primal_space_local,&pcbddc->new_primal_space,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
2506727cdba6SStefano Zampini 
2507a717540cSStefano Zampini   /* flush dbg viewer */
2508b8ffe317SStefano Zampini   if (pcbddc->dbg_flag) {
2509b8ffe317SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
2510b8ffe317SStefano Zampini   }
2511a717540cSStefano Zampini 
2512e310c8b4SStefano Zampini   /* free workspace */
2513a717540cSStefano Zampini   ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2514a717540cSStefano Zampini   ierr = PetscBTDestroy(&qr_needed_idx);CHKERRQ(ierr);
2515984c4197SStefano Zampini   ierr = PetscFree(aux_primal_minloc);CHKERRQ(ierr);
25164641a718SStefano Zampini   ierr = PetscBTDestroy(&change_basis);CHKERRQ(ierr);
2517906d46d4SStefano Zampini   ierr = PetscFree(temp_indices);CHKERRQ(ierr);
2518906d46d4SStefano Zampini   ierr = PetscFree3(temp_quadrature_constraint,temp_indices_to_constraint,temp_indices_to_constraint_B);CHKERRQ(ierr);
2519674ae819SStefano Zampini   PetscFunctionReturn(0);
2520674ae819SStefano Zampini }
2521674ae819SStefano Zampini 
2522674ae819SStefano Zampini #undef __FUNCT__
2523674ae819SStefano Zampini #define __FUNCT__ "PCBDDCAnalyzeInterface"
2524674ae819SStefano Zampini PetscErrorCode PCBDDCAnalyzeInterface(PC pc)
2525674ae819SStefano Zampini {
2526674ae819SStefano Zampini   PC_BDDC     *pcbddc = (PC_BDDC*)pc->data;
2527674ae819SStefano Zampini   PC_IS       *pcis = (PC_IS*)pc->data;
2528674ae819SStefano Zampini   Mat_IS      *matis  = (Mat_IS*)pc->pmat->data;
252963602bcaSStefano Zampini   PetscInt    ierr,i,vertex_size;
2530674ae819SStefano Zampini   PetscViewer viewer=pcbddc->dbg_viewer;
2531674ae819SStefano Zampini 
2532674ae819SStefano Zampini   PetscFunctionBegin;
25338e61c736SStefano Zampini   /* Reset previously computed graph */
25348e61c736SStefano Zampini   ierr = PCBDDCGraphReset(pcbddc->mat_graph);CHKERRQ(ierr);
2535674ae819SStefano Zampini   /* Init local Graph struct */
2536674ae819SStefano Zampini   ierr = PCBDDCGraphInit(pcbddc->mat_graph,matis->mapping);CHKERRQ(ierr);
2537674ae819SStefano Zampini 
2538575ad6abSStefano Zampini   /* Check validity of the csr graph passed in by the user */
2539575ad6abSStefano Zampini   if (pcbddc->mat_graph->nvtxs_csr != pcbddc->mat_graph->nvtxs) {
2540575ad6abSStefano Zampini     ierr = PCBDDCGraphResetCSR(pcbddc->mat_graph);CHKERRQ(ierr);
2541575ad6abSStefano Zampini   }
25429577ea80SStefano Zampini 
2543674ae819SStefano Zampini   /* Set default CSR adjacency of local dofs if not provided by the user with PCBDDCSetLocalAdjacencyGraph */
25444d379d7bSStefano Zampini   if (!pcbddc->mat_graph->xadj || !pcbddc->mat_graph->adjncy) {
2545674ae819SStefano Zampini     Mat       mat_adj;
25464d379d7bSStefano Zampini     PetscInt  *xadj,*adjncy;
25474d379d7bSStefano Zampini     PetscInt  nvtxs;
2548674ae819SStefano Zampini     PetscBool flg_row=PETSC_TRUE;
2549674ae819SStefano Zampini 
2550674ae819SStefano Zampini     ierr = MatConvert(matis->A,MATMPIADJ,MAT_INITIAL_MATRIX,&mat_adj);CHKERRQ(ierr);
25514d379d7bSStefano Zampini     ierr = MatGetRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2552674ae819SStefano Zampini     if (!flg_row) {
2553674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatGetRowIJ called in %s\n",__FUNCT__);
2554674ae819SStefano Zampini     }
25554d379d7bSStefano Zampini     if (pcbddc->use_local_adj) {
25564d379d7bSStefano Zampini       ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,xadj,adjncy,PETSC_COPY_VALUES);CHKERRQ(ierr);
25574d379d7bSStefano Zampini       pcbddc->deluxe_compute_rowadj = PETSC_FALSE;
25584d379d7bSStefano Zampini     } else { /* just compute subdomain's connected components */
25594d379d7bSStefano Zampini       IS                     is_dummy;
25604d379d7bSStefano Zampini       ISLocalToGlobalMapping l2gmap_dummy;
25614d379d7bSStefano Zampini       PetscInt               j,sum;
25624d379d7bSStefano Zampini       PetscInt               *cxadj,*cadjncy;
25634d379d7bSStefano Zampini       const PetscInt         *idxs;
25644d379d7bSStefano Zampini       PCBDDCGraph            graph;
25654d379d7bSStefano Zampini       PetscBT                is_on_boundary;
25664d379d7bSStefano Zampini 
25674d379d7bSStefano Zampini       ierr = ISCreateStride(PETSC_COMM_SELF,pcis->n,0,1,&is_dummy);CHKERRQ(ierr);
25684d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is_dummy,&l2gmap_dummy);CHKERRQ(ierr);
25694d379d7bSStefano Zampini       ierr = ISDestroy(&is_dummy);CHKERRQ(ierr);
25704d379d7bSStefano Zampini       ierr = PCBDDCGraphCreate(&graph);CHKERRQ(ierr);
25714d379d7bSStefano Zampini       ierr = PCBDDCGraphInit(graph,l2gmap_dummy);CHKERRQ(ierr);
25724d379d7bSStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2gmap_dummy);CHKERRQ(ierr);
25734d379d7bSStefano Zampini       graph->xadj = xadj;
25744d379d7bSStefano Zampini       graph->adjncy = adjncy;
25754d379d7bSStefano Zampini       ierr = PCBDDCGraphSetUp(graph,1,NULL,NULL,0,NULL,NULL);CHKERRQ(ierr);
25764d379d7bSStefano Zampini       ierr = PCBDDCGraphComputeConnectedComponents(graph);CHKERRQ(ierr);
25774d379d7bSStefano Zampini 
25784d379d7bSStefano Zampini       if (pcbddc->dbg_flag) {
25794d379d7bSStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] Found %d subdomains\n",PetscGlobalRank,graph->ncc);CHKERRQ(ierr);
25804d379d7bSStefano Zampini         for (i=0;i<graph->ncc;i++) {
25814d379d7bSStefano Zampini           ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"[%d] %d cc size %d\n",PetscGlobalRank,i,graph->cptr[i+1]-graph->cptr[i]);CHKERRQ(ierr);
25824d379d7bSStefano Zampini         }
25834d379d7bSStefano Zampini         ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
25844d379d7bSStefano Zampini       }
25854d379d7bSStefano Zampini 
25864d379d7bSStefano Zampini       ierr = PetscBTCreate(nvtxs,&is_on_boundary);CHKERRQ(ierr);
25874d379d7bSStefano Zampini       ierr = ISGetIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
25884d379d7bSStefano Zampini       for (i=0;i<pcis->n_B;i++) {
25894d379d7bSStefano Zampini         ierr = PetscBTSet(is_on_boundary,idxs[i]);CHKERRQ(ierr);
25904d379d7bSStefano Zampini       }
25914d379d7bSStefano Zampini       ierr = ISRestoreIndices(pcis->is_B_local,&idxs);CHKERRQ(ierr);
25924d379d7bSStefano Zampini 
25934d379d7bSStefano Zampini       ierr = PetscCalloc1(nvtxs+1,&cxadj);CHKERRQ(ierr);
25944d379d7bSStefano Zampini       sum = 0;
25954d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
25964d379d7bSStefano Zampini         PetscInt sizecc = 0;
25974d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
25984d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
25994d379d7bSStefano Zampini             sizecc++;
26004d379d7bSStefano Zampini           }
26014d379d7bSStefano Zampini         }
26024d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
26034d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
26044d379d7bSStefano Zampini             cxadj[graph->queue[j]] = sizecc;
26054d379d7bSStefano Zampini           }
26064d379d7bSStefano Zampini         }
26074d379d7bSStefano Zampini         sum += sizecc*sizecc;
26084d379d7bSStefano Zampini       }
26094d379d7bSStefano Zampini       ierr = PetscMalloc1(sum,&cadjncy);CHKERRQ(ierr);
26104d379d7bSStefano Zampini       sum = 0;
26114d379d7bSStefano Zampini       for (i=0;i<nvtxs;i++) {
26124d379d7bSStefano Zampini         PetscInt temp = cxadj[i];
26134d379d7bSStefano Zampini         cxadj[i] = sum;
26144d379d7bSStefano Zampini         sum += temp;
26154d379d7bSStefano Zampini       }
26164d379d7bSStefano Zampini       cxadj[nvtxs] = sum;
26174d379d7bSStefano Zampini       for (i=0;i<graph->ncc;i++) {
26184d379d7bSStefano Zampini         for (j=graph->cptr[i];j<graph->cptr[i+1];j++) {
26194d379d7bSStefano Zampini           if (PetscBTLookup(is_on_boundary,graph->queue[j])) {
26204d379d7bSStefano Zampini             PetscInt k,sizecc = 0;
26214d379d7bSStefano Zampini             for (k=graph->cptr[i];k<graph->cptr[i+1];k++) {
26224d379d7bSStefano Zampini               if (PetscBTLookup(is_on_boundary,graph->queue[k])) {
26234d379d7bSStefano Zampini                 cadjncy[cxadj[graph->queue[j]]+sizecc]=graph->queue[k];
26244d379d7bSStefano Zampini                 sizecc++;
26254d379d7bSStefano Zampini               }
26264d379d7bSStefano Zampini             }
26274d379d7bSStefano Zampini           }
26284d379d7bSStefano Zampini         }
26294d379d7bSStefano Zampini       }
26304d379d7bSStefano Zampini       if (nvtxs) {
26314d379d7bSStefano Zampini         ierr = PCBDDCSetLocalAdjacencyGraph(pc,nvtxs,cxadj,cadjncy,PETSC_OWN_POINTER);CHKERRQ(ierr);
26324d379d7bSStefano Zampini       } else {
26334d379d7bSStefano Zampini         ierr = PetscFree(cxadj);CHKERRQ(ierr);
26344d379d7bSStefano Zampini         ierr = PetscFree(cadjncy);CHKERRQ(ierr);
26354d379d7bSStefano Zampini       }
26364d379d7bSStefano Zampini       graph->xadj = 0;
26374d379d7bSStefano Zampini       graph->adjncy = 0;
26384d379d7bSStefano Zampini       ierr = PCBDDCGraphDestroy(&graph);CHKERRQ(ierr);
26394d379d7bSStefano Zampini       ierr = PetscBTDestroy(&is_on_boundary);CHKERRQ(ierr);
26404d379d7bSStefano Zampini     }
26414d379d7bSStefano Zampini     ierr = MatRestoreRowIJ(mat_adj,0,PETSC_TRUE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&flg_row);CHKERRQ(ierr);
2642674ae819SStefano Zampini     if (!flg_row) {
2643674ae819SStefano Zampini       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
2644674ae819SStefano Zampini     }
2645674ae819SStefano Zampini     ierr = MatDestroy(&mat_adj);CHKERRQ(ierr);
2646674ae819SStefano Zampini   }
2647674ae819SStefano Zampini 
264863602bcaSStefano Zampini   /* Set default dofs' splitting if no information has been provided by the user with PCBDDCSetDofsSplitting or PCBDDCSetDofsSplittingLocal */
2649674ae819SStefano Zampini   vertex_size = 1;
265063602bcaSStefano Zampini   if (pcbddc->user_provided_isfordofs) {
265163602bcaSStefano Zampini     if (pcbddc->n_ISForDofs) { /* need to convert from global to local and remove references to global dofs splitting */
265295ecbf38SStefano Zampini       ierr = PetscMalloc1(pcbddc->n_ISForDofs,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
265363602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofs;i++) {
2654a7dc3881SStefano Zampini         ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->ISForDofs[i],&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
265563602bcaSStefano Zampini         ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
2656674ae819SStefano Zampini       }
265763602bcaSStefano Zampini       pcbddc->n_ISForDofsLocal = pcbddc->n_ISForDofs;
265863602bcaSStefano Zampini       pcbddc->n_ISForDofs = 0;
265963602bcaSStefano Zampini       ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
2660674ae819SStefano Zampini     }
266163602bcaSStefano Zampini     /* mat block size as vertex size (used for elasticity with rigid body modes as nearnullspace) */
2662674ae819SStefano Zampini     ierr = MatGetBlockSize(matis->A,&vertex_size);CHKERRQ(ierr);
266363602bcaSStefano Zampini   } else {
266463602bcaSStefano Zampini     if (!pcbddc->n_ISForDofsLocal) { /* field split not present, create it in local ordering */
266563602bcaSStefano Zampini       ierr = MatGetBlockSize(pc->pmat,&pcbddc->n_ISForDofsLocal);CHKERRQ(ierr);
2666854ce69bSBarry Smith       ierr = PetscMalloc1(pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
266763602bcaSStefano Zampini       for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
266863602bcaSStefano Zampini         ierr = ISCreateStride(PetscObjectComm((PetscObject)pc),pcis->n/pcbddc->n_ISForDofsLocal,i,pcbddc->n_ISForDofsLocal,&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
266963602bcaSStefano Zampini       }
267063602bcaSStefano Zampini     }
2671674ae819SStefano Zampini   }
2672674ae819SStefano Zampini 
2673674ae819SStefano Zampini   /* Setup of Graph */
2674785d1243SStefano Zampini   if (!pcbddc->DirichletBoundariesLocal && pcbddc->DirichletBoundaries) { /* need to convert from global to local */
2675a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->DirichletBoundaries,&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
2676785d1243SStefano Zampini   }
2677785d1243SStefano Zampini   if (!pcbddc->NeumannBoundariesLocal && pcbddc->NeumannBoundaries) { /* need to convert from global to local */
2678a7dc3881SStefano Zampini     ierr = PCBDDCGlobalToLocal(matis->ctx,pcis->vec1_global,pcis->vec1_N,pcbddc->NeumannBoundaries,&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
2679785d1243SStefano Zampini   }
268063602bcaSStefano Zampini   ierr = PCBDDCGraphSetUp(pcbddc->mat_graph,vertex_size,pcbddc->NeumannBoundariesLocal,pcbddc->DirichletBoundariesLocal,pcbddc->n_ISForDofsLocal,pcbddc->ISForDofsLocal,pcbddc->user_primal_vertices);
2681674ae819SStefano Zampini 
2682674ae819SStefano Zampini   /* Graph's connected components analysis */
2683674ae819SStefano Zampini   ierr = PCBDDCGraphComputeConnectedComponents(pcbddc->mat_graph);CHKERRQ(ierr);
2684674ae819SStefano Zampini 
2685674ae819SStefano Zampini   /* print some info to stdout */
2686674ae819SStefano Zampini   if (pcbddc->dbg_flag) {
2687e49050b4SStefano Zampini     ierr = PCBDDCGraphASCIIView(pcbddc->mat_graph,pcbddc->dbg_flag,viewer);
2688674ae819SStefano Zampini   }
2689fb180af4SStefano Zampini 
2690fb180af4SStefano Zampini   /* mark topography has done */
2691fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
2692674ae819SStefano Zampini   PetscFunctionReturn(0);
2693674ae819SStefano Zampini }
2694674ae819SStefano Zampini 
2695674ae819SStefano Zampini #undef __FUNCT__
2696674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalVerticesLocalIdx"
2697f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalVerticesLocalIdx(PC pc, PetscInt *n_vertices, PetscInt **vertices_idx)
2698674ae819SStefano Zampini {
2699674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2700674ae819SStefano Zampini   PetscInt       *vertices,*row_cmat_indices,n,i,size_of_constraint,local_primal_size;
2701674ae819SStefano Zampini   PetscErrorCode ierr;
2702674ae819SStefano Zampini 
2703674ae819SStefano Zampini   PetscFunctionBegin;
2704674ae819SStefano Zampini   n = 0;
2705674ae819SStefano Zampini   vertices = 0;
2706674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2707674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&i);CHKERRQ(ierr);
2708b120a5c6SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2709b120a5c6SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2710b120a5c6SStefano Zampini       if (size_of_constraint == 1) n++;
2711b120a5c6SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2712b120a5c6SStefano Zampini     }
2713811e8ca2SStefano Zampini     if (vertices_idx) {
2714785e854fSJed Brown       ierr = PetscMalloc1(n,&vertices);CHKERRQ(ierr);
2715b120a5c6SStefano Zampini       n = 0;
2716674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2717674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2718674ae819SStefano Zampini         if (size_of_constraint == 1) {
2719674ae819SStefano Zampini           vertices[n++]=row_cmat_indices[0];
2720674ae819SStefano Zampini         }
2721674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2722674ae819SStefano Zampini       }
2723674ae819SStefano Zampini     }
2724811e8ca2SStefano Zampini   }
2725674ae819SStefano Zampini   *n_vertices = n;
2726811e8ca2SStefano Zampini   if (vertices_idx) *vertices_idx = vertices;
2727674ae819SStefano Zampini   PetscFunctionReturn(0);
2728674ae819SStefano Zampini }
2729674ae819SStefano Zampini 
2730674ae819SStefano Zampini #undef __FUNCT__
2731674ae819SStefano Zampini #define __FUNCT__ "PCBDDCGetPrimalConstraintsLocalIdx"
2732f34684f1SStefano Zampini PetscErrorCode  PCBDDCGetPrimalConstraintsLocalIdx(PC pc, PetscInt *n_constraints, PetscInt **constraints_idx)
2733674ae819SStefano Zampini {
2734674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)(pc->data);
2735674ae819SStefano Zampini   PetscInt       *constraints_index,*row_cmat_indices,*row_cmat_global_indices;
2736674ae819SStefano Zampini   PetscInt       n,i,j,size_of_constraint,local_primal_size,local_size,max_size_of_constraint,min_index,min_loc;
27374641a718SStefano Zampini   PetscBT        touched;
2738674ae819SStefano Zampini   PetscErrorCode ierr;
2739674ae819SStefano Zampini 
2740f34684f1SStefano Zampini     /* This function assumes that the number of local constraints per connected component
2741f34684f1SStefano Zampini        is not greater than the number of nodes defined for the connected component
2742f34684f1SStefano Zampini        (otherwise we will surely have linear dependence between constraints and thus a singular coarse problem) */
2743674ae819SStefano Zampini   PetscFunctionBegin;
2744674ae819SStefano Zampini   n = 0;
2745674ae819SStefano Zampini   constraints_index = 0;
2746674ae819SStefano Zampini   if (pcbddc->ConstraintMatrix) {
2747674ae819SStefano Zampini     ierr = MatGetSize(pcbddc->ConstraintMatrix,&local_primal_size,&local_size);CHKERRQ(ierr);
2748674ae819SStefano Zampini     max_size_of_constraint = 0;
2749674ae819SStefano Zampini     for (i=0;i<local_primal_size;i++) {
2750674ae819SStefano Zampini       ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2751674ae819SStefano Zampini       if (size_of_constraint > 1) {
2752674ae819SStefano Zampini         n++;
2753674ae819SStefano Zampini       }
2754674ae819SStefano Zampini       max_size_of_constraint = PetscMax(size_of_constraint,max_size_of_constraint);
2755674ae819SStefano Zampini       ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,NULL,NULL);CHKERRQ(ierr);
2756674ae819SStefano Zampini     }
2757811e8ca2SStefano Zampini     if (constraints_idx) {
2758785e854fSJed Brown       ierr = PetscMalloc1(n,&constraints_index);CHKERRQ(ierr);
2759785e854fSJed Brown       ierr = PetscMalloc1(max_size_of_constraint,&row_cmat_global_indices);CHKERRQ(ierr);
27604641a718SStefano Zampini       ierr = PetscBTCreate(local_size,&touched);CHKERRQ(ierr);
2761674ae819SStefano Zampini       n = 0;
2762674ae819SStefano Zampini       for (i=0;i<local_primal_size;i++) {
2763674ae819SStefano Zampini         ierr = MatGetRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2764674ae819SStefano Zampini         if (size_of_constraint > 1) {
2765674ae819SStefano Zampini           ierr = ISLocalToGlobalMappingApply(pcbddc->mat_graph->l2gmap,size_of_constraint,row_cmat_indices,row_cmat_global_indices);CHKERRQ(ierr);
276682d3d8afSStefano Zampini           /* find first untouched local node */
276782d3d8afSStefano Zampini           j = 0;
27684641a718SStefano Zampini           while (PetscBTLookup(touched,row_cmat_indices[j])) j++;
276982d3d8afSStefano Zampini           min_index = row_cmat_global_indices[j];
277082d3d8afSStefano Zampini           min_loc = j;
277182d3d8afSStefano Zampini           /* search the minimum among nodes not yet touched on the connected component
277282d3d8afSStefano Zampini              since there can be more than one constraint on a single cc */
2773674ae819SStefano Zampini           for (j=1;j<size_of_constraint;j++) {
27744641a718SStefano Zampini             if (!PetscBTLookup(touched,row_cmat_indices[j]) && min_index > row_cmat_global_indices[j]) {
2775674ae819SStefano Zampini               min_index = row_cmat_global_indices[j];
2776674ae819SStefano Zampini               min_loc = j;
2777674ae819SStefano Zampini             }
2778674ae819SStefano Zampini           }
27794641a718SStefano Zampini           ierr = PetscBTSet(touched,row_cmat_indices[min_loc]);CHKERRQ(ierr);
2780674ae819SStefano Zampini           constraints_index[n++] = row_cmat_indices[min_loc];
2781674ae819SStefano Zampini         }
2782674ae819SStefano Zampini         ierr = MatRestoreRow(pcbddc->ConstraintMatrix,i,&size_of_constraint,(const PetscInt**)&row_cmat_indices,NULL);CHKERRQ(ierr);
2783674ae819SStefano Zampini       }
27844641a718SStefano Zampini       ierr = PetscBTDestroy(&touched);CHKERRQ(ierr);
2785674ae819SStefano Zampini       ierr = PetscFree(row_cmat_global_indices);CHKERRQ(ierr);
2786811e8ca2SStefano Zampini     }
2787811e8ca2SStefano Zampini   }
2788674ae819SStefano Zampini   *n_constraints = n;
2789811e8ca2SStefano Zampini   if (constraints_idx) *constraints_idx = constraints_index;
2790674ae819SStefano Zampini   PetscFunctionReturn(0);
2791674ae819SStefano Zampini }
2792674ae819SStefano Zampini 
2793674ae819SStefano Zampini #undef __FUNCT__
2794674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSubsetNumbering"
2795674ae819SStefano 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[])
2796674ae819SStefano Zampini {
2797674ae819SStefano Zampini   Vec            local_vec,global_vec;
2798674ae819SStefano Zampini   IS             seqis,paris;
2799674ae819SStefano Zampini   VecScatter     scatter_ctx;
2800674ae819SStefano Zampini   PetscScalar    *array;
2801674ae819SStefano Zampini   PetscInt       *temp_global_dofs;
2802674ae819SStefano Zampini   PetscScalar    globalsum;
2803674ae819SStefano Zampini   PetscInt       i,j,s;
2804674ae819SStefano Zampini   PetscInt       nlocals,first_index,old_index,max_local;
2805674ae819SStefano Zampini   PetscMPIInt    rank_prec_comm,size_prec_comm,max_global;
2806674ae819SStefano Zampini   PetscMPIInt    *dof_sizes,*dof_displs;
2807674ae819SStefano Zampini   PetscBool      first_found;
2808674ae819SStefano Zampini   PetscErrorCode ierr;
2809674ae819SStefano Zampini 
2810674ae819SStefano Zampini   PetscFunctionBegin;
2811674ae819SStefano Zampini   /* mpi buffers */
2812b9b85e73SStefano Zampini   ierr = MPI_Comm_size(comm,&size_prec_comm);CHKERRQ(ierr);
2813b9b85e73SStefano Zampini   ierr = MPI_Comm_rank(comm,&rank_prec_comm);CHKERRQ(ierr);
2814674ae819SStefano Zampini   j = ( !rank_prec_comm ? size_prec_comm : 0);
2815785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_sizes);CHKERRQ(ierr);
2816785e854fSJed Brown   ierr = PetscMalloc1(j,&dof_displs);CHKERRQ(ierr);
2817674ae819SStefano Zampini   /* get maximum size of subset */
2818785e854fSJed Brown   ierr = PetscMalloc1(n_local_dofs,&temp_global_dofs);CHKERRQ(ierr);
2819674ae819SStefano Zampini   ierr = ISLocalToGlobalMappingApply(l2gmap,n_local_dofs,local_dofs,temp_global_dofs);CHKERRQ(ierr);
2820674ae819SStefano Zampini   max_local = 0;
2821b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2822674ae819SStefano Zampini     if (max_local < temp_global_dofs[i] ) {
2823674ae819SStefano Zampini       max_local = temp_global_dofs[i];
2824674ae819SStefano Zampini     }
2825674ae819SStefano Zampini   }
2826b9b85e73SStefano Zampini   ierr = MPI_Allreduce(&max_local,&max_global,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
2827674ae819SStefano Zampini   max_global++;
2828674ae819SStefano Zampini   max_local = 0;
2829b9b85e73SStefano Zampini   for (i=0;i<n_local_dofs;i++) {
2830674ae819SStefano Zampini     if (max_local < local_dofs[i] ) {
2831674ae819SStefano Zampini       max_local = local_dofs[i];
2832674ae819SStefano Zampini     }
2833674ae819SStefano Zampini   }
2834674ae819SStefano Zampini   max_local++;
2835674ae819SStefano Zampini   /* allocate workspace */
2836674ae819SStefano Zampini   ierr = VecCreate(PETSC_COMM_SELF,&local_vec);CHKERRQ(ierr);
2837674ae819SStefano Zampini   ierr = VecSetSizes(local_vec,PETSC_DECIDE,max_local);CHKERRQ(ierr);
2838674ae819SStefano Zampini   ierr = VecSetType(local_vec,VECSEQ);CHKERRQ(ierr);
2839674ae819SStefano Zampini   ierr = VecCreate(comm,&global_vec);CHKERRQ(ierr);
2840674ae819SStefano Zampini   ierr = VecSetSizes(global_vec,PETSC_DECIDE,max_global);CHKERRQ(ierr);
2841674ae819SStefano Zampini   ierr = VecSetType(global_vec,VECMPI);CHKERRQ(ierr);
2842674ae819SStefano Zampini   /* create scatter */
2843674ae819SStefano Zampini   ierr = ISCreateGeneral(PETSC_COMM_SELF,n_local_dofs,local_dofs,PETSC_COPY_VALUES,&seqis);CHKERRQ(ierr);
2844674ae819SStefano Zampini   ierr = ISCreateGeneral(comm,n_local_dofs,temp_global_dofs,PETSC_COPY_VALUES,&paris);CHKERRQ(ierr);
2845674ae819SStefano Zampini   ierr = VecScatterCreate(local_vec,seqis,global_vec,paris,&scatter_ctx);CHKERRQ(ierr);
2846674ae819SStefano Zampini   ierr = ISDestroy(&seqis);CHKERRQ(ierr);
2847674ae819SStefano Zampini   ierr = ISDestroy(&paris);CHKERRQ(ierr);
2848674ae819SStefano Zampini   /* init array */
2849674ae819SStefano Zampini   ierr = VecSet(global_vec,0.0);CHKERRQ(ierr);
2850674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2851674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2852674ae819SStefano Zampini   if (local_dofs_mult) {
2853674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2854674ae819SStefano Zampini       array[local_dofs[i]]=(PetscScalar)local_dofs_mult[i];
2855674ae819SStefano Zampini     }
2856674ae819SStefano Zampini   } else {
2857674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
2858674ae819SStefano Zampini       array[local_dofs[i]]=1.0;
2859674ae819SStefano Zampini     }
2860674ae819SStefano Zampini   }
2861674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2862674ae819SStefano Zampini   /* scatter into global vec and get total number of global dofs */
2863674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2864674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,local_vec,global_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2865674ae819SStefano Zampini   ierr = VecSum(global_vec,&globalsum);CHKERRQ(ierr);
28665b08dc53SStefano Zampini   *n_global_subset = (PetscInt)PetscRealPart(globalsum);
2867674ae819SStefano Zampini   /* Fill global_vec with cumulative function for global numbering */
2868674ae819SStefano Zampini   ierr = VecGetArray(global_vec,&array);CHKERRQ(ierr);
2869674ae819SStefano Zampini   ierr = VecGetLocalSize(global_vec,&s);CHKERRQ(ierr);
2870674ae819SStefano Zampini   nlocals = 0;
2871674ae819SStefano Zampini   first_index = -1;
2872674ae819SStefano Zampini   first_found = PETSC_FALSE;
2873674ae819SStefano Zampini   for (i=0;i<s;i++) {
2874b9b85e73SStefano Zampini     if (!first_found && PetscRealPart(array[i]) > 0.1) {
2875674ae819SStefano Zampini       first_found = PETSC_TRUE;
2876674ae819SStefano Zampini       first_index = i;
2877674ae819SStefano Zampini     }
28785b08dc53SStefano Zampini     nlocals += (PetscInt)PetscRealPart(array[i]);
2879674ae819SStefano Zampini   }
2880674ae819SStefano Zampini   ierr = MPI_Gather(&nlocals,1,MPIU_INT,dof_sizes,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2881674ae819SStefano Zampini   if (!rank_prec_comm) {
2882674ae819SStefano Zampini     dof_displs[0]=0;
2883674ae819SStefano Zampini     for (i=1;i<size_prec_comm;i++) {
2884674ae819SStefano Zampini       dof_displs[i] = dof_displs[i-1]+dof_sizes[i-1];
2885674ae819SStefano Zampini     }
2886674ae819SStefano Zampini   }
2887674ae819SStefano Zampini   ierr = MPI_Scatter(dof_displs,1,MPIU_INT,&nlocals,1,MPIU_INT,0,comm);CHKERRQ(ierr);
2888674ae819SStefano Zampini   if (first_found) {
2889674ae819SStefano Zampini     array[first_index] += (PetscScalar)nlocals;
2890674ae819SStefano Zampini     old_index = first_index;
2891674ae819SStefano Zampini     for (i=first_index+1;i<s;i++) {
2892b9b85e73SStefano Zampini       if (PetscRealPart(array[i]) > 0.1) {
2893674ae819SStefano Zampini         array[i] += array[old_index];
2894674ae819SStefano Zampini         old_index = i;
2895674ae819SStefano Zampini       }
2896674ae819SStefano Zampini     }
2897674ae819SStefano Zampini   }
2898674ae819SStefano Zampini   ierr = VecRestoreArray(global_vec,&array);CHKERRQ(ierr);
2899674ae819SStefano Zampini   ierr = VecSet(local_vec,0.0);CHKERRQ(ierr);
2900674ae819SStefano Zampini   ierr = VecScatterBegin(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2901674ae819SStefano Zampini   ierr = VecScatterEnd(scatter_ctx,global_vec,local_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2902674ae819SStefano Zampini   /* get global ordering of local dofs */
2903674ae819SStefano Zampini   ierr = VecGetArray(local_vec,&array);CHKERRQ(ierr);
2904674ae819SStefano Zampini   if (local_dofs_mult) {
2905674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
29065b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-local_dofs_mult[i];
2907674ae819SStefano Zampini     }
2908674ae819SStefano Zampini   } else {
2909674ae819SStefano Zampini     for (i=0;i<n_local_dofs;i++) {
29105b08dc53SStefano Zampini       temp_global_dofs[i] = (PetscInt)PetscRealPart(array[local_dofs[i]])-1;
2911674ae819SStefano Zampini     }
2912674ae819SStefano Zampini   }
2913674ae819SStefano Zampini   ierr = VecRestoreArray(local_vec,&array);CHKERRQ(ierr);
2914674ae819SStefano Zampini   /* free workspace */
2915674ae819SStefano Zampini   ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
2916674ae819SStefano Zampini   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
2917674ae819SStefano Zampini   ierr = VecDestroy(&global_vec);CHKERRQ(ierr);
2918674ae819SStefano Zampini   ierr = PetscFree(dof_sizes);CHKERRQ(ierr);
2919674ae819SStefano Zampini   ierr = PetscFree(dof_displs);CHKERRQ(ierr);
2920674ae819SStefano Zampini   /* return pointer to global ordering of local dofs */
2921674ae819SStefano Zampini   *global_numbering_subset = temp_global_dofs;
2922674ae819SStefano Zampini   PetscFunctionReturn(0);
2923674ae819SStefano Zampini }
29249a7d3425SStefano Zampini 
29259a7d3425SStefano Zampini #undef __FUNCT__
29269a7d3425SStefano Zampini #define __FUNCT__ "PCBDDCOrthonormalizeVecs"
29279a7d3425SStefano Zampini PetscErrorCode PCBDDCOrthonormalizeVecs(PetscInt n, Vec vecs[])
29289a7d3425SStefano Zampini {
29299a7d3425SStefano Zampini   PetscInt       i,j;
29309a7d3425SStefano Zampini   PetscScalar    *alphas;
29319a7d3425SStefano Zampini   PetscErrorCode ierr;
29329a7d3425SStefano Zampini 
29339a7d3425SStefano Zampini   PetscFunctionBegin;
29349a7d3425SStefano Zampini   /* this implements stabilized Gram-Schmidt */
2935785e854fSJed Brown   ierr = PetscMalloc1(n,&alphas);CHKERRQ(ierr);
29369a7d3425SStefano Zampini   for (i=0;i<n;i++) {
29379a7d3425SStefano Zampini     ierr = VecNormalize(vecs[i],NULL);CHKERRQ(ierr);
29389a7d3425SStefano Zampini     if (i<n) { ierr = VecMDot(vecs[i],n-i-1,&vecs[i+1],&alphas[i+1]);CHKERRQ(ierr); }
29399a7d3425SStefano Zampini     for (j=i+1;j<n;j++) { ierr = VecAXPY(vecs[j],PetscConj(-alphas[j]),vecs[i]);CHKERRQ(ierr); }
29409a7d3425SStefano Zampini   }
29419a7d3425SStefano Zampini   ierr = PetscFree(alphas);CHKERRQ(ierr);
29429a7d3425SStefano Zampini   PetscFunctionReturn(0);
29439a7d3425SStefano Zampini }
29449a7d3425SStefano Zampini 
2945e7931f94SStefano Zampini #undef __FUNCT__
294670cf5478SStefano Zampini #define __FUNCT__ "MatISGetSubassemblingPattern"
294728143c3dSStefano Zampini PetscErrorCode MatISGetSubassemblingPattern(Mat mat, PetscInt n_subdomains, PetscBool contiguous, IS* is_sends)
2948e7931f94SStefano Zampini {
2949e7931f94SStefano Zampini   Mat             subdomain_adj;
2950e7931f94SStefano Zampini   IS              new_ranks,ranks_send_to;
2951e7931f94SStefano Zampini   MatPartitioning partitioner;
2952e7931f94SStefano Zampini   Mat_IS          *matis;
2953e7931f94SStefano Zampini   PetscInt        n_neighs,*neighs,*n_shared,**shared;
2954e7931f94SStefano Zampini   PetscInt        prank;
2955e7931f94SStefano Zampini   PetscMPIInt     size,rank,color;
2956e7931f94SStefano Zampini   PetscInt        *xadj,*adjncy,*oldranks;
2957e7931f94SStefano Zampini   PetscInt        *adjncy_wgt,*v_wgt,*is_indices,*ranks_send_to_idx;
29583837a79fSStefano Zampini   PetscInt        i,local_size,threshold=0;
2959e7931f94SStefano Zampini   PetscErrorCode  ierr;
29602b510759SStefano Zampini   PetscBool       use_vwgt=PETSC_FALSE,use_square=PETSC_FALSE;
2961e7931f94SStefano Zampini   PetscSubcomm    subcomm;
2962a57a6d2fSStefano Zampini 
2963e7931f94SStefano Zampini   PetscFunctionBegin;
29642b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_square",&use_square,NULL);CHKERRQ(ierr);
29652b510759SStefano Zampini   ierr = PetscOptionsGetBool(NULL,"-matis_partitioning_use_vwgt",&use_vwgt,NULL);CHKERRQ(ierr);
29662b510759SStefano Zampini   ierr = PetscOptionsGetInt(NULL,"-matis_partitioning_threshold",&threshold,NULL);CHKERRQ(ierr);
2967e7931f94SStefano Zampini 
2968e7931f94SStefano Zampini   /* Get info on mapping */
2969e7931f94SStefano Zampini   matis = (Mat_IS*)(mat->data);
2970e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&local_size);CHKERRQ(ierr);
2971e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingGetInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
2972e7931f94SStefano Zampini 
2973e7931f94SStefano Zampini   /* build local CSR graph of subdomains' connectivity */
2974785e854fSJed Brown   ierr = PetscMalloc1(2,&xadj);CHKERRQ(ierr);
2975e7931f94SStefano Zampini   xadj[0] = 0;
2976e7931f94SStefano Zampini   xadj[1] = PetscMax(n_neighs-1,0);
2977785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy);CHKERRQ(ierr);
2978785e854fSJed Brown   ierr = PetscMalloc1(xadj[1],&adjncy_wgt);CHKERRQ(ierr);
2979e7931f94SStefano Zampini 
29802b510759SStefano Zampini   if (threshold) {
2981d023bfaeSStefano Zampini     PetscInt xadj_count = 0;
29822b510759SStefano Zampini     for (i=1;i<n_neighs;i++) {
2983d023bfaeSStefano Zampini       if (n_shared[i] > threshold) {
2984d023bfaeSStefano Zampini         adjncy[xadj_count] = neighs[i];
2985d023bfaeSStefano Zampini         adjncy_wgt[xadj_count] = n_shared[i];
2986d023bfaeSStefano Zampini         xadj_count++;
2987e7931f94SStefano Zampini       }
2988e7931f94SStefano Zampini     }
2989d023bfaeSStefano Zampini     xadj[1] = xadj_count;
2990c8587f34SStefano Zampini   } else {
2991e7931f94SStefano Zampini     if (xadj[1]) {
2992e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy,&neighs[1],xadj[1]*sizeof(*adjncy));CHKERRQ(ierr);
2993e7931f94SStefano Zampini       ierr = PetscMemcpy(adjncy_wgt,&n_shared[1],xadj[1]*sizeof(*adjncy_wgt));CHKERRQ(ierr);
2994c8587f34SStefano Zampini     }
2995e7931f94SStefano Zampini   }
2996e7931f94SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreInfo(matis->mapping,&n_neighs,&neighs,&n_shared,&shared);CHKERRQ(ierr);
2997e7931f94SStefano Zampini   if (use_square) {
2998e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
2999e7931f94SStefano Zampini       adjncy_wgt[i] = adjncy_wgt[i]*adjncy_wgt[i];
3000e7931f94SStefano Zampini     }
3001e7931f94SStefano Zampini   }
3002e7931f94SStefano Zampini   ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3003e7931f94SStefano Zampini 
30043837a79fSStefano Zampini   ierr = PetscMalloc1(1,&ranks_send_to_idx);CHKERRQ(ierr);
3005e7931f94SStefano Zampini 
3006e7931f94SStefano Zampini   /*
3007e7931f94SStefano Zampini     Restrict work on active processes only.
3008e7931f94SStefano Zampini   */
3009e7931f94SStefano Zampini   ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)mat),&subcomm);CHKERRQ(ierr);
3010e7931f94SStefano Zampini   ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr); /* 2 groups, active process and not active processes */
3011e7931f94SStefano Zampini   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr);
30122b510759SStefano Zampini   ierr = PetscMPIIntCast(!local_size,&color);CHKERRQ(ierr);
3013d3531aaaSJed Brown   ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
3014e7931f94SStefano Zampini   if (color) {
3015e7931f94SStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
3016e7931f94SStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
3017e7931f94SStefano Zampini     ierr = PetscFree(adjncy_wgt);CHKERRQ(ierr);
3018c8587f34SStefano Zampini   } else {
301928143c3dSStefano Zampini     PetscInt coarsening_ratio;
3020e7931f94SStefano Zampini     ierr = MPI_Comm_size(subcomm->comm,&size);CHKERRQ(ierr);
3021785e854fSJed Brown     ierr = PetscMalloc1(size,&oldranks);CHKERRQ(ierr);
3022e7931f94SStefano Zampini     prank = rank;
3023e7931f94SStefano Zampini     ierr = MPI_Allgather(&prank,1,MPIU_INT,oldranks,1,MPIU_INT,subcomm->comm);CHKERRQ(ierr);
30248002ef2cSStefano Zampini     /*
3025e7931f94SStefano Zampini     for (i=0;i<size;i++) {
3026e7931f94SStefano Zampini       PetscPrintf(subcomm->comm,"oldranks[%d] = %d\n",i,oldranks[i]);
3027c8587f34SStefano Zampini     }
30288002ef2cSStefano Zampini     */
3029e7931f94SStefano Zampini     for (i=0;i<xadj[1];i++) {
3030e7931f94SStefano Zampini       ierr = PetscFindInt(adjncy[i],size,oldranks,&adjncy[i]);CHKERRQ(ierr);
3031c8587f34SStefano Zampini     }
3032e7931f94SStefano Zampini     ierr = PetscSortIntWithArray(xadj[1],adjncy,adjncy_wgt);CHKERRQ(ierr);
3033e7931f94SStefano Zampini     ierr = MatCreateMPIAdj(subcomm->comm,1,(PetscInt)size,xadj,adjncy,adjncy_wgt,&subdomain_adj);CHKERRQ(ierr);
303422b6e8a2SStefano Zampini     /* ierr = MatView(subdomain_adj,0);CHKERRQ(ierr); */
3035e7931f94SStefano Zampini 
3036e7931f94SStefano Zampini     /* Partition */
3037e7931f94SStefano Zampini     ierr = MatPartitioningCreate(subcomm->comm,&partitioner);CHKERRQ(ierr);
3038e7931f94SStefano Zampini     ierr = MatPartitioningSetAdjacency(partitioner,subdomain_adj);CHKERRQ(ierr);
3039e7931f94SStefano Zampini     if (use_vwgt) {
30403837a79fSStefano Zampini       ierr = PetscMalloc1(1,&v_wgt);CHKERRQ(ierr);
3041e7931f94SStefano Zampini       v_wgt[0] = local_size;
3042e7931f94SStefano Zampini       ierr = MatPartitioningSetVertexWeights(partitioner,v_wgt);CHKERRQ(ierr);
3043c8587f34SStefano Zampini     }
304428143c3dSStefano Zampini     n_subdomains = PetscMin((PetscInt)size,n_subdomains);
304528143c3dSStefano Zampini     coarsening_ratio = size/n_subdomains;
304628143c3dSStefano Zampini     ierr = MatPartitioningSetNParts(partitioner,n_subdomains);CHKERRQ(ierr);
3047e7931f94SStefano Zampini     ierr = MatPartitioningSetFromOptions(partitioner);CHKERRQ(ierr);
3048e7931f94SStefano Zampini     ierr = MatPartitioningApply(partitioner,&new_ranks);CHKERRQ(ierr);
304922b6e8a2SStefano Zampini     /* ierr = MatPartitioningView(partitioner,0);CHKERRQ(ierr); */
3050e7931f94SStefano Zampini 
3051e7931f94SStefano Zampini     ierr = ISGetIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
305228143c3dSStefano Zampini     if (contiguous) {
305328143c3dSStefano Zampini       ranks_send_to_idx[0] = oldranks[is_indices[0]]; /* contiguos set of processes */
305428143c3dSStefano Zampini     } else {
305584ba6060SStefano Zampini       ranks_send_to_idx[0] = coarsening_ratio*oldranks[is_indices[0]]; /* scattered set of processes */
305628143c3dSStefano Zampini     }
3057e7931f94SStefano Zampini     ierr = ISRestoreIndices(new_ranks,(const PetscInt**)&is_indices);CHKERRQ(ierr);
3058e7931f94SStefano Zampini     /* clean up */
3059e7931f94SStefano Zampini     ierr = PetscFree(oldranks);CHKERRQ(ierr);
3060e7931f94SStefano Zampini     ierr = ISDestroy(&new_ranks);CHKERRQ(ierr);
3061e7931f94SStefano Zampini     ierr = MatDestroy(&subdomain_adj);CHKERRQ(ierr);
3062e7931f94SStefano Zampini     ierr = MatPartitioningDestroy(&partitioner);CHKERRQ(ierr);
3063e7931f94SStefano Zampini   }
3064e7931f94SStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
3065e7931f94SStefano Zampini 
3066e7931f94SStefano Zampini   /* assemble parallel IS for sends */
3067e7931f94SStefano Zampini   i = 1;
3068e7931f94SStefano Zampini   if (color) i=0;
3069e7931f94SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)mat),i,ranks_send_to_idx,PETSC_OWN_POINTER,&ranks_send_to);CHKERRQ(ierr);
3070e7931f94SStefano Zampini 
3071e7931f94SStefano Zampini   /* get back IS */
3072e7931f94SStefano Zampini   *is_sends = ranks_send_to;
3073e7931f94SStefano Zampini   PetscFunctionReturn(0);
3074e7931f94SStefano Zampini }
3075e7931f94SStefano Zampini 
3076e7931f94SStefano Zampini typedef enum {MATDENSE_PRIVATE=0,MATAIJ_PRIVATE,MATBAIJ_PRIVATE,MATSBAIJ_PRIVATE}MatTypePrivate;
3077e7931f94SStefano Zampini 
3078e7931f94SStefano Zampini #undef __FUNCT__
3079e7931f94SStefano Zampini #define __FUNCT__ "MatISSubassemble"
308028143c3dSStefano Zampini PetscErrorCode MatISSubassemble(Mat mat, IS is_sends, PetscInt n_subdomains, PetscBool restrict_comm, MatReuse reuse, Mat *mat_n, PetscInt nis, IS isarray[])
3081e7931f94SStefano Zampini {
308270cf5478SStefano Zampini   Mat                    local_mat;
3083e7931f94SStefano Zampini   Mat_IS                 *matis;
3084e7931f94SStefano Zampini   IS                     is_sends_internal;
30859d30be91SStefano Zampini   PetscInt               rows,cols,new_local_rows;
308628143c3dSStefano Zampini   PetscInt               i,bs,buf_size_idxs,buf_size_idxs_is,buf_size_vals;
30879d30be91SStefano Zampini   PetscBool              ismatis,isdense,newisdense,destroy_mat;
3088e7931f94SStefano Zampini   ISLocalToGlobalMapping l2gmap;
3089e7931f94SStefano Zampini   PetscInt*              l2gmap_indices;
3090e7931f94SStefano Zampini   const PetscInt*        is_indices;
3091e7931f94SStefano Zampini   MatType                new_local_type;
3092e7931f94SStefano Zampini   /* buffers */
3093e7931f94SStefano Zampini   PetscInt               *ptr_idxs,*send_buffer_idxs,*recv_buffer_idxs;
309428143c3dSStefano Zampini   PetscInt               *ptr_idxs_is,*send_buffer_idxs_is,*recv_buffer_idxs_is;
30959d30be91SStefano Zampini   PetscInt               *recv_buffer_idxs_local;
3096e7931f94SStefano Zampini   PetscScalar            *ptr_vals,*send_buffer_vals,*recv_buffer_vals;
3097e7931f94SStefano Zampini   /* MPI */
309828143c3dSStefano Zampini   MPI_Comm               comm,comm_n;
309928143c3dSStefano Zampini   PetscSubcomm           subcomm;
3100e7931f94SStefano Zampini   PetscMPIInt            n_sends,n_recvs,commsize;
310128143c3dSStefano Zampini   PetscMPIInt            *iflags,*ilengths_idxs,*ilengths_vals,*ilengths_idxs_is;
310228143c3dSStefano Zampini   PetscMPIInt            *onodes,*onodes_is,*olengths_idxs,*olengths_idxs_is,*olengths_vals;
310328143c3dSStefano Zampini   PetscMPIInt            len,tag_idxs,tag_idxs_is,tag_vals,source_dest;
310428143c3dSStefano Zampini   MPI_Request            *send_req_idxs,*send_req_idxs_is,*send_req_vals;
310528143c3dSStefano Zampini   MPI_Request            *recv_req_idxs,*recv_req_idxs_is,*recv_req_vals;
3106e7931f94SStefano Zampini   PetscErrorCode         ierr;
3107e7931f94SStefano Zampini 
3108e7931f94SStefano Zampini   PetscFunctionBegin;
310928143c3dSStefano Zampini   /* TODO: add missing checks */
311028143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,n_subdomains,3);
311128143c3dSStefano Zampini   PetscValidLogicalCollectiveBool(mat,restrict_comm,4);
311228143c3dSStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,5);
311328143c3dSStefano Zampini   PetscValidLogicalCollectiveInt(mat,nis,7);
3114e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)mat,MATIS,&ismatis);CHKERRQ(ierr);
311528143c3dSStefano Zampini   if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot use %s on a matrix object which is not of type MATIS",__FUNCT__);
3116e7931f94SStefano Zampini   ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3117e7931f94SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&isdense);CHKERRQ(ierr);
3118e7931f94SStefano Zampini   if (!isdense) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Currently cannot subassemble MATIS when local matrix type is not of type SEQDENSE");
3119e7931f94SStefano Zampini   ierr = MatGetSize(local_mat,&rows,&cols);CHKERRQ(ierr);
3120e7931f94SStefano Zampini   if (rows != cols) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Local MATIS matrices should be square");
312128143c3dSStefano Zampini   if (reuse == MAT_REUSE_MATRIX && *mat_n) {
312270cf5478SStefano Zampini     PetscInt mrows,mcols,mnrows,mncols;
312370cf5478SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*mat_n,MATIS,&ismatis);CHKERRQ(ierr);
312428143c3dSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_SUP,"Cannot reuse a matrix which is not of type MATIS");
312570cf5478SStefano Zampini     ierr = MatGetSize(mat,&mrows,&mcols);CHKERRQ(ierr);
312670cf5478SStefano Zampini     ierr = MatGetSize(*mat_n,&mnrows,&mncols);CHKERRQ(ierr);
312770cf5478SStefano Zampini     if (mrows != mnrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of rows %D != %D",mrows,mnrows);
312870cf5478SStefano Zampini     if (mcols != mncols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix! Wrong number of cols %D != %D",mcols,mncols);
312970cf5478SStefano Zampini   }
3130e7931f94SStefano Zampini   ierr = MatGetBlockSize(local_mat,&bs);CHKERRQ(ierr);
3131e7931f94SStefano Zampini   PetscValidLogicalCollectiveInt(mat,bs,0);
3132e7931f94SStefano Zampini   /* prepare IS for sending if not provided */
3133e7931f94SStefano Zampini   if (!is_sends) {
313428143c3dSStefano Zampini     PetscBool pcontig = PETSC_TRUE;
313528143c3dSStefano Zampini     if (!n_subdomains) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"You should specify either an IS or a target number of subdomains");
313628143c3dSStefano Zampini     ierr = MatISGetSubassemblingPattern(mat,n_subdomains,pcontig,&is_sends_internal);CHKERRQ(ierr);
3137c8587f34SStefano Zampini   } else {
3138e7931f94SStefano Zampini     ierr = PetscObjectReference((PetscObject)is_sends);CHKERRQ(ierr);
3139e7931f94SStefano Zampini     is_sends_internal = is_sends;
3140c8587f34SStefano Zampini   }
3141e7931f94SStefano Zampini 
3142e7931f94SStefano Zampini   /* get pointer of MATIS data */
3143e7931f94SStefano Zampini   matis = (Mat_IS*)mat->data;
3144e7931f94SStefano Zampini 
3145e7931f94SStefano Zampini   /* get comm */
3146a316fed8SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
3147e7931f94SStefano Zampini 
3148e7931f94SStefano Zampini   /* compute number of sends */
3149e7931f94SStefano Zampini   ierr = ISGetLocalSize(is_sends_internal,&i);CHKERRQ(ierr);
3150e7931f94SStefano Zampini   ierr = PetscMPIIntCast(i,&n_sends);CHKERRQ(ierr);
3151e7931f94SStefano Zampini 
3152e7931f94SStefano Zampini   /* compute number of receives */
3153e7931f94SStefano Zampini   ierr = MPI_Comm_size(comm,&commsize);CHKERRQ(ierr);
3154785e854fSJed Brown   ierr = PetscMalloc1(commsize,&iflags);CHKERRQ(ierr);
3155e7931f94SStefano Zampini   ierr = PetscMemzero(iflags,commsize*sizeof(*iflags));CHKERRQ(ierr);
3156e7931f94SStefano Zampini   ierr = ISGetIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3157e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) iflags[is_indices[i]] = 1;
3158e7931f94SStefano Zampini   ierr = PetscGatherNumberOfMessages(comm,iflags,NULL,&n_recvs);CHKERRQ(ierr);
3159e7931f94SStefano Zampini   ierr = PetscFree(iflags);CHKERRQ(ierr);
3160e7931f94SStefano Zampini 
316128143c3dSStefano Zampini   /* restrict comm if requested */
316228143c3dSStefano Zampini   subcomm = 0;
316328143c3dSStefano Zampini   destroy_mat = PETSC_FALSE;
316428143c3dSStefano Zampini   if (restrict_comm) {
316528143c3dSStefano Zampini     PetscMPIInt color,rank,subcommsize;
316628143c3dSStefano Zampini     ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
316728143c3dSStefano Zampini     color = 0;
316828143c3dSStefano Zampini     if (n_sends && !n_recvs) color = 1; /* sending only processes will not partecipate in new comm */
316928143c3dSStefano Zampini     ierr = MPI_Allreduce(&color,&subcommsize,1,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
317028143c3dSStefano Zampini     subcommsize = commsize - subcommsize;
317128143c3dSStefano Zampini     /* check if reuse has been requested */
317228143c3dSStefano Zampini     if (reuse == MAT_REUSE_MATRIX) {
317328143c3dSStefano Zampini       if (*mat_n) {
317428143c3dSStefano Zampini         PetscMPIInt subcommsize2;
317528143c3dSStefano Zampini         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)*mat_n),&subcommsize2);CHKERRQ(ierr);
317628143c3dSStefano Zampini         if (subcommsize != subcommsize2) SETERRQ2(PetscObjectComm((PetscObject)*mat_n),PETSC_ERR_PLIB,"Cannot reuse matrix! wrong subcomm size %d != %d",subcommsize,subcommsize2);
317728143c3dSStefano Zampini         comm_n = PetscObjectComm((PetscObject)*mat_n);
317828143c3dSStefano Zampini       } else {
317928143c3dSStefano Zampini         comm_n = PETSC_COMM_SELF;
318028143c3dSStefano Zampini       }
318128143c3dSStefano Zampini     } else { /* MAT_INITIAL_MATRIX */
318228143c3dSStefano Zampini       ierr = PetscSubcommCreate(comm,&subcomm);CHKERRQ(ierr);
318328143c3dSStefano Zampini       ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
318428143c3dSStefano Zampini       ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
318528143c3dSStefano Zampini       comm_n = subcomm->comm;
318628143c3dSStefano Zampini     }
318728143c3dSStefano Zampini     /* flag to destroy *mat_n if not significative */
318828143c3dSStefano Zampini     if (color) destroy_mat = PETSC_TRUE;
318928143c3dSStefano Zampini   } else {
319028143c3dSStefano Zampini     comm_n = comm;
319128143c3dSStefano Zampini   }
319228143c3dSStefano Zampini 
3193e7931f94SStefano Zampini   /* prepare send/receive buffers */
3194785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_idxs);CHKERRQ(ierr);
3195e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_idxs,commsize*sizeof(*ilengths_idxs));CHKERRQ(ierr);
3196785e854fSJed Brown   ierr = PetscMalloc1(commsize,&ilengths_vals);CHKERRQ(ierr);
3197e7931f94SStefano Zampini   ierr = PetscMemzero(ilengths_vals,commsize*sizeof(*ilengths_vals));CHKERRQ(ierr);
319828143c3dSStefano Zampini   if (nis) {
3199854ce69bSBarry Smith     ierr = PetscCalloc1(commsize,&ilengths_idxs_is);CHKERRQ(ierr);
320028143c3dSStefano Zampini   }
3201e7931f94SStefano Zampini 
320228143c3dSStefano Zampini   /* Get data from local matrices */
3203e7931f94SStefano Zampini   if (!isdense) {
3204a26c9d0eSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Subassembling of AIJ local matrices not yet implemented");
3205e7931f94SStefano Zampini     /* TODO: See below some guidelines on how to prepare the local buffers */
3206e7931f94SStefano Zampini     /*
3207e7931f94SStefano Zampini        send_buffer_vals should contain the raw values of the local matrix
3208e7931f94SStefano Zampini        send_buffer_idxs should contain:
3209e7931f94SStefano Zampini        - MatType_PRIVATE type
3210e7931f94SStefano Zampini        - PetscInt        size_of_l2gmap
3211e7931f94SStefano Zampini        - PetscInt        global_row_indices[size_of_l2gmap]
3212e7931f94SStefano Zampini        - PetscInt        all_other_info_which_is_needed_to_compute_preallocation_and_set_values
3213e7931f94SStefano Zampini     */
3214e7931f94SStefano Zampini   } else {
3215e7931f94SStefano Zampini     ierr = MatDenseGetArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3216e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(matis->mapping,&i);CHKERRQ(ierr);
3217854ce69bSBarry Smith     ierr = PetscMalloc1(i+2,&send_buffer_idxs);CHKERRQ(ierr);
3218e7931f94SStefano Zampini     send_buffer_idxs[0] = (PetscInt)MATDENSE_PRIVATE;
3219e7931f94SStefano Zampini     send_buffer_idxs[1] = i;
3220e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3221e7931f94SStefano Zampini     ierr = PetscMemcpy(&send_buffer_idxs[2],ptr_idxs,i*sizeof(PetscInt));CHKERRQ(ierr);
3222e7931f94SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(matis->mapping,(const PetscInt**)&ptr_idxs);CHKERRQ(ierr);
3223e7931f94SStefano Zampini     ierr = PetscMPIIntCast(i,&len);CHKERRQ(ierr);
3224e7931f94SStefano Zampini     for (i=0;i<n_sends;i++) {
3225e7931f94SStefano Zampini       ilengths_vals[is_indices[i]] = len*len;
3226e7931f94SStefano Zampini       ilengths_idxs[is_indices[i]] = len+2;
3227c8587f34SStefano Zampini     }
3228c8587f34SStefano Zampini   }
3229e7931f94SStefano Zampini   ierr = PetscGatherMessageLengths2(comm,n_sends,n_recvs,ilengths_idxs,ilengths_vals,&onodes,&olengths_idxs,&olengths_vals);CHKERRQ(ierr);
323028143c3dSStefano Zampini   /* additional is (if any) */
323128143c3dSStefano Zampini   if (nis) {
323228143c3dSStefano Zampini     PetscMPIInt psum;
323328143c3dSStefano Zampini     PetscInt j;
323428143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
323528143c3dSStefano Zampini       PetscInt plen;
323628143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
323728143c3dSStefano Zampini       ierr = PetscMPIIntCast(plen,&len);CHKERRQ(ierr);
323828143c3dSStefano Zampini       psum += len+1; /* indices + lenght */
323928143c3dSStefano Zampini     }
3240854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&send_buffer_idxs_is);CHKERRQ(ierr);
324128143c3dSStefano Zampini     for (j=0,psum=0;j<nis;j++) {
324228143c3dSStefano Zampini       PetscInt plen;
324328143c3dSStefano Zampini       const PetscInt *is_array_idxs;
324428143c3dSStefano Zampini       ierr = ISGetLocalSize(isarray[j],&plen);CHKERRQ(ierr);
324528143c3dSStefano Zampini       send_buffer_idxs_is[psum] = plen;
324628143c3dSStefano Zampini       ierr = ISGetIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
324728143c3dSStefano Zampini       ierr = PetscMemcpy(&send_buffer_idxs_is[psum+1],is_array_idxs,plen*sizeof(PetscInt));CHKERRQ(ierr);
324828143c3dSStefano Zampini       ierr = ISRestoreIndices(isarray[j],&is_array_idxs);CHKERRQ(ierr);
324928143c3dSStefano Zampini       psum += plen+1; /* indices + lenght */
325028143c3dSStefano Zampini     }
325128143c3dSStefano Zampini     for (i=0;i<n_sends;i++) {
325228143c3dSStefano Zampini       ilengths_idxs_is[is_indices[i]] = psum;
325328143c3dSStefano Zampini     }
325428143c3dSStefano Zampini     ierr = PetscGatherMessageLengths(comm,n_sends,n_recvs,ilengths_idxs_is,&onodes_is,&olengths_idxs_is);CHKERRQ(ierr);
325528143c3dSStefano Zampini   }
325628143c3dSStefano Zampini 
3257e7931f94SStefano Zampini   buf_size_idxs = 0;
3258e7931f94SStefano Zampini   buf_size_vals = 0;
325928143c3dSStefano Zampini   buf_size_idxs_is = 0;
3260e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3261e7931f94SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
3262e7931f94SStefano Zampini     buf_size_vals += (PetscInt)olengths_vals[i];
326328143c3dSStefano Zampini     if (nis) buf_size_idxs_is += (PetscInt)olengths_idxs_is[i];
3264e7931f94SStefano Zampini   }
3265785e854fSJed Brown   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs);CHKERRQ(ierr);
3266785e854fSJed Brown   ierr = PetscMalloc1(buf_size_vals,&recv_buffer_vals);CHKERRQ(ierr);
326795ecbf38SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs_is,&recv_buffer_idxs_is);CHKERRQ(ierr);
3268e7931f94SStefano Zampini 
3269e7931f94SStefano Zampini   /* get new tags for clean communications */
3270e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs);CHKERRQ(ierr);
3271e7931f94SStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_vals);CHKERRQ(ierr);
327228143c3dSStefano Zampini   ierr = PetscObjectGetNewTag((PetscObject)mat,&tag_idxs_is);CHKERRQ(ierr);
3273e7931f94SStefano Zampini 
3274e7931f94SStefano Zampini   /* allocate for requests */
3275785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_idxs);CHKERRQ(ierr);
3276785e854fSJed Brown   ierr = PetscMalloc1(n_sends,&send_req_vals);CHKERRQ(ierr);
327795ecbf38SStefano Zampini   ierr = PetscMalloc1(n_sends,&send_req_idxs_is);CHKERRQ(ierr);
3278785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_idxs);CHKERRQ(ierr);
3279785e854fSJed Brown   ierr = PetscMalloc1(n_recvs,&recv_req_vals);CHKERRQ(ierr);
328095ecbf38SStefano Zampini   ierr = PetscMalloc1(n_recvs,&recv_req_idxs_is);CHKERRQ(ierr);
3281e7931f94SStefano Zampini 
3282e7931f94SStefano Zampini   /* communications */
3283e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
3284e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
328528143c3dSStefano Zampini   ptr_idxs_is = recv_buffer_idxs_is;
3286e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3287e7931f94SStefano Zampini     source_dest = onodes[i];
3288e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_idxs,olengths_idxs[i],MPIU_INT,source_dest,tag_idxs,comm,&recv_req_idxs[i]);CHKERRQ(ierr);
3289e7931f94SStefano Zampini     ierr = MPI_Irecv(ptr_vals,olengths_vals[i],MPIU_SCALAR,source_dest,tag_vals,comm,&recv_req_vals[i]);CHKERRQ(ierr);
3290e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3291e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
329228143c3dSStefano Zampini     if (nis) {
329328143c3dSStefano 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);
329428143c3dSStefano Zampini       ptr_idxs_is += olengths_idxs_is[i];
329528143c3dSStefano Zampini     }
3296e7931f94SStefano Zampini   }
3297e7931f94SStefano Zampini   for (i=0;i<n_sends;i++) {
3298e7931f94SStefano Zampini     ierr = PetscMPIIntCast(is_indices[i],&source_dest);CHKERRQ(ierr);
3299e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_idxs,ilengths_idxs[source_dest],MPIU_INT,source_dest,tag_idxs,comm,&send_req_idxs[i]);CHKERRQ(ierr);
3300e7931f94SStefano Zampini     ierr = MPI_Isend(send_buffer_vals,ilengths_vals[source_dest],MPIU_SCALAR,source_dest,tag_vals,comm,&send_req_vals[i]);CHKERRQ(ierr);
330128143c3dSStefano Zampini     if (nis) {
330228143c3dSStefano 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);
330328143c3dSStefano Zampini     }
3304e7931f94SStefano Zampini   }
3305e7931f94SStefano Zampini   ierr = ISRestoreIndices(is_sends_internal,&is_indices);CHKERRQ(ierr);
3306e7931f94SStefano Zampini   ierr = ISDestroy(&is_sends_internal);CHKERRQ(ierr);
3307e7931f94SStefano Zampini 
3308e7931f94SStefano Zampini   /* assemble new l2g map */
3309e7931f94SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3310e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
33119d30be91SStefano Zampini   new_local_rows = 0;
3312e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
33139d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3314e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3315e7931f94SStefano Zampini   }
33169d30be91SStefano Zampini   ierr = PetscMalloc1(new_local_rows,&l2gmap_indices);CHKERRQ(ierr);
3317e7931f94SStefano Zampini   ptr_idxs = recv_buffer_idxs;
33189d30be91SStefano Zampini   new_local_rows = 0;
3319e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
33209d30be91SStefano Zampini     ierr = PetscMemcpy(&l2gmap_indices[new_local_rows],ptr_idxs+2,(*(ptr_idxs+1))*sizeof(PetscInt));CHKERRQ(ierr);
33219d30be91SStefano Zampini     new_local_rows += *(ptr_idxs+1); /* second element is the local size of the l2gmap */
3322e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3323e7931f94SStefano Zampini   }
33249d30be91SStefano Zampini   ierr = PetscSortRemoveDupsInt(&new_local_rows,l2gmap_indices);CHKERRQ(ierr);
33259d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingCreate(comm_n,1,new_local_rows,l2gmap_indices,PETSC_COPY_VALUES,&l2gmap);CHKERRQ(ierr);
3326e7931f94SStefano Zampini   ierr = PetscFree(l2gmap_indices);CHKERRQ(ierr);
3327e7931f94SStefano Zampini 
3328e7931f94SStefano Zampini   /* infer new local matrix type from received local matrices type */
3329e7931f94SStefano Zampini   /* currently if all local matrices are of type X, then the resulting matrix will be of type X, except for the dense case */
3330e7931f94SStefano 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) */
3331e7931f94SStefano Zampini   if (n_recvs) {
333228143c3dSStefano Zampini     MatTypePrivate new_local_type_private = (MatTypePrivate)send_buffer_idxs[0];
3333e7931f94SStefano Zampini     ptr_idxs = recv_buffer_idxs;
3334e7931f94SStefano Zampini     for (i=0;i<n_recvs;i++) {
3335e7931f94SStefano Zampini       if ((PetscInt)new_local_type_private != *ptr_idxs) {
3336e7931f94SStefano Zampini         new_local_type_private = MATAIJ_PRIVATE;
3337e7931f94SStefano Zampini         break;
3338e7931f94SStefano Zampini       }
3339e7931f94SStefano Zampini       ptr_idxs += olengths_idxs[i];
3340e7931f94SStefano Zampini     }
3341e7931f94SStefano Zampini     switch (new_local_type_private) {
334228143c3dSStefano Zampini       case MATDENSE_PRIVATE:
334328143c3dSStefano Zampini         if (n_recvs>1) { /* subassembling of dense matrices does not give a dense matrix! */
3344e7931f94SStefano Zampini           new_local_type = MATSEQAIJ;
3345e7931f94SStefano Zampini           bs = 1;
334628143c3dSStefano Zampini         } else { /* if I receive only 1 dense matrix */
334728143c3dSStefano Zampini           new_local_type = MATSEQDENSE;
334828143c3dSStefano Zampini           bs = 1;
334928143c3dSStefano Zampini         }
3350e7931f94SStefano Zampini         break;
3351e7931f94SStefano Zampini       case MATAIJ_PRIVATE:
3352e7931f94SStefano Zampini         new_local_type = MATSEQAIJ;
3353e7931f94SStefano Zampini         bs = 1;
3354e7931f94SStefano Zampini         break;
3355e7931f94SStefano Zampini       case MATBAIJ_PRIVATE:
3356e7931f94SStefano Zampini         new_local_type = MATSEQBAIJ;
3357e7931f94SStefano Zampini         break;
3358e7931f94SStefano Zampini       case MATSBAIJ_PRIVATE:
3359e7931f94SStefano Zampini         new_local_type = MATSEQSBAIJ;
3360e7931f94SStefano Zampini         break;
3361e7931f94SStefano Zampini       default:
33629d30be91SStefano Zampini         SETERRQ2(comm,PETSC_ERR_SUP,"Unsupported private type %d in %s",new_local_type_private,__FUNCT__);
3363e7931f94SStefano Zampini         break;
3364e7931f94SStefano Zampini     }
336528143c3dSStefano Zampini   } else { /* by default, new_local_type is seqdense */
336628143c3dSStefano Zampini     new_local_type = MATSEQDENSE;
336728143c3dSStefano Zampini     bs = 1;
3368e7931f94SStefano Zampini   }
3369e7931f94SStefano Zampini 
337070cf5478SStefano Zampini   /* create MATIS object if needed */
337170cf5478SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
3372e7931f94SStefano Zampini     ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
337328143c3dSStefano Zampini     ierr = MatCreateIS(comm_n,bs,PETSC_DECIDE,PETSC_DECIDE,rows,cols,l2gmap,mat_n);CHKERRQ(ierr);
337470cf5478SStefano Zampini   } else {
337570cf5478SStefano Zampini     /* it also destroys the local matrices */
337670cf5478SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*mat_n,l2gmap,l2gmap);CHKERRQ(ierr);
337770cf5478SStefano Zampini   }
337870cf5478SStefano Zampini   ierr = MatISGetLocalMat(*mat_n,&local_mat);CHKERRQ(ierr);
3379e7931f94SStefano Zampini   ierr = MatSetType(local_mat,new_local_type);CHKERRQ(ierr);
33809d30be91SStefano Zampini 
33819d30be91SStefano Zampini   ierr = MPI_Waitall(n_recvs,recv_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
33829d30be91SStefano Zampini 
33839d30be91SStefano Zampini   /* Global to local map of received indices */
33849d30be91SStefano Zampini   ierr = PetscMalloc1(buf_size_idxs,&recv_buffer_idxs_local);CHKERRQ(ierr); /* needed for values insertion */
33859d30be91SStefano Zampini   ierr = ISGlobalToLocalMappingApply(l2gmap,IS_GTOLM_MASK,buf_size_idxs,recv_buffer_idxs,&i,recv_buffer_idxs_local);CHKERRQ(ierr);
33869d30be91SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&l2gmap);CHKERRQ(ierr);
33879d30be91SStefano Zampini 
33889d30be91SStefano Zampini   /* restore attributes -> type of incoming data and its size */
33899d30be91SStefano Zampini   buf_size_idxs = 0;
33909d30be91SStefano Zampini   for (i=0;i<n_recvs;i++) {
33919d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs] = recv_buffer_idxs[buf_size_idxs];
33929d30be91SStefano Zampini     recv_buffer_idxs_local[buf_size_idxs+1] = recv_buffer_idxs[buf_size_idxs+1];
33939d30be91SStefano Zampini     buf_size_idxs += (PetscInt)olengths_idxs[i];
33949d30be91SStefano Zampini   }
33959d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs);CHKERRQ(ierr);
33969d30be91SStefano Zampini 
33979d30be91SStefano Zampini   /* set preallocation */
33989d30be91SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)local_mat,MATSEQDENSE,&newisdense);CHKERRQ(ierr);
33999d30be91SStefano Zampini   if (!newisdense) {
34009d30be91SStefano Zampini     PetscInt *new_local_nnz=0;
34019d30be91SStefano Zampini 
34029d30be91SStefano Zampini     ptr_vals = recv_buffer_vals;
34039d30be91SStefano Zampini     ptr_idxs = recv_buffer_idxs_local;
34049d30be91SStefano Zampini     if (n_recvs) {
34059d30be91SStefano Zampini       ierr = PetscCalloc1(new_local_rows,&new_local_nnz);CHKERRQ(ierr);
34069d30be91SStefano Zampini     }
34079d30be91SStefano Zampini     for (i=0;i<n_recvs;i++) {
34089d30be91SStefano Zampini       PetscInt j;
34099d30be91SStefano Zampini       if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* preallocation provided for dense case only */
34109d30be91SStefano Zampini         for (j=0;j<*(ptr_idxs+1);j++) {
34119d30be91SStefano Zampini           new_local_nnz[*(ptr_idxs+2+j)] += *(ptr_idxs+1);
34129d30be91SStefano Zampini         }
34139d30be91SStefano Zampini       } else {
34149d30be91SStefano Zampini         /* TODO */
34159d30be91SStefano Zampini       }
34169d30be91SStefano Zampini       ptr_idxs += olengths_idxs[i];
34179d30be91SStefano Zampini     }
34189d30be91SStefano Zampini     if (new_local_nnz) {
34199d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMin(new_local_nnz[i],new_local_rows);
34209d30be91SStefano Zampini       ierr = MatSeqAIJSetPreallocation(local_mat,0,new_local_nnz);CHKERRQ(ierr);
34219d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] /= bs;
34229d30be91SStefano Zampini       ierr = MatSeqBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
34239d30be91SStefano Zampini       for (i=0;i<new_local_rows;i++) new_local_nnz[i] = PetscMax(new_local_nnz[i]-i,0);
34249d30be91SStefano Zampini       ierr = MatSeqSBAIJSetPreallocation(local_mat,bs,0,new_local_nnz);CHKERRQ(ierr);
34259d30be91SStefano Zampini     } else {
34269d30be91SStefano Zampini       ierr = MatSetUp(local_mat);CHKERRQ(ierr);
34279d30be91SStefano Zampini     }
34289d30be91SStefano Zampini     ierr = PetscFree(new_local_nnz);CHKERRQ(ierr);
34299d30be91SStefano Zampini   } else {
34309d30be91SStefano Zampini     ierr = MatSetUp(local_mat);CHKERRQ(ierr);
34319d30be91SStefano Zampini   }
3432e7931f94SStefano Zampini 
3433e7931f94SStefano Zampini   /* set values */
3434e7931f94SStefano Zampini   ptr_vals = recv_buffer_vals;
34359d30be91SStefano Zampini   ptr_idxs = recv_buffer_idxs_local;
3436e7931f94SStefano Zampini   for (i=0;i<n_recvs;i++) {
3437e7931f94SStefano Zampini     if (*ptr_idxs == (PetscInt)MATDENSE_PRIVATE) { /* values insertion provided for dense case only */
3438e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
34399d30be91SStefano Zampini       ierr = MatSetValues(local_mat,*(ptr_idxs+1),ptr_idxs+2,*(ptr_idxs+1),ptr_idxs+2,ptr_vals,ADD_VALUES);CHKERRQ(ierr);
3440e7931f94SStefano Zampini       ierr = MatAssemblyBegin(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3441e7931f94SStefano Zampini       ierr = MatAssemblyEnd(local_mat,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
3442e7931f94SStefano Zampini       ierr = MatSetOption(local_mat,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
344328143c3dSStefano Zampini     } else {
344428143c3dSStefano Zampini       /* TODO */
3445e7931f94SStefano Zampini     }
3446e7931f94SStefano Zampini     ptr_idxs += olengths_idxs[i];
3447e7931f94SStefano Zampini     ptr_vals += olengths_vals[i];
3448e7931f94SStefano Zampini   }
3449e7931f94SStefano Zampini   ierr = MatAssemblyBegin(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3450e7931f94SStefano Zampini   ierr = MatAssemblyEnd(local_mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
345170cf5478SStefano Zampini   ierr = MatAssemblyBegin(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
345270cf5478SStefano Zampini   ierr = MatAssemblyEnd(*mat_n,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
34539d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_vals);CHKERRQ(ierr);
34549d30be91SStefano Zampini   ierr = PetscFree(recv_buffer_idxs_local);CHKERRQ(ierr);
3455e7931f94SStefano Zampini 
3456dfd14d43SStefano Zampini #if 0
345728143c3dSStefano Zampini   if (!restrict_comm) { /* check */
3458e7931f94SStefano Zampini     Vec       lvec,rvec;
3459e7931f94SStefano Zampini     PetscReal infty_error;
3460e7931f94SStefano Zampini 
34612a7a6963SBarry Smith     ierr = MatCreateVecs(mat,&rvec,&lvec);CHKERRQ(ierr);
3462e7931f94SStefano Zampini     ierr = VecSetRandom(rvec,NULL);CHKERRQ(ierr);
3463e7931f94SStefano Zampini     ierr = MatMult(mat,rvec,lvec);CHKERRQ(ierr);
3464e7931f94SStefano Zampini     ierr = VecScale(lvec,-1.0);CHKERRQ(ierr);
346570cf5478SStefano Zampini     ierr = MatMultAdd(*mat_n,rvec,lvec,lvec);CHKERRQ(ierr);
3466e7931f94SStefano Zampini     ierr = VecNorm(lvec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
3467e7931f94SStefano Zampini     ierr = PetscPrintf(PetscObjectComm((PetscObject)mat),"Infinity error subassembling %1.6e\n",infty_error);
3468e7931f94SStefano Zampini     ierr = VecDestroy(&rvec);CHKERRQ(ierr);
3469e7931f94SStefano Zampini     ierr = VecDestroy(&lvec);CHKERRQ(ierr);
3470e7931f94SStefano Zampini   }
347128143c3dSStefano Zampini #endif
3472e7931f94SStefano Zampini 
347328143c3dSStefano Zampini   /* assemble new additional is (if any) */
347428143c3dSStefano Zampini   if (nis) {
347528143c3dSStefano Zampini     PetscInt **temp_idxs,*count_is,j,psum;
347628143c3dSStefano Zampini 
347728143c3dSStefano Zampini     ierr = MPI_Waitall(n_recvs,recv_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3478854ce69bSBarry Smith     ierr = PetscCalloc1(nis,&count_is);CHKERRQ(ierr);
347928143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
348028143c3dSStefano Zampini     psum = 0;
348128143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
348228143c3dSStefano Zampini       for (j=0;j<nis;j++) {
348328143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
348428143c3dSStefano Zampini         count_is[j] += plen; /* increment counting of buffer for j-th IS */
348528143c3dSStefano Zampini         psum += plen;
348628143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
348728143c3dSStefano Zampini       }
348828143c3dSStefano Zampini     }
3489854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&temp_idxs);CHKERRQ(ierr);
3490854ce69bSBarry Smith     ierr = PetscMalloc1(psum,&temp_idxs[0]);CHKERRQ(ierr);
349128143c3dSStefano Zampini     for (i=1;i<nis;i++) {
349228143c3dSStefano Zampini       temp_idxs[i] = temp_idxs[i-1]+count_is[i-1];
349328143c3dSStefano Zampini     }
349428143c3dSStefano Zampini     ierr = PetscMemzero(count_is,nis*sizeof(PetscInt));CHKERRQ(ierr);
349528143c3dSStefano Zampini     ptr_idxs = recv_buffer_idxs_is;
349628143c3dSStefano Zampini     for (i=0;i<n_recvs;i++) {
349728143c3dSStefano Zampini       for (j=0;j<nis;j++) {
349828143c3dSStefano Zampini         PetscInt plen = *(ptr_idxs); /* first element is the local size of IS's indices */
349928143c3dSStefano Zampini         ierr = PetscMemcpy(&temp_idxs[j][count_is[j]],ptr_idxs+1,plen*sizeof(PetscInt));CHKERRQ(ierr);
350028143c3dSStefano Zampini         count_is[j] += plen; /* increment starting point of buffer for j-th IS */
350128143c3dSStefano Zampini         ptr_idxs += plen+1; /* shift pointer to received data */
350228143c3dSStefano Zampini       }
350328143c3dSStefano Zampini     }
350428143c3dSStefano Zampini     for (i=0;i<nis;i++) {
350528143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
350628143c3dSStefano Zampini       ierr = PetscSortRemoveDupsInt(&count_is[i],temp_idxs[i]);CHKERRQ(ierr);CHKERRQ(ierr);
350728143c3dSStefano Zampini       ierr = ISCreateGeneral(comm_n,count_is[i],temp_idxs[i],PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
350828143c3dSStefano Zampini     }
350928143c3dSStefano Zampini     ierr = PetscFree(count_is);CHKERRQ(ierr);
351028143c3dSStefano Zampini     ierr = PetscFree(temp_idxs[0]);CHKERRQ(ierr);
351128143c3dSStefano Zampini     ierr = PetscFree(temp_idxs);CHKERRQ(ierr);
351228143c3dSStefano Zampini   }
3513e7931f94SStefano Zampini   /* free workspace */
351428143c3dSStefano Zampini   ierr = PetscFree(recv_buffer_idxs_is);CHKERRQ(ierr);
3515e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_idxs,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3516e7931f94SStefano Zampini   ierr = PetscFree(send_buffer_idxs);CHKERRQ(ierr);
3517e7931f94SStefano Zampini   ierr = MPI_Waitall(n_sends,send_req_vals,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
3518e7931f94SStefano Zampini   if (isdense) {
3519e7931f94SStefano Zampini     ierr = MatISGetLocalMat(mat,&local_mat);CHKERRQ(ierr);
3520e7931f94SStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&send_buffer_vals);CHKERRQ(ierr);
3521e7931f94SStefano Zampini   } else {
3522e7931f94SStefano Zampini     /* ierr = PetscFree(send_buffer_vals);CHKERRQ(ierr); */
3523e7931f94SStefano Zampini   }
352428143c3dSStefano Zampini   if (nis) {
352528143c3dSStefano Zampini     ierr = MPI_Waitall(n_sends,send_req_idxs_is,MPI_STATUSES_IGNORE);CHKERRQ(ierr);
352628143c3dSStefano Zampini     ierr = PetscFree(send_buffer_idxs_is);CHKERRQ(ierr);
352728143c3dSStefano Zampini   }
3528e7931f94SStefano Zampini   ierr = PetscFree(recv_req_idxs);CHKERRQ(ierr);
3529e7931f94SStefano Zampini   ierr = PetscFree(recv_req_vals);CHKERRQ(ierr);
353028143c3dSStefano Zampini   ierr = PetscFree(recv_req_idxs_is);CHKERRQ(ierr);
3531e7931f94SStefano Zampini   ierr = PetscFree(send_req_idxs);CHKERRQ(ierr);
3532e7931f94SStefano Zampini   ierr = PetscFree(send_req_vals);CHKERRQ(ierr);
353328143c3dSStefano Zampini   ierr = PetscFree(send_req_idxs_is);CHKERRQ(ierr);
3534e7931f94SStefano Zampini   ierr = PetscFree(ilengths_vals);CHKERRQ(ierr);
3535e7931f94SStefano Zampini   ierr = PetscFree(ilengths_idxs);CHKERRQ(ierr);
3536e7931f94SStefano Zampini   ierr = PetscFree(olengths_vals);CHKERRQ(ierr);
3537e7931f94SStefano Zampini   ierr = PetscFree(olengths_idxs);CHKERRQ(ierr);
3538e7931f94SStefano Zampini   ierr = PetscFree(onodes);CHKERRQ(ierr);
353928143c3dSStefano Zampini   if (nis) {
354028143c3dSStefano Zampini     ierr = PetscFree(ilengths_idxs_is);CHKERRQ(ierr);
354128143c3dSStefano Zampini     ierr = PetscFree(olengths_idxs_is);CHKERRQ(ierr);
354228143c3dSStefano Zampini     ierr = PetscFree(onodes_is);CHKERRQ(ierr);
354328143c3dSStefano Zampini   }
354428143c3dSStefano Zampini   ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
354528143c3dSStefano Zampini   if (destroy_mat) { /* destroy mat is true only if restrict comm is true and process will not partecipate */
354628143c3dSStefano Zampini     ierr = MatDestroy(mat_n);CHKERRQ(ierr);
354728143c3dSStefano Zampini     for (i=0;i<nis;i++) {
354828143c3dSStefano Zampini       ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
354928143c3dSStefano Zampini     }
355028143c3dSStefano Zampini   }
3551e7931f94SStefano Zampini   PetscFunctionReturn(0);
3552e7931f94SStefano Zampini }
3553a57a6d2fSStefano Zampini 
355412edc857SStefano Zampini /* temporary hack into ksp private data structure */
355512edc857SStefano Zampini #include <petsc-private/kspimpl.h>
355612edc857SStefano Zampini 
3557c8587f34SStefano Zampini #undef __FUNCT__
3558c8587f34SStefano Zampini #define __FUNCT__ "PCBDDCSetUpCoarseSolver"
3559c8587f34SStefano Zampini PetscErrorCode PCBDDCSetUpCoarseSolver(PC pc,PetscScalar* coarse_submat_vals)
3560c8587f34SStefano Zampini {
3561c8587f34SStefano Zampini   PC_BDDC                *pcbddc = (PC_BDDC*)pc->data;
3562c8587f34SStefano Zampini   PC_IS                  *pcis = (PC_IS*)pc->data;
356320a2ab83SStefano Zampini   Mat                    coarse_mat,coarse_mat_is,coarse_submat_dense;
35649881197aSStefano Zampini   MatNullSpace           CoarseNullSpace=NULL;
356520a2ab83SStefano Zampini   ISLocalToGlobalMapping coarse_islg;
35666e683305SStefano Zampini   IS                     coarse_is,*isarray;
35676e683305SStefano Zampini   PetscInt               i,im_active=-1,active_procs=-1;
35686e683305SStefano Zampini   PetscInt               nis,nisdofs,nisneu;
3569f9eb5b7dSStefano Zampini   PC                     pc_temp;
3570c8587f34SStefano Zampini   PCType                 coarse_pc_type;
3571c8587f34SStefano Zampini   KSPType                coarse_ksp_type;
3572f9eb5b7dSStefano Zampini   PetscBool              multilevel_requested,multilevel_allowed;
35734f3a063dSStefano Zampini   PetscBool              isredundant,isbddc,isnn,coarse_reuse;
35746e683305SStefano Zampini   Mat                    t_coarse_mat_is;
35756e683305SStefano Zampini   PetscInt               void_procs,ncoarse_ml,ncoarse_ds,ncoarse;
35766e683305SStefano Zampini   PetscMPIInt            all_procs;
357774e2c79eSStefano Zampini   PetscBool              csin_ml,csin_ds,csin,csin_type_simple,redist;
357868457ee5SStefano Zampini   PetscBool              compute_vecs = PETSC_FALSE;
357922bc73bbSStefano Zampini   PetscScalar            *array;
35809881197aSStefano Zampini   PetscErrorCode         ierr;
3581fdc09c96SStefano Zampini 
3582c8587f34SStefano Zampini   PetscFunctionBegin;
3583c8587f34SStefano Zampini   /* Assign global numbering to coarse dofs */
358468457ee5SStefano 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 */
358568457ee5SStefano Zampini     compute_vecs = PETSC_TRUE;
3586fa7f1dd8SStefano Zampini     PetscInt ocoarse_size;
3587fa7f1dd8SStefano Zampini     ocoarse_size = pcbddc->coarse_size;
3588f4ddd8eeSStefano Zampini     ierr = PetscFree(pcbddc->global_primal_indices);CHKERRQ(ierr);
3589f4ddd8eeSStefano Zampini     ierr = PCBDDCComputePrimalNumbering(pc,&pcbddc->coarse_size,&pcbddc->global_primal_indices);CHKERRQ(ierr);
3590f4ddd8eeSStefano Zampini     /* see if we can avoid some work */
3591fa7f1dd8SStefano Zampini     if (pcbddc->coarse_ksp) { /* coarse ksp has already been created */
3592fa7f1dd8SStefano Zampini       if (ocoarse_size != pcbddc->coarse_size) { /* ...but with different size, so reset it and set reuse flag to false */
3593727cdba6SStefano Zampini         ierr = KSPReset(pcbddc->coarse_ksp);CHKERRQ(ierr);
3594fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_FALSE;
3595fa7f1dd8SStefano Zampini       } else { /* we can safely reuse already computed coarse matrix */
3596fa7f1dd8SStefano Zampini         coarse_reuse = PETSC_TRUE;
3597f4ddd8eeSStefano Zampini       }
3598fa7f1dd8SStefano Zampini     } else { /* there's no coarse ksp, so we need to create the coarse matrix too */
3599fa7f1dd8SStefano Zampini       coarse_reuse = PETSC_FALSE;
3600f4ddd8eeSStefano Zampini     }
360170cf5478SStefano Zampini     /* reset any subassembling information */
360270cf5478SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling);CHKERRQ(ierr);
36036e683305SStefano Zampini     ierr = ISDestroy(&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
36046e683305SStefano Zampini   } else { /* primal space is unchanged, so we can reuse coarse matrix */
3605fa7f1dd8SStefano Zampini     coarse_reuse = PETSC_TRUE;
3606f4ddd8eeSStefano Zampini   }
3607c8587f34SStefano Zampini 
36086e683305SStefano Zampini   /* count "active" (i.e. with positive local size) and "void" processes */
36092b510759SStefano Zampini   im_active = !!(pcis->n);
36102b510759SStefano Zampini   ierr = MPI_Allreduce(&im_active,&active_procs,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
36116e683305SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)pc),&all_procs);CHKERRQ(ierr);
36126e683305SStefano Zampini   void_procs = all_procs-active_procs;
36136e683305SStefano Zampini   csin_type_simple = PETSC_TRUE;
361474e2c79eSStefano Zampini   redist = PETSC_FALSE;
361522bc73bbSStefano Zampini   if (pcbddc->current_level && void_procs) {
36166e683305SStefano Zampini     csin_ml = PETSC_TRUE;
36176e683305SStefano Zampini     ncoarse_ml = void_procs;
36186e683305SStefano Zampini     csin_ds = PETSC_TRUE;
36196e683305SStefano Zampini     ncoarse_ds = void_procs;
36206e683305SStefano Zampini   } else {
36216e683305SStefano Zampini     csin_ml = PETSC_FALSE;
36226e683305SStefano Zampini     ncoarse_ml = all_procs;
36236e683305SStefano Zampini     if (void_procs) {
36246e683305SStefano Zampini       csin_ds = PETSC_TRUE;
36256e683305SStefano Zampini       ncoarse_ds = void_procs;
36266e683305SStefano Zampini       csin_type_simple = PETSC_FALSE;
36276e683305SStefano Zampini     } else {
362874e2c79eSStefano Zampini       if (pcbddc->redistribute_coarse && pcbddc->redistribute_coarse < all_procs) {
362974e2c79eSStefano Zampini         csin_ds = PETSC_TRUE;
363074e2c79eSStefano Zampini         ncoarse_ds = pcbddc->redistribute_coarse;
363174e2c79eSStefano Zampini         redist = PETSC_TRUE;
363274e2c79eSStefano Zampini       } else {
36336e683305SStefano Zampini         csin_ds = PETSC_FALSE;
36346e683305SStefano Zampini         ncoarse_ds = all_procs;
36356e683305SStefano Zampini       }
36366e683305SStefano Zampini     }
363774e2c79eSStefano Zampini   }
36386e683305SStefano Zampini 
36396e683305SStefano Zampini   /*
36406e683305SStefano Zampini     test if we can go multilevel: three conditions must be satisfied:
36416e683305SStefano Zampini     - we have not exceeded the number of levels requested
36426e683305SStefano Zampini     - we can actually subassemble the active processes
36436e683305SStefano Zampini     - we can find a suitable number of MPI processes where we can place the subassembled problem
36446e683305SStefano Zampini   */
36456e683305SStefano Zampini   multilevel_allowed = PETSC_FALSE;
36466e683305SStefano Zampini   multilevel_requested = PETSC_FALSE;
36476e683305SStefano Zampini   if (pcbddc->current_level < pcbddc->max_levels) {
36486e683305SStefano Zampini     multilevel_requested = PETSC_TRUE;
36496e683305SStefano Zampini     if (active_procs/pcbddc->coarsening_ratio < 2 || ncoarse_ml/pcbddc->coarsening_ratio < 2) {
3650f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_FALSE;
36512b510759SStefano Zampini     } else {
3652f9eb5b7dSStefano Zampini       multilevel_allowed = PETSC_TRUE;
3653c8587f34SStefano Zampini     }
3654c8587f34SStefano Zampini   }
36556e683305SStefano Zampini   /* determine number of process partecipating to coarse solver */
36566e683305SStefano Zampini   if (multilevel_allowed) {
36576e683305SStefano Zampini     ncoarse = ncoarse_ml;
36586e683305SStefano Zampini     csin = csin_ml;
36596e683305SStefano Zampini   } else {
36606e683305SStefano Zampini     ncoarse = ncoarse_ds;
36616e683305SStefano Zampini     csin = csin_ds;
36626e683305SStefano Zampini   }
3663e7931f94SStefano Zampini 
3664abbbba34SStefano Zampini   /* creates temporary l2gmap and IS for coarse indexes */
3665abbbba34SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),pcbddc->local_primal_size,pcbddc->global_primal_indices,PETSC_COPY_VALUES,&coarse_is);CHKERRQ(ierr);
3666abbbba34SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(coarse_is,&coarse_islg);CHKERRQ(ierr);
3667abbbba34SStefano Zampini 
3668abbbba34SStefano Zampini   /* creates temporary MATIS object for coarse matrix */
366922bc73bbSStefano Zampini   ierr = MatCreateSeqDense(PETSC_COMM_SELF,pcbddc->local_primal_size,pcbddc->local_primal_size,NULL,&coarse_submat_dense);CHKERRQ(ierr);
367022bc73bbSStefano Zampini   ierr = MatDenseGetArray(coarse_submat_dense,&array);CHKERRQ(ierr);
367122bc73bbSStefano Zampini   ierr = PetscMemcpy(array,coarse_submat_vals,sizeof(*coarse_submat_vals)*pcbddc->local_primal_size*pcbddc->local_primal_size);CHKERRQ(ierr);
367222bc73bbSStefano Zampini   ierr = MatDenseRestoreArray(coarse_submat_dense,&array);CHKERRQ(ierr);
3673b9b85e73SStefano Zampini #if 0
3674b9b85e73SStefano Zampini   {
3675b9b85e73SStefano Zampini     PetscViewer viewer;
3676b9b85e73SStefano Zampini     char filename[256];
3677b9b85e73SStefano Zampini     sprintf(filename,"local_coarse_mat%d.m",PetscGlobalRank);
3678b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&viewer);CHKERRQ(ierr);
3679b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3680b9b85e73SStefano Zampini     ierr = MatView(coarse_submat_dense,viewer);CHKERRQ(ierr);
3681b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3682b9b85e73SStefano Zampini   }
3683b9b85e73SStefano Zampini #endif
36846e683305SStefano 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);
36856e683305SStefano Zampini   ierr = MatISSetLocalMat(t_coarse_mat_is,coarse_submat_dense);CHKERRQ(ierr);
36866e683305SStefano Zampini   ierr = MatAssemblyBegin(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
36876e683305SStefano Zampini   ierr = MatAssemblyEnd(t_coarse_mat_is,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3688abbbba34SStefano Zampini   ierr = MatDestroy(&coarse_submat_dense);CHKERRQ(ierr);
3689abbbba34SStefano Zampini 
36906e683305SStefano Zampini   /* compute dofs splitting and neumann boundaries for coarse dofs */
36916e683305SStefano Zampini   if (multilevel_allowed && (pcbddc->n_ISForDofsLocal || pcbddc->NeumannBoundariesLocal) ) { /* protects from unneded computations */
36926e683305SStefano Zampini     PetscInt               *tidxs,*tidxs2,nout,tsize,i;
36936e683305SStefano Zampini     const PetscInt         *idxs;
36946e683305SStefano Zampini     ISLocalToGlobalMapping tmap;
36956e683305SStefano Zampini 
36966e683305SStefano Zampini     /* create map between primal indices (in local representative ordering) and local primal numbering */
36970be93d54SStefano Zampini     ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,1,pcbddc->local_primal_size,pcbddc->primal_indices_local_idxs,PETSC_COPY_VALUES,&tmap);CHKERRQ(ierr);
36986e683305SStefano Zampini     /* allocate space for temporary storage */
3699854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs);CHKERRQ(ierr);
3700854ce69bSBarry Smith     ierr = PetscMalloc1(pcbddc->local_primal_size,&tidxs2);CHKERRQ(ierr);
37016e683305SStefano Zampini     /* allocate for IS array */
37026e683305SStefano Zampini     nisdofs = pcbddc->n_ISForDofsLocal;
37036e683305SStefano Zampini     nisneu = !!pcbddc->NeumannBoundariesLocal;
37046e683305SStefano Zampini     nis = nisdofs + nisneu;
3705854ce69bSBarry Smith     ierr = PetscMalloc1(nis,&isarray);CHKERRQ(ierr);
37066e683305SStefano Zampini     /* dofs splitting */
37076e683305SStefano Zampini     for (i=0;i<nisdofs;i++) {
37086e683305SStefano Zampini       /* ierr = ISView(pcbddc->ISForDofsLocal[i],0);CHKERRQ(ierr); */
37096e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->ISForDofsLocal[i],&tsize);CHKERRQ(ierr);
37106e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
37116e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
37126e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->ISForDofsLocal[i],&idxs);CHKERRQ(ierr);
37136e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
37146e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->ISForDofsLocal[i]),nout,tidxs2,PETSC_COPY_VALUES,&isarray[i]);CHKERRQ(ierr);
37156e683305SStefano Zampini       /* ierr = ISView(isarray[i],0);CHKERRQ(ierr); */
37166e683305SStefano Zampini     }
37176e683305SStefano Zampini     /* neumann boundaries */
37186e683305SStefano Zampini     if (pcbddc->NeumannBoundariesLocal) {
37196e683305SStefano Zampini       /* ierr = ISView(pcbddc->NeumannBoundariesLocal,0);CHKERRQ(ierr); */
37206e683305SStefano Zampini       ierr = ISGetLocalSize(pcbddc->NeumannBoundariesLocal,&tsize);CHKERRQ(ierr);
37216e683305SStefano Zampini       ierr = ISGetIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
37226e683305SStefano Zampini       ierr = ISGlobalToLocalMappingApply(tmap,IS_GTOLM_DROP,tsize,idxs,&nout,tidxs);CHKERRQ(ierr);
37236e683305SStefano Zampini       ierr = ISRestoreIndices(pcbddc->NeumannBoundariesLocal,&idxs);CHKERRQ(ierr);
37246e683305SStefano Zampini       ierr = ISLocalToGlobalMappingApply(coarse_islg,nout,tidxs,tidxs2);CHKERRQ(ierr);
37256e683305SStefano Zampini       ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pcbddc->NeumannBoundariesLocal),nout,tidxs2,PETSC_COPY_VALUES,&isarray[nisdofs]);CHKERRQ(ierr);
37266e683305SStefano Zampini       /* ierr = ISView(isarray[nisdofs],0);CHKERRQ(ierr); */
37276e683305SStefano Zampini     }
37286e683305SStefano Zampini     /* free memory */
37296e683305SStefano Zampini     ierr = PetscFree(tidxs);CHKERRQ(ierr);
37306e683305SStefano Zampini     ierr = PetscFree(tidxs2);CHKERRQ(ierr);
37316e683305SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&tmap);CHKERRQ(ierr);
37326e683305SStefano Zampini   } else {
37336e683305SStefano Zampini     nis = 0;
37346e683305SStefano Zampini     nisdofs = 0;
37356e683305SStefano Zampini     nisneu = 0;
37366e683305SStefano Zampini     isarray = NULL;
37376e683305SStefano Zampini   }
37386e683305SStefano Zampini   /* destroy no longer needed map */
37396e683305SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&coarse_islg);CHKERRQ(ierr);
37406e683305SStefano Zampini 
37416e683305SStefano Zampini   /* restrict on coarse candidates (if needed) */
37426e683305SStefano Zampini   coarse_mat_is = NULL;
37436e683305SStefano Zampini   if (csin) {
37446e683305SStefano Zampini     if (!pcbddc->coarse_subassembling_init ) { /* creates subassembling init pattern if not present */
374574e2c79eSStefano Zampini       if (redist) {
374674e2c79eSStefano Zampini         PetscMPIInt rank;
374774e2c79eSStefano Zampini         PetscInt spc,n_spc_p1,dest[1];
374874e2c79eSStefano Zampini 
374974e2c79eSStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
375074e2c79eSStefano Zampini         spc = all_procs/pcbddc->redistribute_coarse;
375174e2c79eSStefano Zampini         n_spc_p1 = all_procs%pcbddc->redistribute_coarse;
375274e2c79eSStefano Zampini         if (rank > n_spc_p1*(spc+1)-1) {
375374e2c79eSStefano Zampini           dest[0] = n_spc_p1+(rank-(n_spc_p1*(spc+1)))/spc;
375474e2c79eSStefano Zampini         } else {
375574e2c79eSStefano Zampini           dest[0] = rank/(spc+1);
375674e2c79eSStefano Zampini         }
375774e2c79eSStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),1,dest,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
375874e2c79eSStefano Zampini       } else {
37596e683305SStefano Zampini         PetscInt j,tissize,*nisindices;
37606e683305SStefano Zampini         PetscInt *coarse_candidates;
37616e683305SStefano Zampini         const PetscInt* tisindices;
37626e683305SStefano Zampini         /* get coarse candidates' ranks in pc communicator */
3763854ce69bSBarry Smith         ierr = PetscMalloc1(all_procs,&coarse_candidates);CHKERRQ(ierr);
37646e683305SStefano Zampini         ierr = MPI_Allgather(&im_active,1,MPIU_INT,coarse_candidates,1,MPIU_INT,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
37656e683305SStefano Zampini         for (i=0,j=0;i<all_procs;i++) {
37666e683305SStefano Zampini           if (!coarse_candidates[i]) {
37676e683305SStefano Zampini             coarse_candidates[j]=i;
37686e683305SStefano Zampini             j++;
37696e683305SStefano Zampini           }
37706e683305SStefano Zampini         }
37716e683305SStefano Zampini         if (j < ncoarse) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"This should not happen! %d < %d",j,ncoarse);
37726e683305SStefano Zampini         /* get a suitable subassembling pattern */
37736e683305SStefano Zampini         if (csin_type_simple) {
37746e683305SStefano Zampini           PetscMPIInt rank;
37756e683305SStefano Zampini           PetscInt    issize,isidx;
37766e683305SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
37776e683305SStefano Zampini           if (im_active) {
37786e683305SStefano Zampini             issize = 1;
37796e683305SStefano Zampini             isidx = (PetscInt)rank;
37806e683305SStefano Zampini           } else {
37816e683305SStefano Zampini             issize = 0;
37826e683305SStefano Zampini             isidx = -1;
37836e683305SStefano Zampini           }
37846e683305SStefano Zampini           ierr = ISCreateGeneral(PetscObjectComm((PetscObject)pc),issize,&isidx,PETSC_COPY_VALUES,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
37856e683305SStefano Zampini         } else {
37866e683305SStefano Zampini           ierr = MatISGetSubassemblingPattern(t_coarse_mat_is,ncoarse,PETSC_TRUE,&pcbddc->coarse_subassembling_init);CHKERRQ(ierr);
37876e683305SStefano Zampini         }
37886e683305SStefano Zampini         if (pcbddc->dbg_flag) {
37896e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
37906e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init (before shift)\n");CHKERRQ(ierr);
37916e683305SStefano Zampini           ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
37926e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse candidates\n");CHKERRQ(ierr);
37936e683305SStefano Zampini           for (i=0;i<j;i++) {
37946e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"%d ",coarse_candidates[i]);CHKERRQ(ierr);
37956e683305SStefano Zampini           }
37966e683305SStefano Zampini           ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"\n");CHKERRQ(ierr);
37976e683305SStefano Zampini           ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
37986e683305SStefano Zampini         }
37996e683305SStefano Zampini         /* shift the pattern on coarse candidates */
38006e683305SStefano Zampini         ierr = ISGetLocalSize(pcbddc->coarse_subassembling_init,&tissize);CHKERRQ(ierr);
38016e683305SStefano Zampini         ierr = ISGetIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
3802854ce69bSBarry Smith         ierr = PetscMalloc1(tissize,&nisindices);CHKERRQ(ierr);
38036e683305SStefano Zampini         for (i=0;i<tissize;i++) nisindices[i] = coarse_candidates[tisindices[i]];
38046e683305SStefano Zampini         ierr = ISRestoreIndices(pcbddc->coarse_subassembling_init,&tisindices);CHKERRQ(ierr);
38056e683305SStefano Zampini         ierr = ISGeneralSetIndices(pcbddc->coarse_subassembling_init,tissize,nisindices,PETSC_OWN_POINTER);CHKERRQ(ierr);
38066e683305SStefano Zampini         ierr = PetscFree(coarse_candidates);CHKERRQ(ierr);
38076e683305SStefano Zampini       }
380874e2c79eSStefano Zampini     }
38096e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38106e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38116e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init\n");CHKERRQ(ierr);
38126e683305SStefano Zampini       ierr = ISView(pcbddc->coarse_subassembling_init,pcbddc->dbg_viewer);CHKERRQ(ierr);
38136e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38146e683305SStefano Zampini     }
38156e683305SStefano Zampini     /* get temporary coarse mat in IS format restricted on coarse procs (plus additional index sets of isarray) */
38166e683305SStefano Zampini     ierr = MatISSubassemble(t_coarse_mat_is,pcbddc->coarse_subassembling_init,0,PETSC_TRUE,MAT_INITIAL_MATRIX,&coarse_mat_is,nis,isarray);CHKERRQ(ierr);
38176e683305SStefano Zampini   } else {
38186e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38196e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38206e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Subassembling pattern init not needed\n");CHKERRQ(ierr);
38216e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38226e683305SStefano Zampini     }
38236e683305SStefano Zampini     ierr = PetscObjectReference((PetscObject)t_coarse_mat_is);CHKERRQ(ierr);
38246e683305SStefano Zampini     coarse_mat_is = t_coarse_mat_is;
38256e683305SStefano Zampini   }
38266e683305SStefano Zampini 
38276e683305SStefano Zampini   /* create local to global scatters for coarse problem */
382868457ee5SStefano Zampini   if (compute_vecs) {
38296e683305SStefano Zampini     PetscInt lrows;
38306e683305SStefano Zampini     ierr = VecDestroy(&pcbddc->coarse_vec);CHKERRQ(ierr);
38316e683305SStefano Zampini     if (coarse_mat_is) {
38326e683305SStefano Zampini       ierr = MatGetLocalSize(coarse_mat_is,&lrows,NULL);CHKERRQ(ierr);
38336e683305SStefano Zampini     } else {
38346e683305SStefano Zampini       lrows = 0;
38356e683305SStefano Zampini     }
38366e683305SStefano Zampini     ierr = VecCreate(PetscObjectComm((PetscObject)pc),&pcbddc->coarse_vec);CHKERRQ(ierr);
38376e683305SStefano Zampini     ierr = VecSetSizes(pcbddc->coarse_vec,lrows,PETSC_DECIDE);CHKERRQ(ierr);
38386e683305SStefano Zampini     ierr = VecSetType(pcbddc->coarse_vec,VECSTANDARD);CHKERRQ(ierr);
38396e683305SStefano Zampini     ierr = VecScatterDestroy(&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38406e683305SStefano Zampini     ierr = VecScatterCreate(pcbddc->vec1_P,NULL,pcbddc->coarse_vec,coarse_is,&pcbddc->coarse_loc_to_glob);CHKERRQ(ierr);
38416e683305SStefano Zampini   }
38426e683305SStefano Zampini   ierr = ISDestroy(&coarse_is);CHKERRQ(ierr);
38436e683305SStefano Zampini   ierr = MatDestroy(&t_coarse_mat_is);CHKERRQ(ierr);
3844c8587f34SStefano Zampini 
3845f9eb5b7dSStefano Zampini   /* set defaults for coarse KSP and PC */
3846f9eb5b7dSStefano Zampini   if (multilevel_allowed) {
3847f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPRICHARDSON;
3848f9eb5b7dSStefano Zampini     coarse_pc_type = PCBDDC;
3849f9eb5b7dSStefano Zampini   } else {
3850f9eb5b7dSStefano Zampini     coarse_ksp_type = KSPPREONLY;
3851f9eb5b7dSStefano Zampini     coarse_pc_type = PCREDUNDANT;
3852c8587f34SStefano Zampini   }
3853c8587f34SStefano Zampini 
38546e683305SStefano Zampini   /* print some info if requested */
38556e683305SStefano Zampini   if (pcbddc->dbg_flag) {
38566e683305SStefano Zampini     if (!multilevel_allowed) {
38576e683305SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
38586e683305SStefano Zampini       if (multilevel_requested) {
38596e683305SStefano 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);
38606e683305SStefano Zampini       } else if (pcbddc->max_levels) {
38616e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Maximum number of requested levels reached (%d)\n",pcbddc->max_levels);CHKERRQ(ierr);
38626e683305SStefano Zampini       }
38636e683305SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
38646e683305SStefano Zampini     }
38656e683305SStefano Zampini   }
38666e683305SStefano Zampini 
3867f9eb5b7dSStefano Zampini   /* create the coarse KSP object only once with defaults */
38686e683305SStefano Zampini   if (coarse_mat_is) {
38696e683305SStefano Zampini     MatReuse coarse_mat_reuse;
38706a1308c2SStefano Zampini     PetscViewer dbg_viewer = NULL;
38716e683305SStefano Zampini     if (pcbddc->dbg_flag) {
38726e683305SStefano Zampini       dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat_is));
38736e683305SStefano Zampini       ierr = PetscViewerASCIIAddTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
38746e683305SStefano Zampini     }
3875f9eb5b7dSStefano Zampini     if (!pcbddc->coarse_ksp) {
3876312be037SStefano Zampini       char prefix[256],str_level[16];
3877e604994aSStefano Zampini       size_t len;
38786e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)coarse_mat_is),&pcbddc->coarse_ksp);CHKERRQ(ierr);
3879c8587f34SStefano Zampini       ierr = PetscObjectIncrementTabLevel((PetscObject)pcbddc->coarse_ksp,(PetscObject)pc,1);CHKERRQ(ierr);
3880f9eb5b7dSStefano Zampini       ierr = KSPSetTolerances(pcbddc->coarse_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr);
38815f76c7aeSStefano Zampini       ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat_is,coarse_mat_is);CHKERRQ(ierr);
3882c8587f34SStefano Zampini       ierr = KSPSetType(pcbddc->coarse_ksp,coarse_ksp_type);CHKERRQ(ierr);
38836e683305SStefano Zampini       ierr = KSPSetNormType(pcbddc->coarse_ksp,KSP_NORM_NONE);CHKERRQ(ierr);
3884c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3885c8587f34SStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3886e604994aSStefano Zampini       /* prefix */
3887e604994aSStefano Zampini       ierr = PetscStrcpy(prefix,"");CHKERRQ(ierr);
3888e604994aSStefano Zampini       ierr = PetscStrcpy(str_level,"");CHKERRQ(ierr);
3889e604994aSStefano Zampini       if (!pcbddc->current_level) {
3890e604994aSStefano Zampini         ierr = PetscStrcpy(prefix,((PetscObject)pc)->prefix);CHKERRQ(ierr);
3891e604994aSStefano Zampini         ierr = PetscStrcat(prefix,"pc_bddc_coarse_");CHKERRQ(ierr);
3892c8587f34SStefano Zampini       } else {
3893e604994aSStefano Zampini         ierr = PetscStrlen(((PetscObject)pc)->prefix,&len);CHKERRQ(ierr);
3894312be037SStefano Zampini         if (pcbddc->current_level>1) len -= 3; /* remove "lX_" with X level number */
3895312be037SStefano Zampini         if (pcbddc->current_level>10) len -= 1; /* remove another char from level number */
389634d6797cSStefano Zampini         ierr = PetscStrncpy(prefix,((PetscObject)pc)->prefix,len+1);CHKERRQ(ierr);
3897312be037SStefano Zampini         sprintf(str_level,"l%d_",(int)(pcbddc->current_level));
3898e604994aSStefano Zampini         ierr = PetscStrcat(prefix,str_level);CHKERRQ(ierr);
3899e604994aSStefano Zampini       }
3900e604994aSStefano Zampini       ierr = KSPSetOptionsPrefix(pcbddc->coarse_ksp,prefix);CHKERRQ(ierr);
3901f9eb5b7dSStefano Zampini       /* allow user customization */
3902f9eb5b7dSStefano Zampini       ierr = KSPSetFromOptions(pcbddc->coarse_ksp);CHKERRQ(ierr);
39037e0def11SStefano Zampini       ierr = PCFactorSetReuseFill(pc_temp,PETSC_TRUE);CHKERRQ(ierr);
3904312be037SStefano Zampini     }
3905f9eb5b7dSStefano Zampini 
3906f9eb5b7dSStefano Zampini     /* get some info after set from options */
3907f9eb5b7dSStefano Zampini     ierr = KSPGetPC(pcbddc->coarse_ksp,&pc_temp);CHKERRQ(ierr);
3908f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCNN,&isnn);CHKERRQ(ierr);
3909f9eb5b7dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCBDDC,&isbddc);CHKERRQ(ierr);
39104f3a063dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc_temp,PCREDUNDANT,&isredundant);CHKERRQ(ierr);
39116e683305SStefano Zampini     if (isbddc && !multilevel_allowed) { /* multilevel can only be requested via pc_bddc_set_levels */
3912f9eb5b7dSStefano Zampini       ierr = PCSetType(pc_temp,coarse_pc_type);CHKERRQ(ierr);
3913f9eb5b7dSStefano Zampini       isbddc = PETSC_FALSE;
3914f9eb5b7dSStefano Zampini     }
39154f3a063dSStefano Zampini     if (isredundant) {
39164f3a063dSStefano Zampini       KSP inner_ksp;
39174f3a063dSStefano Zampini       PC inner_pc;
39184f3a063dSStefano Zampini       ierr = PCRedundantGetKSP(pc_temp,&inner_ksp);CHKERRQ(ierr);
39194f3a063dSStefano Zampini       ierr = KSPGetPC(inner_ksp,&inner_pc);CHKERRQ(ierr);
39204f3a063dSStefano Zampini       ierr = PCFactorSetReuseFill(inner_pc,PETSC_TRUE);CHKERRQ(ierr);
39214f3a063dSStefano Zampini     }
3922f9eb5b7dSStefano Zampini 
39236e683305SStefano Zampini     /* propagate BDDC info to the next level (these are dummy calls if pc_temp is not of type PCBDDC) */
3924f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevel(pc_temp,pcbddc->current_level+1);CHKERRQ(ierr);
3925f9eb5b7dSStefano Zampini     ierr = PCBDDCSetCoarseningRatio(pc_temp,pcbddc->coarsening_ratio);CHKERRQ(ierr);
3926f9eb5b7dSStefano Zampini     ierr = PCBDDCSetLevels(pc_temp,pcbddc->max_levels);CHKERRQ(ierr);
39276e683305SStefano Zampini     if (nisdofs) {
39286e683305SStefano Zampini       ierr = PCBDDCSetDofsSplitting(pc_temp,nisdofs,isarray);CHKERRQ(ierr);
39296e683305SStefano Zampini       for (i=0;i<nisdofs;i++) {
39306e683305SStefano Zampini         ierr = ISDestroy(&isarray[i]);CHKERRQ(ierr);
39311035eff8SStefano Zampini       }
39321035eff8SStefano Zampini     }
39336e683305SStefano Zampini     if (nisneu) {
39346e683305SStefano Zampini       ierr = PCBDDCSetNeumannBoundaries(pc_temp,isarray[nisdofs]);CHKERRQ(ierr);
39356e683305SStefano Zampini       ierr = ISDestroy(&isarray[nisdofs]);CHKERRQ(ierr);
39361035eff8SStefano Zampini     }
3937fdc09c96SStefano Zampini 
3938f9eb5b7dSStefano Zampini     /* assemble coarse matrix */
3939fa7f1dd8SStefano Zampini     if (coarse_reuse) {
394081d9aea3SBarry Smith       ierr = KSPGetOperators(pcbddc->coarse_ksp,&coarse_mat,NULL);CHKERRQ(ierr);
3941fa7f1dd8SStefano Zampini       ierr = PetscObjectReference((PetscObject)coarse_mat);CHKERRQ(ierr);
39426e683305SStefano Zampini       coarse_mat_reuse = MAT_REUSE_MATRIX;
3943fa7f1dd8SStefano Zampini     } else {
39446e683305SStefano Zampini       coarse_mat_reuse = MAT_INITIAL_MATRIX;
3945fa7f1dd8SStefano Zampini     }
3946c8587f34SStefano Zampini     if (isbddc || isnn) {
394722bc73bbSStefano Zampini       if (pcbddc->coarsening_ratio > 1) {
394870cf5478SStefano Zampini         if (!pcbddc->coarse_subassembling) { /* subassembling info is not present */
394928143c3dSStefano Zampini           ierr = MatISGetSubassemblingPattern(coarse_mat_is,active_procs/pcbddc->coarsening_ratio,PETSC_TRUE,&pcbddc->coarse_subassembling);CHKERRQ(ierr);
395022b6e8a2SStefano Zampini           if (pcbddc->dbg_flag) {
39516e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
39526e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"Subassembling pattern\n");CHKERRQ(ierr);
39536e683305SStefano Zampini             ierr = ISView(pcbddc->coarse_subassembling,dbg_viewer);CHKERRQ(ierr);
39546e683305SStefano Zampini             ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
395522b6e8a2SStefano Zampini           }
395670cf5478SStefano Zampini         }
39576e683305SStefano Zampini         ierr = MatISSubassemble(coarse_mat_is,pcbddc->coarse_subassembling,0,PETSC_FALSE,coarse_mat_reuse,&coarse_mat,0,NULL);CHKERRQ(ierr);
395870cf5478SStefano Zampini       } else {
395922bc73bbSStefano Zampini         ierr = PetscObjectReference((PetscObject)coarse_mat_is);CHKERRQ(ierr);
396022bc73bbSStefano Zampini         coarse_mat = coarse_mat_is;
396122bc73bbSStefano Zampini       }
396222bc73bbSStefano Zampini     } else {
39632e1e5fa4SStefano Zampini       ierr = MatISGetMPIXAIJ(coarse_mat_is,coarse_mat_reuse,&coarse_mat);CHKERRQ(ierr);
3964c8587f34SStefano Zampini     }
3965c8587f34SStefano Zampini     ierr = MatDestroy(&coarse_mat_is);CHKERRQ(ierr);
3966c8587f34SStefano Zampini 
3967c8587f34SStefano Zampini     /* propagate symmetry info to coarse matrix */
3968b9d89cd5SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_SYMMETRIC,pcbddc->issym);CHKERRQ(ierr);
39695a16e3a0SStefano Zampini     ierr = MatSetOption(coarse_mat,MAT_STRUCTURALLY_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
3970c8587f34SStefano Zampini 
39716e683305SStefano Zampini     /* set operators */
39725f76c7aeSStefano Zampini     ierr = KSPSetOperators(pcbddc->coarse_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
39736e683305SStefano Zampini     if (pcbddc->dbg_flag) {
39746e683305SStefano Zampini       ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
39756e683305SStefano Zampini     }
39766e683305SStefano Zampini   } else { /* processes non partecipating to coarse solver (if any) */
39776e683305SStefano Zampini     coarse_mat = 0;
39786e683305SStefano Zampini   }
39796e683305SStefano Zampini   ierr = PetscFree(isarray);CHKERRQ(ierr);
3980b9b85e73SStefano Zampini #if 0
3981b9b85e73SStefano Zampini   {
3982b9b85e73SStefano Zampini     PetscViewer viewer;
3983b9b85e73SStefano Zampini     char filename[256];
3984b9b85e73SStefano Zampini     sprintf(filename,"coarse_mat.m");
3985b9b85e73SStefano Zampini     ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,filename,&viewer);CHKERRQ(ierr);
3986b9b85e73SStefano Zampini     ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_MATLAB);CHKERRQ(ierr);
3987b9b85e73SStefano Zampini     ierr = MatView(coarse_mat,viewer);CHKERRQ(ierr);
3988b9b85e73SStefano Zampini     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
3989b9b85e73SStefano Zampini   }
3990b9b85e73SStefano Zampini #endif
3991c8587f34SStefano Zampini 
3992c8587f34SStefano Zampini   /* Compute coarse null space (special handling by BDDC only) */
3993c8587f34SStefano Zampini   if (pcbddc->NullSpace) {
3994c8587f34SStefano Zampini     ierr = PCBDDCNullSpaceAssembleCoarse(pc,coarse_mat,&CoarseNullSpace);CHKERRQ(ierr);
399598a51de6SStefano Zampini   }
399698a51de6SStefano Zampini 
399798a51de6SStefano Zampini   if (pcbddc->coarse_ksp) {
399898a51de6SStefano Zampini     Vec crhs,csol;
399998a51de6SStefano Zampini     PetscBool ispreonly;
400098a51de6SStefano Zampini     if (CoarseNullSpace) {
4001c8587f34SStefano Zampini       if (isbddc) {
4002c8587f34SStefano Zampini         ierr = PCBDDCSetNullSpace(pc_temp,CoarseNullSpace);CHKERRQ(ierr);
4003c8587f34SStefano Zampini       } else {
4004c8587f34SStefano Zampini         ierr = KSPSetNullSpace(pcbddc->coarse_ksp,CoarseNullSpace);CHKERRQ(ierr);
4005c8587f34SStefano Zampini       }
4006c8587f34SStefano Zampini     }
4007f9eb5b7dSStefano Zampini     /* setup coarse ksp */
4008f9eb5b7dSStefano Zampini     ierr = KSPSetUp(pcbddc->coarse_ksp);CHKERRQ(ierr);
4009f347579bSStefano Zampini     ierr = KSPGetSolution(pcbddc->coarse_ksp,&csol);CHKERRQ(ierr);
4010f347579bSStefano Zampini     ierr = KSPGetRhs(pcbddc->coarse_ksp,&crhs);CHKERRQ(ierr);
40116e683305SStefano Zampini     /* hack */
4012f347579bSStefano Zampini     if (!csol) {
40132a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,&((pcbddc->coarse_ksp)->vec_sol),NULL);CHKERRQ(ierr);
4014f9eb5b7dSStefano Zampini     }
4015f347579bSStefano Zampini     if (!crhs) {
40162a7a6963SBarry Smith       ierr = MatCreateVecs(coarse_mat,NULL,&((pcbddc->coarse_ksp)->vec_rhs));CHKERRQ(ierr);
4017f347579bSStefano Zampini     }
4018cbcc2c2aSStefano Zampini     /* Check coarse problem if in debug mode or if solving with an iterative method */
4019cbcc2c2aSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pcbddc->coarse_ksp,KSPPREONLY,&ispreonly);CHKERRQ(ierr);
40206e683305SStefano Zampini     if (pcbddc->dbg_flag || (!ispreonly && pcbddc->use_coarse_estimates) ) {
4021c8587f34SStefano Zampini       KSP       check_ksp;
40222b510759SStefano Zampini       KSPType   check_ksp_type;
4023c8587f34SStefano Zampini       PC        check_pc;
40246e683305SStefano Zampini       Vec       check_vec,coarse_vec;
40256a1308c2SStefano Zampini       PetscReal abs_infty_error,infty_error,lambda_min=1.0,lambda_max=1.0;
40262b510759SStefano Zampini       PetscInt  its;
40276e683305SStefano Zampini       PetscBool compute_eigs;
40286e683305SStefano Zampini       PetscReal *eigs_r,*eigs_c;
40296e683305SStefano Zampini       PetscInt  neigs;
40308e185a42SStefano Zampini       const char *prefix;
4031c8587f34SStefano Zampini 
40322b510759SStefano Zampini       /* Create ksp object suitable for estimation of extreme eigenvalues */
40336e683305SStefano Zampini       ierr = KSPCreate(PetscObjectComm((PetscObject)pcbddc->coarse_ksp),&check_ksp);CHKERRQ(ierr);
403423ee1639SBarry Smith       ierr = KSPSetOperators(check_ksp,coarse_mat,coarse_mat);CHKERRQ(ierr);
4035f4ddd8eeSStefano Zampini       ierr = KSPSetTolerances(check_ksp,1.e-12,1.e-12,PETSC_DEFAULT,pcbddc->coarse_size);CHKERRQ(ierr);
40362b510759SStefano Zampini       if (ispreonly) {
40372b510759SStefano Zampini         check_ksp_type = KSPPREONLY;
40386e683305SStefano Zampini         compute_eigs = PETSC_FALSE;
40392b510759SStefano Zampini       } else {
4040cbcc2c2aSStefano Zampini         check_ksp_type = KSPGMRES;
40416e683305SStefano Zampini         compute_eigs = PETSC_TRUE;
4042c8587f34SStefano Zampini       }
4043c8587f34SStefano Zampini       ierr = KSPSetType(check_ksp,check_ksp_type);CHKERRQ(ierr);
40446e683305SStefano Zampini       ierr = KSPSetComputeSingularValues(check_ksp,compute_eigs);CHKERRQ(ierr);
40456e683305SStefano Zampini       ierr = KSPSetComputeEigenvalues(check_ksp,compute_eigs);CHKERRQ(ierr);
40466e683305SStefano Zampini       ierr = KSPGMRESSetRestart(check_ksp,pcbddc->coarse_size+1);CHKERRQ(ierr);
4047a7dc3881SStefano Zampini       ierr = KSPGetOptionsPrefix(pcbddc->coarse_ksp,&prefix);CHKERRQ(ierr);
4048a7dc3881SStefano Zampini       ierr = KSPSetOptionsPrefix(check_ksp,prefix);CHKERRQ(ierr);
4049a7dc3881SStefano Zampini       ierr = KSPAppendOptionsPrefix(check_ksp,"check_");CHKERRQ(ierr);
4050a7dc3881SStefano Zampini       ierr = KSPSetFromOptions(check_ksp);CHKERRQ(ierr);
4051c8587f34SStefano Zampini       ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
4052c8587f34SStefano Zampini       ierr = KSPGetPC(pcbddc->coarse_ksp,&check_pc);CHKERRQ(ierr);
4053c8587f34SStefano Zampini       ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
4054c8587f34SStefano Zampini       /* create random vec */
40556e683305SStefano Zampini       ierr = KSPGetSolution(pcbddc->coarse_ksp,&coarse_vec);CHKERRQ(ierr);
40566e683305SStefano Zampini       ierr = VecDuplicate(coarse_vec,&check_vec);CHKERRQ(ierr);
4057c8587f34SStefano Zampini       ierr = VecSetRandom(check_vec,NULL);CHKERRQ(ierr);
4058c8587f34SStefano Zampini       if (CoarseNullSpace) {
4059c8587f34SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,check_vec);CHKERRQ(ierr);
4060c8587f34SStefano Zampini       }
40616e683305SStefano Zampini       ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
4062c8587f34SStefano Zampini       /* solve coarse problem */
40636e683305SStefano Zampini       ierr = KSPSolve(check_ksp,coarse_vec,coarse_vec);CHKERRQ(ierr);
4064c8587f34SStefano Zampini       if (CoarseNullSpace) {
40656e683305SStefano Zampini         ierr = MatNullSpaceRemove(CoarseNullSpace,coarse_vec);CHKERRQ(ierr);
4066c8587f34SStefano Zampini       }
4067cbcc2c2aSStefano Zampini       /* set eigenvalue estimation if preonly has not been requested */
40686e683305SStefano Zampini       if (compute_eigs) {
4069854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_r);CHKERRQ(ierr);
4070854ce69bSBarry Smith         ierr = PetscMalloc1(pcbddc->coarse_size+1,&eigs_c);CHKERRQ(ierr);
40716e683305SStefano Zampini         ierr = KSPComputeEigenvalues(check_ksp,pcbddc->coarse_size+1,eigs_r,eigs_c,&neigs);CHKERRQ(ierr);
40726e683305SStefano Zampini         lambda_max = eigs_r[neigs-1];
40736e683305SStefano Zampini         lambda_min = eigs_r[0];
40746e683305SStefano Zampini         if (pcbddc->use_coarse_estimates) {
40756e683305SStefano Zampini           if (lambda_max>lambda_min) {
4076cbcc2c2aSStefano Zampini             ierr = KSPChebyshevSetEigenvalues(pcbddc->coarse_ksp,lambda_max,lambda_min);CHKERRQ(ierr);
4077cbcc2c2aSStefano Zampini             ierr = KSPRichardsonSetScale(pcbddc->coarse_ksp,2.0/(lambda_max+lambda_min));CHKERRQ(ierr);
4078cbcc2c2aSStefano Zampini           }
4079c8587f34SStefano Zampini         }
4080c8587f34SStefano Zampini       }
4081cbcc2c2aSStefano Zampini 
4082c8587f34SStefano Zampini       /* check coarse problem residual error */
40836e683305SStefano Zampini       if (pcbddc->dbg_flag) {
40846e683305SStefano Zampini         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pcbddc->coarse_ksp));
40856e683305SStefano Zampini         ierr = PetscViewerASCIIAddTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
40866e683305SStefano Zampini         ierr = VecAXPY(check_vec,-1.0,coarse_vec);CHKERRQ(ierr);
4087c8587f34SStefano Zampini         ierr = VecNorm(check_vec,NORM_INFINITY,&infty_error);CHKERRQ(ierr);
40886e683305SStefano Zampini         ierr = MatMult(coarse_mat,check_vec,coarse_vec);CHKERRQ(ierr);
40896e683305SStefano Zampini         ierr = VecNorm(coarse_vec,NORM_INFINITY,&abs_infty_error);CHKERRQ(ierr);
4090c8587f34SStefano Zampini         ierr = VecDestroy(&check_vec);CHKERRQ(ierr);
40916e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem details (%d)\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
40926e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(pcbddc->coarse_ksp),dbg_viewer);CHKERRQ(ierr);
40936e683305SStefano Zampini         ierr = PetscObjectPrintClassNamePrefixType((PetscObject)(check_pc),dbg_viewer);CHKERRQ(ierr);
40946e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem exact infty_error   : %1.6e\n",infty_error);CHKERRQ(ierr);
40956e683305SStefano Zampini         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Coarse problem residual infty_error: %1.6e\n",abs_infty_error);CHKERRQ(ierr);
40966e683305SStefano Zampini         if (compute_eigs) {
40976e683305SStefano Zampini           PetscReal lambda_max_s,lambda_min_s;
4098deec49d1SStefano Zampini           ierr = KSPGetType(check_ksp,&check_ksp_type);CHKERRQ(ierr);
4099c8587f34SStefano Zampini           ierr = KSPGetIterationNumber(check_ksp,&its);CHKERRQ(ierr);
41006e683305SStefano Zampini           ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max_s,&lambda_min_s);CHKERRQ(ierr);
41016e683305SStefano 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);
41026e683305SStefano Zampini           for (i=0;i<neigs;i++) {
41036e683305SStefano Zampini             ierr = PetscViewerASCIIPrintf(dbg_viewer,"%1.6e %1.6ei\n",eigs_r[i],eigs_c[i]);CHKERRQ(ierr);
4104c8587f34SStefano Zampini           }
41056e683305SStefano Zampini         }
41066e683305SStefano Zampini         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
41076e683305SStefano Zampini         ierr = PetscViewerASCIISubtractTab(dbg_viewer,2*(pcbddc->current_level+1));CHKERRQ(ierr);
41086e683305SStefano Zampini       }
4109c8587f34SStefano Zampini       ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
41106e683305SStefano Zampini       if (compute_eigs) {
41116e683305SStefano Zampini         ierr = PetscFree(eigs_r);CHKERRQ(ierr);
41126e683305SStefano Zampini         ierr = PetscFree(eigs_c);CHKERRQ(ierr);
4113c8587f34SStefano Zampini       }
41146e683305SStefano Zampini     }
41156e683305SStefano Zampini   }
4116cbcc2c2aSStefano Zampini   /* print additional info */
4117cbcc2c2aSStefano Zampini   if (pcbddc->dbg_flag) {
41186e683305SStefano Zampini     /* waits until all processes reaches this point */
41196e683305SStefano Zampini     ierr = PetscBarrier((PetscObject)pc);CHKERRQ(ierr);
4120cbcc2c2aSStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Coarse solver setup completed at level %d\n",pcbddc->current_level);CHKERRQ(ierr);
4121cbcc2c2aSStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4122cbcc2c2aSStefano Zampini   }
4123cbcc2c2aSStefano Zampini 
41242b510759SStefano Zampini   /* free memory */
4125c8587f34SStefano Zampini   ierr = MatNullSpaceDestroy(&CoarseNullSpace);CHKERRQ(ierr);
4126fdc635d7SStefano Zampini   ierr = MatDestroy(&coarse_mat);CHKERRQ(ierr);
4127c8587f34SStefano Zampini   PetscFunctionReturn(0);
4128c8587f34SStefano Zampini }
4129674ae819SStefano Zampini 
4130f34684f1SStefano Zampini #undef __FUNCT__
4131f34684f1SStefano Zampini #define __FUNCT__ "PCBDDCComputePrimalNumbering"
4132f34684f1SStefano Zampini PetscErrorCode PCBDDCComputePrimalNumbering(PC pc,PetscInt* coarse_size_n,PetscInt** local_primal_indices_n)
4133f34684f1SStefano Zampini {
4134f34684f1SStefano Zampini   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
4135f34684f1SStefano Zampini   PC_IS*         pcis = (PC_IS*)pc->data;
4136f34684f1SStefano Zampini   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
4137727cdba6SStefano Zampini   PetscInt       i,coarse_size;
4138727cdba6SStefano Zampini   PetscInt       *local_primal_indices;
4139f34684f1SStefano Zampini   PetscErrorCode ierr;
4140f34684f1SStefano Zampini 
4141f34684f1SStefano Zampini   PetscFunctionBegin;
4142f34684f1SStefano Zampini   /* Compute global number of coarse dofs */
414389c96988SStefano Zampini   if (!pcbddc->primal_indices_local_idxs && pcbddc->local_primal_size) {
414489c96988SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Local primal indices have not been created");
4145727cdba6SStefano Zampini   }
4146727cdba6SStefano 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);
4147f34684f1SStefano Zampini 
4148f34684f1SStefano Zampini   /* check numbering */
4149f34684f1SStefano Zampini   if (pcbddc->dbg_flag) {
4150f34684f1SStefano Zampini     PetscScalar coarsesum,*array;
4151b9b85e73SStefano Zampini     PetscBool set_error = PETSC_FALSE,set_error_reduced = PETSC_FALSE;
4152f34684f1SStefano Zampini 
4153f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4154f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"--------------------------------------------------\n");CHKERRQ(ierr);
4155f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Check coarse indices\n");CHKERRQ(ierr);
41560fccc4e9SStefano Zampini     ierr = PetscViewerASCIISynchronizedAllow(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
4157f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_N,0.0);CHKERRQ(ierr);
4158f34684f1SStefano Zampini     for (i=0;i<pcbddc->local_primal_size;i++) {
4159727cdba6SStefano Zampini       ierr = VecSetValue(pcis->vec1_N,pcbddc->primal_indices_local_idxs[i],1.0,INSERT_VALUES);CHKERRQ(ierr);
4160f34684f1SStefano Zampini     }
4161f34684f1SStefano Zampini     ierr = VecAssemblyBegin(pcis->vec1_N);CHKERRQ(ierr);
4162f34684f1SStefano Zampini     ierr = VecAssemblyEnd(pcis->vec1_N);CHKERRQ(ierr);
4163f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4164f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4165f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4166f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4167f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_global,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4168f34684f1SStefano Zampini     ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4169f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4170f34684f1SStefano Zampini       if (array[i] == 1.0) {
4171b9b85e73SStefano Zampini         set_error = PETSC_TRUE;
4172f34684f1SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d: local index %d owned by a single process!\n",PetscGlobalRank,i);CHKERRQ(ierr);
4173f34684f1SStefano Zampini       }
4174f34684f1SStefano Zampini     }
4175b9b85e73SStefano Zampini     ierr = MPI_Allreduce(&set_error,&set_error_reduced,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
4176f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4177f34684f1SStefano Zampini     for (i=0;i<pcis->n;i++) {
4178f34684f1SStefano Zampini       if (PetscRealPart(array[i]) > 0.0) array[i] = 1.0/PetscRealPart(array[i]);
4179f34684f1SStefano Zampini     }
4180f34684f1SStefano Zampini     ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr);
4181f34684f1SStefano Zampini     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
4182f34684f1SStefano Zampini     ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4183f34684f1SStefano Zampini     ierr = VecScatterEnd(matis->ctx,pcis->vec1_N,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
4184f34684f1SStefano Zampini     ierr = VecSum(pcis->vec1_global,&coarsesum);CHKERRQ(ierr);
4185f34684f1SStefano Zampini     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Size of coarse problem is %d (%lf)\n",coarse_size,PetscRealPart(coarsesum));CHKERRQ(ierr);
4186b9b85e73SStefano Zampini     if (pcbddc->dbg_flag > 1 || set_error_reduced) {
4187f34684f1SStefano Zampini       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Distribution of local primal indices\n");CHKERRQ(ierr);
4188f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4189f34684f1SStefano Zampini       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d\n",PetscGlobalRank);CHKERRQ(ierr);
4190f34684f1SStefano Zampini       for (i=0;i<pcbddc->local_primal_size;i++) {
4191727cdba6SStefano Zampini         ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"local_primal_indices[%d]=%d (%d)\n",i,local_primal_indices[i],pcbddc->primal_indices_local_idxs[i]);
4192f34684f1SStefano Zampini       }
4193f34684f1SStefano Zampini       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4194f34684f1SStefano Zampini     }
4195f34684f1SStefano Zampini     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
4196b9b85e73SStefano Zampini     if (set_error_reduced) {
4197b9b85e73SStefano Zampini       SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_PLIB,"BDDC Numbering of coarse dofs failed");
4198b9b85e73SStefano Zampini     }
4199f34684f1SStefano Zampini   }
4200f34684f1SStefano Zampini   /* get back data */
4201f34684f1SStefano Zampini   *coarse_size_n = coarse_size;
4202f34684f1SStefano Zampini   *local_primal_indices_n = local_primal_indices;
4203674ae819SStefano Zampini   PetscFunctionReturn(0);
4204674ae819SStefano Zampini }
4205674ae819SStefano Zampini 
4206e456f2a8SStefano Zampini #undef __FUNCT__
4207e456f2a8SStefano Zampini #define __FUNCT__ "PCBDDCGlobalToLocal"
4208a7dc3881SStefano Zampini PetscErrorCode PCBDDCGlobalToLocal(VecScatter g2l_ctx,Vec gwork, Vec lwork, IS globalis, IS* localis)
4209e456f2a8SStefano Zampini {
4210e456f2a8SStefano Zampini   IS             localis_t;
4211a7dc3881SStefano Zampini   PetscInt       i,lsize,*idxs,n;
4212e456f2a8SStefano Zampini   PetscScalar    *vals;
4213e456f2a8SStefano Zampini   PetscErrorCode ierr;
4214e456f2a8SStefano Zampini 
4215e456f2a8SStefano Zampini   PetscFunctionBegin;
4216a7dc3881SStefano Zampini   /* get indices in local ordering exploiting local to global map */
4217e456f2a8SStefano Zampini   ierr = ISGetLocalSize(globalis,&lsize);CHKERRQ(ierr);
4218854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&vals);CHKERRQ(ierr);
4219e456f2a8SStefano Zampini   for (i=0;i<lsize;i++) vals[i] = 1.0;
4220e456f2a8SStefano Zampini   ierr = ISGetIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4221a7dc3881SStefano Zampini   ierr = VecSet(gwork,0.0);CHKERRQ(ierr);
4222a7dc3881SStefano Zampini   ierr = VecSet(lwork,0.0);CHKERRQ(ierr);
42231035eff8SStefano Zampini   if (idxs) { /* multilevel guard */
4224a7dc3881SStefano Zampini     ierr = VecSetValues(gwork,lsize,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
42251035eff8SStefano Zampini   }
4226a7dc3881SStefano Zampini   ierr = VecAssemblyBegin(gwork);CHKERRQ(ierr);
4227e456f2a8SStefano Zampini   ierr = ISRestoreIndices(globalis,(const PetscInt**)&idxs);CHKERRQ(ierr);
4228e456f2a8SStefano Zampini   ierr = PetscFree(vals);CHKERRQ(ierr);
4229a7dc3881SStefano Zampini   ierr = VecAssemblyEnd(gwork);CHKERRQ(ierr);
4230a7dc3881SStefano Zampini   /* now compute set in local ordering */
4231a7dc3881SStefano Zampini   ierr = VecScatterBegin(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4232a7dc3881SStefano Zampini   ierr = VecScatterEnd(g2l_ctx,gwork,lwork,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
4233a7dc3881SStefano Zampini   ierr = VecGetArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4234a7dc3881SStefano Zampini   ierr = VecGetSize(lwork,&n);CHKERRQ(ierr);
4235a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4236ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4237e456f2a8SStefano Zampini       lsize++;
4238e456f2a8SStefano Zampini     }
4239e456f2a8SStefano Zampini   }
4240854ce69bSBarry Smith   ierr = PetscMalloc1(lsize,&idxs);CHKERRQ(ierr);
4241a7dc3881SStefano Zampini   for (i=0,lsize=0;i<n;i++) {
4242ff92baa0SMatthew G. Knepley     if (PetscRealPart(vals[i]) > 0.5) {
4243e456f2a8SStefano Zampini       idxs[lsize++] = i;
4244e456f2a8SStefano Zampini     }
4245e456f2a8SStefano Zampini   }
4246a7dc3881SStefano Zampini   ierr = VecRestoreArrayRead(lwork,(const PetscScalar**)&vals);CHKERRQ(ierr);
4247a7dc3881SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)gwork),lsize,idxs,PETSC_OWN_POINTER,&localis_t);CHKERRQ(ierr);
4248e456f2a8SStefano Zampini   *localis = localis_t;
4249e456f2a8SStefano Zampini   PetscFunctionReturn(0);
4250e456f2a8SStefano Zampini }
4251906d46d4SStefano Zampini 
4252906d46d4SStefano Zampini /* the next two functions will be called in KSPMatMult if a change of basis has been requested */
4253906d46d4SStefano Zampini #undef __FUNCT__
4254906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMult_Private"
4255906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMult_Private(Mat A, Vec x, Vec y)
4256906d46d4SStefano Zampini {
4257906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4258906d46d4SStefano Zampini   PetscErrorCode   ierr;
4259906d46d4SStefano Zampini 
4260906d46d4SStefano Zampini   PetscFunctionBegin;
4261906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4262906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4263906d46d4SStefano Zampini   ierr = MatMult(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4264906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4265906d46d4SStefano Zampini   PetscFunctionReturn(0);
4266906d46d4SStefano Zampini }
4267906d46d4SStefano Zampini 
4268906d46d4SStefano Zampini #undef __FUNCT__
4269906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCMatMultTranspose_Private"
4270906d46d4SStefano Zampini static PetscErrorCode PCBDDCMatMultTranspose_Private(Mat A, Vec x, Vec y)
4271906d46d4SStefano Zampini {
4272906d46d4SStefano Zampini   PCBDDCChange_ctx change_ctx;
4273906d46d4SStefano Zampini   PetscErrorCode   ierr;
4274906d46d4SStefano Zampini 
4275906d46d4SStefano Zampini   PetscFunctionBegin;
4276906d46d4SStefano Zampini   ierr = MatShellGetContext(A,&change_ctx);CHKERRQ(ierr);
4277906d46d4SStefano Zampini   ierr = MatMult(change_ctx->global_change,x,change_ctx->work[0]);CHKERRQ(ierr);
4278906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->original_mat,change_ctx->work[0],change_ctx->work[1]);CHKERRQ(ierr);
4279906d46d4SStefano Zampini   ierr = MatMultTranspose(change_ctx->global_change,change_ctx->work[1],y);CHKERRQ(ierr);
4280906d46d4SStefano Zampini   PetscFunctionReturn(0);
4281906d46d4SStefano Zampini }
4282