1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesmfj.c,v 1.88 1999/06/30 22:51:53 bsmith 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->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 ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr); 109 PetscStrcat(fullname,":");PetscStrcat(fullname,name); 110 ierr = FListAdd_Private(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr); 111 PetscFunctionReturn(0); 112 } 113 114 115 #undef __FUNC__ 116 #define __FUNC__ "MatSNESMFRegisterDestroy" 117 /*@C 118 MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 119 registered by MatSNESMFRegister(). 120 121 Not Collective 122 123 Level: developer 124 125 .keywords: MatSNESMF, register, destroy 126 127 .seealso: MatSNESMFRegister(), MatSNESMFRegisterAll() 128 @*/ 129 int MatSNESMFRegisterDestroy(void) 130 { 131 int ierr; 132 133 PetscFunctionBegin; 134 if (MatSNESMFList) { 135 ierr = FListDestroy( MatSNESMFList );CHKERRQ(ierr); 136 MatSNESMFList = 0; 137 } 138 MatSNESMFRegisterAllCalled = 0; 139 PetscFunctionReturn(0); 140 } 141 142 /* ----------------------------------------------------------------------------------------*/ 143 #undef __FUNC__ 144 #define __FUNC__ "MatSNESMFDestroy_Private" 145 int MatSNESMFDestroy_Private(Mat mat) 146 { 147 int ierr; 148 MatSNESMFCtx ctx; 149 150 PetscFunctionBegin; 151 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 152 ierr = VecDestroy(ctx->w);CHKERRQ(ierr); 153 if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 154 if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 155 ierr = PetscFree(ctx->ops);CHKERRQ(ierr); 156 ierr = PetscFree(ctx);CHKERRQ(ierr); 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNC__ 161 #define __FUNC__ "MatSNESMFView_Private" 162 /* 163 MatSNESMFView_Private - Views matrix-free parameters. 164 165 */ 166 int MatSNESMFView_Private(Mat J,Viewer viewer) 167 { 168 int ierr; 169 MatSNESMFCtx ctx; 170 MPI_Comm comm; 171 FILE *fd; 172 ViewerType vtype; 173 174 PetscFunctionBegin; 175 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 176 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 177 ierr = ViewerGetType(viewer,&vtype);CHKERRQ(ierr); 178 ierr = ViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr); 179 if (PetscTypeCompare(vtype,ASCII_VIEWER)) { 180 ierr = PetscFPrintf(comm,fd," SNES matrix-free approximation:\n");CHKERRQ(ierr); 181 ierr = PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 182 ierr = PetscFPrintf(ctx->comm,fd," 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 SETERRQ(1,1,"Viewer type not supported for this object"); 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);CHKERRQ(ierr); 271 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 272 eval_fct = SNESComputeGradient; 273 ierr = SNESGetGradient(snes,&F);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 mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx); 355 PLogObjectMemory(snes,sizeof(MatSNESMFCtx)); 356 mfctx->comm = snes->comm; 357 mfctx->sp = 0; 358 mfctx->snes = snes; 359 mfctx->error_rel = 1.e-8; /* assumes double precision */ 360 mfctx->currenth = 0.0; 361 mfctx->historyh = PETSC_NULL; 362 mfctx->ncurrenth = 0; 363 mfctx->maxcurrenth = 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 = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops); 372 mfctx->ops->compute = 0; 373 mfctx->ops->destroy = 0; 374 mfctx->ops->view = 0; 375 mfctx->ops->printhelp = 0; 376 mfctx->ops->setfromoptions = 0; 377 mfctx->hctx = 0; 378 379 mfctx->func = 0; 380 mfctx->funcctx = 0; 381 mfctx->funcvec = 0; 382 383 ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 384 ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 385 ierr = VecGetSize(x,&n);CHKERRQ(ierr); 386 ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr); 387 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 388 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 389 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 390 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr); 391 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 392 PLogObjectParent(*J,mfctx->w); 393 PLogObjectParent(snes,*J); 394 395 mfctx->mat = *J; 396 397 398 PetscFunctionReturn(0); 399 } 400 401 #undef __FUNC__ 402 #define __FUNC__ "MatSNESMFSetFromOptions" 403 /*@ 404 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 405 parameter. 406 407 Collective on Mat 408 409 Input Parameters: 410 . mat - the matrix obtained with MatCreateSNESMF() 411 412 Options Database Keys: 413 + -snes_mf_type - <default,wp> 414 - -snes_mf_err - square root of estimated relative error in function evaluation 415 416 Level: advanced 417 418 .keywords: SNES, matrix-free, parameters 419 420 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 421 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 422 @*/ 423 int MatSNESMFSetFromOptions(Mat mat) 424 { 425 MatSNESMFCtx mfctx; 426 int ierr,flg; 427 char ftype[256],p[64]; 428 429 PetscFunctionBegin; 430 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 431 if (mfctx) { 432 /* allow user to set the type */ 433 ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 434 if (flg) { 435 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 436 } 437 438 ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr); 439 if (mfctx->ops->setfromoptions) { 440 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 441 } 442 443 ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr); 444 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 445 if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);} 446 if (flg) { 447 ierr = (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr); 448 if (mfctx->ops->printhelp) { 449 ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 450 } 451 } 452 } 453 PetscFunctionReturn(0); 454 } 455 456 #undef __FUNC__ 457 #define __FUNC__ "MatSNESMFGetH" 458 /*@ 459 MatSNESMFGetH - Gets the last value that was used as the differencing 460 parameter. 461 462 Not Collective 463 464 Input Parameters: 465 . mat - the matrix obtained with MatCreateSNESMF() 466 467 Output Paramter: 468 . h - the differencing step size 469 470 Level: advanced 471 472 .keywords: SNES, matrix-free, parameters 473 474 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 475 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 476 @*/ 477 int MatSNESMFGetH(Mat mat,Scalar *h) 478 { 479 MatSNESMFCtx ctx; 480 int ierr; 481 482 PetscFunctionBegin; 483 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 484 if (ctx) { 485 *h = ctx->currenth; 486 } 487 PetscFunctionReturn(0); 488 } 489 490 #undef __FUNC__ 491 #define __FUNC__ "MatSNESMFKSPMonitor" 492 /* 493 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 494 SNES matrix free routines. Prints the differencing parameter used at 495 each step. 496 */ 497 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy) 498 { 499 PC pc; 500 MatSNESMFCtx ctx; 501 int ierr; 502 Mat mat; 503 MPI_Comm comm; 504 PetscTruth nonzeroinitialguess; 505 506 PetscFunctionBegin; 507 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 508 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 509 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 510 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 511 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 512 if (!ctx) { 513 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 514 } 515 if (n > 0 || nonzeroinitialguess) { 516 #if defined(PETSC_USE_COMPLEX) 517 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 518 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr); 519 #else 520 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 521 #endif 522 } else { 523 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 524 } 525 PetscFunctionReturn(0); 526 } 527 528 #undef __FUNC__ 529 #define __FUNC__ "MatSNESMFSetFunction" 530 /*@C 531 MatSNESMFSetFunction - Sets the function used in applying the matrix free. 532 533 Collective on Mat 534 535 Input Parameters: 536 + mat - the matrix free matrix created via MatCreateSNESMF() 537 . v - workspace vector 538 . func - the function to use 539 - funcctx - optional function context passed to function 540 541 Level: advanced 542 543 Notes: 544 If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 545 matrix inside your compute Jacobian routine 546 547 If this is not set then it will use the function set with SNESSetFunction() 548 549 .keywords: SNES, matrix-free, function 550 551 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 552 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 553 MatSNESMFKSPMonitor(), SNESetFunction() 554 @*/ 555 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 556 { 557 MatSNESMFCtx ctx; 558 int ierr; 559 560 PetscFunctionBegin; 561 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 562 if (ctx) { 563 ctx->func = func; 564 ctx->funcctx = funcctx; 565 ctx->funcvec = v; 566 } 567 PetscFunctionReturn(0); 568 } 569 570 571 #undef __FUNC__ 572 #define __FUNC__ "MatSNESMFSetFunctionError" 573 /*@ 574 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 575 matrix-vector products using finite differences. 576 577 Collective on Mat 578 579 Input Parameters: 580 + mat - the matrix free matrix created via MatCreateSNESMF() 581 - error_rel - relative error (should be set to the square root of 582 the relative error in the function evaluations) 583 584 Options Database Keys: 585 + -snes_mf_err <error_rel> - Sets error_rel 586 587 Level: advanced 588 589 Notes: 590 The default matrix-free matrix-vector product routine computes 591 .vb 592 F'(u)*a = [F(u+h*a) - F(u)]/h where 593 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 594 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 595 .ve 596 597 .keywords: SNES, matrix-free, parameters 598 599 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 600 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 601 MatSNESMFKSPMonitor() 602 @*/ 603 int MatSNESMFSetFunctionError(Mat mat,double error) 604 { 605 MatSNESMFCtx ctx; 606 int ierr; 607 608 PetscFunctionBegin; 609 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 610 if (ctx) { 611 if (error != PETSC_DEFAULT) ctx->error_rel = error; 612 } 613 PetscFunctionReturn(0); 614 } 615 616 #undef __FUNC__ 617 #define __FUNC__ "MatSNESMFAddNullSpace" 618 /*@ 619 MatSNESMFAddNullSpace - Provides a null space that an operator is 620 supposed to have. Since roundoff will create a small component in 621 the null space, if you know the null space you may have it 622 automatically removed. 623 624 Collective on Mat 625 626 Input Parameters: 627 + J - the matrix-free matrix context 628 - nullsp - object created with PCNullSpaceCreate() 629 630 Level: advanced 631 632 .keywords: SNES, matrix-free, null space 633 634 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 635 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 636 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 637 638 @*/ 639 int MatSNESMFAddNullSpace(Mat J,PCNullSpace nullsp) 640 { 641 int ierr; 642 MatSNESMFCtx ctx; 643 MPI_Comm comm; 644 645 PetscFunctionBegin; 646 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 647 648 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 649 /* no context indicates that it is not the "matrix free" matrix type */ 650 if (!ctx) PetscFunctionReturn(0); 651 ctx->sp = nullsp; 652 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 653 PetscFunctionReturn(0); 654 } 655 656 #undef __FUNC__ 657 #define __FUNC__ "MatSNESMFSetHHistory" 658 /*@ 659 MatSNESMFSetHHistory - Sets an array to collect a history of the 660 differencing values (h) computed for the matrix-free product. 661 662 Collective on Mat 663 664 Input Parameters: 665 + J - the matrix-free matrix context 666 . histroy - space to hold the history 667 - nhistory - number of entries in history, if more entries are generated than 668 nhistory, then the later ones are discarded 669 670 Level: advanced 671 672 Notes: 673 Use MatSNESMFResetHHistory() to reset the history counter and collect 674 a new batch of differencing parameters, h. 675 676 .keywords: SNES, matrix-free, h history, differencing history 677 678 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 679 MatSNESMFResetHHistory(), 680 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 681 682 @*/ 683 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 684 { 685 int ierr; 686 MatSNESMFCtx ctx; 687 688 PetscFunctionBegin; 689 690 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 691 /* no context indicates that it is not the "matrix free" matrix type */ 692 if (!ctx) PetscFunctionReturn(0); 693 ctx->historyh = history; 694 ctx->maxcurrenth = nhistory; 695 ctx->currenth = 0; 696 697 PetscFunctionReturn(0); 698 } 699 700 #undef __FUNC__ 701 #define __FUNC__ "MatSNESMFResetHHistory" 702 /*@ 703 MatSNESMFResetHHistory - Resets the counter to zero to begin 704 collecting a new set of differencing histories. 705 706 Collective on Mat 707 708 Input Parameters: 709 . J - the matrix-free matrix context 710 711 Level: advanced 712 713 Notes: 714 Use MatSNESMFSetHHistory() to create the original history counter. 715 716 .keywords: SNES, matrix-free, h history, differencing history 717 718 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 719 MatSNESMFSetHHistory(), 720 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 721 722 @*/ 723 int MatSNESMFResetHHistory(Mat J) 724 { 725 int ierr; 726 MatSNESMFCtx ctx; 727 728 PetscFunctionBegin; 729 730 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 731 /* no context indicates that it is not the "matrix free" matrix type */ 732 if (!ctx) PetscFunctionReturn(0); 733 ctx->ncurrenth = 0; 734 735 PetscFunctionReturn(0); 736 } 737 738