1 #define PETSCKSP_DLL 2 3 /* 4 The basic KSP routines, Create, View etc. are here. 5 */ 6 #include "include/private/kspimpl.h" /*I "petscksp.h" I*/ 7 #include "petscsys.h" 8 9 /* Logging support */ 10 PetscCookie PETSCKSP_DLLEXPORT KSP_COOKIE = 0; 11 PetscEvent KSP_GMRESOrthogonalization = 0, KSP_SetUp = 0, KSP_Solve = 0; 12 13 14 PetscTruth KSPRegisterAllCalled = PETSC_FALSE; 15 16 #undef __FUNCT__ 17 #define __FUNCT__ "KSPView" 18 /*@C 19 KSPView - Prints the KSP data structure. 20 21 Collective on KSP 22 23 Input Parameters: 24 + ksp - the Krylov space context 25 - viewer - visualization context 26 27 Options Database Keys: 28 . -ksp_view - print the ksp data structure at the end of a KSPSolve call 29 30 Note: 31 The available visualization contexts include 32 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 33 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 34 output where only the first processor opens 35 the file. All other processors send their 36 data to the first processor to print. 37 38 The user can open an alternative visualization context with 39 PetscViewerASCIIOpen() - output to a specified file. 40 41 Level: beginner 42 43 .keywords: KSP, view 44 45 .seealso: PCView(), PetscViewerASCIIOpen() 46 @*/ 47 PetscErrorCode PETSCKSP_DLLEXPORT KSPView(KSP ksp,PetscViewer viewer) 48 { 49 const char *type; 50 PetscErrorCode ierr; 51 PetscTruth iascii; 52 53 PetscFunctionBegin; 54 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 55 if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm); 56 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_COOKIE,2); 57 PetscCheckSameComm(ksp,1,viewer,2); 58 59 ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr); 60 if (iascii) { 61 ierr = KSPGetType(ksp,&type);CHKERRQ(ierr); 62 if (ksp->prefix) { 63 ierr = PetscViewerASCIIPrintf(viewer,"KSP Object:(%s)\n",ksp->prefix);CHKERRQ(ierr); 64 } else { 65 ierr = PetscViewerASCIIPrintf(viewer,"KSP Object:\n");CHKERRQ(ierr); 66 } 67 if (type) { 68 ierr = PetscViewerASCIIPrintf(viewer," type: %s\n",type);CHKERRQ(ierr); 69 } else { 70 ierr = PetscViewerASCIIPrintf(viewer," type: not yet set\n");CHKERRQ(ierr); 71 } 72 if (ksp->ops->view) { 73 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 74 ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); 75 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 76 } 77 if (ksp->guess_zero) {ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D, initial guess is zero\n",ksp->max_it);CHKERRQ(ierr);} 78 else {ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D\n", ksp->max_it);CHKERRQ(ierr);} 79 if (ksp->guess_knoll) {ierr = PetscViewerASCIIPrintf(viewer," using preconditioner applied to right hand side for initial guess\n");CHKERRQ(ierr);} 80 ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%G, absolute=%G, divergence=%G\n",ksp->rtol,ksp->abstol,ksp->divtol);CHKERRQ(ierr); 81 if (ksp->pc_side == PC_RIGHT) {ierr = PetscViewerASCIIPrintf(viewer," right preconditioning\n");CHKERRQ(ierr);} 82 else if (ksp->pc_side == PC_SYMMETRIC) {ierr = PetscViewerASCIIPrintf(viewer," symmetric preconditioning\n");CHKERRQ(ierr);} 83 else {ierr = PetscViewerASCIIPrintf(viewer," left preconditioning\n");CHKERRQ(ierr);} 84 } else { 85 if (ksp->ops->view) { 86 ierr = (*ksp->ops->view)(ksp,viewer);CHKERRQ(ierr); 87 } 88 } 89 ierr = PCView(ksp->pc,viewer);CHKERRQ(ierr); 90 PetscFunctionReturn(0); 91 } 92 93 /* 94 Contains the list of registered KSP routines 95 */ 96 PetscFList KSPList = 0; 97 98 #undef __FUNCT__ 99 #define __FUNCT__ "KSPSetNormType" 100 /*@ 101 KSPSetNormType - Sets the norm that is used for convergence testing. 102 103 Collective on KSP 104 105 Input Parameter: 106 + ksp - Krylov solver context 107 - normtype - one of 108 $ KSP_NO_NORM - skips computing the norm, this should only be used if you are using 109 $ the Krylov method as a smoother with a fixed small number of iterations. 110 $ You must also call KSPSetConvergenceTest(ksp,KSPSkipConverged,PETSC_NULL); 111 $ supported only by CG, Richardson, Bi-CG-stab, CR, and CGS methods. 112 $ KSP_PRECONDITIONED_NORM - the default for left preconditioned solves, uses the l2 norm 113 $ of the preconditioned residual 114 $ KSP_UNPRECONDITIONED_NORM - uses the l2 norm of the true b - Ax residual, supported only by 115 $ CG, CHEBYCHEV, and RICHARDSON, automatically true for right (see KSPSetPreconditioningSide) 116 $ preconditioning.. 117 $ KSP_NATURAL_NORM - supported by cg, cr, and cgs 118 119 120 Options Database Key: 121 . -ksp_norm_type <none,preconditioned,unpreconditioned,natural> 122 123 Notes: 124 Currently only works with the CG, Richardson, Bi-CG-stab, CR, and CGS methods. 125 126 Level: advanced 127 128 .keywords: KSP, create, context, norms 129 130 .seealso: KSPSetUp(), KSPSolve(), KSPDestroy(), KSPSkipConverged() 131 @*/ 132 PetscErrorCode PETSCKSP_DLLEXPORT KSPSetNormType(KSP ksp,KSPNormType normtype) 133 { 134 PetscErrorCode ierr; 135 136 PetscFunctionBegin; 137 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 138 ksp->normtype = normtype; 139 if (normtype == KSP_NO_NORM) { 140 ierr = PetscInfo(ksp,"Warning seting KSPNormType to skip computing the norm\n\ 141 make sure you set the KSP convergence test to KSPSkipConvergence\n");CHKERRQ(ierr); 142 } 143 PetscFunctionReturn(0); 144 } 145 146 #undef __FUNCT__ 147 #define __FUNCT__ "KSPPublish_Petsc" 148 static PetscErrorCode KSPPublish_Petsc(PetscObject obj) 149 { 150 PetscFunctionBegin; 151 PetscFunctionReturn(0); 152 } 153 154 #undef __FUNCT__ 155 #define __FUNCT__ "KSPSetOperators" 156 /*@ 157 KSPSetOperators - Sets the matrix associated with the linear system 158 and a (possibly) different one associated with the preconditioner. 159 160 Collective on KSP and Mat 161 162 Input Parameters: 163 + ksp - the KSP context 164 . Amat - the matrix associated with the linear system 165 . Pmat - the matrix to be used in constructing the preconditioner, usually the 166 same as Amat. 167 - flag - flag indicating information about the preconditioner matrix structure 168 during successive linear solves. This flag is ignored the first time a 169 linear system is solved, and thus is irrelevant when solving just one linear 170 system. 171 172 Notes: 173 The flag can be used to eliminate unnecessary work in the preconditioner 174 during the repeated solution of linear systems of the same size. The 175 available options are 176 $ SAME_PRECONDITIONER - 177 $ Pmat is identical during successive linear solves. 178 $ This option is intended for folks who are using 179 $ different Amat and Pmat matrices and want to reuse the 180 $ same preconditioner matrix. For example, this option 181 $ saves work by not recomputing incomplete factorization 182 $ for ILU/ICC preconditioners. 183 $ SAME_NONZERO_PATTERN - 184 $ Pmat has the same nonzero structure during 185 $ successive linear solves. 186 $ DIFFERENT_NONZERO_PATTERN - 187 $ Pmat does not have the same nonzero structure. 188 189 Caution: 190 If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion 191 and does not check the structure of the matrix. If you erroneously 192 claim that the structure is the same when it actually is not, the new 193 preconditioner will not function correctly. Thus, use this optimization 194 feature carefully! 195 196 If in doubt about whether your preconditioner matrix has changed 197 structure or not, use the flag DIFFERENT_NONZERO_PATTERN. 198 199 Level: beginner 200 201 Alternative usage: If the operators have NOT been set with KSP/PCSetOperators() then the operators 202 are created in PC and returned to the user. In this case, if both operators 203 mat and pmat are requested, two DIFFERENT operators will be returned. If 204 only one is requested both operators in the PC will be the same (i.e. as 205 if one had called KSP/PCSetOperators() with the same argument for both Mats). 206 The user must set the sizes of the returned matrices and their type etc just 207 as if the user created them with MatCreate(). For example, 208 209 $ KSP/PCGetOperators(ksp/pc,&mat,PETSC_NULL,PETSC_NULL); is equivalent to 210 $ set size, type, etc of mat 211 212 $ MatCreate(comm,&mat); 213 $ KSP/PCSetOperators(ksp/pc,mat,mat,SAME_NONZERO_PATTERN); 214 $ PetscObjectDereference((PetscObject)mat); 215 $ set size, type, etc of mat 216 217 and 218 219 $ KSP/PCGetOperators(ksp/pc,&mat,&pmat,PETSC_NULL); is equivalent to 220 $ set size, type, etc of mat and pmat 221 222 $ MatCreate(comm,&mat); 223 $ MatCreate(comm,&pmat); 224 $ KSP/PCSetOperators(ksp/pc,mat,pmat,SAME_NONZERO_PATTERN); 225 $ PetscObjectDereference((PetscObject)mat); 226 $ PetscObjectDereference((PetscObject)pmat); 227 $ set size, type, etc of mat and pmat 228 229 The rational for this support is so that when creating a TS, SNES, or KSP the hierarchy 230 of underlying objects (i.e. SNES, KSP, PC, Mat) and their livespans can be completely 231 managed by the top most level object (i.e. the TS, SNES, or KSP). Another way to look 232 at this is when you create a SNES you do not NEED to create a KSP and attach it to 233 the SNES object (the SNES object manages it for you). Similarly when you create a KSP 234 you do not need to attach a PC to it (the KSP object manages the PC object for you). 235 Thus, why should YOU have to create the Mat and attach it to the SNES/KSP/PC, when 236 it can be created for you? 237 238 .keywords: KSP, set, operators, matrix, preconditioner, linear system 239 240 .seealso: KSPSolve(), KSPGetPC(), PCGetOperators(), PCSetOperators(), KSPGetOperators() 241 @*/ 242 PetscErrorCode PETSCKSP_DLLEXPORT KSPSetOperators(KSP ksp,Mat Amat,Mat Pmat,MatStructure flag) 243 { 244 PetscErrorCode ierr; 245 246 PetscFunctionBegin; 247 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 248 if (Amat) PetscValidHeaderSpecific(Amat,MAT_COOKIE,2); 249 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_COOKIE,3); 250 if (Amat) PetscCheckSameComm(ksp,1,Amat,2); 251 if (Pmat) PetscCheckSameComm(ksp,1,Pmat,3); 252 ierr = PCSetOperators(ksp->pc,Amat,Pmat,flag);CHKERRQ(ierr); 253 if (ksp->setupcalled > 1) ksp->setupcalled = 1; /* so that next solve call will call setup */ 254 PetscFunctionReturn(0); 255 } 256 257 #undef __FUNCT__ 258 #define __FUNCT__ "KSPGetOperators" 259 /*@ 260 KSPGetOperators - Gets the matrix associated with the linear system 261 and a (possibly) different one associated with the preconditioner. 262 263 Collective on KSP and Mat 264 265 Input Parameter: 266 . ksp - the KSP context 267 268 Output Parameters: 269 + Amat - the matrix associated with the linear system 270 . Pmat - the matrix to be used in constructing the preconditioner, usually the 271 same as Amat. 272 - flag - flag indicating information about the preconditioner matrix structure 273 during successive linear solves. This flag is ignored the first time a 274 linear system is solved, and thus is irrelevant when solving just one linear 275 system. 276 277 Level: intermediate 278 279 .keywords: KSP, set, get, operators, matrix, preconditioner, linear system 280 281 .seealso: KSPSolve(), KSPGetPC(), PCGetOperators(), PCSetOperators(), KSPSetOperators(), KSPGetOperatorsSet() 282 @*/ 283 PetscErrorCode PETSCKSP_DLLEXPORT KSPGetOperators(KSP ksp,Mat *Amat,Mat *Pmat,MatStructure *flag) 284 { 285 PetscErrorCode ierr; 286 287 PetscFunctionBegin; 288 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 289 ierr = PCGetOperators(ksp->pc,Amat,Pmat,flag);CHKERRQ(ierr); 290 PetscFunctionReturn(0); 291 } 292 293 #undef __FUNCT__ 294 #define __FUNCT__ "KSPGetOperatorsSet" 295 /*@C 296 KSPGetOperatorsSet - Determines if the matrix associated with the linear system and 297 possibly a different one associated with the preconditioner have been set in the KSP. 298 299 Not collective, though the results on all processes should be the same 300 301 Input Parameter: 302 . pc - the preconditioner context 303 304 Output Parameters: 305 + mat - the matrix associated with the linear system was set 306 - pmat - matrix associated with the preconditioner was set, usually the same 307 308 Level: intermediate 309 310 .keywords: KSP, get, operators, matrix, linear system 311 312 .seealso: PCSetOperators(), KSPGetOperators(), KSPSetOperators(), PCGetOperators(), PCGetOperatorsSet() 313 @*/ 314 PetscErrorCode PETSCKSP_DLLEXPORT KSPGetOperatorsSet(KSP ksp,PetscTruth *mat,PetscTruth *pmat) 315 { 316 PetscErrorCode ierr; 317 318 PetscFunctionBegin; 319 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 320 ierr = PCGetOperatorsSet(ksp->pc,mat,pmat);CHKERRQ(ierr); 321 PetscFunctionReturn(0); 322 } 323 324 #undef __FUNCT__ 325 #define __FUNCT__ "KSPCreate" 326 /*@ 327 KSPCreate - Creates the default KSP context. 328 329 Collective on MPI_Comm 330 331 Input Parameter: 332 . comm - MPI communicator 333 334 Output Parameter: 335 . ksp - location to put the KSP context 336 337 Notes: 338 The default KSP type is GMRES with a restart of 30, using modified Gram-Schmidt 339 orthogonalization. 340 341 Level: beginner 342 343 .keywords: KSP, create, context 344 345 .seealso: KSPSetUp(), KSPSolve(), KSPDestroy(), KSP 346 @*/ 347 PetscErrorCode PETSCKSP_DLLEXPORT KSPCreate(MPI_Comm comm,KSP *inksp) 348 { 349 KSP ksp; 350 PetscErrorCode ierr; 351 352 PetscFunctionBegin; 353 PetscValidPointer(inksp,2); 354 *inksp = 0; 355 #ifndef PETSC_USE_DYNAMIC_LIBRARIES 356 ierr = KSPInitializePackage(PETSC_NULL);CHKERRQ(ierr); 357 #endif 358 359 ierr = PetscHeaderCreate(ksp,_p_KSP,struct _KSPOps,KSP_COOKIE,-1,"KSP",comm,KSPDestroy,KSPView);CHKERRQ(ierr); 360 *inksp = ksp; 361 ksp->bops->publish = KSPPublish_Petsc; 362 363 ksp->type = -1; 364 ksp->max_it = 10000; 365 ksp->pc_side = PC_LEFT; 366 ksp->rtol = 1.e-5; 367 ksp->abstol = 1.e-50; 368 ksp->divtol = 1.e4; 369 370 ksp->normtype = KSP_PRECONDITIONED_NORM; 371 ksp->rnorm = 0.0; 372 ksp->its = 0; 373 ksp->guess_zero = PETSC_TRUE; 374 ksp->calc_sings = PETSC_FALSE; 375 ksp->res_hist = PETSC_NULL; 376 ksp->res_hist_len = 0; 377 ksp->res_hist_max = 0; 378 ksp->res_hist_reset = PETSC_TRUE; 379 ksp->numbermonitors = 0; 380 ksp->converged = KSPDefaultConverged; 381 ksp->ops->buildsolution = KSPDefaultBuildSolution; 382 ksp->ops->buildresidual = KSPDefaultBuildResidual; 383 384 ksp->ops->setfromoptions = 0; 385 386 ksp->vec_sol = 0; 387 ksp->vec_rhs = 0; 388 ksp->pc = 0; 389 390 ksp->ops->solve = 0; 391 ksp->ops->setup = 0; 392 ksp->ops->destroy = 0; 393 394 ksp->data = 0; 395 ksp->nwork = 0; 396 ksp->work = 0; 397 398 ksp->cnvP = 0; 399 400 ksp->reason = KSP_CONVERGED_ITERATING; 401 402 ksp->setupcalled = 0; 403 ierr = PetscPublishAll(ksp);CHKERRQ(ierr); 404 ierr = PCCreate(comm,&ksp->pc);CHKERRQ(ierr); 405 PetscFunctionReturn(0); 406 } 407 408 #undef __FUNCT__ 409 #define __FUNCT__ "KSPSetType" 410 /*@C 411 KSPSetType - Builds KSP for a particular solver. 412 413 Collective on KSP 414 415 Input Parameters: 416 + ksp - the Krylov space context 417 - type - a known method 418 419 Options Database Key: 420 . -ksp_type <method> - Sets the method; use -help for a list 421 of available methods (for instance, cg or gmres) 422 423 Notes: 424 See "petsc/include/petscksp.h" for available methods (for instance, 425 KSPCG or KSPGMRES). 426 427 Normally, it is best to use the KSPSetFromOptions() command and 428 then set the KSP type from the options database rather than by using 429 this routine. Using the options database provides the user with 430 maximum flexibility in evaluating the many different Krylov methods. 431 The KSPSetType() routine is provided for those situations where it 432 is necessary to set the iterative solver independently of the command 433 line or options database. This might be the case, for example, when 434 the choice of iterative solver changes during the execution of the 435 program, and the user's application is taking responsibility for 436 choosing the appropriate method. In other words, this routine is 437 not for beginners. 438 439 Level: intermediate 440 441 .keywords: KSP, set, method 442 443 .seealso: PCSetType(), KSPType 444 445 @*/ 446 PetscErrorCode PETSCKSP_DLLEXPORT KSPSetType(KSP ksp, KSPType type) 447 { 448 PetscErrorCode ierr,(*r)(KSP); 449 PetscTruth match; 450 451 PetscFunctionBegin; 452 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 453 PetscValidCharPointer(type,2); 454 455 ierr = PetscTypeCompare((PetscObject)ksp,type,&match);CHKERRQ(ierr); 456 if (match) PetscFunctionReturn(0); 457 458 if (ksp->data) { 459 /* destroy the old private KSP context */ 460 ierr = (*ksp->ops->destroy)(ksp);CHKERRQ(ierr); 461 ksp->data = 0; 462 } 463 /* Get the function pointers for the iterative method requested */ 464 if (!KSPRegisterAllCalled) {ierr = KSPRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 465 ierr = PetscFListFind(ksp->comm,KSPList,type,(void (**)(void)) &r);CHKERRQ(ierr); 466 if (!r) SETERRQ1(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown KSP type given: %s",type); 467 ksp->setupcalled = 0; 468 ierr = (*r)(ksp);CHKERRQ(ierr); 469 ierr = PetscObjectChangeTypeName((PetscObject)ksp,type);CHKERRQ(ierr); 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNCT__ 474 #define __FUNCT__ "KSPRegisterDestroy" 475 /*@ 476 KSPRegisterDestroy - Frees the list of KSP methods that were 477 registered by KSPRegisterDynamic(). 478 479 Not Collective 480 481 Level: advanced 482 483 .keywords: KSP, register, destroy 484 485 .seealso: KSPRegisterDynamic(), KSPRegisterAll() 486 @*/ 487 PetscErrorCode PETSCKSP_DLLEXPORT KSPRegisterDestroy(void) 488 { 489 PetscErrorCode ierr; 490 491 PetscFunctionBegin; 492 if (KSPList) { 493 ierr = PetscFListDestroy(&KSPList);CHKERRQ(ierr); 494 KSPList = 0; 495 } 496 KSPRegisterAllCalled = PETSC_FALSE; 497 PetscFunctionReturn(0); 498 } 499 500 #undef __FUNCT__ 501 #define __FUNCT__ "KSPGetType" 502 /*@C 503 KSPGetType - Gets the KSP type as a string from the KSP object. 504 505 Not Collective 506 507 Input Parameter: 508 . ksp - Krylov context 509 510 Output Parameter: 511 . name - name of KSP method 512 513 Level: intermediate 514 515 .keywords: KSP, get, method, name 516 517 .seealso: KSPSetType() 518 @*/ 519 PetscErrorCode PETSCKSP_DLLEXPORT KSPGetType(KSP ksp,KSPType *type) 520 { 521 PetscFunctionBegin; 522 PetscValidHeaderSpecific(ksp,KSP_COOKIE,1); 523 PetscValidPointer(type,2); 524 *type = ksp->type_name; 525 PetscFunctionReturn(0); 526 } 527 528 #undef __FUNCT__ 529 #define __FUNCT__ "KSPRegister" 530 /*@C 531 KSPRegister - See KSPRegisterDynamic() 532 533 Level: advanced 534 @*/ 535 PetscErrorCode PETSCKSP_DLLEXPORT KSPRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(KSP)) 536 { 537 PetscErrorCode ierr; 538 char fullname[PETSC_MAX_PATH_LEN]; 539 540 PetscFunctionBegin; 541 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 542 ierr = PetscFListAdd(&KSPList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr); 543 PetscFunctionReturn(0); 544 } 545 546 #undef __FUNCT__ 547 #define __FUNCT__ "KSPSetNullSpace" 548 /*@ 549 KSPSetNullSpace - Sets the null space of the operator 550 551 Collective on KSP 552 553 Input Parameters: 554 + ksp - the Krylov space object 555 - nullsp - the null space of the operator 556 557 Level: advanced 558 559 .seealso: KSPSetOperators(), MatNullSpaceCreate(), KSPGetNullSpace() 560 @*/ 561 PetscErrorCode PETSCKSP_DLLEXPORT KSPSetNullSpace(KSP ksp,MatNullSpace nullsp) 562 { 563 PetscErrorCode ierr; 564 565 PetscFunctionBegin; 566 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 567 if (ksp->nullsp) { ierr = MatNullSpaceDestroy(ksp->nullsp);CHKERRQ(ierr); } 568 ksp->nullsp = nullsp; 569 PetscFunctionReturn(0); 570 } 571 572 #undef __FUNCT__ 573 #define __FUNCT__ "KSPGetNullSpace" 574 /*@ 575 KSPGetNullSpace - Gets the null space of the operator 576 577 Collective on KSP 578 579 Input Parameters: 580 + ksp - the Krylov space object 581 - nullsp - the null space of the operator 582 583 Level: advanced 584 585 .seealso: KSPSetOperators(), MatNullSpaceCreate(), KSPSetNullSpace() 586 @*/ 587 PetscErrorCode PETSCKSP_DLLEXPORT KSPGetNullSpace(KSP ksp,MatNullSpace *nullsp) 588 { 589 PetscFunctionBegin; 590 *nullsp = ksp->nullsp; 591 PetscFunctionReturn(0); 592 } 593 594