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