1 /*$Id: snesmfj.c,v 1.106 2000/05/05 22:18:16 balay Exp bsmith $*/ 2 3 #include "src/snes/snesimpl.h" 4 #include "src/snes/mf/snesmfj.h" /*I "petscsnes.h" I*/ 5 6 FList MatSNESMFList = 0; 7 PetscTruth MatSNESMFRegisterAllCalled = PETSC_FALSE; 8 9 #undef __FUNC__ 10 #define __FUNC__ /*<a name=""></a>*/"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(), MatSNESMFRegisterDynamic) 30 @*/ 31 int MatSNESMFSetType(Mat mat,MatSNESMFType 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 MatSNESMFRegisterDynamic - Adds a method to the MatSNESMF registry. 68 69 Synopsis: 70 MatSNESMFRegisterDynamicchar *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 MatSNESMFRegisterDynamic) 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 MatSNESMFRegisterDynamic"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__ /*<a name=""></a>*/"MatSNESMFRegister" 106 int MatSNESMFRegister(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx)) 107 { 108 int ierr; 109 char fullname[256]; 110 111 PetscFunctionBegin; 112 ierr = FListConcat(path,name,fullname);CHKERRQ(ierr); 113 ierr = FListAdd(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr); 114 PetscFunctionReturn(0); 115 } 116 117 118 #undef __FUNC__ 119 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFRegisterDestroy" 120 /*@C 121 MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 122 registered by MatSNESMFRegisterDynamic). 123 124 Not Collective 125 126 Level: developer 127 128 .keywords: MatSNESMF, register, destroy 129 130 .seealso: MatSNESMFRegisterDynamic), 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 = PETSC_FALSE; 142 PetscFunctionReturn(0); 143 } 144 145 /* ----------------------------------------------------------------------------------------*/ 146 #undef __FUNC__ 147 #define __FUNC__ /*<a name=""></a>*/"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 = MatNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 158 PetscHeaderDestroy(ctx); 159 PetscFunctionReturn(0); 160 } 161 162 #undef __FUNC__ 163 #define __FUNC__ /*<a name=""></a>*/"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__ /*<a name=""></a>*/"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__ /*<a name=""></a>*/"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,MATSNESMF_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",PetscRealPart(h),PetscImaginaryPart(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,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 = MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);CHKERRQ(ierr);} 287 288 PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0); 289 PetscFunctionReturn(0); 290 } 291 292 #undef __FUNC__ 293 #define __FUNC__ /*<a name=""></a>*/"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(), MatSNESMFRegisterDynamic) 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 PetscReal precision */ 357 mfctx->recomputeperiod = 1; 358 mfctx->count = 0; 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__ /*<a name=""></a>*/"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 - -snes_mf_period - how often h is recomputed, defaults to 1, everytime 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; 427 PetscTruth flg; 428 char ftype[256],p[64]; 429 430 PetscFunctionBegin; 431 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 432 if (mfctx) { 433 /* allow user to set the type */ 434 ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 435 if (flg) { 436 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 437 } 438 439 ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,PETSC_NULL);CHKERRQ(ierr); 440 ierr = OptionsGetInt(mfctx->snes->prefix,"-snes_mf_period",&mfctx->recomputeperiod,PETSC_NULL);CHKERRQ(ierr); 441 if (mfctx->ops->setfromoptions) { 442 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 443 } 444 445 ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr); 446 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 447 if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);} 448 if (flg) { 449 ierr = (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr); 450 ierr = (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_period <p>: how often h is recomputed (default 1, everytime)\n",p);CHKERRQ(ierr); 451 if (mfctx->ops->printhelp) { 452 ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 453 } 454 } 455 } 456 PetscFunctionReturn(0); 457 } 458 459 #undef __FUNC__ 460 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFGetH" 461 /*@ 462 MatSNESMFGetH - Gets the last value that was used as the differencing 463 parameter. 464 465 Not Collective 466 467 Input Parameters: 468 . mat - the matrix obtained with MatCreateSNESMF() 469 470 Output Paramter: 471 . h - the differencing step size 472 473 Level: advanced 474 475 .keywords: SNES, matrix-free, parameters 476 477 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 478 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 479 @*/ 480 int MatSNESMFGetH(Mat mat,Scalar *h) 481 { 482 MatSNESMFCtx ctx; 483 int ierr; 484 485 PetscFunctionBegin; 486 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 487 if (ctx) { 488 *h = ctx->currenth; 489 } 490 PetscFunctionReturn(0); 491 } 492 493 #undef __FUNC__ 494 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFKSPMonitor" 495 /* 496 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 497 SNES matrix free routines. Prints the differencing parameter used at 498 each step. 499 */ 500 int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy) 501 { 502 PC pc; 503 MatSNESMFCtx ctx; 504 int ierr; 505 Mat mat; 506 MPI_Comm comm; 507 PetscTruth nonzeroinitialguess; 508 509 PetscFunctionBegin; 510 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 511 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 512 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 513 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 514 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 515 if (!ctx) { 516 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 517 } 518 if (n > 0 || nonzeroinitialguess) { 519 #if defined(PETSC_USE_COMPLEX) 520 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 521 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr); 522 #else 523 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 524 #endif 525 } else { 526 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 527 } 528 PetscFunctionReturn(0); 529 } 530 531 #undef __FUNC__ 532 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunction" 533 /*@C 534 MatSNESMFSetFunction - Sets the function used in applying the matrix free. 535 536 Collective on Mat 537 538 Input Parameters: 539 + mat - the matrix free matrix created via MatCreateSNESMF() 540 . v - workspace vector 541 . func - the function to use 542 - funcctx - optional function context passed to function 543 544 Level: advanced 545 546 Notes: 547 If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 548 matrix inside your compute Jacobian routine 549 550 If this is not set then it will use the function set with SNESSetFunction() 551 552 .keywords: SNES, matrix-free, function 553 554 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 555 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 556 MatSNESMFKSPMonitor(), SNESetFunction() 557 @*/ 558 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 559 { 560 MatSNESMFCtx ctx; 561 int ierr; 562 563 PetscFunctionBegin; 564 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 565 if (ctx) { 566 ctx->func = func; 567 ctx->funcctx = funcctx; 568 ctx->funcvec = v; 569 } 570 PetscFunctionReturn(0); 571 } 572 573 574 #undef __FUNC__ 575 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetPeriod" 576 /*@ 577 MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime 578 579 Collective on Mat 580 581 Input Parameters: 582 + mat - the matrix free matrix created via MatCreateSNESMF() 583 - period - 1 for everytime, 2 for every second etc 584 585 Options Database Keys: 586 + -snes_mf_period <period> 587 588 Level: advanced 589 590 591 .keywords: SNES, matrix-free, parameters 592 593 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 594 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 595 MatSNESMFKSPMonitor() 596 @*/ 597 int MatSNESMFSetPeriod(Mat mat,int period) 598 { 599 MatSNESMFCtx ctx; 600 int ierr; 601 602 PetscFunctionBegin; 603 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 604 if (ctx) { 605 ctx->recomputeperiod = period; 606 } 607 PetscFunctionReturn(0); 608 } 609 610 #undef __FUNC__ 611 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunctionError" 612 /*@ 613 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 614 matrix-vector products using finite differences. 615 616 Collective on Mat 617 618 Input Parameters: 619 + mat - the matrix free matrix created via MatCreateSNESMF() 620 - error_rel - relative error (should be set to the square root of 621 the relative error in the function evaluations) 622 623 Options Database Keys: 624 + -snes_mf_err <error_rel> - Sets error_rel 625 626 Level: advanced 627 628 Notes: 629 The default matrix-free matrix-vector product routine computes 630 .vb 631 F'(u)*a = [F(u+h*a) - F(u)]/h where 632 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 633 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 634 .ve 635 636 .keywords: SNES, matrix-free, parameters 637 638 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 639 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 640 MatSNESMFKSPMonitor() 641 @*/ 642 int MatSNESMFSetFunctionError(Mat mat,PetscReal error) 643 { 644 MatSNESMFCtx ctx; 645 int ierr; 646 647 PetscFunctionBegin; 648 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 649 if (ctx) { 650 if (error != PETSC_DEFAULT) ctx->error_rel = error; 651 } 652 PetscFunctionReturn(0); 653 } 654 655 #undef __FUNC__ 656 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFAddNullSpace" 657 /*@ 658 MatSNESMFAddNullSpace - Provides a null space that an operator is 659 supposed to have. Since roundoff will create a small component in 660 the null space, if you know the null space you may have it 661 automatically removed. 662 663 Collective on Mat 664 665 Input Parameters: 666 + J - the matrix-free matrix context 667 - nullsp - object created with MatNullSpaceCreate() 668 669 Level: advanced 670 671 .keywords: SNES, matrix-free, null space 672 673 .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 674 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 675 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 676 @*/ 677 int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp) 678 { 679 int ierr; 680 MatSNESMFCtx ctx; 681 MPI_Comm comm; 682 683 PetscFunctionBegin; 684 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 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->sp = nullsp; 690 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 691 PetscFunctionReturn(0); 692 } 693 694 #undef __FUNC__ 695 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetHHistory" 696 /*@ 697 MatSNESMFSetHHistory - Sets an array to collect a history of the 698 differencing values (h) computed for the matrix-free product. 699 700 Collective on Mat 701 702 Input Parameters: 703 + J - the matrix-free matrix context 704 . histroy - space to hold the history 705 - nhistory - number of entries in history, if more entries are generated than 706 nhistory, then the later ones are discarded 707 708 Level: advanced 709 710 Notes: 711 Use MatSNESMFResetHHistory() to reset the history counter and collect 712 a new batch of differencing parameters, h. 713 714 .keywords: SNES, matrix-free, h history, differencing history 715 716 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 717 MatSNESMFResetHHistory(), 718 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 719 720 @*/ 721 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 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->historyh = history; 732 ctx->maxcurrenth = nhistory; 733 ctx->currenth = 0; 734 735 PetscFunctionReturn(0); 736 } 737 738 #undef __FUNC__ 739 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFResetHHistory" 740 /*@ 741 MatSNESMFResetHHistory - Resets the counter to zero to begin 742 collecting a new set of differencing histories. 743 744 Collective on Mat 745 746 Input Parameters: 747 . J - the matrix-free matrix context 748 749 Level: advanced 750 751 Notes: 752 Use MatSNESMFSetHHistory() to create the original history counter. 753 754 .keywords: SNES, matrix-free, h history, differencing history 755 756 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 757 MatSNESMFSetHHistory(), 758 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 759 760 @*/ 761 int MatSNESMFResetHHistory(Mat J) 762 { 763 int ierr; 764 MatSNESMFCtx ctx; 765 766 PetscFunctionBegin; 767 768 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 769 /* no context indicates that it is not the "matrix free" matrix type */ 770 if (!ctx) PetscFunctionReturn(0); 771 ctx->ncurrenth = 0; 772 773 PetscFunctionReturn(0); 774 } 775 776