Actual source code: bddcnullspace.c

petsc-3.7.3 2016-08-01
Report Typos and Errors
  1: #include <../src/ksp/pc/impls/bddc/bddc.h>
  2: #include <../src/ksp/pc/impls/bddc/bddcprivate.h>

  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;

 19:   tempCoarseNullSpace = 0;
 20:   coarse_nsp_size = 0;
 21:   coarse_nsp_vecs = 0;
 22:   MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);
 23:   if (coarse_mat) {
 24:     PetscMalloc1(nsp_size+1,&coarse_nsp_vecs);
 25:     for (i=0;i<nsp_size+1;i++) {
 26:       MatCreateVecs(coarse_mat,&coarse_nsp_vecs[i],NULL);
 27:     }
 28:     if (pcbddc->dbg_flag) {
 29:       MatCreateVecs(coarse_mat,&wcoarse_vec,&wcoarse_rhs);
 30:     }
 31:   }
 32:   MatCreateVecs(pcbddc->ConstraintMatrix,&local_vec,&local_primal_vec);
 33:   if (nsp_has_cnst) {
 34:     VecSet(local_vec,1.0);
 35:     MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);
 36:     VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);
 37:     VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);
 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:         MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);
 45:         VecNorm(wcoarse_rhs,NORM_INFINITY,&test_null);
 46:         PetscViewerASCIIPrintf(dbg_viewer,"Constant coarse null space error % 1.14e\n",test_null);
 47:         PetscViewerFlush(dbg_viewer);
 48:       }
 49:       VecGetLocalSize(pcbddc->coarse_vec,&lsize);
 50:       VecGetArrayRead(pcbddc->coarse_vec,&array_in);
 51:       VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);
 52:       PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));
 53:       VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);
 54:       VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);
 55:       coarse_nsp_size++;
 56:     }
 57:   }
 58:   for (i=0;i<nsp_size;i++)  {
 59:     VecScatterBegin(matis->rctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);
 60:     VecScatterEnd(matis->rctx,nsp_vecs[i],local_vec,INSERT_VALUES,SCATTER_FORWARD);
 61:     MatMult(pcbddc->ConstraintMatrix,local_vec,local_primal_vec);
 62:     VecScatterBegin(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);
 63:     VecScatterEnd(pcbddc->coarse_loc_to_glob,local_primal_vec,pcbddc->coarse_vec,INSERT_VALUES,SCATTER_FORWARD);
 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:         MatMult(coarse_mat,wcoarse_vec,wcoarse_rhs);
 71:         VecNorm(wcoarse_rhs,NORM_2,&test_null);
 72:         PetscViewerASCIIPrintf(dbg_viewer,"Vec %d coarse null space error % 1.14e\n",i,test_null);
 73:         PetscViewerFlush(dbg_viewer);
 74:       }
 75:       VecGetLocalSize(pcbddc->coarse_vec,&lsize);
 76:       VecGetArrayRead(pcbddc->coarse_vec,&array_in);
 77:       VecGetArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);
 78:       PetscMemcpy(array_out,array_in,lsize*sizeof(PetscScalar));
 79:       VecRestoreArray(coarse_nsp_vecs[coarse_nsp_size],&array_out);
 80:       VecRestoreArrayRead(pcbddc->coarse_vec,&array_in);
 81:       coarse_nsp_size++;
 82:     }
 83:   }
 84:   if (coarse_nsp_size > 0) {
 85:     PCBDDCOrthonormalizeVecs(coarse_nsp_size,coarse_nsp_vecs);
 86:     MatNullSpaceCreate(PetscObjectComm((PetscObject)coarse_mat),PETSC_FALSE,coarse_nsp_size,coarse_nsp_vecs,&tempCoarseNullSpace);
 87:     for (i=0;i<nsp_size+1;i++) {
 88:       VecDestroy(&coarse_nsp_vecs[i]);
 89:     }
 90:   }
 91:   if (coarse_mat) {
 92:     PetscFree(coarse_nsp_vecs);
 93:     if (pcbddc->dbg_flag) {
 94:       VecDestroy(&wcoarse_vec);
 95:       VecDestroy(&wcoarse_rhs);
 96:     }
 97:   }
 98:   VecDestroy(&local_vec);
 99:   VecDestroy(&local_primal_vec);
