xref: /petsc/src/ksp/pc/impls/bddc/bddcnullspace.c (revision fe998a80077c9ee0917a39496df43fc256e1b478)
1 #include <../src/ksp/pc/impls/bddc/bddc.h>
2 #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "PCBDDCNullSpaceAssembleCoarse"
6 PetscErrorCode PCBDDCNullSpaceAssembleCoarse(PC pc, Mat coarse_mat, MatNullSpace* CoarseNullSpace)
7 {
8   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9   Mat_IS         *matis = (Mat_IS*)pc->pmat->data;
10   MatNullSpace   tempCoarseNullSpace=NULL;
11   const Vec      *nsp_vecs;
12   Vec            *coarse_nsp_vecs,local_vec,local_primal_vec,wcoarse_vec,wcoarse_rhs;
13   PetscInt       nsp_size,coarse_nsp_size,i;
14   PetscBool      nsp_has_cnst;
15   PetscReal      test_null;
16   PetscErrorCode ierr;
17 
18   PetscFunctionBegin;
19   tempCoarseNullSpace = 0;
20   coarse_nsp_size = 0;
21   coarse_nsp_vecs = 0;
22   ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr);
23   if (coarse_mat) {
24     ierr = PetscMalloc1(nsp_size+1,&coarse_nsp_vecs);CHKERRQ(ierr);
25     for (i=0;i<nsp_size+1;i++) {
26       ierr = MatCreateVecs(coarse_mat,&coarse_nsp_vecs[i],NULL);CHKERRQ(ierr);
27     }
28     if (pcbddc->dbg_flag) {
29       ierr = MatCreateVecs(coarse_mat,&wcoarse_vec,&wcoarse_rhs);CHKERRQ(ierr);
30     }
31   }
32   ierr = MatCreateVecs(pcbddc->ConstraintMatrix,&local_vec,&local_primal_vec);CHKERRQ(ierr);
33   if (nsp_has_cnst) {
34     ierr = VecSet(local_vec,1.0);CHKERRQ(ierr);
35     ierr = MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);CHKERRQ(ierr);
36     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
37     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
38     if (coarse_mat) {
39       PetscScalar *array_out;
40       const PetscScalar *array_in;
41       PetscInt lsize;
42       if (pcbddc->dbg_flag) {
43         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
44         ierr = MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);CHKERRQ(ierr);
45         ierr = VecNorm(wcoarse_rhs,NORM_INFINITY,&test_null);CHKERRQ(ierr);
46         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Constant coarse null space error % 1.14e\n",test_null);CHKERRQ(ierr);
47         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
48       }
49       ierr = VecGetLocalSize(pcbddc->coarse_vec,&lsize);CHKERRQ(ierr);
50       ierr = VecGetArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr);
51       ierr = VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr);
52       ierr = PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
53       ierr = VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr);
54       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr);
55       coarse_nsp_size++;
56     }
57   }
58   for (i=0;i<nsp_size;i++)  {
59     ierr = VecScatterBegin(matis->ctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
60     ierr = VecScatterEnd(matis->ctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
61     ierr = MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);CHKERRQ(ierr);
62     ierr = VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
63     ierr = VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
64     if (coarse_mat) {
65       PetscScalar *array_out;
66       const PetscScalar *array_in;
67       PetscInt lsize;
68       if (pcbddc->dbg_flag) {
69         PetscViewer dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)coarse_mat));
70         ierr = MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);CHKERRQ(ierr);
71         ierr = VecNorm(wcoarse_rhs,NORM_2,&test_null);CHKERRQ(ierr);
72         ierr = PetscViewerASCIIPrintf(dbg_viewer,"Vec %d coarse null space error % 1.14e\n",i,test_null);CHKERRQ(ierr);
73         ierr = PetscViewerFlush(dbg_viewer);CHKERRQ(ierr);
74       }
75       ierr = VecGetLocalSize(pcbddc->coarse_vec,&lsize);CHKERRQ(ierr);
76       ierr = VecGetArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr);
77       ierr = VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr);
78       ierr = PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));CHKERRQ(ierr);
79       ierr = VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);CHKERRQ(ierr);
80       ierr = VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);CHKERRQ(ierr);
81       coarse_nsp_size++;
82     }
83   }
84   if (coarse_nsp_size > 0) {
85     ierr = PCBDDCOrthonormalizeVecs(coarse_nsp_size,coarse_nsp_vecs);CHKERRQ(ierr);
86     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,coarse_nsp_size,coarse_nsp_vecs,&tempCoarseNullSpace);CHKERRQ(ierr);
87     for (i=0;i<nsp_size+1;i++) {
88       ierr = VecDestroy(&coarse_nsp_vecs[i]);CHKERRQ(ierr);
89     }
90   }
91   if (coarse_mat) {
92     ierr = PetscFree(coarse_nsp_vecs);CHKERRQ(ierr);
93     if (pcbddc->dbg_flag) {
94       ierr = VecDestroy(&wcoarse_vec);CHKERRQ(ierr);
95       ierr = VecDestroy(&wcoarse_rhs);CHKERRQ(ierr);
96     }
97   }
98   ierr = VecDestroy(&local_vec);CHKERRQ(ierr);
99   ierr = VecDestroy(&local_primal_vec);CHKERRQ(ierr);
100   *CoarseNullSpace = tempCoarseNullSpace;
101   PetscFunctionReturn(0);
102 }
103 
104 
105 #undef __FUNCT__
106 #define __FUNCT__ "PCBDDCApplyNullSpaceCorrectionPC"
107 static PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC pc,Vec x,Vec y)
108 {
109   NullSpaceCorrection_ctx pc_ctx;
110   PetscErrorCode          ierr;
111 
112   PetscFunctionBegin;
113   ierr = PCShellGetContext(pc,(void**)&pc_ctx);CHKERRQ(ierr);
114   /* E */
115   ierr = MatMultTranspose(pc_ctx->Lbasis_mat,x,pc_ctx->work_small_2);CHKERRQ(ierr);
116   ierr = MatMultAdd(pc_ctx->Kbasis_mat,pc_ctx->work_small_2,x,pc_ctx->work_full_1);CHKERRQ(ierr);
117   /* P^-1 */
118   ierr = PCApply(pc_ctx->local_pc,pc_ctx->work_full_1,pc_ctx->work_full_2);CHKERRQ(ierr);
119   /* E^T */
120   ierr = MatMultTranspose(pc_ctx->Kbasis_mat,pc_ctx->work_full_2,pc_ctx->work_small_1);CHKERRQ(ierr);
121   ierr = VecScale(pc_ctx->work_small_1,-1.0);CHKERRQ(ierr);
122   ierr = MatMultAdd(pc_ctx->Lbasis_mat,pc_ctx->work_small_1,pc_ctx->work_full_2,pc_ctx->work_full_1);CHKERRQ(ierr);
123   /* Sum contributions */
124   ierr = MatMultAdd(pc_ctx->basis_mat,pc_ctx->work_small_2,pc_ctx->work_full_1,y);CHKERRQ(ierr);
125   PetscFunctionReturn(0);
126 }
127 
128 #undef __FUNCT__
129 #define __FUNCT__ "PCBDDCDestroyNullSpaceCorrectionPC"
130 static PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC pc)
131 {
132   NullSpaceCorrection_ctx pc_ctx;
133   PetscErrorCode          ierr;
134 
135   PetscFunctionBegin;
136   ierr = PCShellGetContext(pc,(void**)&pc_ctx);CHKERRQ(ierr);
137   ierr = VecDestroy(&pc_ctx->work_small_1);CHKERRQ(ierr);
138   ierr = VecDestroy(&pc_ctx->work_small_2);CHKERRQ(ierr);
139   ierr = VecDestroy(&pc_ctx->work_full_1);CHKERRQ(ierr);
140   ierr = VecDestroy(&pc_ctx->work_full_2);CHKERRQ(ierr);
141   ierr = MatDestroy(&pc_ctx->basis_mat);CHKERRQ(ierr);
142   ierr = MatDestroy(&pc_ctx->Lbasis_mat);CHKERRQ(ierr);
143   ierr = MatDestroy(&pc_ctx->Kbasis_mat);CHKERRQ(ierr);
144   ierr = PCDestroy(&pc_ctx->local_pc);CHKERRQ(ierr);
145   ierr = PetscFree(pc_ctx);CHKERRQ(ierr);
146   PetscFunctionReturn(0);
147 }
148 
149 /*
150 PETSC_EXTERN PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC,Vec,Vec);
151 PETSC_EXTERN PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC);
152 */
153 
154 #undef __FUNCT__
155 #define __FUNCT__ "PCBDDCNullSpaceAssembleCorrection"
156 PetscErrorCode PCBDDCNullSpaceAssembleCorrection(PC pc,IS local_dofs)
157 {
158   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
159   PC_IS          *pcis = (PC_IS*)pc->data;
160   Mat_IS*        matis = (Mat_IS*)pc->pmat->data;
161   KSP            *local_ksp;
162   PC             newpc;
163   NullSpaceCorrection_ctx  shell_ctx;
164   Mat            local_mat,local_pmat,small_mat,inv_small_mat;
165   Vec            work1,work2;
166   const Vec      *nullvecs;
167   VecScatter     scatter_ctx;
168   IS             is_aux;
169   MatFactorInfo  matinfo;
170   PetscScalar    *basis_mat,*Kbasis_mat,*array,*array_mat;
171   PetscScalar    one = 1.0,zero = 0.0, m_one = -1.0;
172   PetscInt       basis_dofs,basis_size,nnsp_size,i,k,n_I,n_R;
173   PetscBool      nnsp_has_cnst;
174   PetscErrorCode ierr;
175 
176   PetscFunctionBegin;
177   /* Infer the local solver */
178   ierr = ISGetSize(local_dofs,&basis_dofs);CHKERRQ(ierr);
179   ierr = VecGetSize(pcis->vec1_D,&n_I);CHKERRQ(ierr);
180   ierr = VecGetSize(pcbddc->vec1_R,&n_R);CHKERRQ(ierr);
181   if (basis_dofs == n_I) {
182     /* Dirichlet solver */
183     local_ksp = &pcbddc->ksp_D;
184   } else if (basis_dofs == n_R) {
185     /* Neumann solver */
186     local_ksp = &pcbddc->ksp_R;
187   } else {
188     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error in %s: unknown local IS size %d. n_I=%d, n_R=%d)\n",__FUNCT__,basis_dofs,n_I,n_R);
189   }
190   ierr = KSPGetOperators(*local_ksp,&local_mat,&local_pmat);CHKERRQ(ierr);
191 
192   /* Get null space vecs */
193   ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nnsp_has_cnst,&nnsp_size,&nullvecs);CHKERRQ(ierr);
194   basis_size = nnsp_size;
195   if (nnsp_has_cnst) {
196     basis_size++;
197   }
198 
199   if (basis_dofs) {
200      /* Create shell ctx */
201     ierr = PetscNew(&shell_ctx);CHKERRQ(ierr);
202 
203     /* Create work vectors in shell context */
204     ierr = VecCreate(PETSC_COMM_SELF,&shell_ctx->work_small_1);CHKERRQ(ierr);
205     ierr = VecSetSizes(shell_ctx->work_small_1,basis_size,basis_size);CHKERRQ(ierr);
206     ierr = VecSetType(shell_ctx->work_small_1,VECSEQ);CHKERRQ(ierr);
207     ierr = VecDuplicate(shell_ctx->work_small_1,&shell_ctx->work_small_2);CHKERRQ(ierr);
208     ierr = VecCreate(PETSC_COMM_SELF,&shell_ctx->work_full_1);CHKERRQ(ierr);
209     ierr = VecSetSizes(shell_ctx->work_full_1,basis_dofs,basis_dofs);CHKERRQ(ierr);
210     ierr = VecSetType(shell_ctx->work_full_1,VECSEQ);CHKERRQ(ierr);
211     ierr = VecDuplicate(shell_ctx->work_full_1,&shell_ctx->work_full_2);CHKERRQ(ierr);
212 
213     /* Allocate workspace */
214     ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,NULL,&shell_ctx->basis_mat );CHKERRQ(ierr);
215     ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,NULL,&shell_ctx->Kbasis_mat);CHKERRQ(ierr);
216     ierr = MatDenseGetArray(shell_ctx->basis_mat,&basis_mat);CHKERRQ(ierr);
217     ierr = MatDenseGetArray(shell_ctx->Kbasis_mat,&Kbasis_mat);CHKERRQ(ierr);
218 
219     /* Restrict local null space on selected dofs (Dirichlet or Neumann)
220        and compute matrices N and K*N */
221     ierr = VecDuplicate(shell_ctx->work_full_1,&work1);CHKERRQ(ierr);
222     ierr = VecDuplicate(shell_ctx->work_full_1,&work2);CHKERRQ(ierr);
223     ierr = VecScatterCreate(pcis->vec1_N,local_dofs,work1,(IS)0,&scatter_ctx);CHKERRQ(ierr);
224   }
225 
226   for (k=0;k<nnsp_size;k++) {
227     ierr = VecScatterBegin(matis->ctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
228     ierr = VecScatterEnd(matis->ctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
229     if (basis_dofs) {
230       ierr = VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);CHKERRQ(ierr);
231       ierr = VecScatterBegin(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
232       ierr = VecScatterEnd(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
233       ierr = VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);CHKERRQ(ierr);
234       ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
235       ierr = VecResetArray(work1);CHKERRQ(ierr);
236       ierr = VecResetArray(work2);CHKERRQ(ierr);
237     }
238   }
239 
240   if (basis_dofs) {
241     if (nnsp_has_cnst) {
242       ierr = VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);CHKERRQ(ierr);
243       ierr = VecSet(work1,one);CHKERRQ(ierr);
244       ierr = VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);CHKERRQ(ierr);
245       ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
246       ierr = VecResetArray(work1);CHKERRQ(ierr);
247       ierr = VecResetArray(work2);CHKERRQ(ierr);
248     }
249     ierr = VecDestroy(&work1);CHKERRQ(ierr);
250     ierr = VecDestroy(&work2);CHKERRQ(ierr);
251     ierr = VecScatterDestroy(&scatter_ctx);CHKERRQ(ierr);
252     ierr = MatDenseRestoreArray(shell_ctx->basis_mat,&basis_mat);CHKERRQ(ierr);
253     ierr = MatDenseRestoreArray(shell_ctx->Kbasis_mat,&Kbasis_mat);CHKERRQ(ierr);
254 
255     /* Assemble another Mat object in shell context */
256     ierr = MatTransposeMatMult(shell_ctx->basis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&small_mat);CHKERRQ(ierr);
257     ierr = MatFactorInfoInitialize(&matinfo);CHKERRQ(ierr);
258     ierr = ISCreateStride(PETSC_COMM_SELF,basis_size,0,1,&is_aux);CHKERRQ(ierr);
259     ierr = MatLUFactor(small_mat,is_aux,is_aux,&matinfo);CHKERRQ(ierr);
260     ierr = ISDestroy(&is_aux);CHKERRQ(ierr);
261     ierr = PetscMalloc1(basis_size*basis_size,&array_mat);CHKERRQ(ierr);
262     for (k=0;k<basis_size;k++) {
263       ierr = VecSet(shell_ctx->work_small_1,zero);CHKERRQ(ierr);
264       ierr = VecSetValue(shell_ctx->work_small_1,k,one,INSERT_VALUES);CHKERRQ(ierr);
265       ierr = VecAssemblyBegin(shell_ctx->work_small_1);CHKERRQ(ierr);
266       ierr = VecAssemblyEnd(shell_ctx->work_small_1);CHKERRQ(ierr);
267       ierr = MatSolve(small_mat,shell_ctx->work_small_1,shell_ctx->work_small_2);CHKERRQ(ierr);
268       ierr = VecGetArrayRead(shell_ctx->work_small_2,(const PetscScalar**)&array);CHKERRQ(ierr);
269       for (i=0;i<basis_size;i++) {
270         array_mat[i*basis_size+k]=array[i];
271       }
272       ierr = VecRestoreArrayRead(shell_ctx->work_small_2,(const PetscScalar**)&array);CHKERRQ(ierr);
273     }
274     ierr = MatCreateSeqDense(PETSC_COMM_SELF,basis_size,basis_size,array_mat,&inv_small_mat);CHKERRQ(ierr);
275     ierr = MatMatMult(shell_ctx->basis_mat,inv_small_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&shell_ctx->Lbasis_mat);CHKERRQ(ierr);
276     ierr = PetscFree(array_mat);CHKERRQ(ierr);
277     ierr = MatDestroy(&inv_small_mat);CHKERRQ(ierr);
278     ierr = MatDestroy(&small_mat);CHKERRQ(ierr);
279     ierr = MatScale(shell_ctx->Kbasis_mat,m_one);CHKERRQ(ierr);
280 
281     /* Rebuild local PC */
282     ierr = KSPGetPC(*local_ksp,&shell_ctx->local_pc);CHKERRQ(ierr);
283     ierr = PetscObjectReference((PetscObject)shell_ctx->local_pc);CHKERRQ(ierr);
284     ierr = PCCreate(PETSC_COMM_SELF,&newpc);CHKERRQ(ierr);
285     ierr = PCSetOperators(newpc,local_mat,local_mat);CHKERRQ(ierr);
286     ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
287     ierr = PCShellSetContext(newpc,shell_ctx);CHKERRQ(ierr);
288     ierr = PCShellSetApply(newpc,PCBDDCApplyNullSpaceCorrectionPC);CHKERRQ(ierr);
289     ierr = PCShellSetDestroy(newpc,PCBDDCDestroyNullSpaceCorrectionPC);CHKERRQ(ierr);
290     ierr = PCSetUp(newpc);CHKERRQ(ierr);
291     ierr = KSPSetPC(*local_ksp,newpc);CHKERRQ(ierr);
292     ierr = PCDestroy(&newpc);CHKERRQ(ierr);
293     ierr = KSPSetUp(*local_ksp);CHKERRQ(ierr);
294   }
295   /* test */
296   if (pcbddc->dbg_flag && basis_dofs) {
297     KSP         check_ksp;
298     PC          check_pc;
299     Mat         test_mat;
300     Vec         work3;
301     PetscReal   test_err,lambda_min,lambda_max;
302     PetscBool   setsym,issym=PETSC_FALSE;
303     PetscInt    tabs;
304 
305     ierr = PetscViewerASCIIGetTab(pcbddc->dbg_viewer,&tabs);CHKERRQ(ierr);
306     ierr = KSPGetPC(*local_ksp,&check_pc);CHKERRQ(ierr);
307     ierr = VecDuplicate(shell_ctx->work_full_1,&work1);CHKERRQ(ierr);
308     ierr = VecDuplicate(shell_ctx->work_full_1,&work2);CHKERRQ(ierr);
309     ierr = VecDuplicate(shell_ctx->work_full_1,&work3);CHKERRQ(ierr);
310     ierr = VecSetRandom(shell_ctx->work_small_1,NULL);CHKERRQ(ierr);
311     ierr = MatMult(shell_ctx->basis_mat,shell_ctx->work_small_1,work1);CHKERRQ(ierr);
312     ierr = VecCopy(work1,work2);CHKERRQ(ierr);
313     ierr = MatMult(local_mat,work1,work3);CHKERRQ(ierr);
314     ierr = PCApply(check_pc,work3,work1);CHKERRQ(ierr);
315     ierr = VecAXPY(work1,m_one,work2);CHKERRQ(ierr);
316     ierr = VecNorm(work1,NORM_INFINITY,&test_err);CHKERRQ(ierr);
317     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d error for nullspace correction for ",PetscGlobalRank);
318     ierr = PetscViewerASCIIUseTabs(pcbddc->dbg_viewer,PETSC_FALSE);CHKERRQ(ierr);
319     if (basis_dofs == n_I) {
320       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Dirichlet ");
321     } else {
322       ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Neumann ");
323     }
324     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"solver is :%1.14e\n",test_err);
325     ierr = PetscViewerASCIISetTab(pcbddc->dbg_viewer,tabs);CHKERRQ(ierr);
326     ierr = PetscViewerASCIIUseTabs(pcbddc->dbg_viewer,PETSC_TRUE);CHKERRQ(ierr);
327 
328     ierr = MatTransposeMatMult(shell_ctx->Lbasis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&test_mat);CHKERRQ(ierr);
329     ierr = MatShift(test_mat,one);CHKERRQ(ierr);
330     ierr = MatNorm(test_mat,NORM_INFINITY,&test_err);CHKERRQ(ierr);
331     ierr = MatDestroy(&test_mat);CHKERRQ(ierr);
332     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d error for nullspace matrices is :%1.14e\n",PetscGlobalRank,test_err);
333 
334     /* Create ksp object suitable for extreme eigenvalues' estimation */
335     ierr = KSPCreate(PETSC_COMM_SELF,&check_ksp);CHKERRQ(ierr);
336     ierr = KSPSetOperators(check_ksp,local_mat,local_mat);CHKERRQ(ierr);
337     ierr = KSPSetTolerances(check_ksp,1.e-8,1.e-8,PETSC_DEFAULT,basis_dofs);CHKERRQ(ierr);
338     ierr = KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);CHKERRQ(ierr);
339     ierr = MatIsSymmetricKnown(pc->pmat,&setsym,&issym);CHKERRQ(ierr);
340     if (issym) {
341       ierr = KSPSetType(check_ksp,KSPCG);CHKERRQ(ierr);
342     }
343     ierr = KSPSetPC(check_ksp,check_pc);CHKERRQ(ierr);
344     ierr = KSPSetUp(check_ksp);CHKERRQ(ierr);
345     ierr = VecSetRandom(work1,NULL);CHKERRQ(ierr);
346     ierr = MatMult(local_mat,work1,work2);CHKERRQ(ierr);
347     ierr = KSPSolve(check_ksp,work2,work2);CHKERRQ(ierr);
348     ierr = VecAXPY(work2,m_one,work1);CHKERRQ(ierr);
349     ierr = VecNorm(work2,NORM_INFINITY,&test_err);CHKERRQ(ierr);
350     ierr = KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);CHKERRQ(ierr);
351     ierr = KSPGetIterationNumber(check_ksp,&k);CHKERRQ(ierr);
352     ierr = PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d error for adapted KSP %1.14e (it %d, eigs %1.6e %1.6e)\n",PetscGlobalRank,test_err,k,lambda_min,lambda_max);
353     ierr = KSPDestroy(&check_ksp);CHKERRQ(ierr);
354     ierr = VecDestroy(&work1);CHKERRQ(ierr);
355     ierr = VecDestroy(&work2);CHKERRQ(ierr);
356     ierr = VecDestroy(&work3);CHKERRQ(ierr);
357   }
358   /* all processes shoud call this, even the void ones */
359   if (pcbddc->dbg_flag) {
360     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
361   }
362   PetscFunctionReturn(0);
363 }
364 
365 #undef __FUNCT__
366 #define __FUNCT__ "PCBDDCNullSpaceAdaptGlobal"
367 PetscErrorCode PCBDDCNullSpaceAdaptGlobal(PC pc)
368 {
369   PC_IS*         pcis = (PC_IS*)(pc->data);
370   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
371   KSP            inv_change;
372   const Vec      *nsp_vecs;
373   Vec            *new_nsp_vecs;
374   PetscInt       i,nsp_size,new_nsp_size,start_new;
375   PetscBool      nsp_has_cnst;
376   MatNullSpace   new_nsp;
377   PetscErrorCode ierr;
378 
379   PetscFunctionBegin;
380   /* create KSP for change of basis */
381   ierr = MatGetSize(pcbddc->ChangeOfBasisMatrix,&i,NULL);CHKERRQ(ierr);
382   ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&inv_change);CHKERRQ(ierr);
383   ierr = KSPSetOperators(inv_change,pcbddc->ChangeOfBasisMatrix,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
384   ierr = KSPSetTolerances(inv_change,1.e-8,1.e-8,PETSC_DEFAULT,2*i);CHKERRQ(ierr);
385   if (pcbddc->dbg_flag) {
386     ierr = KSPMonitorSet(inv_change,KSPMonitorDefault,pcbddc->dbg_viewer,NULL);CHKERRQ(ierr);
387   }
388   ierr = KSPSetUp(inv_change);CHKERRQ(ierr);
389 
390   /* get nullspace and transform it */
391   ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr);
392   new_nsp_size = nsp_size;
393   if (nsp_has_cnst) {
394     new_nsp_size++;
395   }
396   ierr = VecDuplicateVecs(pcis->vec1_global,new_nsp_size,&new_nsp_vecs);CHKERRQ(ierr);
397 
398   start_new = 0;
399   if (nsp_has_cnst) {
400     start_new = 1;
401     ierr = VecSet(new_nsp_vecs[0],1.0);CHKERRQ(ierr);
402     if (pcbddc->dbg_flag) {
403       ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
404       ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping constant in nullspace\n");CHKERRQ(ierr);
405     }
406     ierr = KSPSolve(inv_change,new_nsp_vecs[0],new_nsp_vecs[0]);CHKERRQ(ierr);
407   }
408   for (i=0;i<nsp_size;i++) {
409     ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr);
410     ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping %dth vector in nullspace\n",i);CHKERRQ(ierr);
411     ierr = KSPSolve(inv_change,nsp_vecs[i],new_nsp_vecs[i+start_new]);CHKERRQ(ierr);
412   }
413   ierr = PCBDDCOrthonormalizeVecs(new_nsp_size,new_nsp_vecs);CHKERRQ(ierr);
414   ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,new_nsp_size,new_nsp_vecs,&new_nsp);CHKERRQ(ierr);
415   ierr = PCBDDCSetNullSpace(pc,new_nsp);CHKERRQ(ierr);
416 
417   /* free */
418   ierr = KSPDestroy(&inv_change);CHKERRQ(ierr);
419   ierr = MatNullSpaceDestroy(&new_nsp);CHKERRQ(ierr);
420   ierr = VecDestroyVecs(new_nsp_size,&new_nsp_vecs);CHKERRQ(ierr);
421 
422   /* check */
423   if (pcbddc->dbg_flag) {
424     PetscBool nsp_t=PETSC_FALSE;
425     Mat       temp_mat;
426     Mat_IS*   matis = (Mat_IS*)pc->pmat->data;
427 
428     temp_mat = matis->A;
429     matis->A = pcbddc->local_mat;
430     pcbddc->local_mat = temp_mat;
431     ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr);
432     ierr = PetscPrintf(PetscObjectComm((PetscObject)(pc->pmat)),"Check nullspace with change of basis: %d\n",nsp_t);CHKERRQ(ierr);
433     temp_mat = matis->A;
434     matis->A = pcbddc->local_mat;
435     pcbddc->local_mat = temp_mat;
436   }
437   PetscFunctionReturn(0);
438 }
439