1 /*$Id: snesmfj.c,v 1.110 2000/09/02 02:49:35 bsmith Exp balay $*/ 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 ierr = PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 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 ierr = PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0);CHKERRQ(ierr); 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->setfromoptions = 0; 449 mfctx->hctx = 0; 450 451 mfctx->func = 0; 452 mfctx->funcctx = 0; 453 mfctx->funcvec = 0; 454 455 ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 456 ierr = VecGetSize(mfctx->w,&n);CHKERRQ(ierr); 457 ierr = VecGetLocalSize(mfctx->w,&nloc);CHKERRQ(ierr); 458 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 459 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 460 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 461 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr); 462 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 463 PLogObjectParent(*J,mfctx->w); 464 465 mfctx->mat = *J; 466 PetscFunctionReturn(0); 467 } 468 469 #undef __FUNC__ 470 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFromOptions" 471 /*@ 472 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 473 parameter. 474 475 Collective on Mat 476 477 Input Parameters: 478 . mat - the matrix obtained with MatCreateSNESMF() 479 480 Options Database Keys: 481 + -snes_mf_type - <default,wp> 482 - -snes_mf_err - square root of estimated relative error in function evaluation 483 - -snes_mf_period - how often h is recomputed, defaults to 1, everytime 484 485 Level: advanced 486 487 .keywords: SNES, matrix-free, parameters 488 489 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 490 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 491 @*/ 492 int MatSNESMFSetFromOptions(Mat mat) 493 { 494 MatSNESMFCtx mfctx; 495 int ierr; 496 PetscTruth flg; 497 char ftype[256]; 498 499 PetscFunctionBegin; 500 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 501 if (mfctx) { 502 if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 503 504 ierr = OptionsBegin(mfctx->comm,mfctx->prefix,"Set matrix free computation parameters");CHKERRQ(ierr); 505 ierr = OptionsList("-snes_mf_type","Matrix free type","MatSNESMFSetType",MatSNESMFList,mfctx->type_name,ftype,256,&flg);CHKERRQ(ierr); 506 if (flg) { 507 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 508 } 509 510 ierr = OptionsDouble("-snes_mf_err","set sqrt relative error in function","MatSNESMFSetFunctionError",mfctx->error_rel,&mfctx->error_rel,0);CHKERRQ(ierr); 511 ierr = OptionsInt("-snes_mf_period","how often h is recomputed","MatSNESMFSetPeriod",mfctx->recomputeperiod,&mfctx->recomputeperiod,0);CHKERRQ(ierr); 512 if (mfctx->snes) { 513 ierr = OptionsName("-snes_mf_ksp_monitor","Monitor matrix-free parameters","MatSNESMFKSPMonitor",&flg);CHKERRQ(ierr); 514 if (flg) { 515 SLES sles; 516 KSP ksp; 517 ierr = SNESGetSLES(mfctx->snes,&sles);CHKERRQ(ierr); 518 ierr = SLESGetKSP(sles,&ksp);CHKERRQ(ierr); 519 ierr = KSPSetMonitor(ksp,MatSNESMFKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr); 520 } 521 } 522 if (mfctx->ops->setfromoptions) { 523 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 524 } 525 ierr = OptionsEnd();CHKERRQ(ierr); 526 527 } 528 PetscFunctionReturn(0); 529 } 530 531 #undef __FUNC__ 532 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFGetH" 533 /*@ 534 MatSNESMFGetH - Gets the last value that was used as the differencing 535 parameter. 536 537 Not Collective 538 539 Input Parameters: 540 . mat - the matrix obtained with MatCreateSNESMF() 541 542 Output Paramter: 543 . h - the differencing step size 544 545 Level: advanced 546 547 .keywords: SNES, matrix-free, parameters 548 549 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 550 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 551 @*/ 552 int MatSNESMFGetH(Mat mat,Scalar *h) 553 { 554 MatSNESMFCtx ctx; 555 int ierr; 556 557 PetscFunctionBegin; 558 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 559 if (ctx) { 560 *h = ctx->currenth; 561 } 562 PetscFunctionReturn(0); 563 } 564 565 #undef __FUNC__ 566 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFKSPMonitor" 567 /* 568 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 569 SNES matrix free routines. Prints the differencing parameter used at 570 each step. 571 */ 572 int MatSNESMFKSPMonitor(KSP ksp,int n,PetscReal rnorm,void *dummy) 573 { 574 PC pc; 575 MatSNESMFCtx ctx; 576 int ierr; 577 Mat mat; 578 MPI_Comm comm; 579 PetscTruth nonzeroinitialguess; 580 581 PetscFunctionBegin; 582 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 583 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 584 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 585 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 586 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 587 if (!ctx) { 588 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 589 } 590 if (n > 0 || nonzeroinitialguess) { 591 #if defined(PETSC_USE_COMPLEX) 592 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 593 PetscRealPart(ctx->currenth),PetscImaginaryPart(ctx->currenth));CHKERRQ(ierr); 594 #else 595 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 596 #endif 597 } else { 598 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 599 } 600 PetscFunctionReturn(0); 601 } 602 603 #undef __FUNC__ 604 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunction" 605 /*@C 606 MatSNESMFSetFunction - Sets the function used in applying the matrix free. 607 608 Collective on Mat 609 610 Input Parameters: 611 + mat - the matrix free matrix created via MatCreateSNESMF() 612 . v - workspace vector 613 . func - the function to use 614 - funcctx - optional function context passed to function 615 616 Level: advanced 617 618 Notes: 619 If you use this you MUST call MatAssemblyBegin()/MatAssemblyEnd() on the matrix free 620 matrix inside your compute Jacobian routine 621 622 If this is not set then it will use the function set with SNESSetFunction() 623 624 .keywords: SNES, matrix-free, function 625 626 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 627 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 628 MatSNESMFKSPMonitor(), SNESetFunction() 629 @*/ 630 int MatSNESMFSetFunction(Mat mat,Vec v,int (*func)(SNES,Vec,Vec,void *),void *funcctx) 631 { 632 MatSNESMFCtx ctx; 633 int ierr; 634 635 PetscFunctionBegin; 636 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 637 if (ctx) { 638 ctx->func = func; 639 ctx->funcctx = funcctx; 640 ctx->funcvec = v; 641 } 642 PetscFunctionReturn(0); 643 } 644 645 646 #undef __FUNC__ 647 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetPeriod" 648 /*@ 649 MatSNESMFSetPeriod - Sets how often h is recomputed, by default it is everytime 650 651 Collective on Mat 652 653 Input Parameters: 654 + mat - the matrix free matrix created via MatCreateSNESMF() 655 - period - 1 for everytime, 2 for every second etc 656 657 Options Database Keys: 658 + -snes_mf_period <period> 659 660 Level: advanced 661 662 663 .keywords: SNES, matrix-free, parameters 664 665 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 666 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 667 MatSNESMFKSPMonitor() 668 @*/ 669 int MatSNESMFSetPeriod(Mat mat,int period) 670 { 671 MatSNESMFCtx ctx; 672 int ierr; 673 674 PetscFunctionBegin; 675 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 676 if (ctx) { 677 ctx->recomputeperiod = period; 678 } 679 PetscFunctionReturn(0); 680 } 681 682 #undef __FUNC__ 683 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetFunctionError" 684 /*@ 685 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 686 matrix-vector products using finite differences. 687 688 Collective on Mat 689 690 Input Parameters: 691 + mat - the matrix free matrix created via MatCreateSNESMF() 692 - error_rel - relative error (should be set to the square root of 693 the relative error in the function evaluations) 694 695 Options Database Keys: 696 + -snes_mf_err <error_rel> - Sets error_rel 697 698 Level: advanced 699 700 Notes: 701 The default matrix-free matrix-vector product routine computes 702 .vb 703 F'(u)*a = [F(u+h*a) - F(u)]/h where 704 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 705 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 706 .ve 707 708 .keywords: SNES, matrix-free, parameters 709 710 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 711 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 712 MatSNESMFKSPMonitor() 713 @*/ 714 int MatSNESMFSetFunctionError(Mat mat,PetscReal error) 715 { 716 MatSNESMFCtx ctx; 717 int ierr; 718 719 PetscFunctionBegin; 720 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 721 if (ctx) { 722 if (error != PETSC_DEFAULT) ctx->error_rel = error; 723 } 724 PetscFunctionReturn(0); 725 } 726 727 #undef __FUNC__ 728 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFAddNullSpace" 729 /*@ 730 MatSNESMFAddNullSpace - Provides a null space that an operator is 731 supposed to have. Since roundoff will create a small component in 732 the null space, if you know the null space you may have it 733 automatically removed. 734 735 Collective on Mat 736 737 Input Parameters: 738 + J - the matrix-free matrix context 739 - nullsp - object created with MatNullSpaceCreate() 740 741 Level: advanced 742 743 .keywords: SNES, matrix-free, null space 744 745 .seealso: MatNullSpaceCreate(), MatSNESMFGetH(), MatCreateSNESMF(), 746 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 747 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 748 @*/ 749 int MatSNESMFAddNullSpace(Mat J,MatNullSpace nullsp) 750 { 751 int ierr; 752 MatSNESMFCtx ctx; 753 MPI_Comm comm; 754 755 PetscFunctionBegin; 756 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 757 758 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 759 /* no context indicates that it is not the "matrix free" matrix type */ 760 if (!ctx) PetscFunctionReturn(0); 761 ctx->sp = nullsp; 762 ierr = PetscObjectReference((PetscObject)nullsp);CHKERRQ(ierr); 763 PetscFunctionReturn(0); 764 } 765 766 #undef __FUNC__ 767 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetHHistory" 768 /*@ 769 MatSNESMFSetHHistory - Sets an array to collect a history of the 770 differencing values (h) computed for the matrix-free product. 771 772 Collective on Mat 773 774 Input Parameters: 775 + J - the matrix-free matrix context 776 . histroy - space to hold the history 777 - nhistory - number of entries in history, if more entries are generated than 778 nhistory, then the later ones are discarded 779 780 Level: advanced 781 782 Notes: 783 Use MatSNESMFResetHHistory() to reset the history counter and collect 784 a new batch of differencing parameters, h. 785 786 .keywords: SNES, matrix-free, h history, differencing history 787 788 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 789 MatSNESMFResetHHistory(), 790 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 791 792 @*/ 793 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 794 { 795 int ierr; 796 MatSNESMFCtx ctx; 797 798 PetscFunctionBegin; 799 800 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 801 /* no context indicates that it is not the "matrix free" matrix type */ 802 if (!ctx) PetscFunctionReturn(0); 803 ctx->historyh = history; 804 ctx->maxcurrenth = nhistory; 805 ctx->currenth = 0; 806 807 PetscFunctionReturn(0); 808 } 809 810 #undef __FUNC__ 811 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFResetHHistory" 812 /*@ 813 MatSNESMFResetHHistory - Resets the counter to zero to begin 814 collecting a new set of differencing histories. 815 816 Collective on Mat 817 818 Input Parameters: 819 . J - the matrix-free matrix context 820 821 Level: advanced 822 823 Notes: 824 Use MatSNESMFSetHHistory() to create the original history counter. 825 826 .keywords: SNES, matrix-free, h history, differencing history 827 828 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 829 MatSNESMFSetHHistory(), 830 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 831 832 @*/ 833 int MatSNESMFResetHHistory(Mat J) 834 { 835 int ierr; 836 MatSNESMFCtx ctx; 837 838 PetscFunctionBegin; 839 840 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 841 /* no context indicates that it is not the "matrix free" matrix type */ 842 if (!ctx) PetscFunctionReturn(0); 843 ctx->ncurrenth = 0; 844 845 PetscFunctionReturn(0); 846 } 847 848 #undef __FUNC__ 849 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFFormJacobian" 850 int MatSNESMFFormJacobian(SNES snes,Vec x,Mat *jac,Mat *B,MatStructure *flag,void *dummy) 851 { 852 int ierr; 853 PetscFunctionBegin; 854 ierr = MatAssemblyBegin(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 855 ierr = MatAssemblyEnd(*jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 856 PetscFunctionReturn(0); 857 } 858 859 #undef __FUNC__ 860 #define __FUNC__ /*<a name=""></a>*/"MatSNESMFSetBase" 861 int MatSNESMFSetBase(Mat J,Vec U) 862 { 863 int ierr; 864 MatSNESMFCtx ctx; 865 866 PetscFunctionBegin; 867 PetscValidHeaderSpecific(J,MAT_COOKIE); 868 PetscValidHeaderSpecific(U,VEC_COOKIE); 869 870 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 871 ctx->current_u = U; 872 PetscFunctionReturn(0); 873 } 874