100:   *CoarseNullSpace = tempCoarseNullSpace;
101:   return(0);
102: }


107: static PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC pc,Vec x,Vec y)
108: {
109:   NullSpaceCorrection_ctx pc_ctx;
110:   PetscErrorCode          ierr;

113:   PCShellGetContext(pc,(void**)&pc_ctx);
114:   /* E */
115:   MatMultTranspose(pc_ctx->Lbasis_mat,x,pc_ctx->work_small_2);
116:   MatMultAdd(pc_ctx->Kbasis_mat,pc_ctx->work_small_2,x,pc_ctx->work_full_1);
117:   /* P^-1 */
118:   PCApply(pc_ctx->local_pc,pc_ctx->work_full_1,pc_ctx->work_full_2);
119:   /* E^T */
120:   MatMultTranspose(pc_ctx->Kbasis_mat,pc_ctx->work_full_2,pc_ctx->work_small_1);
121:   VecScale(pc_ctx->work_small_1,-1.0);
122:   MatMultAdd(pc_ctx->Lbasis_mat,pc_ctx->work_small_1,pc_ctx->work_full_2,pc_ctx->work_full_1);
123:   /* Sum contributions */
124:   MatMultAdd(pc_ctx->basis_mat,pc_ctx->work_small_2,pc_ctx->work_full_1,y);
125:   return(0);
126: }

130: static PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC pc)
131: {
132:   NullSpaceCorrection_ctx pc_ctx;
133:   PetscErrorCode          ierr;

136:   PCShellGetContext(pc,(void**)&pc_ctx);
137:   VecDestroy(&pc_ctx->work_small_1);
138:   VecDestroy(&pc_ctx->work_small_2);
139:   VecDestroy(&pc_ctx->work_full_1);
140:   VecDestroy(&pc_ctx->work_full_2);
141:   MatDestroy(&pc_ctx->basis_mat);
142:   MatDestroy(&pc_ctx->Lbasis_mat);
143:   MatDestroy(&pc_ctx->Kbasis_mat);
144:   PCDestroy(&pc_ctx->local_pc);
145:   PetscFree(pc_ctx);
146:   return(0);
147: }

149: /*
150: PETSC_EXTERN PetscErrorCode PCBDDCApplyNullSpaceCorrectionPC(PC,Vec,Vec);
151: PETSC_EXTERN PetscErrorCode PCBDDCDestroyNullSpaceCorrectionPC(PC);
152: */

156: PetscErrorCode PCBDDCNullSpaceAssembleCorrection(PC pc, PetscBool isdir, 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;
173:   PetscBool      nnsp_has_cnst;

177:   /* Infer the local solver */
178:   ISGetSize(local_dofs,&basis_dofs);
179:   if (isdir) {
180:     /* Dirichlet solver */
181:     local_ksp = pcbddc->ksp_D;
182:   } else {
183:     /* Neumann solver */
184:     local_ksp = pcbddc->ksp_R;
185:   }
186:   KSPGetOperators(local_ksp,&local_mat,&local_pmat);

188:   /* Get null space vecs */
189:   MatNullSpaceGetVecs(pcbddc->NullSpace,&nnsp_has_cnst,&nnsp_size,&nullvecs);
190:   basis_size = nnsp_size;
191:   if (nnsp_has_cnst) {
192:     basis_size++;
193:   }

195:   if (basis_dofs) {
196:      /* Create shell ctx */
197:     PetscNew(&shell_ctx);

199:     /* Create work vectors in shell context */
200:     VecCreate(PETSC_COMM_SELF,&shell_ctx->work_small_1);
201:     VecSetSizes(shell_ctx->work_small_1,basis_size,basis_size);
202:     VecSetType(shell_ctx->work_small_1,VECSEQ);
203:     VecDuplicate(shell_ctx->work_small_1,&shell_ctx->work_small_2);
204:     VecCreate(PETSC_COMM_SELF,&shell_ctx->work_full_1);
205:     VecSetSizes(shell_ctx->work_full_1,basis_dofs,basis_dofs);
206:     VecSetType(shell_ctx->work_full_1,VECSEQ);
207:     VecDuplicate(shell_ctx->work_full_1,&shell_ctx->work_full_2);

209:     /* Allocate workspace */
210:     MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,NULL,&shell_ctx->basis_mat );
211:     MatCreateSeqDense(PETSC_COMM_SELF,basis_dofs,basis_size,NULL,&shell_ctx->Kbasis_mat);
212:     MatDenseGetArray(shell_ctx->basis_mat,&basis_mat);
213:     MatDenseGetArray(shell_ctx->Kbasis_mat,&Kbasis_mat);

215:     /* Restrict local null space on selected dofs (Dirichlet or Neumann)
216:        and compute matrices N and K*N */
217:     VecDuplicate(shell_ctx->work_full_1,&work1);
218:     VecDuplicate(shell_ctx->work_full_1,&work2);
219:     VecScatterCreate(pcis->vec1_N,local_dofs,work1,(IS)0,&scatter_ctx);
220:   }

