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