1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesmfj.c,v 1.93 1999/10/04 18:53:49 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,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 173 PetscFunctionBegin; 174 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 175 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 176 ierr = ViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr); 177 if (PetscTypeCompare(viewer,ASCII_VIEWER)) { 178 ierr = PetscFPrintf(comm,fd," SNES matrix-free approximation:\n");CHKERRQ(ierr); 179 ierr = PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 180 ierr = PetscFPrintf(ctx->comm,fd," 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 SETERRQ(1,1,"Viewer type not supported for this object"); 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 mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx); 353 PLogObjectMemory(snes,sizeof(MatSNESMFCtx)); 354 mfctx->comm = snes->comm; 355 mfctx->sp = 0; 356 mfctx->snes = snes; 357 mfctx->error_rel = 1.e-8; /* assumes double precision */ 358 mfctx->currenth = 0.0; 359 mfctx->historyh = PETSC_NULL; 360 mfctx->ncurrenth = 0; 361 mfctx->maxcurrenth = 0; 362 ierr = PetscMemzero(mfctx->type_name,256*sizeof(char));CHKERRQ(ierr); 363 364 /* 365 Create the empty data structure to contain compute-h routines. 366 These will be filled in below from the command line options or 367 a later call with MatSNESMFSetType() or if that is not called 368 then it will default in the first use of MatSNESMFMult_private() 369 */ 370 mfctx->ops = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops); 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