1 #ifdef PETSC_RCS_HEADER 2 static char vcid[] = "$Id: snesmfj.c,v 1.85 1999/04/19 22:15:35 bsmith Exp balay $"; 3 #endif 4 5 #include "src/snes/snesimpl.h" 6 #include "src/snes/mf/snesmfj.h" /*I "snes.h" I*/ 7 8 FList MatSNESMFList = 0; 9 int MatSNESMFRegisterAllCalled = 0; 10 11 #undef __FUNC__ 12 #define __FUNC__ "MatSNESMFSetType" 13 /*@C 14 MatSNESMFSetType - Sets the method that is used to compute the 15 differencing parameter for finite difference matrix-free formulations. 16 17 Input Parameters: 18 + mat - the "matrix-free" matrix created via MatCreateSNESMF() 19 - ftype - the type requested 20 21 Level: advanced 22 23 Notes: 24 For example, such routines can compute h for use in 25 Jacobian-vector products of the form 26 27 F(x+ha) - F(x) 28 F'(u)a ~= ---------------- 29 h 30 31 .seealso: MatCreateSNESMF(), MatSNESMFRegister() 32 @*/ 33 int MatSNESMFSetType(Mat mat,char *ftype) 34 { 35 int ierr, (*r)(MatSNESMFCtx); 36 MatSNESMFCtx ctx; 37 38 PetscFunctionBegin; 39 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 40 41 /* already set, so just return */ 42 if (PetscTypeCompare(ctx->type_name,ftype)) PetscFunctionReturn(0); 43 44 /* destroy the old one if it exists */ 45 if (ctx->ops->destroy) { 46 ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr); 47 } 48 49 /* Get the function pointers for the requrested method */ 50 if (!MatSNESMFRegisterAllCalled) {ierr = MatSNESMFRegisterAll(PETSC_NULL);CHKERRQ(ierr);} 51 52 ierr = FListFind(ctx->comm, MatSNESMFList, ftype,(int (**)(void *)) &r );CHKERRQ(ierr); 53 54 if (!r) SETERRQ(1,1,"Unknown MatSNESMF type given"); 55 56 ierr = (*r)(ctx);CHKERRQ(ierr); 57 ierr = PetscStrncpy(ctx->type_name,ftype,256);CHKERRQ(ierr); 58 59 PetscFunctionReturn(0); 60 } 61 62 /*MC 63 MatSNESMFRegister - Adds a method to the MatSNESMF registry. 64 65 Synopsis: 66 MatSNESMFRegister(char *name_solver,char *path,char *name_create,int (*routine_create)(MatSNESMF)) 67 68 Not Collective 69 70 Input Parameters: 71 + name_solver - name of a new user-defined compute-h module 72 . path - path (either absolute or relative) the library containing this solver 73 . name_create - name of routine to create method context 74 - routine_create - routine to create method context 75 76 Level: developer 77 78 Notes: 79 MatSNESMFRegister() may be called multiple times to add several user-defined solvers. 80 81 If dynamic libraries are used, then the fourth input argument (routine_create) 82 is ignored. 83 84 Sample usage: 85 .vb 86 MatSNESMFRegister("my_h",/home/username/my_lib/lib/libO/solaris/mylib.a, 87 "MyHCreate",MyHCreate); 88 .ve 89 90 Then, your solver can be chosen with the procedural interface via 91 $ MatSNESMFSetType(mfctx,"my_h") 92 or at runtime via the option 93 $ -snes_mf_type my_h 94 95 .keywords: MatSNESMF, register 96 97 .seealso: MatSNESMFRegisterAll(), MatSNESMFRegisterDestroy() 98 M*/ 99 100 #undef __FUNC__ 101 #define __FUNC__ "MatSNESMFRegister_Private" 102 int MatSNESMFRegister_Private(char *sname,char *path,char *name,int (*function)(MatSNESMFCtx)) 103 { 104 int ierr; 105 char fullname[256]; 106 107 PetscFunctionBegin; 108 ierr = PetscStrcpy(fullname,path);CHKERRQ(ierr); 109 PetscStrcat(fullname,":");PetscStrcat(fullname,name); 110 ierr = FListAdd_Private(&MatSNESMFList,sname,fullname,(int (*)(void*))function);CHKERRQ(ierr); 111 PetscFunctionReturn(0); 112 } 113 114 115 #undef __FUNC__ 116 #define __FUNC__ "MatSNESMFRegisterDestroy" 117 /*@C 118 MatSNESMFRegisterDestroy - Frees the list of MatSNESMF methods that were 119 registered by MatSNESMFRegister(). 120 121 Not Collective 122 123 Level: developer 124 125 .keywords: MatSNESMF, register, destroy 126 127 .seealso: MatSNESMFRegister(), MatSNESMFRegisterAll() 128 @*/ 129 int MatSNESMFRegisterDestroy(void) 130 { 131 int ierr; 132 133 PetscFunctionBegin; 134 if (MatSNESMFList) { 135 ierr = FListDestroy( MatSNESMFList );CHKERRQ(ierr); 136 MatSNESMFList = 0; 137 } 138 MatSNESMFRegisterAllCalled = 0; 139 PetscFunctionReturn(0); 140 } 141 142 /* ----------------------------------------------------------------------------------------*/ 143 #undef __FUNC__ 144 #define __FUNC__ "MatSNESMFDestroy_Private" 145 int MatSNESMFDestroy_Private(Mat mat) 146 { 147 int ierr; 148 MatSNESMFCtx ctx; 149 150 PetscFunctionBegin; 151 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 152 ierr = VecDestroy(ctx->w);CHKERRQ(ierr); 153 if (ctx->ops->destroy) {ierr = (*ctx->ops->destroy)(ctx);CHKERRQ(ierr);} 154 if (ctx->sp) {ierr = PCNullSpaceDestroy(ctx->sp);CHKERRQ(ierr);} 155 PetscFree(ctx->ops); 156 PetscFree(ctx); 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNC__ 161 #define __FUNC__ "MatSNESMFView_Private" 162 /* 163 MatSNESMFView_Private - Views matrix-free parameters. 164 165 */ 166 int MatSNESMFView_Private(Mat J,Viewer viewer) 167 { 168 int ierr; 169 MatSNESMFCtx ctx; 170 MPI_Comm comm; 171 FILE *fd; 172 ViewerType vtype; 173 174 PetscFunctionBegin; 175 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 176 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 177 ierr = ViewerGetType(viewer,&vtype);CHKERRQ(ierr); 178 ierr = ViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr); 179 if (PetscTypeCompare(vtype,ASCII_VIEWER)) { 180 ierr = PetscFPrintf(comm,fd," SNES matrix-free approximation:\n");CHKERRQ(ierr); 181 ierr = PetscFPrintf(comm,fd," err=%g (relative error in function evaluation)\n",ctx->error_rel);CHKERRQ(ierr); 182 ierr = PetscFPrintf(ctx->comm,fd," Using %s compute h routine\n",ctx->type_name);CHKERRQ(ierr); 183 if (ctx->ops->view) { 184 ierr = (*ctx->ops->view)(ctx,viewer);CHKERRQ(ierr); 185 } 186 } else { 187 SETERRQ(1,1,"Viewer type not supported for this object"); 188 } 189 PetscFunctionReturn(0); 190 } 191 192 #undef __FUNC__ 193 #define __FUNC__ "MatSNESMFAssemblyEnd_Private" 194 /* 195 MatSNESMFAssemblyEnd_Private - Resets the ctx->ncurrenth to zero. This 196 allows the user to indicate the beginning of a new linear solve by calling 197 MatAssemblyXXX() on the matrix free matrix. This then allows the 198 MatSNESMFCreate_WP() to properly compute ||U|| only the first time 199 in the linear solver rather than every time. 200 */ 201 int MatSNESMFAssemblyEnd_Private(Mat J) 202 { 203 int ierr; 204 205 PetscFunctionBegin; 206 ierr = MatSNESMFResetHHistory(J);CHKERRQ(ierr); 207 PetscFunctionReturn(0); 208 } 209 210 211 #undef __FUNC__ 212 #define __FUNC__ "MatSNESMFMult_Private" 213 /* 214 MatSNESMFMult_Private - Default matrix-free form for Jacobian-vector 215 product, y = F'(u)*a: 216 217 y ~= ( F(u + ha) - F(u) )/h, 218 where F = nonlinear function, as set by SNESSetFunction() 219 u = current iterate 220 h = difference interval 221 */ 222 int MatSNESMFMult_Private(Mat mat,Vec a,Vec y) 223 { 224 MatSNESMFCtx ctx; 225 SNES snes; 226 Scalar h, mone = -1.0; 227 Vec w,U,F; 228 int ierr, (*eval_fct)(SNES,Vec,Vec)=0; 229 230 PetscFunctionBegin; 231 /* We log matrix-free matrix-vector products separately, so that we can 232 separate the performance monitoring from the cases that use conventional 233 storage. We may eventually modify event logging to associate events 234 with particular objects, hence alleviating the more general problem. */ 235 PLogEventBegin(MAT_MatrixFreeMult,a,y,0,0); 236 237 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 238 snes = ctx->snes; 239 w = ctx->w; 240 241 ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); 242 if (snes->method_class == SNES_NONLINEAR_EQUATIONS) { 243 eval_fct = SNESComputeFunction; 244 ierr = SNESGetFunction(snes,&F);CHKERRQ(ierr); 245 } else if (snes->method_class == SNES_UNCONSTRAINED_MINIMIZATION) { 246 eval_fct = SNESComputeGradient; 247 ierr = SNESGetGradient(snes,&F);CHKERRQ(ierr); 248 } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Invalid method class"); 249 250 if (!ctx->ops->compute) { 251 ierr = MatSNESMFSetType(mat,"default");CHKERRQ(ierr); 252 ierr = MatSNESMFSetFromOptions(mat);CHKERRQ(ierr); 253 } 254 ierr = (*ctx->ops->compute)(ctx,U,a,&h);CHKERRQ(ierr); 255 256 /* keep a record of the current differencing parameter h */ 257 ctx->currenth = h; 258 #if defined(USE_PETSC_COMPLEX) 259 PLogInfo(mat,"Current differencing parameter: %g + %g i\n",PetscReal(h),PetscImaginary(h)); 260 #else 261 PLogInfo(mat,"Current differencing parameter: %g\n",h); 262 #endif 263 if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { 264 ctx->historyh[ctx->ncurrenth++] = h; 265 } else { 266 ctx->ncurrenth++; 267 } 268 269 /* Evaluate function at F(u + ha) */ 270 ierr = VecWAXPY(&h,a,U,w);CHKERRQ(ierr); 271 ierr = eval_fct(snes,w,y);CHKERRQ(ierr); 272 273 ierr = VecAXPY(&mone,F,y);CHKERRQ(ierr); 274 h = 1.0/h; 275 ierr = VecScale(&h,y);CHKERRQ(ierr); 276 if (ctx->sp) {ierr = PCNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);} 277 278 PLogEventEnd(MAT_MatrixFreeMult,a,y,0,0); 279 PetscFunctionReturn(0); 280 } 281 282 #undef __FUNC__ 283 #define __FUNC__ "MatCreateSNESMF" 284 /*@C 285 MatCreateSNESMF - Creates a matrix-free matrix context for use with 286 a SNES solver. This matrix can be used as the Jacobian argument for 287 the routine SNESSetJacobian(). 288 289 Collective on SNES and Vec 290 291 Input Parameters: 292 + snes - the SNES context 293 - x - vector where SNES solution is to be stored. 294 295 Output Parameter: 296 . J - the matrix-free matrix 297 298 Level: advanced 299 300 Notes: 301 The matrix-free matrix context merely contains the function pointers 302 and work space for performing finite difference approximations of 303 Jacobian-vector products, F'(u)*a, 304 305 The default code uses the following approach to compute h 306 307 .vb 308 F'(u)*a = [F(u+h*a) - F(u)]/h where 309 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 310 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 otherwise 311 where 312 error_rel = square root of relative error in function evaluation 313 umin = minimum iterate parameter 314 .ve 315 316 The user can set the error_rel via MatSNESMFSetFunctionError() and 317 umin via MatSNESMFDefaultSetUmin(); see the nonlinear solvers chapter 318 of the users manual for details. 319 320 The user should call MatDestroy() when finished with the matrix-free 321 matrix context. 322 323 Options Database Keys: 324 + -snes_mf_err <error_rel> - Sets error_rel 325 . -snes_mf_unim <umin> - Sets umin (for default PETSc routine that computes h only) 326 - -snes_mf_ksp_monitor - KSP monitor routine that prints differencing h 327 328 .keywords: SNES, default, matrix-free, create, matrix 329 330 .seealso: MatDestroy(), MatSNESMFSetFunctionError(), MatSNESMFDefaultSetUmin() 331 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 332 MatSNESMFGetH(),MatSNESMFKSPMonitor(), MatSNESMFRegister() 333 334 @*/ 335 int MatCreateSNESMF(SNES snes,Vec x, Mat *J) 336 { 337 MPI_Comm comm; 338 MatSNESMFCtx mfctx; 339 int n, nloc, ierr; 340 341 PetscFunctionBegin; 342 mfctx = (MatSNESMFCtx) PetscMalloc(sizeof(struct _p_MatSNESMFCtx));CHKPTRQ(mfctx); 343 PLogObjectMemory(snes,sizeof(MatSNESMFCtx)); 344 mfctx->comm = snes->comm; 345 mfctx->sp = 0; 346 mfctx->snes = snes; 347 mfctx->error_rel = 1.e-8; /* assumes double precision */ 348 mfctx->currenth = 0.0; 349 mfctx->historyh = PETSC_NULL; 350 mfctx->ncurrenth = 0; 351 mfctx->maxcurrenth = 0; 352 353 /* 354 Create the empty data structure to contain compute-h routines. 355 These will be filled in below from the command line options or 356 a later call with MatSNESMFSetType() or if that is not called 357 then it will default in the first use of MatSNESMFMult_private() 358 */ 359 mfctx->ops = (MFOps *)PetscMalloc(sizeof(MFOps));CHKPTRQ(mfctx->ops); 360 mfctx->ops->compute = 0; 361 mfctx->ops->destroy = 0; 362 mfctx->ops->view = 0; 363 mfctx->ops->printhelp = 0; 364 mfctx->ops->setfromoptions = 0; 365 mfctx->hctx = 0; 366 367 ierr = VecDuplicate(x,&mfctx->w);CHKERRQ(ierr); 368 ierr = PetscObjectGetComm((PetscObject)x,&comm);CHKERRQ(ierr); 369 ierr = VecGetSize(x,&n);CHKERRQ(ierr); 370 ierr = VecGetLocalSize(x,&nloc);CHKERRQ(ierr); 371 ierr = MatCreateShell(comm,nloc,nloc,n,n,mfctx,J);CHKERRQ(ierr); 372 ierr = MatShellSetOperation(*J,MATOP_MULT,(void*)MatSNESMFMult_Private);CHKERRQ(ierr); 373 ierr = MatShellSetOperation(*J,MATOP_DESTROY,(void *)MatSNESMFDestroy_Private);CHKERRQ(ierr); 374 ierr = MatShellSetOperation(*J,MATOP_VIEW,(void *)MatSNESMFView_Private);CHKERRQ(ierr); 375 ierr = MatShellSetOperation(*J,MATOP_ASSEMBLY_END,(void *)MatSNESMFAssemblyEnd_Private);CHKERRQ(ierr); 376 PLogObjectParent(*J,mfctx->w); 377 PLogObjectParent(snes,*J); 378 379 mfctx->mat = *J; 380 381 382 PetscFunctionReturn(0); 383 } 384 385 #undef __FUNC__ 386 #define __FUNC__ "MatSNESMFSetFromOptions" 387 /*@ 388 MatSNESMFSetFromOptions - Sets the MatSNESMF options from the command line 389 parameter. 390 391 Collective on Mat 392 393 Input Parameters: 394 . mat - the matrix obtained with MatCreateSNESMF() 395 396 Options Database Keys: 397 + -snes_mf_type - <default,wp> 398 - -snes_mf_err - square root of estimated relative error in function evaluation 399 400 Level: advanced 401 402 .keywords: SNES, matrix-free, parameters 403 404 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 405 MatSNESMFResetHHistory(), MatSNESMFKSPMonitor() 406 @*/ 407 int MatSNESMFSetFromOptions(Mat mat) 408 { 409 MatSNESMFCtx mfctx; 410 int ierr,flg; 411 char ftype[256],p[64]; 412 413 PetscFunctionBegin; 414 ierr = MatShellGetContext(mat,(void **)&mfctx);CHKERRQ(ierr); 415 if (mfctx) { 416 /* allow user to set the type */ 417 ierr = OptionsGetString(mfctx->snes->prefix,"-snes_mf_type",ftype,256,&flg);CHKERRQ(ierr); 418 if (flg) { 419 ierr = MatSNESMFSetType(mat,ftype);CHKERRQ(ierr); 420 } 421 422 ierr = OptionsGetDouble(mfctx->snes->prefix,"-snes_mf_err",&mfctx->error_rel,&flg);CHKERRQ(ierr); 423 if (mfctx->ops->setfromoptions) { 424 ierr = (*mfctx->ops->setfromoptions)(mfctx);CHKERRQ(ierr); 425 } 426 427 ierr = OptionsHasName(PETSC_NULL,"-help",&flg);CHKERRQ(ierr); 428 ierr = PetscStrcpy(p,"-");CHKERRQ(ierr); 429 if (mfctx->snes->prefix) {ierr = PetscStrcat(p,mfctx->snes->prefix);CHKERRQ(ierr);} 430 if (flg) { 431 ierr = (*PetscHelpPrintf)(mfctx->snes->comm," %ssnes_mf_err <err>: set sqrt rel error in function (default %g)\n",p,mfctx->error_rel);CHKERRQ(ierr); 432 if (mfctx->ops->printhelp) { 433 ierr = (*mfctx->ops->printhelp)(mfctx);CHKERRQ(ierr); 434 } 435 } 436 } 437 PetscFunctionReturn(0); 438 } 439 440 #undef __FUNC__ 441 #define __FUNC__ "MatSNESMFGetH" 442 /*@ 443 MatSNESMFGetH - Gets the last value that was used as the differencing 444 parameter. 445 446 Not Collective 447 448 Input Parameters: 449 . mat - the matrix obtained with MatCreateSNESMF() 450 451 Output Paramter: 452 . h - the differencing step size 453 454 Level: advanced 455 456 .keywords: SNES, matrix-free, parameters 457 458 .seealso: MatCreateSNESMF(),MatSNESMFSetHHistory(), 459 MatSNESMFResetHHistory(),MatSNESMFKSPMonitor() 460 @*/ 461 int MatSNESMFGetH(Mat mat,Scalar *h) 462 { 463 MatSNESMFCtx ctx; 464 int ierr; 465 466 PetscFunctionBegin; 467 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 468 if (ctx) { 469 *h = ctx->currenth; 470 } 471 PetscFunctionReturn(0); 472 } 473 474 #undef __FUNC__ 475 #define __FUNC__ "MatSNESMFKSPMonitor" 476 /* 477 MatSNESMFKSPMonitor - A KSP monitor for use with the default PETSc 478 SNES matrix free routines. Prints the differencing parameter used at 479 each step. 480 */ 481 int MatSNESMFKSPMonitor(KSP ksp,int n,double rnorm,void *dummy) 482 { 483 PC pc; 484 MatSNESMFCtx ctx; 485 int ierr; 486 Mat mat; 487 MPI_Comm comm; 488 PetscTruth nonzeroinitialguess; 489 490 PetscFunctionBegin; 491 ierr = PetscObjectGetComm((PetscObject)ksp,&comm);CHKERRQ(ierr); 492 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 493 ierr = KSPGetInitialGuessNonzero(ksp,&nonzeroinitialguess);CHKERRQ(ierr); 494 ierr = PCGetOperators(pc,&mat,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 495 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 496 if (!ctx) { 497 SETERRQ(1,1,"Matrix is not a matrix free shell matrix"); 498 } 499 if (n > 0 || nonzeroinitialguess) { 500 #if defined(USE_PETSC_COMPLEX) 501 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g + %g i\n",n,rnorm, 502 PetscReal(ctx->currenth),PetscImaginary(ctx->currenth));CHKERRQ(ierr); 503 #else 504 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e h %g \n",n,rnorm,ctx->currenth);CHKERRQ(ierr); 505 #endif 506 } else { 507 ierr = PetscPrintf(comm,"%d KSP Residual norm %14.12e\n",n,rnorm);CHKERRQ(ierr); 508 } 509 PetscFunctionReturn(0); 510 } 511 512 #undef __FUNC__ 513 #define __FUNC__ "MatSNESMFSetFunctionError" 514 /*@ 515 MatSNESMFSetFunctionError - Sets the error_rel for the approximation of 516 matrix-vector products using finite differences. 517 518 Collective on Mat 519 520 Input Parameters: 521 + mat - the matrix free matrix created via MatCreateSNESMF() 522 - error_rel - relative error (should be set to the square root of 523 the relative error in the function evaluations) 524 525 Options Database Keys: 526 + -snes_mf_err <error_rel> - Sets error_rel 527 528 Level: advanced 529 530 Notes: 531 The default matrix-free matrix-vector product routine computes 532 .vb 533 F'(u)*a = [F(u+h*a) - F(u)]/h where 534 h = error_rel*u'a/||a||^2 if |u'a| > umin*||a||_{1} 535 = error_rel*umin*sign(u'a)*||a||_{1}/||a||^2 else 536 .ve 537 538 .keywords: SNES, matrix-free, parameters 539 540 .seealso: MatCreateSNESMF(),MatSNESMFGetH(), 541 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 542 MatSNESMFKSPMonitor() 543 @*/ 544 int MatSNESMFSetFunctionError(Mat mat,double error) 545 { 546 MatSNESMFCtx ctx; 547 int ierr; 548 549 PetscFunctionBegin; 550 ierr = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(ierr); 551 if (ctx) { 552 if (error != PETSC_DEFAULT) ctx->error_rel = error; 553 } 554 PetscFunctionReturn(0); 555 } 556 557 #undef __FUNC__ 558 #define __FUNC__ "MatSNESMFAddNullSpace" 559 /*@ 560 MatSNESMFAddNullSpace - Provides a null space that an operator is 561 supposed to have. Since roundoff will create a small component in 562 the null space, if you know the null space you may have it 563 automatically removed. 564 565 Collective on Mat 566 567 Input Parameters: 568 + J - the matrix-free matrix context 569 . has_cnst - PETSC_TRUE or PETSC_FALSE, indicating whether null space has constants 570 . n - number of vectors (excluding constant vector) in null space 571 - vecs - the vectors that span the null space (excluding the constant vector); 572 these vectors must be orthonormal 573 574 Level: advanced 575 576 .keywords: SNES, matrix-free, null space 577 578 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 579 MatSNESMFSetHHistory(), MatSNESMFResetHHistory(), 580 MatSNESMFKSPMonitor(), MatSNESMFErrorRel() 581 582 @*/ 583 int MatSNESMFAddNullSpace(Mat J,int has_cnst,int n,Vec *vecs) 584 { 585 int ierr; 586 MatSNESMFCtx ctx; 587 MPI_Comm comm; 588 589 PetscFunctionBegin; 590 ierr = PetscObjectGetComm((PetscObject)J,&comm);CHKERRQ(ierr); 591 592 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 593 /* no context indicates that it is not the "matrix free" matrix type */ 594 if (!ctx) PetscFunctionReturn(0); 595 ierr = PCNullSpaceCreate(comm,has_cnst,n,vecs,&ctx->sp);CHKERRQ(ierr); 596 PetscFunctionReturn(0); 597 } 598 599 #undef __FUNC__ 600 #define __FUNC__ "MatSNESMFSetHHistory" 601 /*@ 602 MatSNESMFSetHHistory - Sets an array to collect a history of the 603 differencing values (h) computed for the matrix-free product. 604 605 Collective on Mat 606 607 Input Parameters: 608 + J - the matrix-free matrix context 609 . histroy - space to hold the history 610 - nhistory - number of entries in history, if more entries are generated than 611 nhistory, then the later ones are discarded 612 613 Level: advanced 614 615 Notes: 616 Use MatSNESMFResetHHistory() to reset the history counter and collect 617 a new batch of differencing parameters, h. 618 619 .keywords: SNES, matrix-free, h history, differencing history 620 621 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 622 MatSNESMFResetHHistory(), 623 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 624 625 @*/ 626 int MatSNESMFSetHHistory(Mat J,Scalar *history,int nhistory) 627 { 628 int ierr; 629 MatSNESMFCtx ctx; 630 631 PetscFunctionBegin; 632 633 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 634 /* no context indicates that it is not the "matrix free" matrix type */ 635 if (!ctx) PetscFunctionReturn(0); 636 ctx->historyh = history; 637 ctx->maxcurrenth = nhistory; 638 ctx->currenth = 0; 639 640 PetscFunctionReturn(0); 641 } 642 643 #undef __FUNC__ 644 #define __FUNC__ "MatSNESMFResetHHistory" 645 /*@ 646 MatSNESMFResetHHistory - Resets the counter to zero to begin 647 collecting a new set of differencing histories. 648 649 Collective on Mat 650 651 Input Parameters: 652 . J - the matrix-free matrix context 653 654 Level: advanced 655 656 Notes: 657 Use MatSNESMFSetHHistory() to create the original history counter. 658 659 .keywords: SNES, matrix-free, h history, differencing history 660 661 .seealso: MatSNESMFGetH(), MatCreateSNESMF(), 662 MatSNESMFSetHHistory(), 663 MatSNESMFKSPMonitor(), MatSNESMFSetFunctionError() 664 665 @*/ 666 int MatSNESMFResetHHistory(Mat J) 667 { 668 int ierr; 669 MatSNESMFCtx ctx; 670 671 PetscFunctionBegin; 672 673 ierr = MatShellGetContext(J,(void **)&ctx);CHKERRQ(ierr); 674 /* no context indicates that it is not the "matrix free" matrix type */ 675 if (!ctx) PetscFunctionReturn(0); 676 ctx->ncurrenth = 0; 677 678 PetscFunctionReturn(0); 679 } 680 681