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