Date: 2016-07-24T17:05:31+00:00

Actual source code: bddcnullspace.c
petsc-3.7.3 2016-07-24
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: }