1 /*$Id: snesmfj.c,v 1.113 2000/09/27 20:01:57 bsmith 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,"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 if (!ctx->type_name) { 181 ierr = ViewerASCIIPrintf(viewer," The compute h routine has not yet been set\n");CHKERRQ(ierr); 182 } else { 183 ierr = ViewerASCIIPrintf(viewer," Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr); 184 } 185 if (ctx->ops->view) { 186 ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 187 } 188 } else { 189 SETERRQ1(1,"Viewer type %s not supported for SNES matrix free matrix",((PetscObject)viewer)->type_name); 190 } 191 PetscFunctionReturn(0); 192 } 193 194 #undef __FUNC__ 195 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFAssemblyEnd_Private" 196 /* 197 MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 198 allows the user to indicate the beginning of a new linear solve by calling 199 MatAssemblyXXX() on the matrix free matrix. This then allows the 200 MatSNESMFCreate_WP() to properly compute ||U|| only the first time 201 in the linear solver rather than every time. 202 */ 203 int MatSNESMFAssemblyEnd_Private(Mat J) 204 { 205 int ierr; 206 MatSNESMFCtx j; 207 208 PetscFunctionBegin; 209 ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 210 ierr = MatShellGetContext(J,(void **)&j);CHKERRQ(ierr); 211 if (j->snes) { 212 ierr = SNESGetSolution(j->snes,&j->current_u);CHKERRQ(ierr); 213 if (j->snes->method_class == SNES_NONLINEAR_EQUATIONS) { 214 ierr = SNESGetFunction(j->snes,&j->current_f,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 215 } else if (j->snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 216 ierr = SNESGetGradient(j->snes,&j->current_f,PETSC_NULL);CHKERRQ(ierr); 217 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class"); 218 } 219 PetscFunctionReturn(0); 220 } 221 222 223 #undef __FUNC__ 224 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFMult_Private" 225 /* 226 MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector 227 product, y = F'(u)*a: 228 229 y ~= (F(u + ha) - F(u))/h, 230 where F = nonlinear function, as set by SNESSetFunction() 231 u = current iterate 232 h = difference interval 233 */ 234 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y) 235 { 236 MatSNESMFCtx ctx; 237 SNES snes; 238 Scalar h,mone = -1.0; 239 Vec w,U,F; 240 int ierr,(*eval_fct)(SNES,Vec,Vec)=0; 241 242 PetscFunctionBegin; 243 /* We log matrix-free matrix-vector products separately, so that we can 244 separate the performance monitoring from the cases that use conventional 245 storage. We may eventually modify event logging to associate events 246 with particular objects, hence alleviating the more general problem. */ 247 ierr = PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 248 249 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 250 snes = ctx->snes; 251 w = ctx->w; 252 U = ctx->current_u; 253 254 /* 255 Compute differencing parameter 256 */ 257 if (!ctx->ops->compute) { 258 ierr = MatSNESMFSetType(mat,MATSNESMF_DEFAULT);CHKERRQ(ierr); 259 ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 260 } 261 ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr); 262 263 /* keep a record of the current differencing parameter h */ 264 ctx->currenth = h; 265 #if defined(PETSC_USE_COMPLEX) 266 PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscRealPart(h),PetscImaginaryPart(h)); 267 #else 268 PLogInfo(mat,"Current differencing parameter: %g\n",h); 269 #endif 270 if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 271 ctx->historyh[ctx->ncurrenth] = h; 272 } 273 ctx->ncurrenth++; 274 275 /* w = u + ha */ 276 ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr); 277 278 279 if (!ctx->func) { 280 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 281 eval_fct = SNESComputeFunction; 282 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 283 eval_fct = SNESComputeGradient; 284 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid method class"); 285 F = ctx->current_f; 286 if (!F) SETERRQ(1,"You must call MatAssembly() even on matrix-free matrices"); 287 ierr = eval_fct(snes,w,y);CHKERRQ(ierr); 288 } else { 289 F = ctx->funcvec; 290 /* compute func(U) as base for differencing */ 291 if (ctx->ncurrenth == 1) { 292 ierr = (*ctx->func)(snes,U,F,ctx->funcctx);CHKERRQ(ierr); 293 } 294 ierr = (*ctx->func)(snes,w,y,ctx->funcctx);CHKERRQ(ierr); 295 } 296 297 ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr); 298 h = 1.0/h; 299 ierr = VecScale(&h,y);CHKERRQ(ierr); 300 if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y,PETSC_NULL);CHKERRQ(ierr);} 301 302 ierr = PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 303 PetscFunctionReturn(0); 304 } 305 306 #undef __FUNC__ 307 #define __FUNC__ /*<a name=""></a>*/"MatCreateSNESMF" 308 /*@C 309 MatCreateSNESMF - Creates a matrix-free matrix context for use with 310 a SNES solver. This matrix can be used as the Jacobian argument for 311 the routine SNESSetJacobian(). 312 313 Collective on SNES and Vec 314 315 Input Parameters: 316 + snes - the SNES context 317 - x - vector where SNES solution is to be stored. 318 319 Output Parameter: 320 . J - the matrix-free matrix 321 322 Level: advanced 323 324 Notes: 325 The matrix-free matrix context merely contains the function pointers 326 and work space for performing finite difference approximations of 327 Jacobian-vector products, F'(u)*a, 328 329 The default code uses the following approach to compute h 330 331 .vb 332 F'(u)*a = [F(u+h*a) - F(u)]/h where 333 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 334 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 335 where 336 error_rel = square root of relative error in function evaluation 337 umin = minimum iterate parameter 338 .ve 339 340 The user can set the error_rel via MatSNESMFSetFunctionError() and 341 umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 342 of the users manual for details. 343 344 The user should call MatDestroy() when finished with the matrix-free 345 matrix context. 346 347 Options Database Keys: 348 + -snes_mf_err <error_rel> - Sets error_rel 349 . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 350 - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 351 352 .keywords: SNES, default, matrix-free, create, matrix 353 354 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 355 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateMF(), 356 MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic), MatSNESMFFormJacobian() 357 358 @*/ 359 int MatCreateSNESMF(SNES snes,Vec x,Mat *J) 360 { 361 MatSNESMFCtx mfctx; 362 int ierr; 363 364 PetscFunctionBegin; 365 ierr = MatCreateMF(x,J);CHKERRQ(ierr); 366 ierr = MatShellGetContext(*J,(void **)&mfctx);CHKERRQ(ierr); 367 mfctx->snes = snes; 368 PLogObjectParent(snes,*J); 369 PetscFunctionReturn(0); 370 } 371 372 #undef __FUNC__ 373 #define __FUNC__ /*<a name=""></a>*/"MatCreateMF" 374 /*@C 375 MatCreateMF - Creates a matrix-free matrix. See also MatCreateSNESMF() 376 377 Collective on Vec 378 379 Input Parameters: 380 . x - vector that defines layout of the vectors and matrices 381 382 Output Parameter: 383 . J - the matrix-free matrix 384 385 Level: advanced 386 387 Notes: 388 The matrix-free matrix context merely contains the function pointers 389 and work space for performing finite difference approximations of 390 Jacobian-vector products, F'(u)*a, 391 392 The default code uses the following approach to compute h 393 394 .vb 395 F'(u)*a = [F(u+h*a) - F(u)]/h where 396 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 397 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 398 where 399 error_rel = square root of relative error in function evaluation 400 umin = minimum iterate parameter 401 .ve 402 403 The user can set the error_rel via MatSNESMFSetFunctionError() and 404 umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 405 of the users manual for details. 406 407 The user should call MatDestroy() when finished with the matrix-free 408 matrix context. 409 410 Options Database Keys: 411 + -snes_mf_err <error_rel> - Sets error_rel 412 . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 413 - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 414 415 .keywords: default, matrix-free, create, matrix 416 417 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 418 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), MatCreateSNESMF(), 419 MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegisterDynamic),, MatSNESMFFormJacobian() 420 421 @*/ 422 int MatCreateMF(Vec x,Mat *J) 423 { 424 MPI_Comm comm; 425 MatSNESMFCtx mfctx; 426 int n,nloc,ierr; 427 428 PetscFunctionBegin; 429 ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 430 PetscHeaderCreate(mfctx,_p_MatSNESMFCtx,struct _MFOps,MATSNESMFCTX_COOKIE,0,"SNESMF",comm,MatSNESMFDestroy_Private,MatSNESMFView_Private); 431 PLogObjectCreate(mfctx); 432 mfctx->sp = 0; 433 mfctx->snes = 0; 434 mfctx->error_rel = 1.e-8; /* assumes PetscReal precision */ 435 mfctx->recomputeperiod = 1; 436 mfctx->count = 0; 437 mfctx->currenth = 0.0; 438 mfctx->historyh = PETSC_NULL; 439 mfctx->ncurrenth = 0; 440 mfctx->maxcurrenth = 0; 441 mfctx->type_name = 0; 442 443 /* 444 Create the empty data structure to contain compute-h routines. 445 These will be filled in below from the command line options or 446 a later call with MatSNESMFSetType() or if that is not called 447 then it will default in the first use of MatSNESMFMult_private() 448 */ 449 mfctx->ops->compute = 0; 450 mfctx->ops->destroy = 0; 451 mfctx->ops->view = 0; 452 mfctx->ops->setfromoptions = 0; 453 mfctx->hctx = 0; 454 455 mfctx->func = 0; 456 mfctx->funcctx = 0; 457 mfctx->funcvec = 0; 458 459 ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 460 ierr = VecGetSize(mfctx->w,&n);CHKERRQ(ierr); 461 ierr = VecGetLocalSize(mfctx->w,&nloc);CHKERRQ(ierr); 462 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 463 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 464 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 465 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr); 466 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 467 PLogObjectParent(*J,mfctx->w); 468 469 mfctx->mat = *J; 470 PetscFunctionReturn(0); 471 } 472 473 #undef __FUNC__ 474 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFromOptions" 475 /*@ 476 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 477 parameter. 478 479 Collective on Mat 480 481 Input Parameters: 482 . mat - the matrix obtained with MatCreateSNESMF() 483 484 Options Database Keys: 485 + -snes_mf_type - <default,wp> 486 - -snes_mf_err - square root of estimated relative error in function evaluation 487 - -snes_mf_period - how often h is recomputed, defaults to 1, everytime 488 489 Level: advanced 490 491 .keywords: SNES, matrix-free, parameters 492 493 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 494 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 495 @*/ 496 int MatSNESMFSetFromOptions(Mat mat) 497 { 498 MatSNESMFCtx mfctx; 499 int ierr; 500 PetscTruth flg; 501 char ftype[256]; 502 503 PetscFunctionBegin; 504 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 505 if (mfctx) { 506 if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 507 508 ierr = OptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters","MatSNESMF");CHKERRQ(ierr); 509 ierr = OptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMFList,mfctx->type_name,ftype,256,&flg);CHKERRQ(ierr); 510 if (flg) { 511 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 512 } 513 514 ierr = OptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);CHKERRQ(ierr); 515 ierr = OptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);CHKERRQ(ierr); 516 if (mfctx->snes) { 517 ierr = OptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);CHKERRQ(ierr); 518 if (flg) { 519 SLES sles; 520 KSP ksp; 521 ierr = SNESGetSLES(mfctx->snes,&sles);CHKERRQ(ierr); 522 ierr = SLESGetKSP(sles,&ksp);CHKERRQ(ierr); 523 ierr = KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr); 524 } 525 } 526 if (mfctx->ops->setfromoptions) { 527 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 528 } 529 ierr = OptionsEnd();CHKERRQ(ierr); 530 531 } 532 PetscFunctionReturn(0); 533 } 534 535 #undef __FUNC__ 536 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFGetH" 537 /*@ 538 MatSNESMFGetH - Gets the last value that was used as the differencing 539 parameter. 540 541 Not Collective 542 543 Input Parameters: 544 . mat - the matrix obtained with MatCreateSNESMF() 545 546 Output Paramter: 547 . h - the differencing step size 548 549 Level: advanced 550 551 .keywords: SNES, matrix-free, parameters 552 553 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 554 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 555 @*/ 556 int MatSNESMFGetH(Mat mat,Scalar *h) 557 { 558 MatSNESMFCtx ctx; 559 int ierr; 560 561 PetscFunctionBegin; 562 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 563 if (ctx) { 564 *h = ctx->currenth; 565 } 566 PetscFunctionReturn(0); 567 } 568 569 #undef __FUNC__ 570 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFKSPMonitor" 571 /* 572 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 573 SNES matrix free routines. Prints the differencing parameter used at 574 each step. 575 */ 576 int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy) 577 { 578 PC pc; 579 MatSNESMFCtx ctx; 580 int ierr; 581 Mat mat; 582 MPI_Comm comm; 583 PetscTruth nonzeroinitialguess; 584 585 PetscFunctionBegin; 586 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 587 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 588 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 589 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 590 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 591 if (!ctx) { 592 SETERRQ(1,"Matrix is not a matrix free shell matrix"); 593 } 594 if (n > 0 || nonzeroinitialguess) { 595 #if defined(PETSC_USE_COMPLEX) 596 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 597 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr); 598 #else 599 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 600 #endif 601 } else { 602 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 603 } 604 PetscFunctionReturn(0); 605 } 606 607 #undef __FUNC__ 608 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunction" 609 /*@C 610 MatSNESMFSetFunction - Sets the function used in applying the matrix free. 611 612 Collective on Mat 613 614 Input Parameters: 615 + mat - the matrix free matrix created via MatCreateSNESMF() 616 . v - workspace vector 617 . func - the function to use 618 - funcctx - optional function context passed to function 619 620 Level: advanced 621 622 Notes: 623 If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 624 matrix inside your compute Jacobian routine 625 626 If this is not set then it will use the function set with SNESSetFunction() 627 628 .keywords: SNES, matrix-free, function 629 630 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 631 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 632 MatSNESMFKSPMonitor(), SNESetFunction() 633 @*/ 634 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 635 { 636 MatSNESMFCtx ctx; 637 int ierr; 638 639 PetscFunctionBegin; 640 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 641 if (ctx) { 642 ctx->func = func; 643 ctx->funcctx = funcctx; 644 ctx->funcvec = v; 645 } 646 PetscFunctionReturn(0); 647 } 648 649 650 #undef __FUNC__ 651 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetPeriod" 652 /*@ 653 MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime 654 655 Collective on Mat 656 657 Input Parameters: 658 + mat - the matrix free matrix created via MatCreateSNESMF() 659 - period - 1 for everytime, 2 for every second etc 660 661 Options Database Keys: 662 + -snes_mf_period <period> 663 664 Level: advanced 665 666 667 .keywords: SNES, matrix-free, parameters 668 669 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 670 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 671 MatSNESMFKSPMonitor() 672 @*/ 673 int MatSNESMFSetPeriod(Mat mat,int period) 674 { 675 MatSNESMFCtx ctx; 676 int ierr; 677 678 PetscFunctionBegin; 679 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 680 if (ctx) { 681 ctx->recomputeperiod = period; 682 } 683 PetscFunctionReturn(0); 684 } 685 686 #undef __FUNC__ 687 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunctionError" 688 /*@ 689 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 690 matrix-vector products using finite differences. 691 692 Collective on Mat 693 694 Input Parameters: 695 + mat - the matrix free matrix created via MatCreateSNESMF() 696 - error_rel - relative error (should be set to the square root of 697 the relative error in the function evaluations) 698 699 Options Database Keys: 700 + -snes_mf_err <error_rel> - Sets error_rel 701 702 Level: advanced 703 704 Notes: 705 The default matrix-free matrix-vector product routine computes 706 .vb 707 F'(u)*a = [F(u+h*a) - F(u)]/h where 708 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 709 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 710 .ve 711 712 .keywords: SNES, matrix-free, parameters 713 714 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 715 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 716 MatSNESMFKSPMonitor() 717 @*/ 718 int MatSNESMFSetFunctionError(Mat mat,PetscReal error) 719 { 720 MatSNESMFCtx ctx; 721 int ierr; 722 723 PetscFunctionBegin; 724 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 725 if (ctx) { 726 if (error != PETSC_DEFAULT) ctx->error_rel = error; 727 } 728 PetscFunctionReturn(0); 729 } 730 731 #undef __FUNC__ 732 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFAddNullSpace" 733 /*@ 734 MatSNESMFAddNullSpace - Provides a null space that an operator is 735 supposed to have. Since roundoff will create a small component in 736 the null space, if you know the null space you may have it 737 automatically removed. 738 739 Collective on Mat 740 741 Input Parameters: 742 + J - the matrix-free matrix context 743 - nullsp - object created with MatNullSpaceCreate() 744 745 Level: advanced 746 747 .keywords: SNES, matrix-free, null space 748 749 .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 750 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 751 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 752 @*/ 753 int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp) 754 { 755 int ierr; 756 MatSNESMFCtx ctx; 757 MPI_Comm comm; 758 759 PetscFunctionBegin; 760 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 761 762 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 763 /* no context indicates that it is not the "matrix free" matrix type */ 764 if (!ctx) PetscFunctionReturn(0); 765 ctx->sp = nullsp; 766 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 767 PetscFunctionReturn(0); 768 } 769 770 #undef __FUNC__ 771 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetHHistory" 772 /*@ 773 MatSNESMFSetHHistory - Sets an array to collect a history of the 774 differencing values (h) computed for the matrix-free product. 775 776 Collective on Mat 777 778 Input Parameters: 779 + J - the matrix-free matrix context 780 . histroy - space to hold the history 781 - nhistory - number of entries in history, if more entries are generated than 782 nhistory, then the later ones are discarded 783 784 Level: advanced 785 786 Notes: 787 Use MatSNESMFResetHHistory() to reset the history counter and collect 788 a new batch of differencing parameters, h. 789 790 .keywords: SNES, matrix-free, h history, differencing history 791 792 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 793 MatSNESMFResetHHistory(), 794 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 795 796 @*/ 797 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 798 { 799 int ierr; 800 MatSNESMFCtx ctx; 801 802 PetscFunctionBegin; 803 804 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 805 /* no context indicates that it is not the "matrix free" matrix type */ 806 if (!ctx) PetscFunctionReturn(0); 807 ctx->historyh = history; 808 ctx->maxcurrenth = nhistory; 809 ctx->currenth = 0; 810 811 PetscFunctionReturn(0); 812 } 813 814 #undef __FUNC__ 815 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFResetHHistory" 816 /*@ 817 MatSNESMFResetHHistory - Resets the counter to zero to begin 818 collecting a new set of differencing histories. 819 820 Collective on Mat 821 822 Input Parameters: 823 . J - the matrix-free matrix context 824 825 Level: advanced 826 827 Notes: 828 Use MatSNESMFSetHHistory() to create the original history counter. 829 830 .keywords: SNES, matrix-free, h history, differencing history 831 832 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 833 MatSNESMFSetHHistory(), 834 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 835 836 @*/ 837 int MatSNESMFResetHHistory(Mat J) 838 { 839 int ierr; 840 MatSNESMFCtx ctx; 841 842 PetscFunctionBegin; 843 844 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 845 /* no context indicates that it is not the "matrix free" matrix type */ 846 if (!ctx) PetscFunctionReturn(0); 847 ctx->ncurrenth = 0; 848 849 PetscFunctionReturn(0); 850 } 851 852 #undef __FUNC__ 853 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFFormJacobian" 854 int MatSNESMFFormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 855 { 856 int ierr; 857 PetscFunctionBegin; 858 ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 859 ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 860 PetscFunctionReturn(0); 861 } 862 863 #undef __FUNC__ 864 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetBase" 865 int MatSNESMFSetBase(Mat J,Vec U) 866 { 867 int ierr; 868 MatSNESMFCtx ctx; 869 870 PetscFunctionBegin; 871 PetscValidHeaderSpecific(J,MAT_COOKIE); 872 PetscValidHeaderSpecific(U,VEC_COOKIE); 873 874 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 875 ctx->current_u = U; 876 PetscFunctionReturn(0); 877 } 878