222:   for (k=0;k<nnsp_size;k++) {
223:     VecScatterBegin(matis->rctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);
224:     VecScatterEnd(matis->rctx,nullvecs[k],pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);
225:     if (basis_dofs) {
226:       VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);
227:       VecScatterBegin(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);
228:       VecScatterEnd(scatter_ctx,pcis->vec1_N,work1,INSERT_VALUES,SCATTER_FORWARD);
229:       VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);
230:       MatMult(local_mat,work1,work2);
231:       VecResetArray(work1);
232:       VecResetArray(work2);
233:     }
234:   }

236:   if (basis_dofs) {
237:     if (nnsp_has_cnst) {
238:       VecPlaceArray(work1,(const PetscScalar*)&basis_mat[k*basis_dofs]);
239:       VecSet(work1,one);
240:       VecPlaceArray(work2,(const PetscScalar*)&Kbasis_mat[k*basis_dofs]);
241:       MatMult(local_mat,work1,work2);
242:       VecResetArray(work1);
243:       VecResetArray(work2);
244:     }
245:     VecDestroy(&work1);
246:     VecDestroy(&work2);
247:     VecScatterDestroy(&scatter_ctx);
248:     MatDenseRestoreArray(shell_ctx->basis_mat,&basis_mat);
249:     MatDenseRestoreArray(shell_ctx->Kbasis_mat,&Kbasis_mat);

251:     /* Assemble another Mat object in shell context */
252:     MatTransposeMatMult(shell_ctx->basis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&small_mat);
253:     MatFactorInfoInitialize(&matinfo);
254:     ISCreateStride(PETSC_COMM_SELF,basis_size,0,1,&is_aux);
255:     MatLUFactor(small_mat,is_aux,is_aux,&matinfo);
256:     ISDestroy(&is_aux);
257:     PetscMalloc1(basis_size*basis_size,&array_mat);
258:     for (k=0;k<basis_size;k++) {
259:       VecSet(shell_ctx->work_small_1,zero);
260:       VecSetValue(shell_ctx->work_small_1,k,one,INSERT_VALUES);
261:       VecAssemblyBegin(shell_ctx->work_small_1);
262:       VecAssemblyEnd(shell_ctx->work_small_1);
263:       MatSolve(small_mat,shell_ctx->work_small_1,shell_ctx->work_small_2);
264:       VecGetArrayRead(shell_ctx->work_small_2,(const PetscScalar**)&array);
265:       for (i=0;i<basis_size;i++) {
266:         array_mat[i*basis_size+k]=array[i];
267:       }
268:       VecRestoreArrayRead(shell_ctx->work_small_2,(const PetscScalar**)&array);
269:     }
270:     MatCreateSeqDense(PETSC_COMM_SELF,basis_size,basis_size,array_mat,&inv_small_mat);
271:     MatMatMult(shell_ctx->basis_mat,inv_small_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&shell_ctx->Lbasis_mat);
272:     PetscFree(array_mat);
273:     MatDestroy(&inv_small_mat);
274:     MatDestroy(&small_mat);
275:     MatScale(shell_ctx->Kbasis_mat,m_one);

277:     /* Rebuild local PC */
278:     KSPGetPC(local_ksp,&shell_ctx->local_pc);
279:     PetscObjectReference((PetscObject)shell_ctx->local_pc);
280:     PCCreate(PETSC_COMM_SELF,&newpc);
281:     PCSetOperators(newpc,local_mat,local_mat);
282:     PCSetType(newpc,PCSHELL);
283:     PCShellSetContext(newpc,shell_ctx);
284:     PCShellSetApply(newpc,PCBDDCApplyNullSpaceCorrectionPC);
285:     PCShellSetDestroy(newpc,PCBDDCDestroyNullSpaceCorrectionPC);
286:     PCSetUp(newpc);
287:     KSPSetPC(local_ksp,newpc);
288:     PCDestroy(&newpc);
289:     KSPSetUp(local_ksp);
290:   }
291:   /* test */
292:   if (pcbddc->dbg_flag && basis_dofs) {
293:     KSP         check_ksp;
294:     PC          check_pc;
295:     Mat         test_mat;
296:     Vec         work3;
297:     PetscReal   test_err,lambda_min,lambda_max;
298:     PetscBool   setsym,issym=PETSC_FALSE;
299:     PetscInt    tabs;

301:     PetscViewerASCIIGetTab(pcbddc->dbg_viewer,&tabs);
302:     KSPGetPC(local_ksp,&check_pc);
303:     VecDuplicate(shell_ctx->work_full_1,&work1);
304:     VecDuplicate(shell_ctx->work_full_1,&work2);
305:     VecDuplicate(shell_ctx->work_full_1,&work3);
306:     VecSetRandom(shell_ctx->work_small_1,NULL);
307:     MatMult(shell_ctx->basis_mat,shell_ctx->work_small_1,work1);
308:     VecCopy(work1,work2);
309:     MatMult(local_mat,work1,work3);
310:     PCApply(check_pc,work3,work1);
311:     VecAXPY(work1,m_one,work2);
312:     VecNorm(work1,NORM_INFINITY,&test_err);
313:     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d error for nullspace correction for ",PetscGlobalRank);
314:     PetscViewerASCIIUseTabs(pcbddc->dbg_viewer,PETSC_FALSE);
315:     if (isdir) {
316:       PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Dirichlet ");
317:     } else {
318:       PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Neumann ");
319:     }
320:     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"solver is :%1.14e\n",test_err);
321:     PetscViewerASCIISetTab(pcbddc->dbg_viewer,tabs);
322:     PetscViewerASCIIUseTabs(pcbddc->dbg_viewer,PETSC_TRUE);

