1 #include <petsc-private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petsc-private/dmimpl.h> /*I "petscdm.h" I*/ 3 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMCoarsenHook_TSDM" 7 /* Attaches the SNESDM to the coarse level. 8 * Under what conditions should we copy versus duplicate? 9 */ 10 static PetscErrorCode DMCoarsenHook_TSDM(DM dm,DM dmc,void *ctx) 11 { 12 PetscErrorCode ierr; 13 14 PetscFunctionBegin; 15 ierr = DMTSCopyContext(dm,dmc);CHKERRQ(ierr); 16 PetscFunctionReturn(0); 17 } 18 19 #undef __FUNCT__ 20 #define __FUNCT__ "DMRestrictHook_TSDM" 21 /* This could restrict auxiliary information to the coarse level. 22 */ 23 static PetscErrorCode DMRestrictHook_TSDM(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx) 24 { 25 26 PetscFunctionBegin; 27 PetscFunctionReturn(0); 28 } 29 30 31 #undef __FUNCT__ 32 #define __FUNCT__ "PetscContainerDestroy_TSDM" 33 static PetscErrorCode PetscContainerDestroy_TSDM(void *ctx) 34 { 35 PetscErrorCode ierr; 36 TSDM tsdm = (TSDM)ctx; 37 38 PetscFunctionBegin; 39 if (tsdm->destroy) {ierr = (*tsdm->destroy)(tsdm);CHKERRQ(ierr);} 40 ierr = PetscFree(tsdm);CHKERRQ(ierr); 41 PetscFunctionReturn(0); 42 } 43 44 #undef __FUNCT__ 45 #define __FUNCT__ "DMTSGetContext" 46 /*@C 47 DMTSGetContext - get read-only private TSDM context from a DM 48 49 Not Collective 50 51 Input Argument: 52 . dm - DM to be used with TS 53 54 Output Argument: 55 . tsdm - private TSDM context 56 57 Level: developer 58 59 Notes: 60 Use DMTSGetContextWrite() if write access is needed. The DMTSSetXXX API should be used wherever possible. 61 62 .seealso: DMTSGetContextWrite() 63 @*/ 64 PetscErrorCode DMTSGetContext(DM dm,TSDM *tsdm) 65 { 66 PetscErrorCode ierr; 67 PetscContainer container; 68 TSDM tsdmnew; 69 70 71 PetscFunctionBegin; 72 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 73 ierr = PetscObjectQuery((PetscObject)dm,"TSDM",(PetscObject*)&container);CHKERRQ(ierr); 74 if (container) { 75 ierr = PetscContainerGetPointer(container,(void**)tsdm);CHKERRQ(ierr); 76 } else { 77 ierr = PetscInfo(dm,"Creating new TSDM\n");CHKERRQ(ierr); 78 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 79 ierr = PetscNewLog(dm,struct _n_TSDM,&tsdmnew);CHKERRQ(ierr); 80 ierr = PetscContainerSetPointer(container,tsdmnew);CHKERRQ(ierr); 81 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_TSDM);CHKERRQ(ierr); 82 ierr = PetscObjectCompose((PetscObject)dm,"TSDM",(PetscObject)container);CHKERRQ(ierr); 83 ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_TSDM,DMRestrictHook_TSDM,PETSC_NULL);CHKERRQ(ierr); 84 ierr = PetscContainerGetPointer(container,(void**)tsdm);CHKERRQ(ierr); 85 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 86 } 87 PetscFunctionReturn(0); 88 } 89 90 #undef __FUNCT__ 91 #define __FUNCT__ "DMTSGetContextWrite" 92 /*@C 93 DMTSGetContextWrite - get write access to private TSDM context from a DM 94 95 Not Collective 96 97 Input Argument: 98 . dm - DM to be used with TS 99 100 Output Argument: 101 . tsdm - private TSDM context 102 103 Level: developer 104 105 .seealso: DMTSGetContext() 106 @*/ 107 PetscErrorCode DMTSGetContextWrite(DM dm,TSDM *tsdm) 108 { 109 PetscErrorCode ierr; 110 TSDM sdm; 111 112 PetscFunctionBegin; 113 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 114 ierr = DMTSGetContext(dm,&sdm);CHKERRQ(ierr); 115 if (!sdm->originaldm) sdm->originaldm = dm; 116 if (sdm->originaldm != dm) { /* Copy on write */ 117 PetscContainer container; 118 TSDM oldsdm = sdm; 119 ierr = PetscInfo(dm,"Copying TSDM due to write\n");CHKERRQ(ierr); 120 ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr); 121 ierr = PetscNewLog(dm,struct _n_TSDM,&sdm);CHKERRQ(ierr); 122 ierr = PetscMemcpy(sdm,oldsdm,sizeof *sdm);CHKERRQ(ierr); 123 ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr); 124 ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_TSDM);CHKERRQ(ierr); 125 ierr = PetscObjectCompose((PetscObject)dm,"TSDM",(PetscObject)container);CHKERRQ(ierr); 126 ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 127 } 128 *tsdm = sdm; 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "DMTSCopyContext" 134 /*@C 135 DMTSCopyContext - copies a DM context to a new DM 136 137 Logically Collective 138 139 Input Arguments: 140 + dmsrc - DM to obtain context from 141 - dmdest - DM to add context to 142 143 Level: developer 144 145 Note: 146 The context is copied by reference. This function does not ensure that a context exists. 147 148 .seealso: DMTSGetContext(), TSSetDM() 149 @*/ 150 PetscErrorCode DMTSCopyContext(DM dmsrc,DM dmdest) 151 { 152 PetscErrorCode ierr; 153 PetscContainer container; 154 155 PetscFunctionBegin; 156 PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1); 157 PetscValidHeaderSpecific(dmdest,DM_CLASSID,2); 158 ierr = PetscObjectQuery((PetscObject)dmsrc,"TSDM",(PetscObject*)&container);CHKERRQ(ierr); 159 if (container) { 160 ierr = PetscObjectCompose((PetscObject)dmdest,"TSDM",(PetscObject)container);CHKERRQ(ierr); 161 ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_TSDM,DMRestrictHook_TSDM,PETSC_NULL);CHKERRQ(ierr); 162 } 163 PetscFunctionReturn(0); 164 } 165 166 #undef __FUNCT__ 167 #define __FUNCT__ "DMTSSetIFunction" 168 /*@C 169 DMTSSetIFunction - set TS implicit function evaluation function 170 171 Not Collective 172 173 Input Arguments: 174 + dm - DM to be used with TS 175 . func - function evaluation function, see TSSetIFunction() for calling sequence 176 - ctx - context for residual evaluation 177 178 Level: advanced 179 180 Note: 181 TSSetFunction() is normally used, but it calls this function internally because the user context is actually 182 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 183 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 184 185 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian() 186 @*/ 187 PetscErrorCode DMTSSetIFunction(DM dm,TSIFunction func,void *ctx) 188 { 189 PetscErrorCode ierr; 190 TSDM tsdm; 191 192 PetscFunctionBegin; 193 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 194 ierr = DMTSGetContextWrite(dm,&tsdm);CHKERRQ(ierr); 195 if (func) tsdm->ifunction = func; 196 if (ctx) tsdm->ifunctionctx = ctx; 197 PetscFunctionReturn(0); 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "DMTSGetIFunction" 202 /*@C 203 DMTSGetIFunction - get TS implicit residual evaluation function 204 205 Not Collective 206 207 Input Argument: 208 . dm - DM to be used with TS 209 210 Output Arguments: 211 + func - function evaluation function, see TSSetIFunction() for calling sequence 212 - ctx - context for residual evaluation 213 214 Level: advanced 215 216 Note: 217 TSGetFunction() is normally used, but it calls this function internally because the user context is actually 218 associated with the DM. 219 220 .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction() 221 @*/ 222 PetscErrorCode DMTSGetIFunction(DM dm,TSIFunction *func,void **ctx) 223 { 224 PetscErrorCode ierr; 225 TSDM tsdm; 226 227 PetscFunctionBegin; 228 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 229 ierr = DMTSGetContext(dm,&tsdm);CHKERRQ(ierr); 230 if (func) *func = tsdm->ifunction; 231 if (ctx) *ctx = tsdm->ifunctionctx; 232 PetscFunctionReturn(0); 233 } 234 235 236 #undef __FUNCT__ 237 #define __FUNCT__ "DMTSSetRHSFunction" 238 /*@C 239 DMTSSetRHSFunction - set TS explicit residual evaluation function 240 241 Not Collective 242 243 Input Arguments: 244 + dm - DM to be used with TS 245 . func - RHS function evaluation function, see TSSetRHSFunction() for calling sequence 246 - ctx - context for residual evaluation 247 248 Level: advanced 249 250 Note: 251 TSSetFunction() is normally used, but it calls this function internally because the user context is actually 252 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 253 not. If DM took a more central role at some later date, this could become the primary method of setting the residual. 254 255 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian() 256 @*/ 257 PetscErrorCode DMTSSetRHSFunction(DM dm,TSRHSFunction func,void *ctx) 258 { 259 PetscErrorCode ierr; 260 TSDM tsdm; 261 262 PetscFunctionBegin; 263 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 264 ierr = DMTSGetContextWrite(dm,&tsdm);CHKERRQ(ierr); 265 if (func) tsdm->rhsfunction = func; 266 if (ctx) tsdm->rhsfunctionctx = ctx; 267 PetscFunctionReturn(0); 268 } 269 270 #undef __FUNCT__ 271 #define __FUNCT__ "DMTSGetRHSFunction" 272 /*@C 273 DMTSGetRHSFunction - get TS explicit residual evaluation function 274 275 Not Collective 276 277 Input Argument: 278 . dm - DM to be used with TS 279 280 Output Arguments: 281 + func - residual evaluation function, see TSSetRHSFunction() for calling sequence 282 - ctx - context for residual evaluation 283 284 Level: advanced 285 286 Note: 287 TSGetFunction() is normally used, but it calls this function internally because the user context is actually 288 associated with the DM. 289 290 .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction() 291 @*/ 292 PetscErrorCode DMTSGetRHSFunction(DM dm,TSRHSFunction *func,void **ctx) 293 { 294 PetscErrorCode ierr; 295 TSDM tsdm; 296 297 PetscFunctionBegin; 298 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 299 ierr = DMTSGetContext(dm,&tsdm);CHKERRQ(ierr); 300 if (func) *func = tsdm->rhsfunction; 301 if (ctx) *ctx = tsdm->rhsfunctionctx; 302 PetscFunctionReturn(0); 303 } 304 305 #undef __FUNCT__ 306 #define __FUNCT__ "DMTSSetIJacobian" 307 /*@C 308 DMTSSetIJacobian - set TS Jacobian evaluation function 309 310 Not Collective 311 312 Input Argument: 313 + dm - DM to be used with TS 314 . func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence 315 - ctx - context for residual evaluation 316 317 Level: advanced 318 319 Note: 320 TSSetJacobian() is normally used, but it calls this function internally because the user context is actually 321 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 322 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 323 324 .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian() 325 @*/ 326 PetscErrorCode DMTSSetIJacobian(DM dm,TSIJacobian func,void *ctx) 327 { 328 PetscErrorCode ierr; 329 TSDM sdm; 330 331 PetscFunctionBegin; 332 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 333 ierr = DMTSGetContextWrite(dm,&sdm);CHKERRQ(ierr); 334 if (func) sdm->ijacobian = func; 335 if (ctx) sdm->ijacobianctx = ctx; 336 PetscFunctionReturn(0); 337 } 338 339 #undef __FUNCT__ 340 #define __FUNCT__ "DMTSGetIJacobian" 341 /*@C 342 DMTSGetIJacobian - get TS Jacobian evaluation function 343 344 Not Collective 345 346 Input Argument: 347 . dm - DM to be used with TS 348 349 Output Arguments: 350 + func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence 351 - ctx - context for residual evaluation 352 353 Level: advanced 354 355 Note: 356 TSGetJacobian() is normally used, but it calls this function internally because the user context is actually 357 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 358 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 359 360 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian() 361 @*/ 362 PetscErrorCode DMTSGetIJacobian(DM dm,TSIJacobian *func,void **ctx) 363 { 364 PetscErrorCode ierr; 365 TSDM tsdm; 366 367 PetscFunctionBegin; 368 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 369 ierr = DMTSGetContext(dm,&tsdm);CHKERRQ(ierr); 370 if (func) *func = tsdm->ijacobian; 371 if (ctx) *ctx = tsdm->ijacobianctx; 372 PetscFunctionReturn(0); 373 } 374 375 376 #undef __FUNCT__ 377 #define __FUNCT__ "DMTSSetRHSJacobian" 378 /*@C 379 DMTSSetRHSJacobian - set TS Jacobian evaluation function 380 381 Not Collective 382 383 Input Argument: 384 + dm - DM to be used with TS 385 . func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence 386 - ctx - context for residual evaluation 387 388 Level: advanced 389 390 Note: 391 TSSetJacobian() 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 Jacobian. 394 395 .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian() 396 @*/ 397 PetscErrorCode DMTSSetRHSJacobian(DM dm,TSRHSJacobian func,void *ctx) 398 { 399 PetscErrorCode ierr; 400 TSDM tsdm; 401 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 404 ierr = DMTSGetContextWrite(dm,&tsdm);CHKERRQ(ierr); 405 if (func) tsdm->rhsjacobian = func; 406 if (ctx) tsdm->rhsjacobianctx = ctx; 407 PetscFunctionReturn(0); 408 } 409 410 #undef __FUNCT__ 411 #define __FUNCT__ "DMTSGetRHSJacobian" 412 /*@C 413 DMTSGetRHSJacobian - get TS Jacobian evaluation function 414 415 Not Collective 416 417 Input Argument: 418 . dm - DM to be used with TS 419 420 Output Arguments: 421 + func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence 422 - ctx - context for residual evaluation 423 424 Level: advanced 425 426 Note: 427 TSGetJacobian() is normally used, but it calls this function internally because the user context is actually 428 associated with the DM. This makes the interface consistent regardless of whether the user interacts with a DM or 429 not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian. 430 431 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian() 432 @*/ 433 PetscErrorCode DMTSGetRHSJacobian(DM dm,TSRHSJacobian *func,void **ctx) 434 { 435 PetscErrorCode ierr; 436 TSDM tsdm; 437 438 PetscFunctionBegin; 439 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 440 ierr = DMTSGetContext(dm,&tsdm);CHKERRQ(ierr); 441 if (func) *func = tsdm->rhsjacobian; 442 if (ctx) *ctx = tsdm->rhsjacobianctx; 443 PetscFunctionReturn(0); 444 } 445