1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesmfj.c,v 1.81 1999/03/19 21:22:38 bsmith Exp curfman $"; 3 #endif 4 5 #include "src/snes/snesimpl.h" 6 #include "src/snes/mf/snesmfj.h" /*I "snes.h" I*/ 7 8 FList MatSNESMFList = 0; 9 int MatSNESMFRegisterAllCalled = 0; 10 11 #undef __FUNC__ 12 #define __FUNC__ "MatSNESMFSetType" 13 /*@ 14 MatSNESMFSetType - Sets the method that is used to compute the 15 differencing parameter for finite difference matrix-free formulations. 16 17 Input Parameters: 18 + mat - the matrix free matrix created via MatCreateSNESMF() 19 - ftype - the type requested 20 21 Level: advanced 22 23 Notes: 24 For example, such routines can compute h for use in 25 Jacobian-vector products of the form 26 27 F(x+ha) - F(x) 28 F'(u)a =approx ---------------- 29 h 30 31 .seealso: MatCreateSNESMF(), MatSNESMFRegister() 32 @*/ 33 int MatSNESMFSetType(Mat mat,char *ftype) 34 { 35 int ierr, (*r)(MatSNESMFCtx); 36 MatSNESMFCtx ctx; 37 38 PetscFunctionBegin; 39 ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 40 41 /* already set, so just return */ 42 if (PetscTypeCompare(ctx->type_name,ftype)) PetscFunctionReturn(0); 43 44 /* destroy the old one if it exists */ 45 if (ctx->ops->destroy) { 46 ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr); 47 } 48 49 /* Get the function pointers for the requrested method */ 50 if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL); CHKERRQ(ierr);} 51 52 ierr = FListFind(ctx->comm, MatSNESMFList, ftype,(int (**)(void *)) &r );CHKERRQ(ierr); 53 54 if (!r) SETERRQ(1,1,"Unknown MatSNESMF type given"); 55 56 ierr = (*r)(ctx); CHKERRQ(ierr); 57 ierr = PetscStrncpy(ctx->type_name,ftype,256);CHKERRQ(ierr); 58 59 PetscFunctionReturn(0); 60 } 61 62 /*MC 63 MatSNESMFRegister - Adds a method to the MatSNESMF registry. 64 65 Synopsis: 66 MatSNESMFRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF)) 67 68 Not Collective 69 70 Input Parameters: 71 + name_solver - name of a new user-defined compute-h module 72 . path - path (either absolute or relative) the library containing this solver 73 . name_create - name of routine to create method context 74 - routine_create - routine to create method context 75 76 Level: developer 77 78 Notes: 79 MatSNESMFRegister() may be called multiple times to add several user-defined solvers. 80 81 If dynamic libraries are used, then the fourth input argument (routine_create) 82 is ignored. 83 84 Sample usage: 85 .vb 86 MatSNESMFRegister("my_h",/home/username/my_lib/lib/libO/solaris/mylib.a, 87 "MyHCreate",MyHCreate); 88 .ve 89 90 Then, your solver can be chosen with the procedural interface via 91 $ MatSNESMFSetType(mfctx,"my_h") 92 or at runtime via the option 93 $ -snes_mf_type my_h 94 95 .keywords: MatSNESMF, register 96 97 .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy() 98 M*/ 99 100 #undef __FUNC__ 101 #define __FUNC__ "MatSNESMFRegister_Private" 102 int MatSNESMFRegister_Private(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx)) 103 { 104 int ierr; 105 char fullname[256]; 106 107 PetscFunctionBegin; 108 PetscStrcpy(fullname,path); PetscStrcat(fullname,":");PetscStrcat(fullname,name); 109 ierr = FListAdd_Private(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr); 110 PetscFunctionReturn(0); 111 } 112 113 114 #undef __FUNC__ 115 #define __FUNC__ "MatSNESMFRegisterDestroy" 116 /*@C 117 MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 118 registered by MatSNESMFRegister(). 119 120 Not Collective 121 122 Level: developer 123 124 .keywords: MatSNESMF, register, destroy 125 126 .seealso: MatSNESMFRegister(), MatSNESMFRegisterAll() 127 @*/ 128 int MatSNESMFRegisterDestroy(void) 129 { 130 int ierr; 131 132 PetscFunctionBegin; 133 if (MatSNESMFList) { 134 ierr = FListDestroy( MatSNESMFList );CHKERRQ(ierr); 135 MatSNESMFList = 0; 136 } 137 MatSNESMFRegisterAllCalled = 0; 138 PetscFunctionReturn(0); 139 } 140 141 /* ----------------------------------------------------------------------------------------*/ 142 #undef __FUNC__ 143 #define __FUNC__ "MatSNESMFDestroy_Private" 144 int MatSNESMFDestroy_Private(Mat mat) 145 { 146 int ierr; 147 MatSNESMFCtx ctx; 148 149 PetscFunctionBegin; 150 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 151 ierr = VecDestroy(ctx->w); CHKERRQ(ierr); 152 if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 153 if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 154 PetscFree(ctx->ops); 155 PetscFree(ctx); 156 PetscFunctionReturn(0); 157 } 158 159 #undef __FUNC__ 160 #define __FUNC__ "MatSNESMFView_Private" 161 /* 162 MatSNESMFView_Private - Views matrix-free parameters. 163 164 */ 165 int MatSNESMFView_Private(Mat J,Viewer viewer) 166 { 167 int ierr; 168 MatSNESMFCtx ctx; 169 MPI_Comm comm; 170 FILE *fd; 171 ViewerType vtype; 172 173 PetscFunctionBegin; 174 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 175 ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 176 ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 177 ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 178 if (PetscTypeCompare(vtype,ASCII_VIEWER)) { 179 PetscFPrintf(comm,fd," SNES matrix-free approximation:\n"); 180 PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel); 181 PetscFPrintf(ctx->comm,fd," Using %s compute h routine\n",ctx->type_name); 182 if (ctx->ops->view) { 183 ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 184 } 185 } else { 186 SETERRQ(1,1,"Viewer type not supported for this object"); 187 } 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNC__ 192 #define __FUNC__ "MatSNESMFAssemblyEnd_Private" 193 /* 194 MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 195 allows the user to indicate the beginning of a new linear solve by calling 196 MatAssemblyXXX() on the matrix free matrix. This then allows the 197 MatSNESMFCreate_WP() to properly compute ||U|| only the first time 198 in the linear solver rather than every time. 199 */ 200 int MatSNESMFAssemblyEnd_Private(Mat J) 201 { 202 int ierr; 203 204 PetscFunctionBegin; 205 ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 206 PetscFunctionReturn(0); 207 } 208 209 210 #undef __FUNC__ 211 #define __FUNC__ "MatSNESMFMult_Private" 212 /* 213 MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector 214 product, y = F'(u)*a: 215 216 y ~= ( F(u + ha) - F(u) )/h, 217 where F = nonlinear function, as set by SNESSetFunction() 218 u = current iterate 219 h = difference interval 220 */ 221 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y) 222 { 223 MatSNESMFCtx ctx; 224 SNES snes; 225 Scalar h, mone = -1.0; 226 Vec w,U,F; 227 int ierr, (*eval_fct)(SNES,Vec,Vec)=0; 228 229 PetscFunctionBegin; 230 /* We log matrix-free matrix-vector products separately, so that we can 231 separate the performance monitoring from the cases that use conventional 232 storage. We may eventually modify event logging to associate events 233 with particular objects, hence alleviating the more general problem. */ 234 PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0); 235 236 ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 237 snes = ctx->snes; 238 w = ctx->w; 239 240 ierr = SNESGetSolution(snes,&U); CHKERRQ(ierr); 241 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 242 eval_fct = SNESComputeFunction; 243 ierr = SNESGetFunction(snes,&F); CHKERRQ(ierr); 244 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 245 eval_fct = SNESComputeGradient; 246 ierr = SNESGetGradient(snes,&F); CHKERRQ(ierr); 247 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class"); 248 249 if (!ctx->ops->compute) { 250 ierr = MatSNESMFSetType(mat,"default");CHKERRQ(ierr); 251 ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 252 } 253 ierr = (*ctx->ops->compute)(ctx,U,a,&h); CHKERRQ(ierr); 254 255 /* keep a record of the current differencing parameter h */ 256 ctx->currenth = h; 257 #if defined(USE_PETSC_COMPLEX) 258 PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h)); 259 #else 260 PLogInfo(mat,"Current differencing parameter: %g\n",h); 261 #endif 262 if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 263 ctx->historyh[ctx->ncurrenth++] = h; 264 } else { 265 ctx->ncurrenth++; 266 } 267 268 /* Evaluate function at F(u + ha) */ 269 ierr = VecWAXPY(&h,a,U,w); CHKERRQ(ierr); 270 ierr = eval_fct(snes,w,y); CHKERRQ(ierr); 271 272 ierr = VecAXPY(&mone,F,y); CHKERRQ(ierr); 273 h = 1.0/h; 274 ierr = VecScale(&h,y); CHKERRQ(ierr); 275 if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y); CHKERRQ(ierr);} 276 277 PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0); 278 PetscFunctionReturn(0); 279 } 280 281 #undef __FUNC__ 282 #define __FUNC__ "MatCreateSNESMF" 283 /*@C 284 MatCreateSNESMF - Creates a matrix-free matrix context for use with 285 a SNES solver. This matrix can be used as the Jacobian argument for 286 the routine SNESSetJacobian(). 287 288 Collective on SNES and Vec 289 290 Input Parameters: 291 + snes - the SNES context 292 - x - vector where SNES solution is to be stored. 293 294 Output Parameter: 295 . J - the matrix-free matrix 296 297 Level: advanced 298 299 Notes: 300 The matrix-free matrix context merely contains the function pointers 301 and work space for performing finite difference approximations of 302 Jacobian-vector products, F'(u)*a, 303 304 The default code uses the following approach to compute h 305 306 .vb 307 F'(u)*a = [F(u+h*a) - F(u)]/h where 308 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 309 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 310 where 311 error_rel = square root of relative error in function evaluation 312 umin = minimum iterate parameter 313 .ve 314 315 The user can set the error_rel via MatSNESMFSetFunctionError() and 316 umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 317 of the users manual for details. 318 319 The user should call MatDestroy() when finished with the matrix-free 320 matrix context. 321 322 Options Database Keys: 323 + -snes_mf_err <error_rel> - Sets error_rel 324 . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 325 - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 326 327 .keywords: SNES, default, matrix-free, create, matrix 328 329 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 330 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 331 MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegister() 332 333 @*/ 334 int MatCreateSNESMF(SNES snes,Vec x, Mat *J) 335 { 336 MPI_Comm comm; 337 MatSNESMFCtx mfctx; 338 int n, nloc, ierr; 339 340 PetscFunctionBegin; 341 mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx)); CHKPTRQ(mfctx); 342 PLogObjectMemory(snes,sizeof(MatSNESMFCtx)); 343 mfctx->comm = snes->comm; 344 mfctx->sp = 0; 345 mfctx->snes = snes; 346 mfctx->error_rel = 1.e-8; /* assumes double precision */ 347 mfctx->currenth = 0.0; 348 mfctx->historyh = PETSC_NULL; 349 mfctx->ncurrenth = 0; 350 mfctx->maxcurrenth = 0; 351 352 /* 353 Create the empty data structure to contain compute-h routines. 354 These will be filled in below from the command line options or 355 a later call with MatSNESMFSetType() or if that is not called 356 then it will default in the first use of MatSNESMFMult_private() 357 */ 358 mfctx->ops = (MFOps *)PetscMalloc(sizeof(MFOps)); CHKPTRQ(mfctx->ops); 359 mfctx->ops->compute = 0; 360 mfctx->ops->destroy = 0; 361 mfctx->ops->view = 0; 362 mfctx->ops->printhelp = 0; 363 mfctx->ops->setfromoptions = 0; 364 mfctx->hctx = 0; 365 366 ierr = VecDuplicate(x,&mfctx->w); CHKERRQ(ierr); 367 ierr = PetscObjectGetComm((PetscObject)x,&comm); CHKERRQ(ierr); 368 ierr = VecGetSize(x,&n); CHKERRQ(ierr); 369 ierr = VecGetLocalSize(x,&nloc); CHKERRQ(ierr); 370 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J); CHKERRQ(ierr); 371 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 372 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 373 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private); CHKERRQ(ierr); 374 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 375 PLogObjectParent(*J,mfctx->w); 376 PLogObjectParent(snes,*J); 377 378 mfctx->mat = *J; 379 380 381 PetscFunctionReturn(0); 382 } 383 384 #undef __FUNC__ 385 #define __FUNC__ "MatSNESMFSetFromOptions" 386 /*@ 387 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 388 parameter. 389 390 Collective on Mat 391 392 Input Parameters: 393 . mat - the matrix obtained with MatCreateSNESMF() 394 395 Options Database Keys: 396 + -snes_mf_type - <default,wp> 397 - -snes_mf_err - square root of estimated relative error in function evaluation 398 399 Level: advanced 400 401 .keywords: SNES, matrix-free, parameters 402 403 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 404 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 405 @*/ 406 int MatSNESMFSetFromOptions(Mat mat) 407 { 408 MatSNESMFCtx mfctx; 409 int ierr,flg; 410 char ftype[256],p[64]; 411 412 PetscFunctionBegin; 413 ierr = MatShellGetContext(mat,(void **)&mfctx); CHKERRQ(ierr); 414 if (mfctx) { 415 /* allow user to set the type */ 416 ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 417 if (flg) { 418 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 419 } 420 421 ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr); 422 if (mfctx->ops->setfromoptions) { 423 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 424 } 425 426 ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr); 427 PetscStrcpy(p,"-"); 428 if (mfctx->snes->prefix) PetscStrcat(p,mfctx->snes->prefix); 429 if (flg) { 430 (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel); 431 if (mfctx->ops->printhelp) { 432 (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 433 } 434 } 435 } 436 PetscFunctionReturn(0); 437 } 438 439 #undef __FUNC__ 440 #define __FUNC__ "MatSNESMFGetH" 441 /*@ 442 MatSNESMFGetH - Gets the last value that was used as the differencing 443 parameter. 444 445 Not Collective 446 447 Input Parameters: 448 . mat - the matrix obtained with MatCreateSNESMF() 449 450 Output Paramter: 451 . h - the differencing step size 452 453 Level: advanced 454 455 .keywords: SNES, matrix-free, parameters 456 457 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 458 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 459 @*/ 460 int MatSNESMFGetH(Mat mat,Scalar *h) 461 { 462 MatSNESMFCtx ctx; 463 int ierr; 464 465 PetscFunctionBegin; 466 ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 467 if (ctx) { 468 *h = ctx->currenth; 469 } 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNC__ 474 #define __FUNC__ "MatSNESMFKSPMonitor" 475 /* 476 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 477 SNES matrix free routines. Prints the differencing parameter used at 478 each step. 479 */ 480 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy) 481 { 482 PC pc; 483 MatSNESMFCtx ctx; 484 int ierr; 485 Mat mat; 486 MPI_Comm comm; 487 PetscTruth nonzeroinitialguess; 488 489 PetscFunctionBegin; 490 ierr = PetscObjectGetComm((PetscObject)ksp,&comm); CHKERRQ(ierr); 491 ierr = KSPGetPC(ksp,&pc); CHKERRQ(ierr); 492 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess); CHKERRQ(ierr); 493 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr); 494 ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 495 if (!ctx) { 496 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 497 } 498 if (n > 0 || nonzeroinitialguess) { 499 #if defined(USE_PETSC_COMPLEX) 500 PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 501 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth)); 502 #else 503 PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth); 504 #endif 505 } else { 506 PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm); 507 } 508 PetscFunctionReturn(0); 509 } 510 511 #undef __FUNC__ 512 #define __FUNC__ "MatSNESMFSetFunctionError" 513 /*@ 514 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 515 matrix-vector products using finite differences. 516 517 Collective on Mat 518 519 Input Parameters: 520 + mat - the matrix free matrix created via MatCreateSNESMF() 521 - error_rel - relative error (should be set to the square root of 522 the relative error in the function evaluations) 523 524 Options Database Keys: 525 + -snes_mf_err <error_rel> - Sets error_rel 526 527 Level: advanced 528 529 Notes: 530 The default matrix-free matrix-vector product routine computes 531 .vb 532 F'(u)*a = [F(u+h*a) - F(u)]/h where 533 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 534 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 535 .ve 536 537 .keywords: SNES, matrix-free, parameters 538 539 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 540 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 541 MatSNESMFKSPMonitor() 542 @*/ 543 int MatSNESMFSetFunctionError(Mat mat,double error) 544 { 545 MatSNESMFCtx ctx; 546 int ierr; 547 548 PetscFunctionBegin; 549 ierr = MatShellGetContext(mat,(void **)&ctx); CHKERRQ(ierr); 550 if (ctx) { 551 if (error != PETSC_DEFAULT) ctx->error_rel = error; 552 } 553 PetscFunctionReturn(0); 554 } 555 556 #undef __FUNC__ 557 #define __FUNC__ "MatSNESMFAddNullSpace" 558 /*@ 559 MatSNESMFAddNullSpace - Provides a null space that an operator is 560 supposed to have. Since roundoff will create a small component in 561 the null space, if you know the null space you may have it 562 automatically removed. 563 564 Collective on Mat 565 566 Input Parameters: 567 + J - the matrix-free matrix context 568 . has_cnst - PETSC_TRUE or PETSC_FALSE, indicating whether null space has constants 569 . n - number of vectors (excluding constant vector) in null space 570 - vecs - the vectors that span the null space (excluding the constant vector); 571 these vectors must be orthonormal 572 573 Level: advanced 574 575 .keywords: SNES, matrix-free, null space 576 577 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 578 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 579 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 580 581 @*/ 582 int MatSNESMFAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs) 583 { 584 int ierr; 585 MatSNESMFCtx ctx; 586 MPI_Comm comm; 587 588 PetscFunctionBegin; 589 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 590 591 ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 592 /* no context indicates that it is not the "matrix free" matrix type */ 593 if (!ctx) PetscFunctionReturn(0); 594 ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp); CHKERRQ(ierr); 595 PetscFunctionReturn(0); 596 } 597 598 #undef __FUNC__ 599 #define __FUNC__ "MatSNESMFSetHHistory" 600 /*@ 601 MatSNESMFSetHHistory - Sets an array to collect a history of the 602 differencing values (h) computed for the matrix-free product. 603 604 Collective on Mat 605 606 Input Parameters: 607 + J - the matrix-free matrix context 608 . histroy - space to hold the history 609 - nhistory - number of entries in history, if more entries are generated than 610 nhistory, then the later ones are discarded 611 612 Level: advanced 613 614 Notes: 615 Use MatSNESMFResetHHistory() to reset the history counter and collect 616 a new batch of differencing parameters, h. 617 618 .keywords: SNES, matrix-free, h history, differencing history 619 620 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 621 MatSNESMFResetHHistory(), 622 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 623 624 @*/ 625 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 626 { 627 int ierr; 628 MatSNESMFCtx ctx; 629 630 PetscFunctionBegin; 631 632 ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 633 /* no context indicates that it is not the "matrix free" matrix type */ 634 if (!ctx) PetscFunctionReturn(0); 635 ctx->historyh = history; 636 ctx->maxcurrenth = nhistory; 637 ctx->currenth = 0; 638 639 PetscFunctionReturn(0); 640 } 641 642 #undef __FUNC__ 643 #define __FUNC__ "MatSNESMFResetHHistory" 644 /*@ 645 MatSNESMFResetHHistory - Resets the counter to zero to begin 646 collecting a new set of differencing histories. 647 648 Collective on Mat 649 650 Input Parameters: 651 . J - the matrix-free matrix context 652 653 Level: advanced 654 655 Notes: 656 Use MatSNESMFSetHHistory() to create the original history counter. 657 658 .keywords: SNES, matrix-free, h history, differencing history 659 660 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 661 MatSNESMFSetHHistory(), 662 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 663 664 @*/ 665 int MatSNESMFResetHHistory(Mat J) 666 { 667 int ierr; 668 MatSNESMFCtx ctx; 669 670 PetscFunctionBegin; 671 672 ierr = MatShellGetContext(J,(void **)&ctx); CHKERRQ(ierr); 673 /* no context indicates that it is not the "matrix free" matrix type */ 674 if (!ctx) PetscFunctionReturn(0); 675 ctx->ncurrenth = 0; 676 677 PetscFunctionReturn(0); 678 } 679 680