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