324:     MatTransposeMatMult(shell_ctx->Lbasis_mat,shell_ctx->Kbasis_mat,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&test_mat);
325:     MatShift(test_mat,one);
326:     MatNorm(test_mat,NORM_INFINITY,&test_err);
327:     MatDestroy(&test_mat);
328:     PetscViewerASCIISynchronizedPrintf(pcbddc->dbg_viewer,"Subdomain %04d error for nullspace matrices is :%1.14e\n",PetscGlobalRank,test_err);

330:     /* Create ksp object suitable for extreme eigenvalues' estimation */
331:     KSPCreate(PETSC_COMM_SELF,&check_ksp);
332:     KSPSetErrorIfNotConverged(check_ksp,pc->erroriffailure);
333:     KSPSetOperators(check_ksp,local_mat,local_mat);
334:     KSPSetTolerances(check_ksp,1.e-8,1.e-8,PETSC_DEFAULT,basis_dofs);
335:     KSPSetComputeSingularValues(check_ksp,PETSC_TRUE);
336:     MatIsSymmetricKnown(pc->pmat,&setsym,&issym);
337:     if (issym) {
338:       KSPSetType(check_ksp,KSPCG);
339:     }
340:     KSPSetPC(check_ksp,check_pc);
341:     KSPSetUp(check_ksp);
342:     VecSetRandom(work1,NULL);
343:     MatMult(local_mat,work1,work2);
344:     KSPSolve(check_ksp,work2,work2);
345:     VecAXPY(work2,m_one,work1);
346:     VecNorm(work2,NORM_INFINITY,&test_err);
347:     KSPComputeExtremeSingularValues(check_ksp,&lambda_max,&lambda_min);
348:     KSPGetIterationNumber(check_ksp,&k);
349:     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);
350:     KSPDestroy(&check_ksp);
351:     VecDestroy(&work1);
352:     VecDestroy(&work2);
353:     VecDestroy(&work3);
354:   }
355:   /* all processes shoud call this, even the void ones */
356:   if (pcbddc->dbg_flag) {
357:     PetscViewerFlush(pcbddc->dbg_viewer);
358:   }
359:   return(0);
360: }

