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