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