1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesmfj.c,v 1.94 1999/10/04 23:23:03 balay Exp balay $"; 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 38 PetscFunctionBegin; 39 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 40 41 /* already set, so just return */ 42 if (PetscTypeCompare(ctx,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 ierr = FListConcat_Private(path,name,fullname); CHKERRQ(ierr); 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 ierr = PetscFree(ctx->ops);CHKERRQ(ierr); 155 ierr = PetscFree(ctx);CHKERRQ(ierr); 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 172 PetscFunctionBegin; 173 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 174 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 175 ierr = ViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr); 176 if (PetscTypeCompare(viewer,ASCII_VIEWER)) { 177 ierr = PetscFPrintf(comm,fd," SNES matrix-free approximation:\n");CHKERRQ(ierr); 178 ierr = PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 179 ierr = PetscFPrintf(ctx->comm,fd," Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr); 180 if (ctx->ops->view) { 181 ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 182 } 183 } else { 184 SETERRQ(1,1,"Viewer type not supported for this object"); 185 } 186 PetscFunctionReturn(0); 187 } 188 189 #undef __FUNC__ 190 #define __FUNC__ "MatSNESMFAssemblyEnd_Private" 191 /* 192 MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 193 allows the user to indicate the beginning of a new linear solve by calling 194 MatAssemblyXXX() on the matrix free matrix. This then allows the 195 MatSNESMFCreate_WP() to properly compute ||U|| only the first time 196 in the linear solver rather than every time. 197 */ 198 int MatSNESMFAssemblyEnd_Private(Mat J) 199 { 200 int ierr; 201 202 PetscFunctionBegin; 203 ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 204 PetscFunctionReturn(0); 205 } 206 207 208 #undef __FUNC__ 209 #define __FUNC__ "MatSNESMFMult_Private" 210 /* 211 MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector 212 product, y = F'(u)*a: 213 214 y ~= ( F(u + ha) - F(u) )/h, 215 where F = nonlinear function, as set by SNESSetFunction() 216 u = current iterate 217 h = difference interval 218 */ 219 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y) 220 { 221 MatSNESMFCtx ctx; 222 SNES snes; 223 Scalar h, mone = -1.0; 224 Vec w,U,F; 225 int ierr, (*eval_fct)(SNES,Vec,Vec)=0; 226 227 PetscFunctionBegin; 228 /* We log matrix-free matrix-vector products separately, so that we can 229 separate the performance monitoring from the cases that use conventional 230 storage. We may eventually modify event logging to associate events 231 with particular objects, hence alleviating the more general problem. */ 232 PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0); 233 234 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 235 snes = ctx->snes; 236 w = ctx->w; 237 ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); 238 239 /* 240 Compute differencing parameter 241 */ 242 if (!ctx->ops->compute) { 243 ierr = MatSNESMFSetType(mat,"default");CHKERRQ(ierr); 244 ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 245 } 246 ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr); 247 248 /* keep a record of the current differencing parameter h */ 249 ctx->currenth = h; 250 #if defined(PETSC_USE_COMPLEX) 251 PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h)); 252 #else 253 PLogInfo(mat,"Current differencing parameter: %g\n",h); 254 #endif 255 if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 256 ctx->historyh[ctx->ncurrenth] = h; 257 } 258 ctx->ncurrenth++; 259 260 /* w = u + ha */ 261 ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr); 262 263 264 if (!ctx->func) { 265 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 266 eval_fct = SNESComputeFunction; 267 ierr = SNESGetFunction(snes,&F,PETSC_NULL);CHKERRQ(ierr); 268 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 269 eval_fct = SNESComputeGradient; 270 ierr = SNESGetGradient(snes,&F,PETSC_NULL);CHKERRQ(ierr); 271 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class"); 272 ierr = eval_fct(snes,w,y);CHKERRQ(ierr); 273 } else { 274 F = ctx->funcvec; 275 /* compute func(U) as base for differencing */ 276 if (ctx->ncurrenth == 1) { 277 ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr); 278 } 279 ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr); 280 } 281 282 ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr); 283 h = 1.0/h; 284 ierr = VecScale(&h,y);CHKERRQ(ierr); 285 if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);} 286 287 PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0); 288 PetscFunctionReturn(0); 289 } 290 291 #undef __FUNC__ 292 #define __FUNC__ "MatCreateSNESMF" 293 /*@C 294 MatCreateSNESMF - Creates a matrix-free matrix context for use with 295 a SNES solver. This matrix can be used as the Jacobian argument for 296 the routine SNESSetJacobian(). 297 298 Collective on SNES and Vec 299 300 Input Parameters: 301 + snes - the SNES context 302 - x - vector where SNES solution is to be stored. 303 304 Output Parameter: 305 . J - the matrix-free matrix 306 307 Level: advanced 308 309 Notes: 310 The matrix-free matrix context merely contains the function pointers 311 and work space for performing finite difference approximations of 312 Jacobian-vector products, F'(u)*a, 313 314 The default code uses the following approach to compute h 315 316 .vb 317 F'(u)*a = [F(u+h*a) - F(u)]/h where 318 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 319 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 320 where 321 error_rel = square root of relative error in function evaluation 322 umin = minimum iterate parameter 323 .ve 324 325 The user can set the error_rel via MatSNESMFSetFunctionError() and 326 umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 327 of the users manual for details. 328 329 The user should call MatDestroy() when finished with the matrix-free 330 matrix context. 331 332 Options Database Keys: 333 + -snes_mf_err <error_rel> - Sets error_rel 334 . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 335 - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 336 337 .keywords: SNES, default, matrix-free, create, matrix 338 339 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 340 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 341 MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegister() 342 343 @*/ 344 int MatCreateSNESMF(SNES snes,Vec x, Mat *J) 345 { 346 MPI_Comm comm; 347 MatSNESMFCtx mfctx; 348 int n, nloc, ierr; 349 350 PetscFunctionBegin; 351 mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx); 352 PLogObjectMemory(snes,sizeof(MatSNESMFCtx)); 353 mfctx->comm = snes->comm; 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 ierr = PetscMemzero(mfctx->type_name,256*sizeof(char));CHKERRQ(ierr); 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 = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops); 370 mfctx->ops->compute = 0; 371 mfctx->ops->destroy = 0; 372 mfctx->ops->view = 0; 373 mfctx->ops->printhelp = 0; 374 mfctx->ops->setfromoptions = 0; 375 mfctx->hctx = 0; 376 377 mfctx->func = 0; 378 mfctx->funcctx = 0; 379 mfctx->funcvec = 0; 380 381 ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 382 ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 383 ierr = VecGetSize(x,&n);CHKERRQ(ierr); 384 ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr); 385 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 386 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 387 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 388 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr); 389 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 390 PLogObjectParent(*J,mfctx->w); 391 PLogObjectParent(snes,*J); 392 393 mfctx->mat = *J; 394 395 396 PetscFunctionReturn(0); 397 } 398 399 #undef __FUNC__ 400 #define __FUNC__ "MatSNESMFSetFromOptions" 401 /*@ 402 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 403 parameter. 404 405 Collective on Mat 406 407 Input Parameters: 408 . mat - the matrix obtained with MatCreateSNESMF() 409 410 Options Database Keys: 411 + -snes_mf_type - <default,wp> 412 - -snes_mf_err - square root of estimated relative error in function evaluation 413 414 Level: advanced 415 416 .keywords: SNES, matrix-free, parameters 417 418 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 419 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 420 @*/ 421 int MatSNESMFSetFromOptions(Mat mat) 422 { 423 MatSNESMFCtx mfctx; 424 int ierr,flg; 425 char ftype[256],p[64]; 426 427 PetscFunctionBegin; 428 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 429 if (mfctx) { 430 /* allow user to set the type */ 431 ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 432 if (flg) { 433 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 434 } 435 436 ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr); 437 if (mfctx->ops->setfromoptions) { 438 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 439 } 440 441 ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr); 442 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 443 if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);} 444 if (flg) { 445 ierr = (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr); 446 if (mfctx->ops->printhelp) { 447 ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 448 } 449 } 450 } 451 PetscFunctionReturn(0); 452 } 453 454 #undef __FUNC__ 455 #define __FUNC__ "MatSNESMFGetH" 456 /*@ 457 MatSNESMFGetH - Gets the last value that was used as the differencing 458 parameter. 459 460 Not Collective 461 462 Input Parameters: 463 . mat - the matrix obtained with MatCreateSNESMF() 464 465 Output Paramter: 466 . h - the differencing step size 467 468 Level: advanced 469 470 .keywords: SNES, matrix-free, parameters 471 472 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 473 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 474 @*/ 475 int MatSNESMFGetH(Mat mat,Scalar *h) 476 { 477 MatSNESMFCtx ctx; 478 int ierr; 479 480 PetscFunctionBegin; 481 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 482 if (ctx) { 483 *h = ctx->currenth; 484 } 485 PetscFunctionReturn(0); 486 } 487 488 #undef __FUNC__ 489 #define __FUNC__ "MatSNESMFKSPMonitor" 490 /* 491 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 492 SNES matrix free routines. Prints the differencing parameter used at 493 each step. 494 */ 495 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy) 496 { 497 PC pc; 498 MatSNESMFCtx ctx; 499 int ierr; 500 Mat mat; 501 MPI_Comm comm; 502 PetscTruth nonzeroinitialguess; 503 504 PetscFunctionBegin; 505 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 506 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 507 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 508 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 509 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 510 if (!ctx) { 511 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 512 } 513 if (n > 0 || nonzeroinitialguess) { 514 #if defined(PETSC_USE_COMPLEX) 515 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 516 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr); 517 #else 518 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 519 #endif 520 } else { 521 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 522 } 523 PetscFunctionReturn(0); 524 } 525 526 #undef __FUNC__ 527 #define __FUNC__ "MatSNESMFSetFunction" 528 /*@C 529 MatSNESMFSetFunction - Sets the function used in applying the matrix free. 530 531 Collective on Mat 532 533 Input Parameters: 534 + mat - the matrix free matrix created via MatCreateSNESMF() 535 . v - workspace vector 536 . func - the function to use 537 - funcctx - optional function context passed to function 538 539 Level: advanced 540 541 Notes: 542 If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 543 matrix inside your compute Jacobian routine 544 545 If this is not set then it will use the function set with SNESSetFunction() 546 547 .keywords: SNES, matrix-free, function 548 549 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 550 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 551 MatSNESMFKSPMonitor(), SNESetFunction() 552 @*/ 553 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 554 { 555 MatSNESMFCtx ctx; 556 int ierr; 557 558 PetscFunctionBegin; 559 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 560 if (ctx) { 561 ctx->func = func; 562 ctx->funcctx = funcctx; 563 ctx->funcvec = v; 564 } 565 PetscFunctionReturn(0); 566 } 567 568 569 #undef __FUNC__ 570 #define __FUNC__ "MatSNESMFSetFunctionError" 571 /*@ 572 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 573 matrix-vector products using finite differences. 574 575 Collective on Mat 576 577 Input Parameters: 578 + mat - the matrix free matrix created via MatCreateSNESMF() 579 - error_rel - relative error (should be set to the square root of 580 the relative error in the function evaluations) 581 582 Options Database Keys: 583 + -snes_mf_err <error_rel> - Sets error_rel 584 585 Level: advanced 586 587 Notes: 588 The default matrix-free matrix-vector product routine computes 589 .vb 590 F'(u)*a = [F(u+h*a) - F(u)]/h where 591 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 592 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 593 .ve 594 595 .keywords: SNES, matrix-free, parameters 596 597 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 598 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 599 MatSNESMFKSPMonitor() 600 @*/ 601 int MatSNESMFSetFunctionError(Mat mat,double error) 602 { 603 MatSNESMFCtx ctx; 604 int ierr; 605 606 PetscFunctionBegin; 607 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 608 if (ctx) { 609 if (error != PETSC_DEFAULT) ctx->error_rel = error; 610 } 611 PetscFunctionReturn(0); 612 } 613 614 #undef __FUNC__ 615 #define __FUNC__ "MatSNESMFAddNullSpace" 616 /*@ 617 MatSNESMFAddNullSpace - Provides a null space that an operator is 618 supposed to have. Since roundoff will create a small component in 619 the null space, if you know the null space you may have it 620 automatically removed. 621 622 Collective on Mat 623 624 Input Parameters: 625 + J - the matrix-free matrix context 626 - nullsp - object created with PCNullSpaceCreate() 627 628 Level: advanced 629 630 .keywords: SNES, matrix-free, null space 631 632 .seealso: PCNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 633 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 634 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 635 @*/ 636 int MatSNESMFAddNullSpace(Mat J,PCNullSpace nullsp) 637 { 638 int ierr; 639 MatSNESMFCtx ctx; 640 MPI_Comm comm; 641 642 PetscFunctionBegin; 643 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 644 645 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 646 /* no context indicates that it is not the "matrix free" matrix type */ 647 if (!ctx) PetscFunctionReturn(0); 648 ctx->sp = nullsp; 649 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 650 PetscFunctionReturn(0); 651 } 652 653 #undef __FUNC__ 654 #define __FUNC__ "MatSNESMFSetHHistory" 655 /*@ 656 MatSNESMFSetHHistory - Sets an array to collect a history of the 657 differencing values (h) computed for the matrix-free product. 658 659 Collective on Mat 660 661 Input Parameters: 662 + J - the matrix-free matrix context 663 . histroy - space to hold the history 664 - nhistory - number of entries in history, if more entries are generated than 665 nhistory, then the later ones are discarded 666 667 Level: advanced 668 669 Notes: 670 Use MatSNESMFResetHHistory() to reset the history counter and collect 671 a new batch of differencing parameters, h. 672 673 .keywords: SNES, matrix-free, h history, differencing history 674 675 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 676 MatSNESMFResetHHistory(), 677 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 678 679 @*/ 680 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 681 { 682 int ierr; 683 MatSNESMFCtx ctx; 684 685 PetscFunctionBegin; 686 687 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 688 /* no context indicates that it is not the "matrix free" matrix type */ 689 if (!ctx) PetscFunctionReturn(0); 690 ctx->historyh = history; 691 ctx->maxcurrenth = nhistory; 692 ctx->currenth = 0; 693 694 PetscFunctionReturn(0); 695 } 696 697 #undef __FUNC__ 698 #define __FUNC__ "MatSNESMFResetHHistory" 699 /*@ 700 MatSNESMFResetHHistory - Resets the counter to zero to begin 701 collecting a new set of differencing histories. 702 703 Collective on Mat 704 705 Input Parameters: 706 . J - the matrix-free matrix context 707 708 Level: advanced 709 710 Notes: 711 Use MatSNESMFSetHHistory() to create the original history counter. 712 713 .keywords: SNES, matrix-free, h history, differencing history 714 715 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 716 MatSNESMFSetHHistory(), 717 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 718 719 @*/ 720 int MatSNESMFResetHHistory(Mat J) 721 { 722 int ierr; 723 MatSNESMFCtx ctx; 724 725 PetscFunctionBegin; 726 727 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 728 /* no context indicates that it is not the "matrix free" matrix type */ 729 if (!ctx) PetscFunctionReturn(0); 730 ctx->ncurrenth = 0; 731 732 PetscFunctionReturn(0); 733 } 734 735