364: PetscErrorCode PCBDDCNullSpaceAdaptGlobal(PC pc)
365: {
366:   PC_IS*         pcis = (PC_IS*)(pc->data);
367:   PC_BDDC*       pcbddc = (PC_BDDC*)(pc->data);
368:   KSP            inv_change;
369:   const Vec      *nsp_vecs;
370:   Vec            *new_nsp_vecs;
371:   PetscInt       i,nsp_size,new_nsp_size,start_new;
372:   PetscBool      nsp_has_cnst;
373:   MatNullSpace   new_nsp;

377:   /* create KSP for change of basis */
378:   MatGetSize(pcbddc->ChangeOfBasisMatrix,&i,NULL);
379:   KSPCreate(PetscObjectComm((PetscObject)pc),&inv_change);
380:   KSPSetErrorIfNotConverged(inv_change,pc->erroriffailure);
381:   KSPSetOperators(inv_change,pcbddc->ChangeOfBasisMatrix,pcbddc->ChangeOfBasisMatrix);
382:   KSPSetTolerances(inv_change,1.e-8,1.e-8,PETSC_DEFAULT,2*i);
383:   KSPSetUp(inv_change);

385:   /* get nullspace and transform it */
386:   MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);
387:   new_nsp_size = nsp_size;
388:   if (nsp_has_cnst) {
389:     new_nsp_size++;
390:   }
391:   VecDuplicateVecs(pcis->vec1_global,new_nsp_size,&new_nsp_vecs);

393:   start_new = 0;
394:   if (nsp_has_cnst) {
395:     start_new = 1;
396:     VecSet(new_nsp_vecs[0],1.0);
397:     if (pcbddc->dbg_flag) {
398:       PetscViewerFlush(pcbddc->dbg_viewer);
399:       PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping constant in nullspace\n");
400:     }
401:     KSPSolve(inv_change,new_nsp_vecs[0],new_nsp_vecs[0]);
402:   }
403:   for (i=0;i<nsp_size;i++) {
404:     PetscViewerFlush(pcbddc->dbg_viewer);
405:     PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping %dth vector in nullspace\n",i);
406:     KSPSolve(inv_change,nsp_vecs[i],new_nsp_vecs[i+start_new]);
407:   }
408:   PCBDDCOrthonormalizeVecs(new_nsp_size,new_nsp_vecs);
409:   MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,new_nsp_size,new_nsp_vecs,&new_nsp);
410:   PCBDDCSetNullSpace(pc,new_nsp);

412:   /* free */
413:   KSPDestroy(&inv_change);
414:   MatNullSpaceDestroy(&new_nsp);
415:   VecDestroyVecs(new_nsp_size,&new_nsp_vecs);

417:   /* check */
418:   if (pcbddc->dbg_flag) {
419:     PetscBool nsp_t=PETSC_FALSE;
420:     Mat       temp_mat;
421:     Mat_IS*   matis = (Mat_IS*)pc->pmat->data;

423:     temp_mat = matis->A;
424:     matis->A = pcbddc->local_mat;
425:     pcbddc->local_mat = temp_mat;
426:     MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);
427:     PetscPrintf(PetscObjectComm((PetscObject)(pc->pmat)),"Check nullspace with change of basis: %d\n",nsp_t);
428:     temp_mat = matis->A;
429:     matis->A = pcbddc->local_mat;
430:     pcbddc->local_mat = temp_mat;
431:   }
432:   return(0);
433: }