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