1 #include <petsc/private/petscdsimpl.h> /*I "petscds.h" I*/ 2 3 PetscClassId PETSCDS_CLASSID = 0; 4 5 PetscFunctionList PetscDSList = NULL; 6 PetscBool PetscDSRegisterAllCalled = PETSC_FALSE; 7 8 /* A PetscDS (Discrete System) encodes a set of equations posed in a discrete space, which represents a set of 9 nonlinear continuum equations. The equations can have multiple fields, each field having a different 10 discretization. In addition, different pieces of the domain can have different field combinations and equations. 11 12 The DS provides the user a description of the approximation space on any given cell. It also gives pointwise 13 functions representing the equations. 14 15 Each field is associated with a label, marking the cells on which it is supported. Note that a field can be 16 supported on the closure of a cell not in the label due to overlap of the boundary of neighboring cells. The DM 17 then creates a DS for each set of cells with identical approximation spaces. When assembling, the user asks for 18 the space associated with a given cell. DMPlex uses the labels associated with each DS in the default integration loop. 19 */ 20 21 /*@C 22 PetscDSRegister - Adds a new `PetscDS` implementation 23 24 Not Collective 25 26 Input Parameters: 27 + name - The name of a new user-defined creation routine 28 - create_func - The creation routine itself 29 30 Sample usage: 31 .vb 32 PetscDSRegister("my_ds", MyPetscDSCreate); 33 .ve 34 35 Then, your PetscDS type can be chosen with the procedural interface via 36 .vb 37 PetscDSCreate(MPI_Comm, PetscDS *); 38 PetscDSSetType(PetscDS, "my_ds"); 39 .ve 40 or at runtime via the option 41 .vb 42 -petscds_type my_ds 43 .ve 44 45 Level: advanced 46 47 Note: 48 `PetscDSRegister()` may be called multiple times to add several user-defined `PetscDSs` 49 50 Fortran Note: 51 Not available from Fortran 52 53 .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()` 54 @*/ 55 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS)) 56 { 57 PetscFunctionBegin; 58 PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function)); 59 PetscFunctionReturn(PETSC_SUCCESS); 60 } 61 62 /*@C 63 PetscDSSetType - Builds a particular `PetscDS` 64 65 Collective on prob 66 67 Input Parameters: 68 + prob - The `PetscDS` object 69 - name - The `PetscDSType` 70 71 Options Database Key: 72 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types 73 74 Level: intermediate 75 76 Fortran Note: 77 Not available from Fortran 78 79 .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()` 80 @*/ 81 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name) 82 { 83 PetscErrorCode (*r)(PetscDS); 84 PetscBool match; 85 86 PetscFunctionBegin; 87 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 88 PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match)); 89 if (match) PetscFunctionReturn(PETSC_SUCCESS); 90 91 PetscCall(PetscDSRegisterAll()); 92 PetscCall(PetscFunctionListFind(PetscDSList, name, &r)); 93 PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name); 94 95 PetscTryTypeMethod(prob, destroy); 96 prob->ops->destroy = NULL; 97 98 PetscCall((*r)(prob)); 99 PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name)); 100 PetscFunctionReturn(PETSC_SUCCESS); 101 } 102 103 /*@C 104 PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS` 105 106 Not Collective 107 108 Input Parameter: 109 . prob - The `PetscDS` 110 111 Output Parameter: 112 . name - The `PetscDSType` name 113 114 Level: intermediate 115 116 Fortran Note: 117 Not available from Fortran 118 119 .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()` 120 @*/ 121 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name) 122 { 123 PetscFunctionBegin; 124 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 125 PetscValidPointer(name, 2); 126 PetscCall(PetscDSRegisterAll()); 127 *name = ((PetscObject)prob)->type_name; 128 PetscFunctionReturn(PETSC_SUCCESS); 129 } 130 131 static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer) 132 { 133 PetscViewerFormat format; 134 const PetscScalar *constants; 135 PetscInt Nf, numConstants, f; 136 137 PetscFunctionBegin; 138 PetscCall(PetscDSGetNumFields(ds, &Nf)); 139 PetscCall(PetscViewerGetFormat(viewer, &format)); 140 PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf)); 141 PetscCall(PetscViewerASCIIPushTab(viewer)); 142 PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp)); 143 if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n")); 144 for (f = 0; f < Nf; ++f) { 145 DSBoundary b; 146 PetscObject obj; 147 PetscClassId id; 148 PetscQuadrature q; 149 const char *name; 150 PetscInt Nc, Nq, Nqc; 151 152 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 153 PetscCall(PetscObjectGetClassId(obj, &id)); 154 PetscCall(PetscObjectGetName(obj, &name)); 155 PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>")); 156 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 157 if (id == PETSCFE_CLASSID) { 158 PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 159 PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q)); 160 PetscCall(PetscViewerASCIIPrintf(viewer, " FEM")); 161 } else if (id == PETSCFV_CLASSID) { 162 PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 163 PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q)); 164 PetscCall(PetscViewerASCIIPrintf(viewer, " FVM")); 165 } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 166 if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc)); 167 else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc)); 168 if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)")); 169 else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)")); 170 if (q) { 171 PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL)); 172 PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc)); 173 } 174 PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f])); 175 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 176 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 177 PetscCall(PetscViewerASCIIPushTab(viewer)); 178 if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer)); 179 else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer)); 180 PetscCall(PetscViewerASCIIPopTab(viewer)); 181 182 for (b = ds->boundary; b; b = b->next) { 183 char *name; 184 PetscInt c, i; 185 186 if (b->field != f) continue; 187 PetscCall(PetscViewerASCIIPushTab(viewer)); 188 PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type])); 189 if (!b->Nc) { 190 PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n")); 191 } else { 192 PetscCall(PetscViewerASCIIPrintf(viewer, " components: ")); 193 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 194 for (c = 0; c < b->Nc; ++c) { 195 if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 196 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c])); 197 } 198 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 199 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 200 } 201 PetscCall(PetscViewerASCIIPrintf(viewer, " values: ")); 202 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 203 for (i = 0; i < b->Nv; ++i) { 204 if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 205 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i])); 206 } 207 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 208 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 209 #if defined(__clang__) 210 #pragma clang diagnostic push 211 #pragma clang diagnostic ignored "-Wformat-pedantic" 212 #elif defined(__GNUC__) || defined(__GNUG__) 213 #pragma GCC diagnostic push 214 #pragma GCC diagnostic ignored "-Wformat" 215 #endif 216 if (b->func) { 217 PetscCall(PetscDLAddr(b->func, &name)); 218 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name)); 219 else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func)); 220 PetscCall(PetscFree(name)); 221 } 222 if (b->func_t) { 223 PetscCall(PetscDLAddr(b->func_t, &name)); 224 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name)); 225 else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t)); 226 PetscCall(PetscFree(name)); 227 } 228 #if defined(__clang__) 229 #pragma clang diagnostic pop 230 #elif defined(__GNUC__) || defined(__GNUG__) 231 #pragma GCC diagnostic pop 232 #endif 233 PetscCall(PetscWeakFormView(b->wf, viewer)); 234 PetscCall(PetscViewerASCIIPopTab(viewer)); 235 } 236 } 237 PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 238 if (numConstants) { 239 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants)); 240 PetscCall(PetscViewerASCIIPushTab(viewer)); 241 for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f]))); 242 PetscCall(PetscViewerASCIIPopTab(viewer)); 243 } 244 PetscCall(PetscWeakFormView(ds->wf, viewer)); 245 PetscCall(PetscViewerASCIIPopTab(viewer)); 246 PetscFunctionReturn(PETSC_SUCCESS); 247 } 248 249 /*@C 250 PetscDSViewFromOptions - View a `PetscDS` based on values in the options database 251 252 Collective on PetscDS 253 254 Input Parameters: 255 + A - the `PetscDS` object 256 . obj - Optional object 257 - name - command line option 258 259 Level: intermediate 260 261 .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()` 262 @*/ 263 PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[]) 264 { 265 PetscFunctionBegin; 266 PetscValidHeaderSpecific(A, PETSCDS_CLASSID, 1); 267 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 268 PetscFunctionReturn(PETSC_SUCCESS); 269 } 270 271 /*@C 272 PetscDSView - Views a `PetscDS` 273 274 Collective on prob 275 276 Input Parameters: 277 + prob - the `PetscDS` object to view 278 - v - the viewer 279 280 Level: developer 281 282 .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()` 283 @*/ 284 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v) 285 { 286 PetscBool iascii; 287 288 PetscFunctionBegin; 289 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 290 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v)); 291 else PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 292 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 293 if (iascii) PetscCall(PetscDSView_Ascii(prob, v)); 294 PetscTryTypeMethod(prob, view, v); 295 PetscFunctionReturn(PETSC_SUCCESS); 296 } 297 298 /*@ 299 PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database 300 301 Collective on prob 302 303 Input Parameter: 304 . prob - the `PetscDS` object to set options for 305 306 Options Database Keys: 307 + -petscds_type <type> - Set the `PetscDS` type 308 . -petscds_view <view opt> - View the `PetscDS` 309 . -petscds_jac_pre - Turn formation of a separate Jacobian preconditioner on or off 310 . -bc_<name> <ids> - Specify a list of label ids for a boundary condition 311 - -bc_<name>_comp <comps> - Specify a list of field components to constrain for a boundary condition 312 313 Level: intermediate 314 315 .seealso: `PetscDS`, `PetscDSView()` 316 @*/ 317 PetscErrorCode PetscDSSetFromOptions(PetscDS prob) 318 { 319 DSBoundary b; 320 const char *defaultType; 321 char name[256]; 322 PetscBool flg; 323 324 PetscFunctionBegin; 325 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 326 if (!((PetscObject)prob)->type_name) { 327 defaultType = PETSCDSBASIC; 328 } else { 329 defaultType = ((PetscObject)prob)->type_name; 330 } 331 PetscCall(PetscDSRegisterAll()); 332 333 PetscObjectOptionsBegin((PetscObject)prob); 334 for (b = prob->boundary; b; b = b->next) { 335 char optname[1024]; 336 PetscInt ids[1024], len = 1024; 337 PetscBool flg; 338 339 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name)); 340 PetscCall(PetscMemzero(ids, sizeof(ids))); 341 PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg)); 342 if (flg) { 343 b->Nv = len; 344 PetscCall(PetscFree(b->values)); 345 PetscCall(PetscMalloc1(len, &b->values)); 346 PetscCall(PetscArraycpy(b->values, ids, len)); 347 PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values)); 348 } 349 len = 1024; 350 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name)); 351 PetscCall(PetscMemzero(ids, sizeof(ids))); 352 PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg)); 353 if (flg) { 354 b->Nc = len; 355 PetscCall(PetscFree(b->comps)); 356 PetscCall(PetscMalloc1(len, &b->comps)); 357 PetscCall(PetscArraycpy(b->comps, ids, len)); 358 } 359 } 360 PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg)); 361 if (flg) { 362 PetscCall(PetscDSSetType(prob, name)); 363 } else if (!((PetscObject)prob)->type_name) { 364 PetscCall(PetscDSSetType(prob, defaultType)); 365 } 366 PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg)); 367 PetscCall(PetscOptionsBool("-petscds_force_quad", "Discrete System", "PetscDSSetForceQuad", prob->forceQuad, &prob->forceQuad, &flg)); 368 PetscTryTypeMethod(prob, setfromoptions); 369 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 370 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject)); 371 PetscOptionsEnd(); 372 if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view")); 373 PetscFunctionReturn(PETSC_SUCCESS); 374 } 375 376 /*@C 377 PetscDSSetUp - Construct data structures for the `PetscDS` 378 379 Collective on prob 380 381 Input Parameter: 382 . prob - the `PetscDS` object to setup 383 384 Level: developer 385 386 .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()` 387 @*/ 388 PetscErrorCode PetscDSSetUp(PetscDS prob) 389 { 390 const PetscInt Nf = prob->Nf; 391 PetscBool hasH = PETSC_FALSE; 392 PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f; 393 394 PetscFunctionBegin; 395 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 396 if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS); 397 /* Calculate sizes */ 398 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 399 PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed)); 400 prob->totDim = prob->totComp = 0; 401 PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb)); 402 PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer)); 403 PetscCall(PetscCalloc6(Nf + 1, &prob->offCohesive[0], Nf + 1, &prob->offCohesive[1], Nf + 1, &prob->offCohesive[2], Nf + 1, &prob->offDerCohesive[0], Nf + 1, &prob->offDerCohesive[1], Nf + 1, &prob->offDerCohesive[2])); 404 PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf)); 405 if (prob->forceQuad) { 406 PetscQuadrature mq = NULL, mfq = NULL; 407 PetscInt maxOrder = -1, maxFOrder = -1; 408 409 for (f = 0; f < Nf; ++f) { 410 PetscObject obj; 411 PetscClassId id; 412 PetscQuadrature q = NULL, fq = NULL; 413 PetscInt order = -1, forder = -1; 414 415 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 416 if (!obj) continue; 417 PetscCall(PetscObjectGetClassId(obj, &id)); 418 if (id == PETSCFE_CLASSID) { 419 PetscFE fe = (PetscFE)obj; 420 421 PetscCall(PetscFEGetQuadrature(fe, &q)); 422 PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 423 } else if (id == PETSCFV_CLASSID) { 424 PetscFV fv = (PetscFV)obj; 425 426 PetscCall(PetscFVGetQuadrature(fv, &q)); 427 } 428 if (q) PetscCall(PetscQuadratureGetOrder(q, &order)); 429 if (fq) PetscCall(PetscQuadratureGetOrder(fq, &forder)); 430 if (order > maxOrder) { 431 maxOrder = order; 432 mq = q; 433 } 434 if (forder > maxFOrder) { 435 maxFOrder = forder; 436 mfq = fq; 437 } 438 } 439 for (f = 0; f < Nf; ++f) { 440 PetscObject obj; 441 PetscClassId id; 442 443 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 444 if (!obj) continue; 445 PetscCall(PetscObjectGetClassId(obj, &id)); 446 if (id == PETSCFE_CLASSID) { 447 PetscFE fe = (PetscFE)obj; 448 449 PetscCall(PetscFESetQuadrature(fe, mq)); 450 PetscCall(PetscFESetFaceQuadrature(fe, mfq)); 451 } else if (id == PETSCFV_CLASSID) { 452 PetscFV fv = (PetscFV)obj; 453 454 PetscCall(PetscFVSetQuadrature(fv, mq)); 455 } 456 } 457 } 458 for (f = 0; f < Nf; ++f) { 459 PetscObject obj; 460 PetscClassId id; 461 PetscQuadrature q = NULL; 462 PetscInt Nq = 0, Nb, Nc; 463 464 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 465 if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE; 466 if (!obj) { 467 /* Empty mesh */ 468 Nb = Nc = 0; 469 prob->T[f] = prob->Tf[f] = NULL; 470 } else { 471 PetscCall(PetscObjectGetClassId(obj, &id)); 472 if (id == PETSCFE_CLASSID) { 473 PetscFE fe = (PetscFE)obj; 474 475 PetscCall(PetscFEGetQuadrature(fe, &q)); 476 PetscCall(PetscFEGetDimension(fe, &Nb)); 477 PetscCall(PetscFEGetNumComponents(fe, &Nc)); 478 PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f])); 479 PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f])); 480 } else if (id == PETSCFV_CLASSID) { 481 PetscFV fv = (PetscFV)obj; 482 483 PetscCall(PetscFVGetQuadrature(fv, &q)); 484 PetscCall(PetscFVGetNumComponents(fv, &Nc)); 485 Nb = Nc; 486 PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f])); 487 /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */ 488 } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 489 } 490 prob->Nc[f] = Nc; 491 prob->Nb[f] = Nb; 492 prob->off[f + 1] = Nc + prob->off[f]; 493 prob->offDer[f + 1] = Nc * dim + prob->offDer[f]; 494 prob->offCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f]; 495 prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f]; 496 prob->offCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f]; 497 prob->offDerCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f]; 498 prob->offCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f]; 499 prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f]; 500 if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL)); 501 NqMax = PetscMax(NqMax, Nq); 502 NbMax = PetscMax(NbMax, Nb); 503 NcMax = PetscMax(NcMax, Nc); 504 prob->totDim += Nb; 505 prob->totComp += Nc; 506 /* There are two faces for all fields on a cohesive cell, except for cohesive fields */ 507 if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb; 508 } 509 prob->offCohesive[1][Nf] = prob->offCohesive[0][Nf]; 510 prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf]; 511 /* Allocate works space */ 512 NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */ 513 PetscCall(PetscMalloc3(NsMax * prob->totComp, &prob->u, NsMax * prob->totComp, &prob->u_t, NsMax * prob->totComp * dimEmbed + (hasH ? NsMax * prob->totComp * dimEmbed * dimEmbed : 0), &prob->u_x)); 514 PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal)); 515 PetscCall(PetscMalloc6(NsMax * NqMax * NcMax, &prob->f0, NsMax * NqMax * NcMax * dimEmbed, &prob->f1, NsMax * NsMax * NqMax * NcMax * NcMax, &prob->g0, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed, &prob->g1, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed, 516 &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3)); 517 PetscTryTypeMethod(prob, setup); 518 prob->setup = PETSC_TRUE; 519 PetscFunctionReturn(PETSC_SUCCESS); 520 } 521 522 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob) 523 { 524 PetscFunctionBegin; 525 PetscCall(PetscFree2(prob->Nc, prob->Nb)); 526 PetscCall(PetscFree2(prob->off, prob->offDer)); 527 PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2])); 528 PetscCall(PetscFree2(prob->T, prob->Tf)); 529 PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x)); 530 PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal)); 531 PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3)); 532 PetscFunctionReturn(PETSC_SUCCESS); 533 } 534 535 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew) 536 { 537 PetscObject *tmpd; 538 PetscBool *tmpi; 539 PetscInt *tmpk; 540 PetscBool *tmpc; 541 PetscPointFunc *tmpup; 542 PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t; 543 void **tmpexactCtx, **tmpexactCtx_t; 544 void **tmpctx; 545 PetscInt Nf = prob->Nf, f; 546 547 PetscFunctionBegin; 548 if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS); 549 prob->setup = PETSC_FALSE; 550 PetscCall(PetscDSDestroyStructs_Static(prob)); 551 PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk)); 552 for (f = 0; f < Nf; ++f) { 553 tmpd[f] = prob->disc[f]; 554 tmpi[f] = prob->implicit[f]; 555 tmpc[f] = prob->cohesive[f]; 556 tmpk[f] = prob->jetDegree[f]; 557 } 558 for (f = Nf; f < NfNew; ++f) { 559 tmpd[f] = NULL; 560 tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE; 561 tmpk[f] = 1; 562 } 563 PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree)); 564 PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew)); 565 prob->Nf = NfNew; 566 prob->disc = tmpd; 567 prob->implicit = tmpi; 568 prob->cohesive = tmpc; 569 prob->jetDegree = tmpk; 570 PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx)); 571 for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f]; 572 for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f]; 573 for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL; 574 for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL; 575 PetscCall(PetscFree2(prob->update, prob->ctx)); 576 prob->update = tmpup; 577 prob->ctx = tmpctx; 578 PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t)); 579 for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f]; 580 for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f]; 581 for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f]; 582 for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f]; 583 for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL; 584 for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL; 585 for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL; 586 for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL; 587 PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t)); 588 prob->exactSol = tmpexactSol; 589 prob->exactCtx = tmpexactCtx; 590 prob->exactSol_t = tmpexactSol_t; 591 prob->exactCtx_t = tmpexactCtx_t; 592 PetscFunctionReturn(PETSC_SUCCESS); 593 } 594 595 /*@ 596 PetscDSDestroy - Destroys a PetscDS object 597 598 Collective on prob 599 600 Input Parameter: 601 . prob - the PetscDS object to destroy 602 603 Level: developer 604 605 .seealso: `PetscDSView()` 606 @*/ 607 PetscErrorCode PetscDSDestroy(PetscDS *ds) 608 { 609 PetscInt f; 610 611 PetscFunctionBegin; 612 if (!*ds) PetscFunctionReturn(PETSC_SUCCESS); 613 PetscValidHeaderSpecific((*ds), PETSCDS_CLASSID, 1); 614 615 if (--((PetscObject)(*ds))->refct > 0) { 616 *ds = NULL; 617 PetscFunctionReturn(PETSC_SUCCESS); 618 } 619 ((PetscObject)(*ds))->refct = 0; 620 if ((*ds)->subprobs) { 621 PetscInt dim, d; 622 623 PetscCall(PetscDSGetSpatialDimension(*ds, &dim)); 624 for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d])); 625 } 626 PetscCall(PetscFree((*ds)->subprobs)); 627 PetscCall(PetscDSDestroyStructs_Static(*ds)); 628 for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f])); 629 PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree)); 630 PetscCall(PetscWeakFormDestroy(&(*ds)->wf)); 631 PetscCall(PetscFree2((*ds)->update, (*ds)->ctx)); 632 PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t)); 633 PetscTryTypeMethod((*ds), destroy); 634 PetscCall(PetscDSDestroyBoundary(*ds)); 635 PetscCall(PetscFree((*ds)->constants)); 636 PetscCall(PetscHeaderDestroy(ds)); 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@ 641 PetscDSCreate - Creates an empty `PetscDS` object. The type can then be set with `PetscDSSetType()`. 642 643 Collective 644 645 Input Parameter: 646 . comm - The communicator for the `PetscDS` object 647 648 Output Parameter: 649 . ds - The `PetscDS` object 650 651 Level: beginner 652 653 .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType` 654 @*/ 655 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds) 656 { 657 PetscDS p; 658 659 PetscFunctionBegin; 660 PetscValidPointer(ds, 2); 661 *ds = NULL; 662 PetscCall(PetscDSInitializePackage()); 663 664 PetscCall(PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView)); 665 666 p->Nf = 0; 667 p->setup = PETSC_FALSE; 668 p->numConstants = 0; 669 p->constants = NULL; 670 p->dimEmbed = -1; 671 p->useJacPre = PETSC_TRUE; 672 p->forceQuad = PETSC_TRUE; 673 PetscCall(PetscWeakFormCreate(comm, &p->wf)); 674 675 *ds = p; 676 PetscFunctionReturn(PETSC_SUCCESS); 677 } 678 679 /*@ 680 PetscDSGetNumFields - Returns the number of fields in the `PetscDS` 681 682 Not collective 683 684 Input Parameter: 685 . prob - The PetscDS object 686 687 Output Parameter: 688 . Nf - The number of fields 689 690 Level: beginner 691 692 .seealso: `PetscDS`, `PetscDSGetSpatialDimension()`, `PetscDSCreate()` 693 @*/ 694 PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf) 695 { 696 PetscFunctionBegin; 697 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 698 PetscValidIntPointer(Nf, 2); 699 *Nf = prob->Nf; 700 PetscFunctionReturn(PETSC_SUCCESS); 701 } 702 703 /*@ 704 PetscDSGetSpatialDimension - Returns the spatial dimension of the `PetscDS`, meaning the topological dimension of the discretizations 705 706 Not collective 707 708 Input Parameter: 709 . prob - The `PetscDS` object 710 711 Output Parameter: 712 . dim - The spatial dimension 713 714 Level: beginner 715 716 .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 717 @*/ 718 PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim) 719 { 720 PetscFunctionBegin; 721 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 722 PetscValidIntPointer(dim, 2); 723 *dim = 0; 724 if (prob->Nf) { 725 PetscObject obj; 726 PetscClassId id; 727 728 PetscCall(PetscDSGetDiscretization(prob, 0, &obj)); 729 if (obj) { 730 PetscCall(PetscObjectGetClassId(obj, &id)); 731 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetSpatialDimension((PetscFE)obj, dim)); 732 else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetSpatialDimension((PetscFV)obj, dim)); 733 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0); 734 } 735 } 736 PetscFunctionReturn(PETSC_SUCCESS); 737 } 738 739 /*@ 740 PetscDSGetCoordinateDimension - Returns the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded 741 742 Not collective 743 744 Input Parameter: 745 . prob - The `PetscDS` object 746 747 Output Parameter: 748 . dimEmbed - The coordinate dimension 749 750 Level: beginner 751 752 .seealso: `PetscDS`, `PetscDSSetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 753 @*/ 754 PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed) 755 { 756 PetscFunctionBegin; 757 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 758 PetscValidIntPointer(dimEmbed, 2); 759 PetscCheck(prob->dimEmbed >= 0, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS"); 760 *dimEmbed = prob->dimEmbed; 761 PetscFunctionReturn(PETSC_SUCCESS); 762 } 763 764 /*@ 765 PetscDSSetCoordinateDimension - Set the coordinate dimension of the `PetscDS`, meaning the dimension of the space into which the discretiaztions are embedded 766 767 Logically collective on prob 768 769 Input Parameters: 770 + prob - The `PetscDS` object 771 - dimEmbed - The coordinate dimension 772 773 Level: beginner 774 775 .seealso: `PetscDS`, `PetscDSGetCoordinateDimension()`, `PetscDSGetSpatialDimension()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 776 @*/ 777 PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed) 778 { 779 PetscFunctionBegin; 780 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 781 PetscCheck(dimEmbed >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %" PetscInt_FMT, dimEmbed); 782 prob->dimEmbed = dimEmbed; 783 PetscFunctionReturn(PETSC_SUCCESS); 784 } 785 786 /*@ 787 PetscDSGetForceQuad - Returns the flag to force matching quadratures among the field discretizations 788 789 Not collective 790 791 Input Parameter: 792 . prob - The `PetscDS` object 793 794 Output Parameter: 795 . forceQuad - The flag 796 797 Level: intermediate 798 799 .seealso: `PetscDS`, `PetscDSSetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 800 @*/ 801 PetscErrorCode PetscDSGetForceQuad(PetscDS ds, PetscBool *forceQuad) 802 { 803 PetscFunctionBegin; 804 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 805 PetscValidIntPointer(forceQuad, 2); 806 *forceQuad = ds->forceQuad; 807 PetscFunctionReturn(PETSC_SUCCESS); 808 } 809 810 /*@ 811 PetscDSSetForceQuad - Set the flag to force matching quadratures among the field discretizations 812 813 Logically collective on ds 814 815 Input Parameters: 816 + ds - The `PetscDS` object 817 - forceQuad - The flag 818 819 Level: intermediate 820 821 .seealso: `PetscDS`, `PetscDSGetForceQuad()`, `PetscDSGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 822 @*/ 823 PetscErrorCode PetscDSSetForceQuad(PetscDS ds, PetscBool forceQuad) 824 { 825 PetscFunctionBegin; 826 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 827 ds->forceQuad = forceQuad; 828 PetscFunctionReturn(PETSC_SUCCESS); 829 } 830 831 /*@ 832 PetscDSIsCohesive - Returns the flag indicating that this `PetscDS` is for a cohesive cell 833 834 Not collective 835 836 Input Parameter: 837 . ds - The `PetscDS` object 838 839 Output Parameter: 840 . isCohesive - The flag 841 842 Level: developer 843 844 .seealso: `PetscDS`, `PetscDSGetNumCohesive()`, `PetscDSGetCohesive()`, `PetscDSSetCohesive()`, `PetscDSCreate()` 845 @*/ 846 PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive) 847 { 848 PetscFunctionBegin; 849 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 850 PetscValidBoolPointer(isCohesive, 2); 851 *isCohesive = ds->isCohesive; 852 PetscFunctionReturn(PETSC_SUCCESS); 853 } 854 855 /*@ 856 PetscDSGetNumCohesive - Returns the numer of cohesive fields, meaning those defined on the interior of a cohesive cell 857 858 Not collective 859 860 Input Parameter: 861 . ds - The `PetscDS` object 862 863 Output Parameter: 864 . numCohesive - The number of cohesive fields 865 866 Level: developer 867 868 .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSCreate()` 869 @*/ 870 PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive) 871 { 872 PetscInt f; 873 874 PetscFunctionBegin; 875 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 876 PetscValidIntPointer(numCohesive, 2); 877 *numCohesive = 0; 878 for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0; 879 PetscFunctionReturn(PETSC_SUCCESS); 880 } 881 882 /*@ 883 PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell 884 885 Not collective 886 887 Input Parameters: 888 + ds - The `PetscDS` object 889 - f - The field index 890 891 Output Parameter: 892 . isCohesive - The flag 893 894 Level: developer 895 896 .seealso: `PetscDS`, `PetscDSSetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()` 897 @*/ 898 PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive) 899 { 900 PetscFunctionBegin; 901 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 902 PetscValidBoolPointer(isCohesive, 3); 903 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 904 *isCohesive = ds->cohesive[f]; 905 PetscFunctionReturn(PETSC_SUCCESS); 906 } 907 908 /*@ 909 PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell 910 911 Not collective 912 913 Input Parameters: 914 + ds - The `PetscDS` object 915 . f - The field index 916 - isCohesive - The flag for a cohesive field 917 918 Level: developer 919 920 .seealso: `PetscDS`, `PetscDSGetCohesive()`, `PetscDSIsCohesive()`, `PetscDSCreate()` 921 @*/ 922 PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive) 923 { 924 PetscInt i; 925 926 PetscFunctionBegin; 927 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 928 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 929 ds->cohesive[f] = isCohesive; 930 ds->isCohesive = PETSC_FALSE; 931 for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE; 932 PetscFunctionReturn(PETSC_SUCCESS); 933 } 934 935 /*@ 936 PetscDSGetTotalDimension - Returns the total size of the approximation space for this system 937 938 Not collective 939 940 Input Parameter: 941 . prob - The `PetscDS` object 942 943 Output Parameter: 944 . dim - The total problem dimension 945 946 Level: beginner 947 948 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 949 @*/ 950 PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim) 951 { 952 PetscFunctionBegin; 953 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 954 PetscCall(PetscDSSetUp(prob)); 955 PetscValidIntPointer(dim, 2); 956 *dim = prob->totDim; 957 PetscFunctionReturn(PETSC_SUCCESS); 958 } 959 960 /*@ 961 PetscDSGetTotalComponents - Returns the total number of components in this system 962 963 Not collective 964 965 Input Parameter: 966 . prob - The `PetscDS` object 967 968 Output Parameter: 969 . dim - The total number of components 970 971 Level: beginner 972 973 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 974 @*/ 975 PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 979 PetscCall(PetscDSSetUp(prob)); 980 PetscValidIntPointer(Nc, 2); 981 *Nc = prob->totComp; 982 PetscFunctionReturn(PETSC_SUCCESS); 983 } 984 985 /*@ 986 PetscDSGetDiscretization - Returns the discretization object for the given field 987 988 Not collective 989 990 Input Parameters: 991 + prob - The `PetscDS` object 992 - f - The field number 993 994 Output Parameter: 995 . disc - The discretization object 996 997 Level: beginner 998 999 .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1000 @*/ 1001 PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc) 1002 { 1003 PetscFunctionBeginHot; 1004 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1005 PetscValidPointer(disc, 3); 1006 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 1007 *disc = prob->disc[f]; 1008 PetscFunctionReturn(PETSC_SUCCESS); 1009 } 1010 1011 /*@ 1012 PetscDSSetDiscretization - Sets the discretization object for the given field 1013 1014 Not collective 1015 1016 Input Parameters: 1017 + prob - The `PetscDS` object 1018 . f - The field number 1019 - disc - The discretization object 1020 1021 Level: beginner 1022 1023 .seealso: `PetscDS`, `PetscFE`, `PetscFV`, `PetscDSGetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1024 @*/ 1025 PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc) 1026 { 1027 PetscFunctionBegin; 1028 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1029 if (disc) PetscValidPointer(disc, 3); 1030 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1031 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 1032 PetscCall(PetscObjectDereference(prob->disc[f])); 1033 prob->disc[f] = disc; 1034 PetscCall(PetscObjectReference(disc)); 1035 if (disc) { 1036 PetscClassId id; 1037 1038 PetscCall(PetscObjectGetClassId(disc, &id)); 1039 if (id == PETSCFE_CLASSID) { 1040 PetscCall(PetscDSSetImplicit(prob, f, PETSC_TRUE)); 1041 } else if (id == PETSCFV_CLASSID) { 1042 PetscCall(PetscDSSetImplicit(prob, f, PETSC_FALSE)); 1043 } 1044 PetscCall(PetscDSSetJetDegree(prob, f, 1)); 1045 } 1046 PetscFunctionReturn(PETSC_SUCCESS); 1047 } 1048 1049 /*@ 1050 PetscDSGetWeakForm - Returns the weak form object 1051 1052 Not collective 1053 1054 Input Parameter: 1055 . ds - The `PetscDS` object 1056 1057 Output Parameter: 1058 . wf - The weak form object 1059 1060 Level: beginner 1061 1062 .seealso: `PetscWeakForm`, `PetscDSSetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1063 @*/ 1064 PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf) 1065 { 1066 PetscFunctionBegin; 1067 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1068 PetscValidPointer(wf, 2); 1069 *wf = ds->wf; 1070 PetscFunctionReturn(PETSC_SUCCESS); 1071 } 1072 1073 /*@ 1074 PetscDSSetWeakForm - Sets the weak form object 1075 1076 Not collective 1077 1078 Input Parameters: 1079 + ds - The `PetscDS` object 1080 - wf - The weak form object 1081 1082 Level: beginner 1083 1084 .seealso: `PetscWeakForm`, `PetscDSGetWeakForm()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1085 @*/ 1086 PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf) 1087 { 1088 PetscFunctionBegin; 1089 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1090 PetscValidHeaderSpecific(wf, PETSCWEAKFORM_CLASSID, 2); 1091 PetscCall(PetscObjectDereference((PetscObject)ds->wf)); 1092 ds->wf = wf; 1093 PetscCall(PetscObjectReference((PetscObject)wf)); 1094 PetscCall(PetscWeakFormSetNumFields(wf, ds->Nf)); 1095 PetscFunctionReturn(PETSC_SUCCESS); 1096 } 1097 1098 /*@ 1099 PetscDSAddDiscretization - Adds a discretization object 1100 1101 Not collective 1102 1103 Input Parameters: 1104 + prob - The `PetscDS` object 1105 - disc - The boundary discretization object 1106 1107 Level: beginner 1108 1109 .seealso: `PetscWeakForm`, `PetscDSGetDiscretization()`, `PetscDSSetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1110 @*/ 1111 PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc) 1112 { 1113 PetscFunctionBegin; 1114 PetscCall(PetscDSSetDiscretization(prob, prob->Nf, disc)); 1115 PetscFunctionReturn(PETSC_SUCCESS); 1116 } 1117 1118 /*@ 1119 PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the `PetscDS` 1120 1121 Not collective 1122 1123 Input Parameter: 1124 . prob - The `PetscDS` object 1125 1126 Output Parameter: 1127 . q - The quadrature object 1128 1129 Level: intermediate 1130 1131 .seealso: `PetscDS`, `PetscQuadrature`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1132 @*/ 1133 PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q) 1134 { 1135 PetscObject obj; 1136 PetscClassId id; 1137 1138 PetscFunctionBegin; 1139 *q = NULL; 1140 if (!prob->Nf) PetscFunctionReturn(PETSC_SUCCESS); 1141 PetscCall(PetscDSGetDiscretization(prob, 0, &obj)); 1142 PetscCall(PetscObjectGetClassId(obj, &id)); 1143 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetQuadrature((PetscFE)obj, q)); 1144 else if (id == PETSCFV_CLASSID) PetscCall(PetscFVGetQuadrature((PetscFV)obj, q)); 1145 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0); 1146 PetscFunctionReturn(PETSC_SUCCESS); 1147 } 1148 1149 /*@ 1150 PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for `TSIMEX` 1151 1152 Not collective 1153 1154 Input Parameters: 1155 + prob - The `PetscDS` object 1156 - f - The field number 1157 1158 Output Parameter: 1159 . implicit - The flag indicating what kind of solve to use for this field 1160 1161 Level: developer 1162 1163 .seealso: `TSIMEX`, `PetscDS`, `PetscDSSetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1164 @*/ 1165 PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit) 1166 { 1167 PetscFunctionBegin; 1168 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1169 PetscValidBoolPointer(implicit, 3); 1170 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 1171 *implicit = prob->implicit[f]; 1172 PetscFunctionReturn(PETSC_SUCCESS); 1173 } 1174 1175 /*@ 1176 PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for `TSIMEX` 1177 1178 Not collective 1179 1180 Input Parameters: 1181 + prob - The `PetscDS` object 1182 . f - The field number 1183 - implicit - The flag indicating what kind of solve to use for this field 1184 1185 Level: developer 1186 1187 .seealso: `TSIMEX`, `PetscDSGetImplicit()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1188 @*/ 1189 PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit) 1190 { 1191 PetscFunctionBegin; 1192 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1193 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 1194 prob->implicit[f] = implicit; 1195 PetscFunctionReturn(PETSC_SUCCESS); 1196 } 1197 1198 /*@ 1199 PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate. 1200 1201 Not collective 1202 1203 Input Parameters: 1204 + ds - The `PetscDS` object 1205 - f - The field number 1206 1207 Output Parameter: 1208 . k - The highest derivative we need to tabulate 1209 1210 Level: developer 1211 1212 .seealso: `PetscDS`, `PetscDSSetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1213 @*/ 1214 PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k) 1215 { 1216 PetscFunctionBegin; 1217 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1218 PetscValidIntPointer(k, 3); 1219 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1220 *k = ds->jetDegree[f]; 1221 PetscFunctionReturn(PETSC_SUCCESS); 1222 } 1223 1224 /*@ 1225 PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate. 1226 1227 Not collective 1228 1229 Input Parameters: 1230 + ds - The `PetscDS` object 1231 . f - The field number 1232 - k - The highest derivative we need to tabulate 1233 1234 Level: developer 1235 1236 .seealso: ``PetscDS`, PetscDSGetJetDegree()`, `PetscDSSetDiscretization()`, `PetscDSAddDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 1237 @*/ 1238 PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k) 1239 { 1240 PetscFunctionBegin; 1241 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1242 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1243 ds->jetDegree[f] = k; 1244 PetscFunctionReturn(PETSC_SUCCESS); 1245 } 1246 1247 PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f, void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 1248 { 1249 PetscPointFunc *tmp; 1250 PetscInt n; 1251 1252 PetscFunctionBegin; 1253 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1254 PetscValidPointer(obj, 3); 1255 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1256 PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp)); 1257 *obj = tmp ? tmp[0] : NULL; 1258 PetscFunctionReturn(PETSC_SUCCESS); 1259 } 1260 1261 PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f, void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 1262 { 1263 PetscFunctionBegin; 1264 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1265 if (obj) PetscValidFunction(obj, 3); 1266 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1267 PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj)); 1268 PetscFunctionReturn(PETSC_SUCCESS); 1269 } 1270 1271 /*@C 1272 PetscDSGetResidual - Get the pointwise residual function for a given test field 1273 1274 Not collective 1275 1276 Input Parameters: 1277 + ds - The `PetscDS` 1278 - f - The test field number 1279 1280 Output Parameters: 1281 + f0 - integrand for the test function term 1282 - f1 - integrand for the test function gradient term 1283 1284 Calling sequence for the callbacks f0 and f1: 1285 .vb 1286 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1287 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1288 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1289 PetscReal t, const PetscReal x[], PetscScalar f0[]) 1290 .ve 1291 + dim - the spatial dimension 1292 . Nf - the number of fields 1293 . uOff - the offset into u[] and u_t[] for each field 1294 . uOff_x - the offset into u_x[] for each field 1295 . u - each field evaluated at the current point 1296 . u_t - the time derivative of each field evaluated at the current point 1297 . u_x - the gradient of each field evaluated at the current point 1298 . aOff - the offset into a[] and a_t[] for each auxiliary field 1299 . aOff_x - the offset into a_x[] for each auxiliary field 1300 . a - each auxiliary field evaluated at the current point 1301 . a_t - the time derivative of each auxiliary field evaluated at the current point 1302 . a_x - the gradient of auxiliary each field evaluated at the current point 1303 . t - current time 1304 . x - coordinates of the current point 1305 . numConstants - number of constant parameters 1306 . constants - constant parameters 1307 - f0 - output values at the current point 1308 1309 Level: intermediate 1310 1311 Note: 1312 We are using a first order FEM model for the weak form: \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t) 1313 1314 .seealso: `PetscDS`, `PetscDSSetResidual()` 1315 @*/ 1316 PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1317 { 1318 PetscPointFunc *tmp0, *tmp1; 1319 PetscInt n0, n1; 1320 1321 PetscFunctionBegin; 1322 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1323 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1324 PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1)); 1325 *f0 = tmp0 ? tmp0[0] : NULL; 1326 *f1 = tmp1 ? tmp1[0] : NULL; 1327 PetscFunctionReturn(PETSC_SUCCESS); 1328 } 1329 1330 /*@C 1331 PetscDSSetResidual - Set the pointwise residual function for a given test field 1332 1333 Not collective 1334 1335 Input Parameters: 1336 + ds - The `PetscDS` 1337 . f - The test field number 1338 . f0 - integrand for the test function term 1339 - f1 - integrand for the test function gradient term 1340 1341 Calling sequence for the callbacks f0 and f1: 1342 .vb 1343 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1344 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1345 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1346 PetscReal t, const PetscReal x[], PetscScalar f0[]) 1347 .ve 1348 + dim - the spatial dimension 1349 . Nf - the number of fields 1350 . uOff - the offset into u[] and u_t[] for each field 1351 . uOff_x - the offset into u_x[] for each field 1352 . u - each field evaluated at the current point 1353 . u_t - the time derivative of each field evaluated at the current point 1354 . u_x - the gradient of each field evaluated at the current point 1355 . aOff - the offset into a[] and a_t[] for each auxiliary field 1356 . aOff_x - the offset into a_x[] for each auxiliary field 1357 . a - each auxiliary field evaluated at the current point 1358 . a_t - the time derivative of each auxiliary field evaluated at the current point 1359 . a_x - the gradient of auxiliary each field evaluated at the current point 1360 . t - current time 1361 . x - coordinates of the current point 1362 . numConstants - number of constant parameters 1363 . constants - constant parameters 1364 - f0 - output values at the current point 1365 1366 Level: intermediate 1367 1368 Note: 1369 We are using a first order FEM model for the weak form: \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t) 1370 1371 .seealso: `PetscDS`, `PetscDSGetResidual()` 1372 @*/ 1373 PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1374 { 1375 PetscFunctionBegin; 1376 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1377 if (f0) PetscValidFunction(f0, 3); 1378 if (f1) PetscValidFunction(f1, 4); 1379 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1380 PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1)); 1381 PetscFunctionReturn(PETSC_SUCCESS); 1382 } 1383 1384 /*@C 1385 PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field 1386 1387 Not collective 1388 1389 Input Parameters: 1390 + ds - The `PetscDS` 1391 - f - The test field number 1392 1393 Output Parameters: 1394 + f0 - integrand for the test function term 1395 - f1 - integrand for the test function gradient term 1396 1397 Calling sequence for the callbacks f0 and f1: 1398 .vb 1399 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1400 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1401 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1402 PetscReal t, const PetscReal x[], PetscScalar f0[]) 1403 .ve 1404 + dim - the spatial dimension 1405 . Nf - the number of fields 1406 . uOff - the offset into u[] and u_t[] for each field 1407 . uOff_x - the offset into u_x[] for each field 1408 . u - each field evaluated at the current point 1409 . u_t - the time derivative of each field evaluated at the current point 1410 . u_x - the gradient of each field evaluated at the current point 1411 . aOff - the offset into a[] and a_t[] for each auxiliary field 1412 . aOff_x - the offset into a_x[] for each auxiliary field 1413 . a - each auxiliary field evaluated at the current point 1414 . a_t - the time derivative of each auxiliary field evaluated at the current point 1415 . a_x - the gradient of auxiliary each field evaluated at the current point 1416 . t - current time 1417 . x - coordinates of the current point 1418 . numConstants - number of constant parameters 1419 . constants - constant parameters 1420 - f0 - output values at the current point 1421 1422 Level: intermediate 1423 1424 Note: 1425 We are using a first order FEM model for the weak form: \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t) 1426 1427 .seealso: `PetscDS`, `PetscDSSetRHSResidual()` 1428 @*/ 1429 PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1430 { 1431 PetscPointFunc *tmp0, *tmp1; 1432 PetscInt n0, n1; 1433 1434 PetscFunctionBegin; 1435 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1436 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1437 PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1)); 1438 *f0 = tmp0 ? tmp0[0] : NULL; 1439 *f1 = tmp1 ? tmp1[0] : NULL; 1440 PetscFunctionReturn(PETSC_SUCCESS); 1441 } 1442 1443 /*@C 1444 PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field 1445 1446 Not collective 1447 1448 Input Parameters: 1449 + ds - The `PetscDS` 1450 . f - The test field number 1451 . f0 - integrand for the test function term 1452 - f1 - integrand for the test function gradient term 1453 1454 Clling sequence for the callbacks f0 and f1: 1455 .vb 1456 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1457 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1458 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1459 PetscReal t, const PetscReal x[], PetscScalar f0[]) 1460 .ve 1461 + dim - the spatial dimension 1462 . Nf - the number of fields 1463 . uOff - the offset into u[] and u_t[] for each field 1464 . uOff_x - the offset into u_x[] for each field 1465 . u - each field evaluated at the current point 1466 . u_t - the time derivative of each field evaluated at the current point 1467 . u_x - the gradient of each field evaluated at the current point 1468 . aOff - the offset into a[] and a_t[] for each auxiliary field 1469 . aOff_x - the offset into a_x[] for each auxiliary field 1470 . a - each auxiliary field evaluated at the current point 1471 . a_t - the time derivative of each auxiliary field evaluated at the current point 1472 . a_x - the gradient of auxiliary each field evaluated at the current point 1473 . t - current time 1474 . x - coordinates of the current point 1475 . numConstants - number of constant parameters 1476 . constants - constant parameters 1477 - f0 - output values at the current point 1478 1479 Level: intermediate 1480 1481 Note: 1482 We are using a first order FEM model for the weak form: \int_\Omega \phi f_0(u, u_t, \nabla u, x, t) + \nabla\phi \cdot {\vec f}_1(u, u_t, \nabla u, x, t) 1483 1484 .seealso: `PetscDS`, `PetscDSGetResidual()` 1485 @*/ 1486 PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1487 { 1488 PetscFunctionBegin; 1489 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1490 if (f0) PetscValidFunction(f0, 3); 1491 if (f1) PetscValidFunction(f1, 4); 1492 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1493 PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1)); 1494 PetscFunctionReturn(PETSC_SUCCESS); 1495 } 1496 1497 /*@C 1498 PetscDSHasJacobian - Checks that the Jacobian functions have been set 1499 1500 Not collective 1501 1502 Input Parameter: 1503 . prob - The `PetscDS` 1504 1505 Output Parameter: 1506 . hasJac - flag that pointwise function for the Jacobian has been set 1507 1508 Level: intermediate 1509 1510 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1511 @*/ 1512 PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac) 1513 { 1514 PetscFunctionBegin; 1515 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1516 PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac)); 1517 PetscFunctionReturn(PETSC_SUCCESS); 1518 } 1519 1520 /*@C 1521 PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field 1522 1523 Not collective 1524 1525 Input Parameters: 1526 + ds - The `PetscDS` 1527 . f - The test field number 1528 - g - The field number 1529 1530 Output Parameters: 1531 + g0 - integrand for the test and basis function term 1532 . g1 - integrand for the test function and basis function gradient term 1533 . g2 - integrand for the test function gradient and basis function term 1534 - g3 - integrand for the test function gradient and basis function gradient term 1535 1536 Calling sequence for the callbacks g0, g1, g2 and g3: 1537 .vb 1538 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1539 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1540 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1541 PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1542 .ve 1543 + dim - the spatial dimension 1544 . Nf - the number of fields 1545 . uOff - the offset into u[] and u_t[] for each field 1546 . uOff_x - the offset into u_x[] for each field 1547 . u - each field evaluated at the current point 1548 . u_t - the time derivative of each field evaluated at the current point 1549 . u_x - the gradient of each field evaluated at the current point 1550 . aOff - the offset into a[] and a_t[] for each auxiliary field 1551 . aOff_x - the offset into a_x[] for each auxiliary field 1552 . a - each auxiliary field evaluated at the current point 1553 . a_t - the time derivative of each auxiliary field evaluated at the current point 1554 . a_x - the gradient of auxiliary each field evaluated at the current point 1555 . t - current time 1556 . u_tShift - the multiplier a for dF/dU_t 1557 . x - coordinates of the current point 1558 . numConstants - number of constant parameters 1559 . constants - constant parameters 1560 - g0 - output values at the current point 1561 1562 Level: intermediate 1563 1564 Note: 1565 We are using a first order FEM model for the weak form: 1566 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1567 1568 .seealso: `PetscDS`, `PetscDSSetJacobian()` 1569 @*/ 1570 PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1571 { 1572 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1573 PetscInt n0, n1, n2, n3; 1574 1575 PetscFunctionBegin; 1576 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1577 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1578 PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf); 1579 PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1580 *g0 = tmp0 ? tmp0[0] : NULL; 1581 *g1 = tmp1 ? tmp1[0] : NULL; 1582 *g2 = tmp2 ? tmp2[0] : NULL; 1583 *g3 = tmp3 ? tmp3[0] : NULL; 1584 PetscFunctionReturn(PETSC_SUCCESS); 1585 } 1586 1587 /*@C 1588 PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields 1589 1590 Not collective 1591 1592 Input Parameters: 1593 + ds - The `PetscDS` 1594 . f - The test field number 1595 . g - The field number 1596 . g0 - integrand for the test and basis function term 1597 . g1 - integrand for the test function and basis function gradient term 1598 . g2 - integrand for the test function gradient and basis function term 1599 - g3 - integrand for the test function gradient and basis function gradient term 1600 1601 Calling sequence for the callbacks g0, g1, g2 and g3: 1602 .vb 1603 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1604 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1605 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1606 PetscReal t, const PetscReal x[], PetscScalar g0[]) 1607 .ve 1608 + dim - the spatial dimension 1609 . Nf - the number of fields 1610 . uOff - the offset into u[] and u_t[] for each field 1611 . uOff_x - the offset into u_x[] for each field 1612 . u - each field evaluated at the current point 1613 . u_t - the time derivative of each field evaluated at the current point 1614 . u_x - the gradient of each field evaluated at the current point 1615 . aOff - the offset into a[] and a_t[] for each auxiliary field 1616 . aOff_x - the offset into a_x[] for each auxiliary field 1617 . a - each auxiliary field evaluated at the current point 1618 . a_t - the time derivative of each auxiliary field evaluated at the current point 1619 . a_x - the gradient of auxiliary each field evaluated at the current point 1620 . t - current time 1621 . u_tShift - the multiplier a for dF/dU_t 1622 . x - coordinates of the current point 1623 . numConstants - number of constant parameters 1624 . constants - constant parameters 1625 - g0 - output values at the current point 1626 1627 Level: intermediate 1628 1629 Note: 1630 We are using a first order FEM model for the weak form: 1631 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1632 1633 .seealso: `PetscDS`, `PetscDSGetJacobian()` 1634 @*/ 1635 PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1636 { 1637 PetscFunctionBegin; 1638 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1639 if (g0) PetscValidFunction(g0, 4); 1640 if (g1) PetscValidFunction(g1, 5); 1641 if (g2) PetscValidFunction(g2, 6); 1642 if (g3) PetscValidFunction(g3, 7); 1643 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1644 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1645 PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1646 PetscFunctionReturn(PETSC_SUCCESS); 1647 } 1648 1649 /*@C 1650 PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner 1651 1652 Not collective 1653 1654 Input Parameters: 1655 + prob - The `PetscDS` 1656 - useJacPre - flag that enables construction of a Jacobian preconditioner 1657 1658 Level: intermediate 1659 1660 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1661 @*/ 1662 PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre) 1663 { 1664 PetscFunctionBegin; 1665 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1666 prob->useJacPre = useJacPre; 1667 PetscFunctionReturn(PETSC_SUCCESS); 1668 } 1669 1670 /*@C 1671 PetscDSHasJacobianPreconditioner - Checks if a Jacobian preconditioner matrix has been set 1672 1673 Not collective 1674 1675 Input Parameter: 1676 . prob - The `PetscDS` 1677 1678 Output Parameter: 1679 . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set 1680 1681 Level: intermediate 1682 1683 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1684 @*/ 1685 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre) 1686 { 1687 PetscFunctionBegin; 1688 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1689 *hasJacPre = PETSC_FALSE; 1690 if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS); 1691 PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre)); 1692 PetscFunctionReturn(PETSC_SUCCESS); 1693 } 1694 1695 /*@C 1696 PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian preconditioner function for given test and basis field. If this is missing, 1697 the system matrix is used to build the preconditioner. 1698 1699 Not collective 1700 1701 Input Parameters: 1702 + ds - The `PetscDS` 1703 . f - The test field number 1704 - g - The field number 1705 1706 Output Parameters: 1707 + g0 - integrand for the test and basis function term 1708 . g1 - integrand for the test function and basis function gradient term 1709 . g2 - integrand for the test function gradient and basis function term 1710 - g3 - integrand for the test function gradient and basis function gradient term 1711 1712 Calling sequence for the callbacks g0, g1, g2 and g3: 1713 .vb 1714 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1715 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1716 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1717 PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1718 .ve 1719 + dim - the spatial dimension 1720 . Nf - the number of fields 1721 . uOff - the offset into u[] and u_t[] for each field 1722 . uOff_x - the offset into u_x[] for each field 1723 . u - each field evaluated at the current point 1724 . u_t - the time derivative of each field evaluated at the current point 1725 . u_x - the gradient of each field evaluated at the current point 1726 . aOff - the offset into a[] and a_t[] for each auxiliary field 1727 . aOff_x - the offset into a_x[] for each auxiliary field 1728 . a - each auxiliary field evaluated at the current point 1729 . a_t - the time derivative of each auxiliary field evaluated at the current point 1730 . a_x - the gradient of auxiliary each field evaluated at the current point 1731 . t - current time 1732 . u_tShift - the multiplier a for dF/dU_t 1733 . x - coordinates of the current point 1734 . numConstants - number of constant parameters 1735 . constants - constant parameters 1736 - g0 - output values at the current point 1737 1738 Level: intermediate 1739 1740 Note: 1741 We are using a first order FEM model for the weak form: 1742 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1743 1744 .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1745 @*/ 1746 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1747 { 1748 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1749 PetscInt n0, n1, n2, n3; 1750 1751 PetscFunctionBegin; 1752 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1753 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1754 PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf); 1755 PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1756 *g0 = tmp0 ? tmp0[0] : NULL; 1757 *g1 = tmp1 ? tmp1[0] : NULL; 1758 *g2 = tmp2 ? tmp2[0] : NULL; 1759 *g3 = tmp3 ? tmp3[0] : NULL; 1760 PetscFunctionReturn(PETSC_SUCCESS); 1761 } 1762 1763 /*@C 1764 PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian preconditioner function for given test and basis fields. 1765 If this is missing, the system matrix is used to build the preconditioner. 1766 1767 Not collective 1768 1769 Input Parameters: 1770 + ds - The `PetscDS` 1771 . f - The test field number 1772 . g - The field number 1773 . g0 - integrand for the test and basis function term 1774 . g1 - integrand for the test function and basis function gradient term 1775 . g2 - integrand for the test function gradient and basis function term 1776 - g3 - integrand for the test function gradient and basis function gradient term 1777 1778 Calling sequence for the callbacks g0, g1, g2 and g3: 1779 .vb 1780 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1781 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1782 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1783 PetscReal t, const PetscReal x[], PetscScalar g0[]) 1784 .ve 1785 + dim - the spatial dimension 1786 . Nf - the number of fields 1787 . uOff - the offset into u[] and u_t[] for each field 1788 . uOff_x - the offset into u_x[] for each field 1789 . u - each field evaluated at the current point 1790 . u_t - the time derivative of each field evaluated at the current point 1791 . u_x - the gradient of each field evaluated at the current point 1792 . aOff - the offset into a[] and a_t[] for each auxiliary field 1793 . aOff_x - the offset into a_x[] for each auxiliary field 1794 . a - each auxiliary field evaluated at the current point 1795 . a_t - the time derivative of each auxiliary field evaluated at the current point 1796 . a_x - the gradient of auxiliary each field evaluated at the current point 1797 . t - current time 1798 . u_tShift - the multiplier a for dF/dU_t 1799 . x - coordinates of the current point 1800 . numConstants - number of constant parameters 1801 . constants - constant parameters 1802 - g0 - output values at the current point 1803 1804 Level: intermediate 1805 1806 Note: 1807 We are using a first order FEM model for the weak form: 1808 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1809 1810 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()` 1811 @*/ 1812 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1813 { 1814 PetscFunctionBegin; 1815 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1816 if (g0) PetscValidFunction(g0, 4); 1817 if (g1) PetscValidFunction(g1, 5); 1818 if (g2) PetscValidFunction(g2, 6); 1819 if (g3) PetscValidFunction(g3, 7); 1820 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1821 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1822 PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1823 PetscFunctionReturn(PETSC_SUCCESS); 1824 } 1825 1826 /*@C 1827 PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set 1828 1829 Not collective 1830 1831 Input Parameter: 1832 . ds - The `PetscDS` 1833 1834 Output Parameter: 1835 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set 1836 1837 Level: intermediate 1838 1839 .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()` 1840 @*/ 1841 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac) 1842 { 1843 PetscFunctionBegin; 1844 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1845 PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac)); 1846 PetscFunctionReturn(PETSC_SUCCESS); 1847 } 1848 1849 /*@C 1850 PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field 1851 1852 Not collective 1853 1854 Input Parameters: 1855 + ds - The `PetscDS` 1856 . f - The test field number 1857 - g - The field number 1858 1859 Output Parameters: 1860 + g0 - integrand for the test and basis function term 1861 . g1 - integrand for the test function and basis function gradient term 1862 . g2 - integrand for the test function gradient and basis function term 1863 - g3 - integrand for the test function gradient and basis function gradient term 1864 1865 Calling sequence for the callbacks g0, g1, g2 and g3: 1866 .vb 1867 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1868 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1869 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1870 PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1871 .ve 1872 + dim - the spatial dimension 1873 . Nf - the number of fields 1874 . uOff - the offset into u[] and u_t[] for each field 1875 . uOff_x - the offset into u_x[] for each field 1876 . u - each field evaluated at the current point 1877 . u_t - the time derivative of each field evaluated at the current point 1878 . u_x - the gradient of each field evaluated at the current point 1879 . aOff - the offset into a[] and a_t[] for each auxiliary field 1880 . aOff_x - the offset into a_x[] for each auxiliary field 1881 . a - each auxiliary field evaluated at the current point 1882 . a_t - the time derivative of each auxiliary field evaluated at the current point 1883 . a_x - the gradient of auxiliary each field evaluated at the current point 1884 . t - current time 1885 . u_tShift - the multiplier a for dF/dU_t 1886 . x - coordinates of the current point 1887 . numConstants - number of constant parameters 1888 . constants - constant parameters 1889 - g0 - output values at the current point 1890 1891 Level: intermediate 1892 1893 Note: 1894 We are using a first order FEM model for the weak form: 1895 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1896 1897 .seealso: `PetscDS`, `PetscDSSetJacobian()` 1898 @*/ 1899 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1900 { 1901 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1902 PetscInt n0, n1, n2, n3; 1903 1904 PetscFunctionBegin; 1905 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1906 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 1907 PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf); 1908 PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1909 *g0 = tmp0 ? tmp0[0] : NULL; 1910 *g1 = tmp1 ? tmp1[0] : NULL; 1911 *g2 = tmp2 ? tmp2[0] : NULL; 1912 *g3 = tmp3 ? tmp3[0] : NULL; 1913 PetscFunctionReturn(PETSC_SUCCESS); 1914 } 1915 1916 /*@C 1917 PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields 1918 1919 Not collective 1920 1921 Input Parameters: 1922 + ds - The `PetscDS` 1923 . f - The test field number 1924 . g - The field number 1925 . g0 - integrand for the test and basis function term 1926 . g1 - integrand for the test function and basis function gradient term 1927 . g2 - integrand for the test function gradient and basis function term 1928 - g3 - integrand for the test function gradient and basis function gradient term 1929 1930 Calling sequence for the callbacks g0, g1, g2 and g3: 1931 .vb 1932 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1933 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1934 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1935 PetscReal t, const PetscReal x[], PetscScalar g0[]) 1936 .ve 1937 + dim - the spatial dimension 1938 . Nf - the number of fields 1939 . uOff - the offset into u[] and u_t[] for each field 1940 . uOff_x - the offset into u_x[] for each field 1941 . u - each field evaluated at the current point 1942 . u_t - the time derivative of each field evaluated at the current point 1943 . u_x - the gradient of each field evaluated at the current point 1944 . aOff - the offset into a[] and a_t[] for each auxiliary field 1945 . aOff_x - the offset into a_x[] for each auxiliary field 1946 . a - each auxiliary field evaluated at the current point 1947 . a_t - the time derivative of each auxiliary field evaluated at the current point 1948 . a_x - the gradient of auxiliary each field evaluated at the current point 1949 . t - current time 1950 . u_tShift - the multiplier a for dF/dU_t 1951 . x - coordinates of the current point 1952 . numConstants - number of constant parameters 1953 . constants - constant parameters 1954 - g0 - output values at the current point 1955 1956 Level: intermediate 1957 1958 Note: 1959 We are using a first order FEM model for the weak form: 1960 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1961 1962 .seealso: `PetscDS`, `PetscDSGetJacobian()` 1963 @*/ 1964 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1965 { 1966 PetscFunctionBegin; 1967 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1968 if (g0) PetscValidFunction(g0, 4); 1969 if (g1) PetscValidFunction(g1, 5); 1970 if (g2) PetscValidFunction(g2, 6); 1971 if (g3) PetscValidFunction(g3, 7); 1972 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1973 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1974 PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1975 PetscFunctionReturn(PETSC_SUCCESS); 1976 } 1977 1978 /*@C 1979 PetscDSGetRiemannSolver - Returns the Riemann solver for the given field 1980 1981 Not collective 1982 1983 Input Parameters: 1984 + ds - The `PetscDS` object 1985 - f - The field number 1986 1987 Output Parameter: 1988 . r - Riemann solver 1989 1990 Calling sequence for r: 1991 .vb 1992 r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 1993 .ve 1994 + dim - The spatial dimension 1995 . Nf - The number of fields 1996 . x - The coordinates at a point on the interface 1997 . n - The normal vector to the interface 1998 . uL - The state vector to the left of the interface 1999 . uR - The state vector to the right of the interface 2000 . flux - output array of flux through the interface 2001 . numConstants - number of constant parameters 2002 . constants - constant parameters 2003 - ctx - optional user context 2004 2005 Level: intermediate 2006 2007 .seealso: `PetscDS`, `PetscDSSetRiemannSolver()` 2008 @*/ 2009 PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, void (**r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx)) 2010 { 2011 PetscRiemannFunc *tmp; 2012 PetscInt n; 2013 2014 PetscFunctionBegin; 2015 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2016 PetscValidPointer(r, 3); 2017 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2018 PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp)); 2019 *r = tmp ? tmp[0] : NULL; 2020 PetscFunctionReturn(PETSC_SUCCESS); 2021 } 2022 2023 /*@C 2024 PetscDSSetRiemannSolver - Sets the Riemann solver for the given field 2025 2026 Not collective 2027 2028 Input Parameters: 2029 + ds - The `PetscDS` object 2030 . f - The field number 2031 - r - Riemann solver 2032 2033 Calling sequence for r: 2034 .vb 2035 r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 2036 .ve 2037 + dim - The spatial dimension 2038 . Nf - The number of fields 2039 . x - The coordinates at a point on the interface 2040 . n - The normal vector to the interface 2041 . uL - The state vector to the left of the interface 2042 . uR - The state vector to the right of the interface 2043 . flux - output array of flux through the interface 2044 . numConstants - number of constant parameters 2045 . constants - constant parameters 2046 - ctx - optional user context 2047 2048 Level: intermediate 2049 2050 .seealso: `PetscDS`, `PetscDSGetRiemannSolver()` 2051 @*/ 2052 PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, void (*r)(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscInt numConstants, const PetscScalar constants[], PetscScalar flux[], void *ctx)) 2053 { 2054 PetscFunctionBegin; 2055 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2056 if (r) PetscValidFunction(r, 3); 2057 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2058 PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r)); 2059 PetscFunctionReturn(PETSC_SUCCESS); 2060 } 2061 2062 /*@C 2063 PetscDSGetUpdate - Get the pointwise update function for a given field 2064 2065 Not collective 2066 2067 Input Parameters: 2068 + ds - The `PetscDS` 2069 - f - The field number 2070 2071 Output Parameter: 2072 . update - update function 2073 2074 Calling sequence for the callback update: 2075 .vb 2076 update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2077 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2078 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2079 PetscReal t, const PetscReal x[], PetscScalar uNew[]) 2080 .ve 2081 + dim - the spatial dimension 2082 . Nf - the number of fields 2083 . uOff - the offset into u[] and u_t[] for each field 2084 . uOff_x - the offset into u_x[] for each field 2085 . u - each field evaluated at the current point 2086 . u_t - the time derivative of each field evaluated at the current point 2087 . u_x - the gradient of each field evaluated at the current point 2088 . aOff - the offset into a[] and a_t[] for each auxiliary field 2089 . aOff_x - the offset into a_x[] for each auxiliary field 2090 . a - each auxiliary field evaluated at the current point 2091 . a_t - the time derivative of each auxiliary field evaluated at the current point 2092 . a_x - the gradient of auxiliary each field evaluated at the current point 2093 . t - current time 2094 . x - coordinates of the current point 2095 - uNew - new value for field at the current point 2096 2097 Level: intermediate 2098 2099 .seealso: `PetscDS`, `PetscDSSetUpdate()`, `PetscDSSetResidual()` 2100 @*/ 2101 PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 2102 { 2103 PetscFunctionBegin; 2104 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2105 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2106 if (update) { 2107 PetscValidPointer(update, 3); 2108 *update = ds->update[f]; 2109 } 2110 PetscFunctionReturn(PETSC_SUCCESS); 2111 } 2112 2113 /*@C 2114 PetscDSSetUpdate - Set the pointwise update function for a given field 2115 2116 Not collective 2117 2118 Input Parameters: 2119 + ds - The `PetscDS` 2120 . f - The field number 2121 - update - update function 2122 2123 Calling sequence for the callback update: 2124 .vb 2125 update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2126 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2127 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2128 PetscReal t, const PetscReal x[], PetscScalar uNew[]) 2129 .ve 2130 + dim - the spatial dimension 2131 . Nf - the number of fields 2132 . uOff - the offset into u[] and u_t[] for each field 2133 . uOff_x - the offset into u_x[] for each field 2134 . u - each field evaluated at the current point 2135 . u_t - the time derivative of each field evaluated at the current point 2136 . u_x - the gradient of each field evaluated at the current point 2137 . aOff - the offset into a[] and a_t[] for each auxiliary field 2138 . aOff_x - the offset into a_x[] for each auxiliary field 2139 . a - each auxiliary field evaluated at the current point 2140 . a_t - the time derivative of each auxiliary field evaluated at the current point 2141 . a_x - the gradient of auxiliary each field evaluated at the current point 2142 . t - current time 2143 . x - coordinates of the current point 2144 - uNew - new field values at the current point 2145 2146 Level: intermediate 2147 2148 .seealso: `PetscDS`, `PetscDSGetResidual()` 2149 @*/ 2150 PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 2151 { 2152 PetscFunctionBegin; 2153 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2154 if (update) PetscValidFunction(update, 3); 2155 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2156 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 2157 ds->update[f] = update; 2158 PetscFunctionReturn(PETSC_SUCCESS); 2159 } 2160 2161 PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx) 2162 { 2163 PetscFunctionBegin; 2164 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2165 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2166 PetscValidPointer(ctx, 3); 2167 *(void **)ctx = ds->ctx[f]; 2168 PetscFunctionReturn(PETSC_SUCCESS); 2169 } 2170 2171 PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx) 2172 { 2173 PetscFunctionBegin; 2174 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2175 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2176 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 2177 ds->ctx[f] = ctx; 2178 PetscFunctionReturn(PETSC_SUCCESS); 2179 } 2180 2181 /*@C 2182 PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field 2183 2184 Not collective 2185 2186 Input Parameters: 2187 + ds - The PetscDS 2188 - f - The test field number 2189 2190 Output Parameters: 2191 + f0 - boundary integrand for the test function term 2192 - f1 - boundary integrand for the test function gradient term 2193 2194 Calling sequence for the callbacks f0 and f1: 2195 .vb 2196 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2197 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2198 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2199 PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 2200 .ve 2201 + dim - the spatial dimension 2202 . Nf - the number of fields 2203 . uOff - the offset into u[] and u_t[] for each field 2204 . uOff_x - the offset into u_x[] for each field 2205 . u - each field evaluated at the current point 2206 . u_t - the time derivative of each field evaluated at the current point 2207 . u_x - the gradient of each field evaluated at the current point 2208 . aOff - the offset into a[] and a_t[] for each auxiliary field 2209 . aOff_x - the offset into a_x[] for each auxiliary field 2210 . a - each auxiliary field evaluated at the current point 2211 . a_t - the time derivative of each auxiliary field evaluated at the current point 2212 . a_x - the gradient of auxiliary each field evaluated at the current point 2213 . t - current time 2214 . x - coordinates of the current point 2215 . n - unit normal at the current point 2216 . numConstants - number of constant parameters 2217 . constants - constant parameters 2218 - f0 - output values at the current point 2219 2220 Level: intermediate 2221 2222 Note: 2223 We are using a first order FEM model for the weak form: 2224 \int_\Gamma \phi {\vec f}_0(u, u_t, \nabla u, x, t) \cdot \hat n + \nabla\phi \cdot {\overleftrightarrow f}_1(u, u_t, \nabla u, x, t) \cdot \hat n 2225 2226 .seealso: `PetscDS`, `PetscDSSetBdResidual()` 2227 @*/ 2228 PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 2229 { 2230 PetscBdPointFunc *tmp0, *tmp1; 2231 PetscInt n0, n1; 2232 2233 PetscFunctionBegin; 2234 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2235 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2236 PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1)); 2237 *f0 = tmp0 ? tmp0[0] : NULL; 2238 *f1 = tmp1 ? tmp1[0] : NULL; 2239 PetscFunctionReturn(PETSC_SUCCESS); 2240 } 2241 2242 /*@C 2243 PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field 2244 2245 Not collective 2246 2247 Input Parameters: 2248 + ds - The `PetscDS` 2249 . f - The test field number 2250 . f0 - boundary integrand for the test function term 2251 - f1 - boundary integrand for the test function gradient term 2252 2253 Calling sequence for the callbacks f0 and f1: 2254 .vb 2255 f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2256 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2257 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2258 PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 2259 .ve 2260 + dim - the spatial dimension 2261 . Nf - the number of fields 2262 . uOff - the offset into u[] and u_t[] for each field 2263 . uOff_x - the offset into u_x[] for each field 2264 . u - each field evaluated at the current point 2265 . u_t - the time derivative of each field evaluated at the current point 2266 . u_x - the gradient of each field evaluated at the current point 2267 . aOff - the offset into a[] and a_t[] for each auxiliary field 2268 . aOff_x - the offset into a_x[] for each auxiliary field 2269 . a - each auxiliary field evaluated at the current point 2270 . a_t - the time derivative of each auxiliary field evaluated at the current point 2271 . a_x - the gradient of auxiliary each field evaluated at the current point 2272 . t - current time 2273 . x - coordinates of the current point 2274 . n - unit normal at the current point 2275 . numConstants - number of constant parameters 2276 . constants - constant parameters 2277 - f0 - output values at the current point 2278 2279 Level: intermediate 2280 2281 Note: 2282 We are using a first order FEM model for the weak form: 2283 \int_\Gamma \phi {\vec f}_0(u, u_t, \nabla u, x, t) \cdot \hat n + \nabla\phi \cdot {\overleftrightarrow f}_1(u, u_t, \nabla u, x, t) \cdot \hat n 2284 2285 .seealso: `PetscDS`, `PetscDSGetBdResidual()` 2286 @*/ 2287 PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 2288 { 2289 PetscFunctionBegin; 2290 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2291 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2292 PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1)); 2293 PetscFunctionReturn(PETSC_SUCCESS); 2294 } 2295 2296 /*@ 2297 PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set 2298 2299 Not collective 2300 2301 Input Parameter: 2302 . ds - The `PetscDS` 2303 2304 Output Parameter: 2305 . hasBdJac - flag that pointwise function for the boundary Jacobian has been set 2306 2307 Level: intermediate 2308 2309 .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()` 2310 @*/ 2311 PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac) 2312 { 2313 PetscFunctionBegin; 2314 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2315 PetscValidBoolPointer(hasBdJac, 2); 2316 PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac)); 2317 PetscFunctionReturn(PETSC_SUCCESS); 2318 } 2319 2320 /*@C 2321 PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field 2322 2323 Not collective 2324 2325 Input Parameters: 2326 + ds - The `PetscDS` 2327 . f - The test field number 2328 - g - The field number 2329 2330 Output Parameters: 2331 + g0 - integrand for the test and basis function term 2332 . g1 - integrand for the test function and basis function gradient term 2333 . g2 - integrand for the test function gradient and basis function term 2334 - g3 - integrand for the test function gradient and basis function gradient term 2335 2336 Calling sequence for the callbacks g0, g1, g2 and g3: 2337 .vb 2338 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2339 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2340 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2341 PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2342 .ve 2343 + dim - the spatial dimension 2344 . Nf - the number of fields 2345 . uOff - the offset into u[] and u_t[] for each field 2346 . uOff_x - the offset into u_x[] for each field 2347 . u - each field evaluated at the current point 2348 . u_t - the time derivative of each field evaluated at the current point 2349 . u_x - the gradient of each field evaluated at the current point 2350 . aOff - the offset into a[] and a_t[] for each auxiliary field 2351 . aOff_x - the offset into a_x[] for each auxiliary field 2352 . a - each auxiliary field evaluated at the current point 2353 . a_t - the time derivative of each auxiliary field evaluated at the current point 2354 . a_x - the gradient of auxiliary each field evaluated at the current point 2355 . t - current time 2356 . u_tShift - the multiplier a for dF/dU_t 2357 . x - coordinates of the current point 2358 . n - normal at the current point 2359 . numConstants - number of constant parameters 2360 . constants - constant parameters 2361 - g0 - output values at the current point 2362 2363 Level: intermediate 2364 2365 Note: 2366 We are using a first order FEM model for the weak form: 2367 \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi 2368 2369 .seealso: `PetscDS`, `PetscDSSetBdJacobian()` 2370 @*/ 2371 PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2372 { 2373 PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3; 2374 PetscInt n0, n1, n2, n3; 2375 2376 PetscFunctionBegin; 2377 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2378 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2379 PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf); 2380 PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 2381 *g0 = tmp0 ? tmp0[0] : NULL; 2382 *g1 = tmp1 ? tmp1[0] : NULL; 2383 *g2 = tmp2 ? tmp2[0] : NULL; 2384 *g3 = tmp3 ? tmp3[0] : NULL; 2385 PetscFunctionReturn(PETSC_SUCCESS); 2386 } 2387 2388 /*@C 2389 PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field 2390 2391 Not collective 2392 2393 Input Parameters: 2394 + ds - The PetscDS 2395 . f - The test field number 2396 . g - The field number 2397 . g0 - integrand for the test and basis function term 2398 . g1 - integrand for the test function and basis function gradient term 2399 . g2 - integrand for the test function gradient and basis function term 2400 - g3 - integrand for the test function gradient and basis function gradient term 2401 2402 Calling sequence for the callbacks g0, g1, g2 and g3: 2403 .vb 2404 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2405 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2406 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2407 PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2408 .ve 2409 + dim - the spatial dimension 2410 . Nf - the number of fields 2411 . uOff - the offset into u[] and u_t[] for each field 2412 . uOff_x - the offset into u_x[] for each field 2413 . u - each field evaluated at the current point 2414 . u_t - the time derivative of each field evaluated at the current point 2415 . u_x - the gradient of each field evaluated at the current point 2416 . aOff - the offset into a[] and a_t[] for each auxiliary field 2417 . aOff_x - the offset into a_x[] for each auxiliary field 2418 . a - each auxiliary field evaluated at the current point 2419 . a_t - the time derivative of each auxiliary field evaluated at the current point 2420 . a_x - the gradient of auxiliary each field evaluated at the current point 2421 . t - current time 2422 . u_tShift - the multiplier a for dF/dU_t 2423 . x - coordinates of the current point 2424 . n - normal at the current point 2425 . numConstants - number of constant parameters 2426 . constants - constant parameters 2427 - g0 - output values at the current point 2428 2429 Level: intermediate 2430 2431 Note: 2432 We are using a first order FEM model for the weak form: 2433 \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi 2434 2435 .seealso: `PetscDS`, `PetscDSGetBdJacobian()` 2436 @*/ 2437 PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2438 { 2439 PetscFunctionBegin; 2440 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2441 if (g0) PetscValidFunction(g0, 4); 2442 if (g1) PetscValidFunction(g1, 5); 2443 if (g2) PetscValidFunction(g2, 6); 2444 if (g3) PetscValidFunction(g3, 7); 2445 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2446 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 2447 PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 2448 PetscFunctionReturn(PETSC_SUCCESS); 2449 } 2450 2451 /*@ 2452 PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set 2453 2454 Not collective 2455 2456 Input Parameter: 2457 . ds - The `PetscDS` 2458 2459 Output Parameter: 2460 . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set 2461 2462 Level: intermediate 2463 2464 .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()` 2465 @*/ 2466 PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre) 2467 { 2468 PetscFunctionBegin; 2469 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2470 PetscValidBoolPointer(hasBdJacPre, 2); 2471 PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre)); 2472 PetscFunctionReturn(PETSC_SUCCESS); 2473 } 2474 2475 /*@C 2476 PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field 2477 2478 Not collective 2479 2480 Input Parameters: 2481 + ds - The `PetscDS` 2482 . f - The test field number 2483 - g - The field number 2484 2485 Output Parameters: 2486 + g0 - integrand for the test and basis function term 2487 . g1 - integrand for the test function and basis function gradient term 2488 . g2 - integrand for the test function gradient and basis function term 2489 - g3 - integrand for the test function gradient and basis function gradient term 2490 2491 Calling sequence for the callbacks g0, g1, g2 and g3: 2492 .vb 2493 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2494 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2495 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2496 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 2497 .ve 2498 + dim - the spatial dimension 2499 . Nf - the number of fields 2500 . NfAux - the number of auxiliary fields 2501 . uOff - the offset into u[] and u_t[] for each field 2502 . uOff_x - the offset into u_x[] for each field 2503 . u - each field evaluated at the current point 2504 . u_t - the time derivative of each field evaluated at the current point 2505 . u_x - the gradient of each field evaluated at the current point 2506 . aOff - the offset into a[] and a_t[] for each auxiliary field 2507 . aOff_x - the offset into a_x[] for each auxiliary field 2508 . a - each auxiliary field evaluated at the current point 2509 . a_t - the time derivative of each auxiliary field evaluated at the current point 2510 . a_x - the gradient of auxiliary each field evaluated at the current point 2511 . t - current time 2512 . u_tShift - the multiplier a for dF/dU_t 2513 . x - coordinates of the current point 2514 . n - normal at the current point 2515 . numConstants - number of constant parameters 2516 . constants - constant parameters 2517 - g0 - output values at the current point 2518 2519 Level: intermediate 2520 2521 Note: 2522 We are using a first order FEM model for the weak form: 2523 \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi 2524 2525 Fortran Note: 2526 This is not yet available in Fortran. 2527 2528 .seealso: `PetscDS`, `PetscDSSetBdJacobianPreconditioner()` 2529 @*/ 2530 PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2531 { 2532 PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3; 2533 PetscInt n0, n1, n2, n3; 2534 2535 PetscFunctionBegin; 2536 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2537 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2538 PetscCheck(!(g < 0) && !(g >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", g, ds->Nf); 2539 PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 2540 *g0 = tmp0 ? tmp0[0] : NULL; 2541 *g1 = tmp1 ? tmp1[0] : NULL; 2542 *g2 = tmp2 ? tmp2[0] : NULL; 2543 *g3 = tmp3 ? tmp3[0] : NULL; 2544 PetscFunctionReturn(PETSC_SUCCESS); 2545 } 2546 2547 /*@C 2548 PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field 2549 2550 Not collective 2551 2552 Input Parameters: 2553 + ds - The `PetscDS` 2554 . f - The test field number 2555 . g - The field number 2556 . g0 - integrand for the test and basis function term 2557 . g1 - integrand for the test function and basis function gradient term 2558 . g2 - integrand for the test function gradient and basis function term 2559 - g3 - integrand for the test function gradient and basis function gradient term 2560 2561 Calling sequence for the callbacks g0, g1, g2 and g3: 2562 .vb 2563 g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2564 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2565 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2566 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 2567 .ve 2568 + dim - the spatial dimension 2569 . Nf - the number of fields 2570 . NfAux - the number of auxiliary fields 2571 . uOff - the offset into u[] and u_t[] for each field 2572 . uOff_x - the offset into u_x[] for each field 2573 . u - each field evaluated at the current point 2574 . u_t - the time derivative of each field evaluated at the current point 2575 . u_x - the gradient of each field evaluated at the current point 2576 . aOff - the offset into a[] and a_t[] for each auxiliary field 2577 . aOff_x - the offset into a_x[] for each auxiliary field 2578 . a - each auxiliary field evaluated at the current point 2579 . a_t - the time derivative of each auxiliary field evaluated at the current point 2580 . a_x - the gradient of auxiliary each field evaluated at the current point 2581 . t - current time 2582 . u_tShift - the multiplier a for dF/dU_t 2583 . x - coordinates of the current point 2584 . n - normal at the current point 2585 . numConstants - number of constant parameters 2586 . constants - constant parameters 2587 - g0 - output values at the current point 2588 2589 Level: intermediate 2590 2591 Note: 2592 We are using a first order FEM model for the weak form: 2593 \int_\Gamma \phi {\vec g}_0(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \cdot \hat n \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \cdot \hat n \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \hat n \cdot \nabla \psi 2594 2595 Fortran Note: 2596 This is not yet available in Fortran. 2597 2598 .seealso: `PetscDS`, `PetscDSGetBdJacobianPreconditioner()` 2599 @*/ 2600 PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2601 { 2602 PetscFunctionBegin; 2603 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2604 if (g0) PetscValidFunction(g0, 4); 2605 if (g1) PetscValidFunction(g1, 5); 2606 if (g2) PetscValidFunction(g2, 6); 2607 if (g3) PetscValidFunction(g3, 7); 2608 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2609 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 2610 PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 2611 PetscFunctionReturn(PETSC_SUCCESS); 2612 } 2613 2614 /*@C 2615 PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field 2616 2617 Not collective 2618 2619 Input Parameters: 2620 + prob - The PetscDS 2621 - f - The test field number 2622 2623 Output Parameters: 2624 + exactSol - exact solution for the test field 2625 - exactCtx - exact solution context 2626 2627 Calling sequence for the solution functions: 2628 .vb 2629 sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2630 .ve 2631 + dim - the spatial dimension 2632 . t - current time 2633 . x - coordinates of the current point 2634 . Nc - the number of field components 2635 . u - the solution field evaluated at the current point 2636 - ctx - a user context 2637 2638 Level: intermediate 2639 2640 .seealso: `PetscDS`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()` 2641 @*/ 2642 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2643 { 2644 PetscFunctionBegin; 2645 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2646 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 2647 if (sol) { 2648 PetscValidPointer(sol, 3); 2649 *sol = prob->exactSol[f]; 2650 } 2651 if (ctx) { 2652 PetscValidPointer(ctx, 4); 2653 *ctx = prob->exactCtx[f]; 2654 } 2655 PetscFunctionReturn(PETSC_SUCCESS); 2656 } 2657 2658 /*@C 2659 PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field 2660 2661 Not collective 2662 2663 Input Parameters: 2664 + prob - The `PetscDS` 2665 . f - The test field number 2666 . sol - solution function for the test fields 2667 - ctx - solution context or NULL 2668 2669 Calling sequence for solution functions: 2670 .vb 2671 sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2672 .ve 2673 + dim - the spatial dimension 2674 . t - current time 2675 . x - coordinates of the current point 2676 . Nc - the number of field components 2677 . u - the solution field evaluated at the current point 2678 - ctx - a user context 2679 2680 Level: intermediate 2681 2682 .seealso: `PetscDS`, `PetscDSGetExactSolution()` 2683 @*/ 2684 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2685 { 2686 PetscFunctionBegin; 2687 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2688 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2689 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2690 if (sol) { 2691 PetscValidFunction(sol, 3); 2692 prob->exactSol[f] = sol; 2693 } 2694 if (ctx) { 2695 PetscValidFunction(ctx, 4); 2696 prob->exactCtx[f] = ctx; 2697 } 2698 PetscFunctionReturn(PETSC_SUCCESS); 2699 } 2700 2701 /*@C 2702 PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field 2703 2704 Not collective 2705 2706 Input Parameters: 2707 + prob - The `PetscDS` 2708 - f - The test field number 2709 2710 Output Parameters: 2711 + exactSol - time derivative of the exact solution for the test field 2712 - exactCtx - time derivative of the exact solution context 2713 2714 Calling sequence for the solution functions: 2715 .vb 2716 sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2717 .ve 2718 + dim - the spatial dimension 2719 . t - current time 2720 . x - coordinates of the current point 2721 . Nc - the number of field components 2722 . u - the solution field evaluated at the current point 2723 - ctx - a user context 2724 2725 Level: intermediate 2726 2727 .seealso: `PetscDS`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()` 2728 @*/ 2729 PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2730 { 2731 PetscFunctionBegin; 2732 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2733 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 2734 if (sol) { 2735 PetscValidPointer(sol, 3); 2736 *sol = prob->exactSol_t[f]; 2737 } 2738 if (ctx) { 2739 PetscValidPointer(ctx, 4); 2740 *ctx = prob->exactCtx_t[f]; 2741 } 2742 PetscFunctionReturn(PETSC_SUCCESS); 2743 } 2744 2745 /*@C 2746 PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field 2747 2748 Not collective 2749 2750 Input Parameters: 2751 + prob - The `PetscDS` 2752 . f - The test field number 2753 . sol - time derivative of the solution function for the test fields 2754 - ctx - time derivative of the solution context or NULL 2755 2756 Calling sequence for solution functions: 2757 .vb 2758 sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2759 .ve 2760 + dim - the spatial dimension 2761 . t - current time 2762 . x - coordinates of the current point 2763 . Nc - the number of field components 2764 . u - the solution field evaluated at the current point 2765 - ctx - a user context 2766 2767 Level: intermediate 2768 2769 .seealso: `PetscDS`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()` 2770 @*/ 2771 PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2772 { 2773 PetscFunctionBegin; 2774 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2775 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2776 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2777 if (sol) { 2778 PetscValidFunction(sol, 3); 2779 prob->exactSol_t[f] = sol; 2780 } 2781 if (ctx) { 2782 PetscValidFunction(ctx, 4); 2783 prob->exactCtx_t[f] = ctx; 2784 } 2785 PetscFunctionReturn(PETSC_SUCCESS); 2786 } 2787 2788 /*@C 2789 PetscDSGetConstants - Returns the array of constants passed to point functions 2790 2791 Not collective 2792 2793 Input Parameter: 2794 . prob - The `PetscDS` object 2795 2796 Output Parameters: 2797 + numConstants - The number of constants 2798 - constants - The array of constants, NULL if there are none 2799 2800 Level: intermediate 2801 2802 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()` 2803 @*/ 2804 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[]) 2805 { 2806 PetscFunctionBegin; 2807 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2808 if (numConstants) { 2809 PetscValidIntPointer(numConstants, 2); 2810 *numConstants = prob->numConstants; 2811 } 2812 if (constants) { 2813 PetscValidPointer(constants, 3); 2814 *constants = prob->constants; 2815 } 2816 PetscFunctionReturn(PETSC_SUCCESS); 2817 } 2818 2819 /*@C 2820 PetscDSSetConstants - Set the array of constants passed to point functions 2821 2822 Not collective 2823 2824 Input Parameters: 2825 + prob - The `PetscDS` object 2826 . numConstants - The number of constants 2827 - constants - The array of constants, NULL if there are none 2828 2829 Level: intermediate 2830 2831 .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()` 2832 @*/ 2833 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[]) 2834 { 2835 PetscFunctionBegin; 2836 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2837 if (numConstants != prob->numConstants) { 2838 PetscCall(PetscFree(prob->constants)); 2839 prob->numConstants = numConstants; 2840 if (prob->numConstants) { 2841 PetscCall(PetscMalloc1(prob->numConstants, &prob->constants)); 2842 } else { 2843 prob->constants = NULL; 2844 } 2845 } 2846 if (prob->numConstants) { 2847 PetscValidScalarPointer(constants, 3); 2848 PetscCall(PetscArraycpy(prob->constants, constants, prob->numConstants)); 2849 } 2850 PetscFunctionReturn(PETSC_SUCCESS); 2851 } 2852 2853 /*@ 2854 PetscDSGetFieldIndex - Returns the index of the given field 2855 2856 Not collective 2857 2858 Input Parameters: 2859 + prob - The `PetscDS` object 2860 - disc - The discretization object 2861 2862 Output Parameter: 2863 . f - The field number 2864 2865 Level: beginner 2866 2867 .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2868 @*/ 2869 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2870 { 2871 PetscInt g; 2872 2873 PetscFunctionBegin; 2874 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2875 PetscValidIntPointer(f, 3); 2876 *f = -1; 2877 for (g = 0; g < prob->Nf; ++g) { 2878 if (disc == prob->disc[g]) break; 2879 } 2880 PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2881 *f = g; 2882 PetscFunctionReturn(PETSC_SUCCESS); 2883 } 2884 2885 /*@ 2886 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2887 2888 Not collective 2889 2890 Input Parameters: 2891 + prob - The `PetscDS` object 2892 - f - The field number 2893 2894 Output Parameter: 2895 . size - The size 2896 2897 Level: beginner 2898 2899 .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2900 @*/ 2901 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2902 { 2903 PetscFunctionBegin; 2904 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2905 PetscValidIntPointer(size, 3); 2906 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 2907 PetscCall(PetscDSSetUp(prob)); 2908 *size = prob->Nb[f]; 2909 PetscFunctionReturn(PETSC_SUCCESS); 2910 } 2911 2912 /*@ 2913 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2914 2915 Not collective 2916 2917 Input Parameters: 2918 + prob - The `PetscDS` object 2919 - f - The field number 2920 2921 Output Parameter: 2922 . off - The offset 2923 2924 Level: beginner 2925 2926 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2927 @*/ 2928 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2929 { 2930 PetscInt size, g; 2931 2932 PetscFunctionBegin; 2933 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2934 PetscValidIntPointer(off, 3); 2935 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 2936 *off = 0; 2937 for (g = 0; g < f; ++g) { 2938 PetscCall(PetscDSGetFieldSize(prob, g, &size)); 2939 *off += size; 2940 } 2941 PetscFunctionReturn(PETSC_SUCCESS); 2942 } 2943 2944 /*@ 2945 PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell 2946 2947 Not collective 2948 2949 Input Parameters: 2950 + prob - The `PetscDS` object 2951 - f - The field number 2952 2953 Output Parameter: 2954 . off - The offset 2955 2956 Level: beginner 2957 2958 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2959 @*/ 2960 PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off) 2961 { 2962 PetscInt size, g; 2963 2964 PetscFunctionBegin; 2965 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2966 PetscValidIntPointer(off, 3); 2967 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2968 *off = 0; 2969 for (g = 0; g < f; ++g) { 2970 PetscBool cohesive; 2971 2972 PetscCall(PetscDSGetCohesive(ds, g, &cohesive)); 2973 PetscCall(PetscDSGetFieldSize(ds, g, &size)); 2974 *off += cohesive ? size : size * 2; 2975 } 2976 PetscFunctionReturn(PETSC_SUCCESS); 2977 } 2978 2979 /*@ 2980 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 2981 2982 Not collective 2983 2984 Input Parameter: 2985 . prob - The `PetscDS` object 2986 2987 Output Parameter: 2988 . dimensions - The number of dimensions 2989 2990 Level: beginner 2991 2992 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2993 @*/ 2994 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 2995 { 2996 PetscFunctionBegin; 2997 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2998 PetscCall(PetscDSSetUp(prob)); 2999 PetscValidPointer(dimensions, 2); 3000 *dimensions = prob->Nb; 3001 PetscFunctionReturn(PETSC_SUCCESS); 3002 } 3003 3004 /*@ 3005 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 3006 3007 Not collective 3008 3009 Input Parameter: 3010 . prob - The `PetscDS` object 3011 3012 Output Parameter: 3013 . components - The number of components 3014 3015 Level: beginner 3016 3017 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3018 @*/ 3019 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 3020 { 3021 PetscFunctionBegin; 3022 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3023 PetscCall(PetscDSSetUp(prob)); 3024 PetscValidPointer(components, 2); 3025 *components = prob->Nc; 3026 PetscFunctionReturn(PETSC_SUCCESS); 3027 } 3028 3029 /*@ 3030 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 3031 3032 Not collective 3033 3034 Input Parameters: 3035 + prob - The `PetscDS` object 3036 - f - The field number 3037 3038 Output Parameter: 3039 . off - The offset 3040 3041 Level: beginner 3042 3043 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3044 @*/ 3045 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 3046 { 3047 PetscFunctionBegin; 3048 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3049 PetscValidIntPointer(off, 3); 3050 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 3051 PetscCall(PetscDSSetUp(prob)); 3052 *off = prob->off[f]; 3053 PetscFunctionReturn(PETSC_SUCCESS); 3054 } 3055 3056 /*@ 3057 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 3058 3059 Not collective 3060 3061 Input Parameter: 3062 . prob - The `PetscDS` object 3063 3064 Output Parameter: 3065 . offsets - The offsets 3066 3067 Level: beginner 3068 3069 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3070 @*/ 3071 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 3072 { 3073 PetscFunctionBegin; 3074 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3075 PetscValidPointer(offsets, 2); 3076 PetscCall(PetscDSSetUp(prob)); 3077 *offsets = prob->off; 3078 PetscFunctionReturn(PETSC_SUCCESS); 3079 } 3080 3081 /*@ 3082 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 3083 3084 Not collective 3085 3086 Input Parameter: 3087 . prob - The `PetscDS` object 3088 3089 Output Parameter: 3090 . offsets - The offsets 3091 3092 Level: beginner 3093 3094 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3095 @*/ 3096 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 3097 { 3098 PetscFunctionBegin; 3099 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3100 PetscValidPointer(offsets, 2); 3101 PetscCall(PetscDSSetUp(prob)); 3102 *offsets = prob->offDer; 3103 PetscFunctionReturn(PETSC_SUCCESS); 3104 } 3105 3106 /*@ 3107 PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point 3108 3109 Not collective 3110 3111 Input Parameters: 3112 + ds - The `PetscDS` object 3113 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3114 3115 Output Parameter: 3116 . offsets - The offsets 3117 3118 Level: beginner 3119 3120 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3121 @*/ 3122 PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3123 { 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3126 PetscValidPointer(offsets, 3); 3127 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3128 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3129 PetscCall(PetscDSSetUp(ds)); 3130 *offsets = ds->offCohesive[s]; 3131 PetscFunctionReturn(PETSC_SUCCESS); 3132 } 3133 3134 /*@ 3135 PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point 3136 3137 Not collective 3138 3139 Input Parameters: 3140 + ds - The `PetscDS` object 3141 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3142 3143 Output Parameter: 3144 . offsets - The offsets 3145 3146 Level: beginner 3147 3148 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3149 @*/ 3150 PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3151 { 3152 PetscFunctionBegin; 3153 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3154 PetscValidPointer(offsets, 3); 3155 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3156 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3157 PetscCall(PetscDSSetUp(ds)); 3158 *offsets = ds->offDerCohesive[s]; 3159 PetscFunctionReturn(PETSC_SUCCESS); 3160 } 3161 3162 /*@C 3163 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 3164 3165 Not collective 3166 3167 Input Parameter: 3168 . prob - The `PetscDS` object 3169 3170 Output Parameter: 3171 . T - The basis function and derivatives tabulation at quadrature points for each field 3172 3173 Level: intermediate 3174 3175 .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()` 3176 @*/ 3177 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) 3178 { 3179 PetscFunctionBegin; 3180 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3181 PetscValidPointer(T, 2); 3182 PetscCall(PetscDSSetUp(prob)); 3183 *T = prob->T; 3184 PetscFunctionReturn(PETSC_SUCCESS); 3185 } 3186 3187 /*@C 3188 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 3189 3190 Not collective 3191 3192 Input Parameter: 3193 . prob - The `PetscDS` object 3194 3195 Output Parameter: 3196 . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field 3197 3198 Level: intermediate 3199 3200 .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()` 3201 @*/ 3202 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 3203 { 3204 PetscFunctionBegin; 3205 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3206 PetscValidPointer(Tf, 2); 3207 PetscCall(PetscDSSetUp(prob)); 3208 *Tf = prob->Tf; 3209 PetscFunctionReturn(PETSC_SUCCESS); 3210 } 3211 3212 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x) 3213 { 3214 PetscFunctionBegin; 3215 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3216 PetscCall(PetscDSSetUp(prob)); 3217 if (u) { 3218 PetscValidPointer(u, 2); 3219 *u = prob->u; 3220 } 3221 if (u_t) { 3222 PetscValidPointer(u_t, 3); 3223 *u_t = prob->u_t; 3224 } 3225 if (u_x) { 3226 PetscValidPointer(u_x, 4); 3227 *u_x = prob->u_x; 3228 } 3229 PetscFunctionReturn(PETSC_SUCCESS); 3230 } 3231 3232 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3) 3233 { 3234 PetscFunctionBegin; 3235 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3236 PetscCall(PetscDSSetUp(prob)); 3237 if (f0) { 3238 PetscValidPointer(f0, 2); 3239 *f0 = prob->f0; 3240 } 3241 if (f1) { 3242 PetscValidPointer(f1, 3); 3243 *f1 = prob->f1; 3244 } 3245 if (g0) { 3246 PetscValidPointer(g0, 4); 3247 *g0 = prob->g0; 3248 } 3249 if (g1) { 3250 PetscValidPointer(g1, 5); 3251 *g1 = prob->g1; 3252 } 3253 if (g2) { 3254 PetscValidPointer(g2, 6); 3255 *g2 = prob->g2; 3256 } 3257 if (g3) { 3258 PetscValidPointer(g3, 7); 3259 *g3 = prob->g3; 3260 } 3261 PetscFunctionReturn(PETSC_SUCCESS); 3262 } 3263 3264 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 3265 { 3266 PetscFunctionBegin; 3267 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3268 PetscCall(PetscDSSetUp(prob)); 3269 if (x) { 3270 PetscValidPointer(x, 2); 3271 *x = prob->x; 3272 } 3273 if (basisReal) { 3274 PetscValidPointer(basisReal, 3); 3275 *basisReal = prob->basisReal; 3276 } 3277 if (basisDerReal) { 3278 PetscValidPointer(basisDerReal, 4); 3279 *basisDerReal = prob->basisDerReal; 3280 } 3281 if (testReal) { 3282 PetscValidPointer(testReal, 5); 3283 *testReal = prob->testReal; 3284 } 3285 if (testDerReal) { 3286 PetscValidPointer(testDerReal, 6); 3287 *testDerReal = prob->testDerReal; 3288 } 3289 PetscFunctionReturn(PETSC_SUCCESS); 3290 } 3291 3292 /*@C 3293 PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3294 In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3295 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3296 3297 Collective on ds 3298 3299 Input Parameters: 3300 + ds - The PetscDS object 3301 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3302 . name - The BC name 3303 . label - The label defining constrained points 3304 . Nv - The number of `DMLabel` values for constrained points 3305 . values - An array of label values for constrained points 3306 . field - The field to constrain 3307 . Nc - The number of constrained field components (0 will constrain all fields) 3308 . comps - An array of constrained component numbers 3309 . bcFunc - A pointwise function giving boundary values 3310 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3311 - ctx - An optional user context for bcFunc 3312 3313 Output Parameters: 3314 - bd - The boundary number 3315 3316 Options Database Keys: 3317 + -bc_<boundary name> <num> - Overrides the boundary ids 3318 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3319 3320 Level: developer 3321 3322 Note: 3323 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, Then the calling sequence is: 3324 3325 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3326 3327 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is: 3328 .vb 3329 bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3330 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3331 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3332 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3333 .ve 3334 + dim - the spatial dimension 3335 . Nf - the number of fields 3336 . uOff - the offset into u[] and u_t[] for each field 3337 . uOff_x - the offset into u_x[] for each field 3338 . u - each field evaluated at the current point 3339 . u_t - the time derivative of each field evaluated at the current point 3340 . u_x - the gradient of each field evaluated at the current point 3341 . aOff - the offset into a[] and a_t[] for each auxiliary field 3342 . aOff_x - the offset into a_x[] for each auxiliary field 3343 . a - each auxiliary field evaluated at the current point 3344 . a_t - the time derivative of each auxiliary field evaluated at the current point 3345 . a_x - the gradient of auxiliary each field evaluated at the current point 3346 . t - current time 3347 . x - coordinates of the current point 3348 . numConstants - number of constant parameters 3349 . constants - constant parameters 3350 - bcval - output values at the current point 3351 3352 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3353 @*/ 3354 PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 3355 { 3356 DSBoundary head = ds->boundary, b; 3357 PetscInt n = 0; 3358 const char *lname; 3359 3360 PetscFunctionBegin; 3361 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3362 PetscValidLogicalCollectiveEnum(ds, type, 2); 3363 PetscValidCharPointer(name, 3); 3364 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 3365 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3366 PetscValidLogicalCollectiveInt(ds, field, 7); 3367 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3368 PetscCheck(field >= 0 && field < ds->Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", field, ds->Nf); 3369 if (Nc > 0) { 3370 PetscInt *fcomps; 3371 PetscInt c; 3372 3373 PetscCall(PetscDSGetComponents(ds, &fcomps)); 3374 PetscCheck(Nc <= fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Number of constrained components %" PetscInt_FMT " > %" PetscInt_FMT " components for field %" PetscInt_FMT, Nc, fcomps[field], field); 3375 for (c = 0; c < Nc; ++c) { 3376 PetscCheck(comps[c] >= 0 && comps[c] < fcomps[field], PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Constrained component[%" PetscInt_FMT "] %" PetscInt_FMT " not in [0, %" PetscInt_FMT ") components for field %" PetscInt_FMT, c, comps[c], fcomps[field], field); 3377 } 3378 } 3379 PetscCall(PetscNew(&b)); 3380 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3381 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3382 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3383 PetscCall(PetscMalloc1(Nv, &b->values)); 3384 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3385 PetscCall(PetscMalloc1(Nc, &b->comps)); 3386 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3387 PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 3388 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3389 b->type = type; 3390 b->label = label; 3391 b->Nv = Nv; 3392 b->field = field; 3393 b->Nc = Nc; 3394 b->func = bcFunc; 3395 b->func_t = bcFunc_t; 3396 b->ctx = ctx; 3397 b->next = NULL; 3398 /* Append to linked list so that we can preserve the order */ 3399 if (!head) ds->boundary = b; 3400 while (head) { 3401 if (!head->next) { 3402 head->next = b; 3403 head = b; 3404 } 3405 head = head->next; 3406 ++n; 3407 } 3408 if (bd) { 3409 PetscValidIntPointer(bd, 13); 3410 *bd = n; 3411 } 3412 PetscFunctionReturn(PETSC_SUCCESS); 3413 } 3414 3415 /*@C 3416 PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3417 In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that 3418 boundary integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3419 3420 Collective on ds 3421 3422 Input Parameters: 3423 + ds - The `PetscDS` object 3424 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3425 . name - The BC name 3426 . lname - The naem of the label defining constrained points 3427 . Nv - The number of `DMLabel` values for constrained points 3428 . values - An array of label values for constrained points 3429 . field - The field to constrain 3430 . Nc - The number of constrained field components (0 will constrain all fields) 3431 . comps - An array of constrained component numbers 3432 . bcFunc - A pointwise function giving boundary values 3433 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3434 - ctx - An optional user context for bcFunc 3435 3436 Output Parameters: 3437 - bd - The boundary number 3438 3439 Options Database Keys: 3440 + -bc_<boundary name> <num> - Overrides the boundary ids 3441 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3442 3443 Calling Sequence of bcFunc() and bcFunc_t(): 3444 If the type is `DM_BC_ESSENTIAL` 3445 .vb 3446 bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3447 .ve 3448 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, 3449 .vb 3450 bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3451 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3452 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3453 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3454 .ve 3455 + dim - the spatial dimension 3456 . Nf - the number of fields 3457 . uOff - the offset into u[] and u_t[] for each field 3458 . uOff_x - the offset into u_x[] for each field 3459 . u - each field evaluated at the current point 3460 . u_t - the time derivative of each field evaluated at the current point 3461 . u_x - the gradient of each field evaluated at the current point 3462 . aOff - the offset into a[] and a_t[] for each auxiliary field 3463 . aOff_x - the offset into a_x[] for each auxiliary field 3464 . a - each auxiliary field evaluated at the current point 3465 . a_t - the time derivative of each auxiliary field evaluated at the current point 3466 . a_x - the gradient of auxiliary each field evaluated at the current point 3467 . t - current time 3468 . x - coordinates of the current point 3469 . numConstants - number of constant parameters 3470 . constants - constant parameters 3471 - bcval - output values at the current point 3472 3473 Level: developer 3474 3475 Note: 3476 This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built. 3477 3478 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3479 @*/ 3480 PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 3481 { 3482 DSBoundary head = ds->boundary, b; 3483 PetscInt n = 0; 3484 3485 PetscFunctionBegin; 3486 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3487 PetscValidLogicalCollectiveEnum(ds, type, 2); 3488 PetscValidCharPointer(name, 3); 3489 PetscValidCharPointer(lname, 4); 3490 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3491 PetscValidLogicalCollectiveInt(ds, field, 7); 3492 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3493 PetscCall(PetscNew(&b)); 3494 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3495 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3496 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3497 PetscCall(PetscMalloc1(Nv, &b->values)); 3498 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3499 PetscCall(PetscMalloc1(Nc, &b->comps)); 3500 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3501 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3502 b->type = type; 3503 b->label = NULL; 3504 b->Nv = Nv; 3505 b->field = field; 3506 b->Nc = Nc; 3507 b->func = bcFunc; 3508 b->func_t = bcFunc_t; 3509 b->ctx = ctx; 3510 b->next = NULL; 3511 /* Append to linked list so that we can preserve the order */ 3512 if (!head) ds->boundary = b; 3513 while (head) { 3514 if (!head->next) { 3515 head->next = b; 3516 head = b; 3517 } 3518 head = head->next; 3519 ++n; 3520 } 3521 if (bd) { 3522 PetscValidIntPointer(bd, 13); 3523 *bd = n; 3524 } 3525 PetscFunctionReturn(PETSC_SUCCESS); 3526 } 3527 3528 /*@C 3529 PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3530 In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals 3531 should be performed, using the kernels from `PetscDSSetBdResidual()`. 3532 3533 Input Parameters: 3534 + ds - The `PetscDS` object 3535 . bd - The boundary condition number 3536 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3537 . name - The BC name 3538 . label - The label defining constrained points 3539 . Nv - The number of `DMLabel` ids for constrained points 3540 . values - An array of ids for constrained points 3541 . field - The field to constrain 3542 . Nc - The number of constrained field components 3543 . comps - An array of constrained component numbers 3544 . bcFunc - A pointwise function giving boundary values 3545 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3546 - ctx - An optional user context for bcFunc 3547 3548 Level: developer 3549 3550 Note: 3551 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`. 3552 See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks. 3553 3554 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel` 3555 @*/ 3556 PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx) 3557 { 3558 DSBoundary b = ds->boundary; 3559 PetscInt n = 0; 3560 3561 PetscFunctionBegin; 3562 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3563 while (b) { 3564 if (n == bd) break; 3565 b = b->next; 3566 ++n; 3567 } 3568 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3569 if (name) { 3570 PetscCall(PetscFree(b->name)); 3571 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3572 } 3573 b->type = type; 3574 if (label) { 3575 const char *name; 3576 3577 b->label = label; 3578 PetscCall(PetscFree(b->lname)); 3579 PetscCall(PetscObjectGetName((PetscObject)label, &name)); 3580 PetscCall(PetscStrallocpy(name, (char **)&b->lname)); 3581 } 3582 if (Nv >= 0) { 3583 b->Nv = Nv; 3584 PetscCall(PetscFree(b->values)); 3585 PetscCall(PetscMalloc1(Nv, &b->values)); 3586 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3587 } 3588 if (field >= 0) b->field = field; 3589 if (Nc >= 0) { 3590 b->Nc = Nc; 3591 PetscCall(PetscFree(b->comps)); 3592 PetscCall(PetscMalloc1(Nc, &b->comps)); 3593 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3594 } 3595 if (bcFunc) b->func = bcFunc; 3596 if (bcFunc_t) b->func_t = bcFunc_t; 3597 if (ctx) b->ctx = ctx; 3598 PetscFunctionReturn(PETSC_SUCCESS); 3599 } 3600 3601 /*@ 3602 PetscDSGetNumBoundary - Get the number of registered BC 3603 3604 Input Parameters: 3605 . ds - The `PetscDS` object 3606 3607 Output Parameters: 3608 . numBd - The number of BC 3609 3610 Level: intermediate 3611 3612 .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()` 3613 @*/ 3614 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3615 { 3616 DSBoundary b = ds->boundary; 3617 3618 PetscFunctionBegin; 3619 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3620 PetscValidIntPointer(numBd, 2); 3621 *numBd = 0; 3622 while (b) { 3623 ++(*numBd); 3624 b = b->next; 3625 } 3626 PetscFunctionReturn(PETSC_SUCCESS); 3627 } 3628 3629 /*@C 3630 PetscDSGetBoundary - Gets a boundary condition to the model 3631 3632 Input Parameters: 3633 + ds - The `PetscDS` object 3634 - bd - The BC number 3635 3636 Output Parameters: 3637 + wf - The `PetscWeakForm` holding the pointwise functions 3638 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3639 . name - The BC name 3640 . label - The label defining constrained points 3641 . Nv - The number of `DMLabel` ids for constrained points 3642 . values - An array of ids for constrained points 3643 . field - The field to constrain 3644 . Nc - The number of constrained field components 3645 . comps - An array of constrained component numbers 3646 . bcFunc - A pointwise function giving boundary values 3647 . bcFunc_t - A pointwise function giving the time derivative of the boundary values 3648 - ctx - An optional user context for bcFunc 3649 3650 Options Database Keys: 3651 + -bc_<boundary name> <num> - Overrides the boundary ids 3652 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3653 3654 Level: developer 3655 3656 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel` 3657 @*/ 3658 PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx) 3659 { 3660 DSBoundary b = ds->boundary; 3661 PetscInt n = 0; 3662 3663 PetscFunctionBegin; 3664 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3665 while (b) { 3666 if (n == bd) break; 3667 b = b->next; 3668 ++n; 3669 } 3670 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3671 if (wf) { 3672 PetscValidPointer(wf, 3); 3673 *wf = b->wf; 3674 } 3675 if (type) { 3676 PetscValidPointer(type, 4); 3677 *type = b->type; 3678 } 3679 if (name) { 3680 PetscValidPointer(name, 5); 3681 *name = b->name; 3682 } 3683 if (label) { 3684 PetscValidPointer(label, 6); 3685 *label = b->label; 3686 } 3687 if (Nv) { 3688 PetscValidIntPointer(Nv, 7); 3689 *Nv = b->Nv; 3690 } 3691 if (values) { 3692 PetscValidPointer(values, 8); 3693 *values = b->values; 3694 } 3695 if (field) { 3696 PetscValidIntPointer(field, 9); 3697 *field = b->field; 3698 } 3699 if (Nc) { 3700 PetscValidIntPointer(Nc, 10); 3701 *Nc = b->Nc; 3702 } 3703 if (comps) { 3704 PetscValidPointer(comps, 11); 3705 *comps = b->comps; 3706 } 3707 if (func) { 3708 PetscValidPointer(func, 12); 3709 *func = b->func; 3710 } 3711 if (func_t) { 3712 PetscValidPointer(func_t, 13); 3713 *func_t = b->func_t; 3714 } 3715 if (ctx) { 3716 PetscValidPointer(ctx, 14); 3717 *ctx = b->ctx; 3718 } 3719 PetscFunctionReturn(PETSC_SUCCESS); 3720 } 3721 3722 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3723 { 3724 PetscFunctionBegin; 3725 PetscCall(PetscNew(bNew)); 3726 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf)); 3727 PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf)); 3728 PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name))); 3729 PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname))); 3730 (*bNew)->type = b->type; 3731 (*bNew)->label = b->label; 3732 (*bNew)->Nv = b->Nv; 3733 PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values)); 3734 PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv)); 3735 (*bNew)->field = b->field; 3736 (*bNew)->Nc = b->Nc; 3737 PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps)); 3738 PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc)); 3739 (*bNew)->func = b->func; 3740 (*bNew)->func_t = b->func_t; 3741 (*bNew)->ctx = b->ctx; 3742 PetscFunctionReturn(PETSC_SUCCESS); 3743 } 3744 3745 /*@ 3746 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 3747 3748 Not collective 3749 3750 Input Parameters: 3751 + ds - The source `PetscDS` object 3752 . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields 3753 - fields - The selected fields, or NULL for all fields 3754 3755 Output Parameter: 3756 . newds - The target `PetscDS`, now with a copy of the boundary conditions 3757 3758 Level: intermediate 3759 3760 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3761 @*/ 3762 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3763 { 3764 DSBoundary b, *lastnext; 3765 3766 PetscFunctionBegin; 3767 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3768 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3769 if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS); 3770 PetscCall(PetscDSDestroyBoundary(newds)); 3771 lastnext = &(newds->boundary); 3772 for (b = ds->boundary; b; b = b->next) { 3773 DSBoundary bNew; 3774 PetscInt fieldNew = -1; 3775 3776 if (numFields > 0 && fields) { 3777 PetscInt f; 3778 3779 for (f = 0; f < numFields; ++f) 3780 if (b->field == fields[f]) break; 3781 if (f == numFields) continue; 3782 fieldNew = f; 3783 } 3784 PetscCall(DSBoundaryDuplicate_Internal(b, &bNew)); 3785 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3786 *lastnext = bNew; 3787 lastnext = &(bNew->next); 3788 } 3789 PetscFunctionReturn(PETSC_SUCCESS); 3790 } 3791 3792 /*@ 3793 PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS` 3794 3795 Not collective 3796 3797 Input Parameter: 3798 . ds - The `PetscDS` object 3799 3800 Level: intermediate 3801 3802 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()` 3803 @*/ 3804 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3805 { 3806 DSBoundary next = ds->boundary; 3807 3808 PetscFunctionBegin; 3809 while (next) { 3810 DSBoundary b = next; 3811 3812 next = b->next; 3813 PetscCall(PetscWeakFormDestroy(&b->wf)); 3814 PetscCall(PetscFree(b->name)); 3815 PetscCall(PetscFree(b->lname)); 3816 PetscCall(PetscFree(b->values)); 3817 PetscCall(PetscFree(b->comps)); 3818 PetscCall(PetscFree(b)); 3819 } 3820 PetscFunctionReturn(PETSC_SUCCESS); 3821 } 3822 3823 /*@ 3824 PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout 3825 3826 Not collective 3827 3828 Input Parameters: 3829 + prob - The `PetscDS` object 3830 . numFields - Number of new fields 3831 - fields - Old field number for each new field 3832 3833 Output Parameter: 3834 . newprob - The `PetscDS` copy 3835 3836 Level: intermediate 3837 3838 .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3839 @*/ 3840 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3841 { 3842 PetscInt Nf, Nfn, fn; 3843 3844 PetscFunctionBegin; 3845 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3846 if (fields) PetscValidIntPointer(fields, 3); 3847 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3848 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3849 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3850 numFields = numFields < 0 ? Nf : numFields; 3851 for (fn = 0; fn < numFields; ++fn) { 3852 const PetscInt f = fields ? fields[fn] : fn; 3853 PetscObject disc; 3854 3855 if (f >= Nf) continue; 3856 PetscCall(PetscDSGetDiscretization(prob, f, &disc)); 3857 PetscCall(PetscDSSetDiscretization(newprob, fn, disc)); 3858 } 3859 PetscFunctionReturn(PETSC_SUCCESS); 3860 } 3861 3862 /*@ 3863 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 3864 3865 Not collective 3866 3867 Input Parameters: 3868 + prob - The `PetscDS` object 3869 . numFields - Number of new fields 3870 - fields - Old field number for each new field 3871 3872 Output Parameter: 3873 . newprob - The `PetscDS` copy 3874 3875 Level: intermediate 3876 3877 .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3878 @*/ 3879 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3880 { 3881 PetscInt Nf, Nfn, fn, gn; 3882 3883 PetscFunctionBegin; 3884 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3885 if (fields) PetscValidIntPointer(fields, 3); 3886 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3887 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3888 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3889 PetscCheck(numFields <= Nfn, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields %" PetscInt_FMT " to transfer must not be greater then the total number of fields %" PetscInt_FMT, numFields, Nfn); 3890 for (fn = 0; fn < numFields; ++fn) { 3891 const PetscInt f = fields ? fields[fn] : fn; 3892 PetscPointFunc obj; 3893 PetscPointFunc f0, f1; 3894 PetscBdPointFunc f0Bd, f1Bd; 3895 PetscRiemannFunc r; 3896 3897 if (f >= Nf) continue; 3898 PetscCall(PetscDSGetObjective(prob, f, &obj)); 3899 PetscCall(PetscDSGetResidual(prob, f, &f0, &f1)); 3900 PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd)); 3901 PetscCall(PetscDSGetRiemannSolver(prob, f, &r)); 3902 PetscCall(PetscDSSetObjective(newprob, fn, obj)); 3903 PetscCall(PetscDSSetResidual(newprob, fn, f0, f1)); 3904 PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd)); 3905 PetscCall(PetscDSSetRiemannSolver(newprob, fn, r)); 3906 for (gn = 0; gn < numFields; ++gn) { 3907 const PetscInt g = fields ? fields[gn] : gn; 3908 PetscPointJac g0, g1, g2, g3; 3909 PetscPointJac g0p, g1p, g2p, g3p; 3910 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3911 3912 if (g >= Nf) continue; 3913 PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3)); 3914 PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p)); 3915 PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd)); 3916 PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3)); 3917 PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p)); 3918 PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd)); 3919 } 3920 } 3921 PetscFunctionReturn(PETSC_SUCCESS); 3922 } 3923 3924 /*@ 3925 PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS` 3926 3927 Not collective 3928 3929 Input Parameter: 3930 . prob - The `PetscDS` object 3931 3932 Output Parameter: 3933 . newprob - The `PetscDS` copy 3934 3935 Level: intermediate 3936 3937 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3938 @*/ 3939 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3940 { 3941 PetscWeakForm wf, newwf; 3942 PetscInt Nf, Ng; 3943 3944 PetscFunctionBegin; 3945 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3946 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3947 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3948 PetscCall(PetscDSGetNumFields(newprob, &Ng)); 3949 PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng); 3950 PetscCall(PetscDSGetWeakForm(prob, &wf)); 3951 PetscCall(PetscDSGetWeakForm(newprob, &newwf)); 3952 PetscCall(PetscWeakFormCopy(wf, newwf)); 3953 PetscFunctionReturn(PETSC_SUCCESS); 3954 } 3955 3956 /*@ 3957 PetscDSCopyConstants - Copy all constants to another `PetscDS` 3958 3959 Not collective 3960 3961 Input Parameter: 3962 . prob - The `PetscDS` object 3963 3964 Output Parameter: 3965 . newprob - The `PetscDS` copy 3966 3967 Level: intermediate 3968 3969 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3970 @*/ 3971 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3972 { 3973 PetscInt Nc; 3974 const PetscScalar *constants; 3975 3976 PetscFunctionBegin; 3977 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3978 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3979 PetscCall(PetscDSGetConstants(prob, &Nc, &constants)); 3980 PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants)); 3981 PetscFunctionReturn(PETSC_SUCCESS); 3982 } 3983 3984 /*@ 3985 PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS` 3986 3987 Not collective 3988 3989 Input Parameter: 3990 . ds - The `PetscDS` object 3991 3992 Output Parameter: 3993 . newds - The `PetscDS` copy 3994 3995 Level: intermediate 3996 3997 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3998 @*/ 3999 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 4000 { 4001 PetscSimplePointFunc sol; 4002 void *ctx; 4003 PetscInt Nf, f; 4004 4005 PetscFunctionBegin; 4006 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4007 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 4008 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4009 for (f = 0; f < Nf; ++f) { 4010 PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx)); 4011 PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx)); 4012 PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx)); 4013 PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx)); 4014 } 4015 PetscFunctionReturn(PETSC_SUCCESS); 4016 } 4017 4018 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 4019 { 4020 PetscInt dim, Nf, f; 4021 4022 PetscFunctionBegin; 4023 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 4024 PetscValidPointer(subprob, 3); 4025 if (height == 0) { 4026 *subprob = prob; 4027 PetscFunctionReturn(PETSC_SUCCESS); 4028 } 4029 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4030 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 4031 PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height); 4032 if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs)); 4033 if (!prob->subprobs[height - 1]) { 4034 PetscInt cdim; 4035 4036 PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1])); 4037 PetscCall(PetscDSGetCoordinateDimension(prob, &cdim)); 4038 PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim)); 4039 for (f = 0; f < Nf; ++f) { 4040 PetscFE subfe; 4041 PetscObject obj; 4042 PetscClassId id; 4043 4044 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 4045 PetscCall(PetscObjectGetClassId(obj, &id)); 4046 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe)); 4047 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f); 4048 PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe)); 4049 } 4050 } 4051 *subprob = prob->subprobs[height - 1]; 4052 PetscFunctionReturn(PETSC_SUCCESS); 4053 } 4054 4055 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 4056 { 4057 PetscObject obj; 4058 PetscClassId id; 4059 PetscInt Nf; 4060 4061 PetscFunctionBegin; 4062 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4063 PetscValidPointer(disctype, 3); 4064 *disctype = PETSC_DISC_NONE; 4065 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4066 PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf); 4067 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 4068 if (obj) { 4069 PetscCall(PetscObjectGetClassId(obj, &id)); 4070 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 4071 else *disctype = PETSC_DISC_FV; 4072 } 4073 PetscFunctionReturn(PETSC_SUCCESS); 4074 } 4075 4076 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 4077 { 4078 PetscFunctionBegin; 4079 PetscCall(PetscFree(ds->data)); 4080 PetscFunctionReturn(PETSC_SUCCESS); 4081 } 4082 4083 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 4084 { 4085 PetscFunctionBegin; 4086 ds->ops->setfromoptions = NULL; 4087 ds->ops->setup = NULL; 4088 ds->ops->view = NULL; 4089 ds->ops->destroy = PetscDSDestroy_Basic; 4090 PetscFunctionReturn(PETSC_SUCCESS); 4091 } 4092 4093 /*MC 4094 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 4095 4096 Level: intermediate 4097 4098 .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()` 4099 M*/ 4100 4101 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 4102 { 4103 PetscDS_Basic *b; 4104 4105 PetscFunctionBegin; 4106 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4107 PetscCall(PetscNew(&b)); 4108 ds->data = b; 4109 4110 PetscCall(PetscDSInitialize_Basic(ds)); 4111 PetscFunctionReturn(PETSC_SUCCESS); 4112 } 4113