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__ "DMSNESGetContext" 152 /*@C 153 DMSNESGetContext - get read-only private SNESDM context from a DM 154 155 Not Collective 156 157 Input Argument: 158 . dm - DM to be used with SNES 159 160 Output Argument: 161 . snesdm - private SNESDM context 162 163 Level: developer 164 165 Notes: 166 Use DMSNESGetContextWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible. 167 168 .seealso: DMSNESGetContextWrite() 169 @*/ 170 PetscErrorCode DMSNESGetContext(DM dm,SNESDM *snesdm) 171 { 172 PetscErrorCode ierr; 173 PetscContainer container; 174 SNESDM sdm; 175 176 PetscFunctionBegin; 177 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 178 ierr = PetscObjectQuery((PetscObject)dm,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr); 179 if (container) { 180 ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr); 181 } else { 182 ierr = PetscInfo(dm,"Creating new SNESDM\n");CHKERRQ(ierr); 183 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 184 ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr); 185 ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr); 186 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr); 187 ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 188 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr); 189 ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr); 190 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 191 } 192 PetscFunctionReturn(0); 193 } 194 195 #undef __FUNCT__ 196 #define __FUNCT__ "DMSNESGetContextWrite" 197 /*@C 198 DMSNESGetContextWrite - get write access to private SNESDM context from a DM 199 200 Not Collective 201 202 Input Argument: 203 . dm - DM to be used with SNES 204 205 Output Argument: 206 . snesdm - private SNESDM context 207 208 Level: developer 209 210 .seealso: DMSNESGetContext() 211 @*/ 212 PetscErrorCode DMSNESGetContextWrite(DM dm,SNESDM *snesdm) 213 { 214 PetscErrorCode ierr; 215 SNESDM sdm; 216 217 PetscFunctionBegin; 218 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 219 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 220 if (!sdm->originaldm) sdm->originaldm = dm; 221 if (sdm->originaldm != dm) { /* Copy on write */ 222 PetscContainer container; 223 SNESDM oldsdm = sdm; 224 ierr = PetscInfo(dm,"Copying SNESDM due to write\n");CHKERRQ(ierr); 225 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 226 ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr); 227 ierr = PetscMemcpy(sdm,oldsdm,sizeof(*sdm));CHKERRQ(ierr); 228 ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr); 229 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr); 230 ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 231 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 232 } 233 *snesdm = sdm; 234 PetscFunctionReturn(0); 235 } 236 237 #undef __FUNCT__ 238 #define __FUNCT__ "DMSNESCopyContext" 239 /*@C 240 DMSNESCopyContext - copies a DM context to a new DM 241 242 Logically Collective 243 244 Input Arguments: 245 + dmsrc - DM to obtain context from 246 - dmdest - DM to add context to 247 248 Level: developer 249 250 Note: 251 The context is copied by reference. This function does not ensure that a context exists. 252 253 .seealso: DMSNESGetContext(), SNESSetDM() 254 @*/ 255 PetscErrorCode DMSNESCopyContext(DM dmsrc,DM dmdest) 256 { 257 PetscErrorCode ierr; 258 PetscContainer container; 259 260 PetscFunctionBegin; 261 PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1); 262 PetscValidHeaderSpecific(dmdest,DM_CLASSID,2); 263 ierr = PetscObjectQuery((PetscObject)dmsrc,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr); 264 if (container) { 265 ierr = PetscObjectCompose((PetscObject)dmdest,"SNESDM",(PetscObject)container);CHKERRQ(ierr); 266 ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr); 267 } 268 PetscFunctionReturn(0); 269 } 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "DMSNESSetFunction" 273 /*@C 274 DMSNESSetFunction - set SNES residual evaluation function 275 276 Not Collective 277 278 Input Arguments: 279 + dm - DM to be used with SNES 280 . func - residual evaluation function, see SNESSetFunction() for calling sequence 281 - ctx - context for residual evaluation 282 283 Level: advanced 284 285 Note: 286 SNESSetFunction() is normally used, but it calls this function internally because the user context is actually 287 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 288 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 289 290 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 291 @*/ 292 PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx) 293 { 294 PetscErrorCode ierr; 295 SNESDM sdm; 296 297 PetscFunctionBegin; 298 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 299 ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 300 if (func) sdm->computefunction = func; 301 if (ctx) sdm->functionctx = ctx; 302 PetscFunctionReturn(0); 303 } 304 305 #undef __FUNCT__ 306 #define __FUNCT__ "DMSNESGetFunction" 307 /*@C 308 DMSNESGetFunction - get SNES residual evaluation function 309 310 Not Collective 311 312 Input Argument: 313 . dm - DM to be used with SNES 314 315 Output Arguments: 316 + func - residual evaluation function, see SNESSetFunction() for calling sequence 317 - ctx - context for residual evaluation 318 319 Level: advanced 320 321 Note: 322 SNESGetFunction() is normally used, but it calls this function internally because the user context is actually 323 associated with the DM. 324 325 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction() 326 @*/ 327 PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx) 328 { 329 PetscErrorCode ierr; 330 SNESDM sdm; 331 332 PetscFunctionBegin; 333 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 334 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 335 if (func) *func = sdm->computefunction; 336 if (ctx) *ctx = sdm->functionctx; 337 PetscFunctionReturn(0); 338 } 339 340 #undef __FUNCT__ 341 #define __FUNCT__ "DMSNESSetGS" 342 /*@C 343 DMSNESSetGS - set SNES Gauss-Seidel relaxation function 344 345 Not Collective 346 347 Input Argument: 348 + dm - DM to be used with SNES 349 . func - relaxation function, see SNESSetGS() for calling sequence 350 - ctx - context for residual evaluation 351 352 Level: advanced 353 354 Note: 355 SNESSetGS() is normally used, but it calls this function internally because the user context is actually 356 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 357 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 358 359 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction() 360 @*/ 361 PetscErrorCode DMSNESSetGS(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx) 362 { 363 PetscErrorCode ierr; 364 SNESDM sdm; 365 366 PetscFunctionBegin; 367 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 368 ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 369 if (func) sdm->computegs = func; 370 if (ctx) sdm->gsctx = ctx; 371 PetscFunctionReturn(0); 372 } 373 374 #undef __FUNCT__ 375 #define __FUNCT__ "DMSNESGetGS" 376 /*@C 377 DMSNESGetGS - get SNES Gauss-Seidel relaxation function 378 379 Not Collective 380 381 Input Argument: 382 . dm - DM to be used with SNES 383 384 Output Arguments: 385 + func - relaxation function, see SNESSetGS() for calling sequence 386 - ctx - context for residual evaluation 387 388 Level: advanced 389 390 Note: 391 SNESGetGS() is normally used, but it calls this function internally because the user context is actually 392 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 393 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 394 395 .seealso: DMSNESSetContext(), SNESGetGS(), DMSNESGetJacobian(), DMSNESGetFunction() 396 @*/ 397 PetscErrorCode DMSNESGetGS(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx) 398 { 399 PetscErrorCode ierr; 400 SNESDM sdm; 401 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 404 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 405 if (func) *func = sdm->computegs; 406 if (ctx) *ctx = sdm->gsctx; 407 PetscFunctionReturn(0); 408 } 409 410 #undef __FUNCT__ 411 #define __FUNCT__ "DMSNESSetJacobian" 412 /*@C 413 DMSNESSetJacobian - set SNES Jacobian evaluation function 414 415 Not Collective 416 417 Input Argument: 418 + dm - DM to be used with SNES 419 . func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 420 - ctx - context for residual evaluation 421 422 Level: advanced 423 424 Note: 425 SNESSetJacobian() is normally used, but it calls this function internally because the user context is actually 426 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 427 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 428 429 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian() 430 @*/ 431 PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx) 432 { 433 PetscErrorCode ierr; 434 SNESDM sdm; 435 436 PetscFunctionBegin; 437 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 438 ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr); 439 if (func) sdm->computejacobian = func; 440 if (ctx) sdm->jacobianctx = ctx; 441 PetscFunctionReturn(0); 442 } 443 444 #undef __FUNCT__ 445 #define __FUNCT__ "DMSNESGetJacobian" 446 /*@C 447 DMSNESGetJacobian - get SNES Jacobian evaluation function 448 449 Not Collective 450 451 Input Argument: 452 . dm - DM to be used with SNES 453 454 Output Arguments: 455 + func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 456 - ctx - context for residual evaluation 457 458 Level: advanced 459 460 Note: 461 SNESGetJacobian() 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 Jacobian. 464 465 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 466 @*/ 467 PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx) 468 { 469 PetscErrorCode ierr; 470 SNESDM sdm; 471 472 PetscFunctionBegin; 473 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 474 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 475 if (func) *func = sdm->computejacobian; 476 if (ctx) *ctx = sdm->jacobianctx; 477 PetscFunctionReturn(0); 478 } 479 480 #undef __FUNCT__ 481 #define __FUNCT__ "DMSNESSetPicard" 482 /*@C 483 DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions. 484 485 Not Collective 486 487 Input Argument: 488 + dm - DM to be used with SNES 489 . func - RHS evaluation function, see SNESSetFunction() for calling sequence 490 . pjac - Picard matrix evaluation function, see SNESSetJacobian() for calling sequence 491 - ctx - context for residual evaluation 492 493 Level: advanced 494 495 .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian() 496 @*/ 497 PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (*pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx) 498 { 499 PetscErrorCode ierr; 500 SNESDM sdm; 501 502 PetscFunctionBegin; 503 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 504 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 505 if (pfunc) sdm->computepfunction = pfunc; 506 if (pjac) sdm->computepjacobian = pjac; 507 if (ctx) sdm->pctx = ctx; 508 PetscFunctionReturn(0); 509 } 510 511 512 #undef __FUNCT__ 513 #define __FUNCT__ "DMSNESGetPicard" 514 /*@C 515 DMSNESGetPicard - get SNES Picard iteration evaluation functions 516 517 Not Collective 518 519 Input Argument: 520 . dm - DM to be used with SNES 521 522 Output Arguments: 523 + pfunc - Jacobian evaluation function, see SNESSetJacobian() for calling sequence 524 . pjac - RHS evaluation function, see SNESSetFunction() for calling sequence 525 - ctx - context for residual evaluation 526 527 Level: advanced 528 529 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian() 530 @*/ 531 PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (**pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx) 532 { 533 PetscErrorCode ierr; 534 SNESDM sdm; 535 536 PetscFunctionBegin; 537 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 538 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 539 if (pfunc) *pfunc = sdm->computepfunction; 540 if (pjac) *pjac = sdm->computepjacobian; 541 if (ctx) *ctx = sdm->pctx; 542 PetscFunctionReturn(0); 543 } 544 545 546 #undef __FUNCT__ 547 #define __FUNCT__ "SNESDefaultComputeFunction_DMLegacy" 548 static PetscErrorCode SNESDefaultComputeFunction_DMLegacy(SNES snes,Vec X,Vec F,void *ctx) 549 { 550 PetscErrorCode ierr; 551 DM dm; 552 553 PetscFunctionBegin; 554 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 555 ierr = DMComputeFunction(dm,X,F);CHKERRQ(ierr); 556 PetscFunctionReturn(0); 557 } 558 559 #undef __FUNCT__ 560 #define __FUNCT__ "SNESDefaultComputeJacobian_DMLegacy" 561 static PetscErrorCode SNESDefaultComputeJacobian_DMLegacy(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx) 562 { 563 PetscErrorCode ierr; 564 DM dm; 565 566 PetscFunctionBegin; 567 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 568 ierr = DMComputeJacobian(dm,X,*A,*B,mstr);CHKERRQ(ierr); 569 PetscFunctionReturn(0); 570 } 571 572 #undef __FUNCT__ 573 #define __FUNCT__ "DMSNESSetUpLegacy" 574 /* Sets up calling of legacy DM routines */ 575 PetscErrorCode DMSNESSetUpLegacy(DM dm) 576 { 577 PetscErrorCode ierr; 578 SNESDM sdm; 579 580 PetscFunctionBegin; 581 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 582 if (!sdm->computefunction) {ierr = DMSNESSetFunction(dm,SNESDefaultComputeFunction_DMLegacy,PETSC_NULL);CHKERRQ(ierr);} 583 ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr); 584 if (!sdm->computejacobian) { 585 if (dm->ops->functionj) { 586 ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobian_DMLegacy,PETSC_NULL);CHKERRQ(ierr); 587 } else { 588 ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobianColor,PETSC_NULL);CHKERRQ(ierr); 589 } 590 } 591 PetscFunctionReturn(0); 592 } 593