1 #include <petsc-private/snesimpl.h> /*I "petscsnes.h" I*/ 2 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 3 4 #undef __FUNCT__ 5 #define __FUNCT__ "SNESDMComputeFunction" 6 /*@C 7 SNESDMComputeFunction - This is a universal function evaluation routine that 8 may be used with SNESSetFunction() as long as the user context has a DM 9 as its first record and the user has called DMSetLocalFunction(). 10 11 Collective on SNES 12 13 Input Parameters: 14 + snes - the SNES context 15 . X - input vector 16 . F - function vector 17 - ptr - pointer to a structure that must have a DM as its first entry. 18 This ptr must have been passed into SNESDMComputeFunction() as the context. 19 20 Level: intermediate 21 22 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian() 23 @*/ 24 PetscErrorCode SNESDMComputeFunction(SNES snes, Vec X, Vec F, void *ptr) 25 { 26 DM dm = *(DM*) ptr; 27 PetscErrorCode (*lf)(DM, Vec, Vec, void *); 28 Vec localX, localF; 29 PetscInt N, n; 30 PetscErrorCode ierr; 31 32 PetscFunctionBegin; 33 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 34 PetscValidHeaderSpecific(X, VEC_CLASSID, 2); 35 PetscValidHeaderSpecific(F, VEC_CLASSID, 3); 36 if (!dm) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONGSTATE, "Looks like you called SNESSetFromFuntion(snes,SNESDMComputeFunction,) without the DM context"); 37 PetscValidHeaderSpecific(dm, DM_CLASSID, 4); 38 39 /* determine whether X = localX */ 40 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 41 ierr = DMGetLocalVector(dm, &localF);CHKERRQ(ierr); 42 ierr = VecGetSize(X, &N);CHKERRQ(ierr); 43 ierr = VecGetSize(localX, &n);CHKERRQ(ierr); 44 45 if (n != N){ /* X != localX */ 46 /* Scatter ghost points to local vector, using the 2-step process 47 DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). 48 */ 49 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 50 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 51 } else { 52 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 53 localX = X; 54 } 55 ierr = DMGetLocalFunction(dm, &lf);CHKERRQ(ierr); 56 ierr = (*lf)(dm, localX, localF, ptr);CHKERRQ(ierr); 57 if (n != N){ 58 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 59 } 60 ierr = DMLocalToGlobalBegin(dm, localF, ADD_VALUES, F);CHKERRQ(ierr); 61 ierr = DMLocalToGlobalEnd(dm, localF, ADD_VALUES, F);CHKERRQ(ierr); 62 ierr = DMRestoreLocalVector(dm, &localF);CHKERRQ(ierr); 63 PetscFunctionReturn(0); 64 } 65 66 #undef __FUNCT__ 67 #define __FUNCT__ "SNESDMComputeJacobian" 68 /* 69 SNESDMComputeJacobian - This is a universal Jacobian evaluation routine that 70 may be used with SNESSetJacobian() as long as the user context has a DM 71 as its first record and the user has called DMSetLocalJacobian(). 72 73 Collective on SNES 74 75 Input Parameters: 76 + snes - the SNES context 77 . X - input vector 78 . J - Jacobian 79 . B - Jacobian used in preconditioner (usally same as J) 80 . flag - indicates if the matrix changed its structure 81 - ptr - pointer to a structure that must have a DM as its first entry. 82 This ptr must have been passed into SNESDMComputeFunction() as the context. 83 84 Level: intermediate 85 86 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian() 87 */ 88 PetscErrorCode SNESDMComputeJacobian(SNES snes, Vec X, Mat *J, Mat *B, MatStructure *flag, void *ptr) 89 { 90 DM dm = *(DM*) ptr; 91 PetscErrorCode (*lj)(DM, Vec, Mat, Mat, void *); 92 Vec localX; 93 PetscErrorCode ierr; 94 95 PetscFunctionBegin; 96 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 97 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 98 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 99 ierr = DMGetLocalJacobian(dm, &lj);CHKERRQ(ierr); 100 ierr = (*lj)(dm, localX, *J, *B, ptr);CHKERRQ(ierr); 101 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 102 /* Assemble true Jacobian; if it is different */ 103 if (*J != *B) { 104 ierr = MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 105 ierr = MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 106 } 107 ierr = MatSetOption(*B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr); 108 *flag = SAME_NONZERO_PATTERN; 109 PetscFunctionReturn(0); 110 } 111 112 #undef __FUNCT__ 113 #define __FUNCT__ "PetscContainerDestroy_SNESDM" 114 static PetscErrorCode PetscContainerDestroy_SNESDM(void *ctx) 115 { 116 PetscErrorCode ierr; 117 SNESDM sdm = (SNESDM)ctx; 118 119 PetscFunctionBegin; 120 if (sdm->destroy) {ierr = (*sdm->destroy)(sdm);CHKERRQ(ierr);} 121 ierr = PetscFree(sdm);CHKERRQ(ierr); 122 PetscFunctionReturn(0); 123 } 124 125 #undef __FUNCT__ 126 #define __FUNCT__ "DMCoarsenHook_SNESDM" 127 /* Attaches the SNESDM to the coarse level. 128 * Under what conditions should we copy versus duplicate? 129 */ 130 static PetscErrorCode DMCoarsenHook_SNESDM(DM dm,DM dmc,void *ctx) 131 { 132 PetscErrorCode ierr; 133 134 PetscFunctionBegin; 135 ierr = DMSNESCopyContext(dm,dmc);CHKERRQ(ierr); 136 PetscFunctionReturn(0); 137 } 138 139 #undef __FUNCT__ 140 #define __FUNCT__ "DMRestrictHook_SNESDM" 141 /* This could restrict auxiliary information to the coarse level. 142 */ 143 static PetscErrorCode DMRestrictHook_SNESDM(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx) 144 { 145 146 PetscFunctionBegin; 147 PetscFunctionReturn(0); 148 } 149 150 #undef __FUNCT__ 151 #define __FUNCT__ "DMRefineHook_SNESDM" 152 static PetscErrorCode DMRefineHook_SNESDM(DM dm,DM dmf,void *ctx) 153 { 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 ierr = DMSNESCopyContext(dm,dmf);CHKERRQ(ierr); 158 PetscFunctionReturn(0); 159 } 160 161 #undef __FUNCT__ 162 #define __FUNCT__ "DMInterpolateHook_SNESDM" 163 /* This could restrict auxiliary information to the coarse level. 164 */ 165 static PetscErrorCode DMInterpolateHook_SNESDM(DM dm,Mat Interp,DM dmf,void *ctx) 166 { 167 168 PetscFunctionBegin; 169 PetscFunctionReturn(0); 170 } 171 172 #undef __FUNCT__ 173 #define __FUNCT__ "DMSNESGetContext" 174 /*@C 175 DMSNESGetContext - get read-only private SNESDM context from a DM 176 177 Not Collective 178 179 Input Argument: 180 . dm - DM to be used with SNES 181 182 Output Argument: 183 . snesdm - private SNESDM context 184 185 Level: developer 186 187 Notes: 188 Use DMSNESGetContextWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible. 189 190 .seealso: DMSNESGetContextWrite() 191 @*/ 192 PetscErrorCode DMSNESGetContext(DM dm,SNESDM *snesdm) 193 { 194 PetscErrorCode ierr; 195 PetscContainer container; 196 SNESDM sdm; 197 198 PetscFunctionBegin; 199 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 200 ierr = PetscObjectQuery((PetscObject)dm,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr); 201 if (container) { 202 ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr); 203 } else { 204 ierr = PetscInfo(dm,"Creating new SNESDM\n");CHKERRQ(ierr); 205 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 206 ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr); 207 ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr); 208 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr); 209 ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 210 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr); 211 ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr); 212 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 213 } 214 PetscFunctionReturn(0); 215 } 216 217 #undef __FUNCT__ 218 #define __FUNCT__ "DMSNESGetContextWrite" 219 /*@C 220 DMSNESGetContextWrite - get write access to private SNESDM context from a DM 221 222 Not Collective 223 224 Input Argument: 225 . dm - DM to be used with SNES 226 227 Output Argument: 228 . snesdm - private SNESDM context 229 230 Level: developer 231 232 .seealso: DMSNESGetContext() 233 @*/ 234 PetscErrorCode DMSNESGetContextWrite(DM dm,SNESDM *snesdm) 235 { 236 PetscErrorCode ierr; 237 SNESDM sdm; 238 239 PetscFunctionBegin; 240 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 241 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 242 if (!sdm->originaldm) sdm->originaldm = dm; 243 if (sdm->originaldm != dm) { /* Copy on write */ 244 PetscContainer container; 245 SNESDM oldsdm = sdm; 246 ierr = PetscInfo(dm,"Copying SNESDM due to write\n");CHKERRQ(ierr); 247 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 248 ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr); 249 ierr = PetscMemcpy(sdm,oldsdm,sizeof(*sdm));CHKERRQ(ierr); 250 ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr); 251 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr); 252 ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 253 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 254 /* implementation specific copy hooks */ 255 ierr = (sdm->duplicate)(oldsdm,dm);CHKERRQ(ierr); 256 } 257 *snesdm = sdm; 258 PetscFunctionReturn(0); 259 } 260 261 #undef __FUNCT__ 262 #define __FUNCT__ "DMSNESCopyContext" 263 /*@C 264 DMSNESCopyContext - copies a DM context to a new DM 265 266 Logically Collective 267 268 Input Arguments: 269 + dmsrc - DM to obtain context from 270 - dmdest - DM to add context to 271 272 Level: developer 273 274 Note: 275 The context is copied by reference. This function does not ensure that a context exists. 276 277 .seealso: DMSNESGetContext(), SNESSetDM() 278 @*/ 279 PetscErrorCode DMSNESCopyContext(DM dmsrc,DM dmdest) 280 { 281 PetscErrorCode ierr; 282 PetscContainer container; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1); 286 PetscValidHeaderSpecific(dmdest,DM_CLASSID,2); 287 ierr = PetscObjectQuery((PetscObject)dmsrc,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr); 288 if (container) { 289 ierr = PetscObjectCompose((PetscObject)dmdest,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 290 ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr); 291 ierr = DMRefineHookAdd(dmdest,DMRefineHook_SNESDM,DMInterpolateHook_SNESDM,PETSC_NULL);CHKERRQ(ierr); 292 } 293 PetscFunctionReturn(0); 294 } 295 296 #undef __FUNCT__ 297 #define __FUNCT__ "DMSNESSetFunction" 298 /*@C 299 DMSNESSetFunction - set SNES residual evaluation function 300 301 Not Collective 302 303 Input Arguments: 304 + dm - DM to be used with SNES 305 . func - residual evaluation function, see SNESSetFunction() for calling sequence 306 - ctx - context for residual evaluation 307 308 Level: advanced 309 310 Note: 311 SNESSetFunction() is normally used, but it calls this function internally because the user context is actually 312 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 313 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 314 315 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 316 @*/ 317 PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx) 318 { 319 PetscErrorCode ierr; 320 SNESDM sdm; 321 322 PetscFunctionBegin; 323 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 324 if (func || ctx)ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 325 if (func) sdm->computefunction = func; 326 if (ctx) sdm->functionctx = ctx; 327 PetscFunctionReturn(0); 328 } 329 330 #undef __FUNCT__ 331 #define __FUNCT__ "DMSNESGetFunction" 332 /*@C 333 DMSNESGetFunction - get SNES residual evaluation function 334 335 Not Collective 336 337 Input Argument: 338 . dm - DM to be used with SNES 339 340 Output Arguments: 341 + func - residual evaluation function, see SNESSetFunction() for calling sequence 342 - ctx - context for residual evaluation 343 344 Level: advanced 345 346 Note: 347 SNESGetFunction() is normally used, but it calls this function internally because the user context is actually 348 associated with the DM. 349 350 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction() 351 @*/ 352 PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx) 353 { 354 PetscErrorCode ierr; 355 SNESDM sdm; 356 357 PetscFunctionBegin; 358 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 359 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 360 if (func) *func = sdm->computefunction; 361 if (ctx) *ctx = sdm->functionctx; 362 PetscFunctionReturn(0); 363 } 364 365 #undef __FUNCT__ 366 #define __FUNCT__ "DMSNESSetObjective" 367 /*@C 368 DMSNESSetObjective - set SNES objective evaluation function 369 370 Not Collective 371 372 Input Arguments: 373 + dm - DM to be used with SNES 374 . func - residual evaluation function, see SNESSetObjective() for calling sequence 375 - ctx - context for residual evaluation 376 377 Level: advanced 378 379 .seealso: DMSNESSetContext(), SNESGetObjective(), DMSNESSetFunction() 380 @*/ 381 PetscErrorCode DMSNESSetObjective(DM dm,SNESObjective func,void *ctx) 382 { 383 PetscErrorCode ierr; 384 SNESDM sdm; 385 386 PetscFunctionBegin; 387 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 388 if (func || ctx)ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 389 if (func) sdm->computeobjective = func; 390 if (ctx) sdm->objectivectx = ctx; 391 PetscFunctionReturn(0); 392 } 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "DMSNESGetObjective" 396 /*@C 397 DMSNESGetObjective - get SNES objective evaluation function 398 399 Not Collective 400 401 Input Argument: 402 . dm - DM to be used with SNES 403 404 Output Arguments: 405 + func - residual evaluation function, see SNESSetObjective() for calling sequence 406 - ctx - context for residual evaluation 407 408 Level: advanced 409 410 Note: 411 SNESGetFunction() is normally used, but it calls this function internally because the user context is actually 412 associated with the DM. 413 414 .seealso: DMSNESSetContext(), DMSNESSetObjective(), SNESSetFunction() 415 @*/ 416 PetscErrorCode DMSNESGetObjective(DM dm,SNESObjective *func,void **ctx) 417 { 418 PetscErrorCode ierr; 419 SNESDM sdm; 420 421 PetscFunctionBegin; 422 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 423 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 424 if (func) *func = sdm->computeobjective; 425 if (ctx) *ctx = sdm->objectivectx; 426 PetscFunctionReturn(0); 427 } 428 429 #undef __FUNCT__ 430 #define __FUNCT__ "DMSNESSetGS" 431 /*@C 432 DMSNESSetGS - set SNES Gauss-Seidel relaxation function 433 434 Not Collective 435 436 Input Argument: 437 + dm - DM to be used with SNES 438 . func - relaxation function, see SNESSetGS() for calling sequence 439 - ctx - context for residual evaluation 440 441 Level: advanced 442 443 Note: 444 SNESSetGS() is normally used, but it calls this function internally because the user context is actually 445 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 446 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 447 448 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction() 449 @*/ 450 PetscErrorCode DMSNESSetGS(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx) 451 { 452 PetscErrorCode ierr; 453 SNESDM sdm; 454 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 457 if (func || ctx)ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 458 if (func) sdm->computegs = func; 459 if (ctx) sdm->gsctx = ctx; 460 PetscFunctionReturn(0); 461 } 462 463 #undef __FUNCT__ 464 #define __FUNCT__ "DMSNESGetGS" 465 /*@C 466 DMSNESGetGS - get SNES Gauss-Seidel relaxation function 467 468 Not Collective 469 470 Input Argument: 471 . dm - DM to be used with SNES 472 473 Output Arguments: 474 + func - relaxation function, see SNESSetGS() for calling sequence 475 - ctx - context for residual evaluation 476 477 Level: advanced 478 479 Note: 480 SNESGetGS() is normally used, but it calls this function internally because the user context is actually 481 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 482 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 483 484 .seealso: DMSNESSetContext(), SNESGetGS(), DMSNESGetJacobian(), DMSNESGetFunction() 485 @*/ 486 PetscErrorCode DMSNESGetGS(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx) 487 { 488 PetscErrorCode ierr; 489 SNESDM sdm; 490 491 PetscFunctionBegin; 492 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 493 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 494 if (func) *func = sdm->computegs; 495 if (ctx) *ctx = sdm->gsctx; 496 PetscFunctionReturn(0); 497 } 498 499 #undef __FUNCT__ 500 #define __FUNCT__ "DMSNESSetJacobian" 501 /*@C 502 DMSNESSetJacobian - set SNES Jacobian evaluation function 503 504 Not Collective 505 506 Input Argument: 507 + dm - DM to be used with SNES 508 . func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 509 - ctx - context for residual evaluation 510 511 Level: advanced 512 513 Note: 514 SNESSetJacobian() is normally used, but it calls this function internally because the user context is actually 515 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 516 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 517 518 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian() 519 @*/ 520 PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx) 521 { 522 PetscErrorCode ierr; 523 SNESDM sdm; 524 525 PetscFunctionBegin; 526 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 527 if (func || ctx) { 528 ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 529 } 530 if (func) sdm->computejacobian = func; 531 if (ctx) sdm->jacobianctx = ctx; 532 PetscFunctionReturn(0); 533 } 534 535 #undef __FUNCT__ 536 #define __FUNCT__ "DMSNESGetJacobian" 537 /*@C 538 DMSNESGetJacobian - get SNES Jacobian evaluation function 539 540 Not Collective 541 542 Input Argument: 543 . dm - DM to be used with SNES 544 545 Output Arguments: 546 + func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 547 - ctx - context for residual evaluation 548 549 Level: advanced 550 551 Note: 552 SNESGetJacobian() is normally used, but it calls this function internally because the user context is actually 553 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 554 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 555 556 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 557 @*/ 558 PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx) 559 { 560 PetscErrorCode ierr; 561 SNESDM sdm; 562 563 PetscFunctionBegin; 564 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 565 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 566 if (func) *func = sdm->computejacobian; 567 if (ctx) *ctx = sdm->jacobianctx; 568 PetscFunctionReturn(0); 569 } 570 571 #undef __FUNCT__ 572 #define __FUNCT__ "DMSNESSetPicard" 573 /*@C 574 DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions. 575 576 Not Collective 577 578 Input Argument: 579 + dm - DM to be used with SNES 580 . func - RHS evaluation function, see SNESSetFunction() for calling sequence 581 . pjac - Picard matrix evaluation function, see SNESSetJacobian() for calling sequence 582 - ctx - context for residual evaluation 583 584 Level: advanced 585 586 .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian() 587 @*/ 588 PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (*pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx) 589 { 590 PetscErrorCode ierr; 591 SNESDM sdm; 592 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 595 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 596 if (pfunc) sdm->computepfunction = pfunc; 597 if (pjac) sdm->computepjacobian = pjac; 598 if (ctx) sdm->pctx = ctx; 599 PetscFunctionReturn(0); 600 } 601 602 603 #undef __FUNCT__ 604 #define __FUNCT__ "DMSNESGetPicard" 605 /*@C 606 DMSNESGetPicard - get SNES Picard iteration evaluation functions 607 608 Not Collective 609 610 Input Argument: 611 . dm - DM to be used with SNES 612 613 Output Arguments: 614 + pfunc - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 615 . pjac - RHS evaluation function, see SNESSetFunction() for calling sequence 616 - ctx - context for residual evaluation 617 618 Level: advanced 619 620 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 621 @*/ 622 PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (**pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx) 623 { 624 PetscErrorCode ierr; 625 SNESDM sdm; 626 627 PetscFunctionBegin; 628 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 629 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 630 if (pfunc) *pfunc = sdm->computepfunction; 631 if (pjac) *pjac = sdm->computepjacobian; 632 if (ctx) *ctx = sdm->pctx; 633 PetscFunctionReturn(0); 634 } 635 636 637 #undef __FUNCT__ 638 #define __FUNCT__ "SNESDefaultComputeFunction_DMLegacy" 639 static PetscErrorCode SNESDefaultComputeFunction_DMLegacy(SNES snes,Vec X,Vec F,void *ctx) 640 { 641 PetscErrorCode ierr; 642 DM dm; 643 644 PetscFunctionBegin; 645 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 646 ierr = DMComputeFunction(dm,X,F);CHKERRQ(ierr); 647 PetscFunctionReturn(0); 648 } 649 650 #undef __FUNCT__ 651 #define __FUNCT__ "SNESDefaultComputeJacobian_DMLegacy" 652 static PetscErrorCode SNESDefaultComputeJacobian_DMLegacy(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx) 653 { 654 PetscErrorCode ierr; 655 DM dm; 656 657 PetscFunctionBegin; 658 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 659 ierr = DMComputeJacobian(dm,X,*A,*B,mstr);CHKERRQ(ierr); 660 PetscFunctionReturn(0); 661 } 662 663 #undef __FUNCT__ 664 #define __FUNCT__ "DMSNESSetUpLegacy" 665 /* Sets up calling of legacy DM routines */ 666 PetscErrorCode DMSNESSetUpLegacy(DM dm) 667 { 668 PetscErrorCode ierr; 669 SNESDM sdm; 670 671 PetscFunctionBegin; 672 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 673 if (!sdm->computefunction) {ierr = DMSNESSetFunction(dm,SNESDefaultComputeFunction_DMLegacy,PETSC_NULL);CHKERRQ(ierr);} 674 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 675 if (!sdm->computejacobian) { 676 if (dm->ops->functionj) { 677 ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobian_DMLegacy,PETSC_NULL);CHKERRQ(ierr); 678 } else { 679 ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobianColor,PETSC_NULL);CHKERRQ(ierr); 680 } 681 } 682 PetscFunctionReturn(0); 683 } 684 685 /* block functions */ 686 687 #undef __FUNCT__ 688 #define __FUNCT__ "DMSNESSetBlockFunction" 689 /*@C 690 DMSNESSetBlockFunction - set SNES residual evaluation function 691 692 Not Collective 693 694 Input Arguments: 695 + dm - DM to be used with SNES 696 . func - residual evaluation function, see SNESSetFunction() for calling sequence 697 - ctx - context for residual evaluation 698 699 Level: developer 700 701 Note: 702 Mostly for use in DM implementations and transferred to a block function rather than being called from here. 703 704 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 705 @*/ 706 PetscErrorCode DMSNESSetBlockFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx) 707 { 708 PetscErrorCode ierr; 709 SNESDM sdm; 710 711 PetscFunctionBegin; 712 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 713 if (func || ctx)ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 714 if (func) sdm->computeblockfunction = func; 715 if (ctx) sdm->blockfunctionctx = ctx; 716 PetscFunctionReturn(0); 717 } 718 719 #undef __FUNCT__ 720 #define __FUNCT__ "DMSNESGetBlockFunction" 721 /*@C 722 DMSNESGetBlockFunction - get SNES residual evaluation function 723 724 Not Collective 725 726 Input Argument: 727 . dm - DM to be used with SNES 728 729 Output Arguments: 730 + func - residual evaluation function, see SNESSetFunction() for calling sequence 731 - ctx - context for residual evaluation 732 733 Level: developer 734 735 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction() 736 @*/ 737 PetscErrorCode DMSNESGetBlockFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx) 738 { 739 PetscErrorCode ierr; 740 SNESDM sdm; 741 742 PetscFunctionBegin; 743 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 744 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 745 if (func) *func = sdm->computeblockfunction; 746 if (ctx) *ctx = sdm->blockfunctionctx; 747 PetscFunctionReturn(0); 748 } 749 750 751 #undef __FUNCT__ 752 #define __FUNCT__ "DMSNESSetBlockJacobian" 753 /*@C 754 DMSNESSetJacobian - set SNES Jacobian evaluation function 755 756 Not Collective 757 758 Input Argument: 759 + dm - DM to be used with SNES 760 . func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 761 - ctx - context for residual evaluation 762 763 Level: advanced 764 765 Note: 766 Mostly for use in DM implementations and transferred to a block function rather than being called from here. 767 768 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian() 769 @*/ 770 PetscErrorCode DMSNESSetBlockJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx) 771 { 772 PetscErrorCode ierr; 773 SNESDM sdm; 774 775 PetscFunctionBegin; 776 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 777 if (func || ctx)ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 778 if (func) sdm->computeblockjacobian = func; 779 if (ctx) sdm->blockjacobianctx = ctx; 780 PetscFunctionReturn(0); 781 } 782 783 #undef __FUNCT__ 784 #define __FUNCT__ "DMSNESGetBlockJacobian" 785 /*@C 786 DMSNESGetBlockJacobian - get SNES Jacobian evaluation function 787 788 Not Collective 789 790 Input Argument: 791 . dm - DM to be used with SNES 792 793 Output Arguments: 794 + func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 795 - ctx - context for residual evaluation 796 797 Level: advanced 798 799 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 800 @*/ 801 PetscErrorCode DMSNESGetBlockJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx) 802 { 803 PetscErrorCode ierr; 804 SNESDM sdm; 805 806 PetscFunctionBegin; 807 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 808 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 809 if (func) *func = sdm->computeblockjacobian; 810 if (ctx) *ctx = sdm->blockjacobianctx; 811 PetscFunctionReturn(0); 812 } 813