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; No Fortran Support 25 26 Input Parameters: 27 + sname - The name of a new user-defined creation routine 28 - function - 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 .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()` 51 @*/ 52 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS)) 53 { 54 PetscFunctionBegin; 55 PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function)); 56 PetscFunctionReturn(PETSC_SUCCESS); 57 } 58 59 /*@C 60 PetscDSSetType - Builds a particular `PetscDS` 61 62 Collective; No Fortran Support 63 64 Input Parameters: 65 + prob - The `PetscDS` object 66 - name - The `PetscDSType` 67 68 Options Database Key: 69 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types 70 71 Level: intermediate 72 73 .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()` 74 @*/ 75 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name) 76 { 77 PetscErrorCode (*r)(PetscDS); 78 PetscBool match; 79 80 PetscFunctionBegin; 81 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 82 PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match)); 83 if (match) PetscFunctionReturn(PETSC_SUCCESS); 84 85 PetscCall(PetscDSRegisterAll()); 86 PetscCall(PetscFunctionListFind(PetscDSList, name, &r)); 87 PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name); 88 89 PetscTryTypeMethod(prob, destroy); 90 prob->ops->destroy = NULL; 91 92 PetscCall((*r)(prob)); 93 PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name)); 94 PetscFunctionReturn(PETSC_SUCCESS); 95 } 96 97 /*@C 98 PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS` 99 100 Not Collective; No Fortran Support 101 102 Input Parameter: 103 . prob - The `PetscDS` 104 105 Output Parameter: 106 . name - The `PetscDSType` name 107 108 Level: intermediate 109 110 .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()` 111 @*/ 112 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name) 113 { 114 PetscFunctionBegin; 115 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 116 PetscValidPointer(name, 2); 117 PetscCall(PetscDSRegisterAll()); 118 *name = ((PetscObject)prob)->type_name; 119 PetscFunctionReturn(PETSC_SUCCESS); 120 } 121 122 static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer) 123 { 124 PetscViewerFormat format; 125 const PetscScalar *constants; 126 PetscInt Nf, numConstants, f; 127 128 PetscFunctionBegin; 129 PetscCall(PetscDSGetNumFields(ds, &Nf)); 130 PetscCall(PetscViewerGetFormat(viewer, &format)); 131 PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf)); 132 PetscCall(PetscViewerASCIIPushTab(viewer)); 133 PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp)); 134 if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n")); 135 for (f = 0; f < Nf; ++f) { 136 DSBoundary b; 137 PetscObject obj; 138 PetscClassId id; 139 PetscQuadrature q; 140 const char *name; 141 PetscInt Nc, Nq, Nqc; 142 143 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 144 PetscCall(PetscObjectGetClassId(obj, &id)); 145 PetscCall(PetscObjectGetName(obj, &name)); 146 PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>")); 147 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 148 if (id == PETSCFE_CLASSID) { 149 PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 150 PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q)); 151 PetscCall(PetscViewerASCIIPrintf(viewer, " FEM")); 152 } else if (id == PETSCFV_CLASSID) { 153 PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 154 PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q)); 155 PetscCall(PetscViewerASCIIPrintf(viewer, " FVM")); 156 } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 157 if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc)); 158 else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc)); 159 if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)")); 160 else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)")); 161 if (q) { 162 PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL)); 163 PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc)); 164 } 165 PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f])); 166 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 167 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 168 PetscCall(PetscViewerASCIIPushTab(viewer)); 169 if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer)); 170 else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer)); 171 PetscCall(PetscViewerASCIIPopTab(viewer)); 172 173 for (b = ds->boundary; b; b = b->next) { 174 char *name; 175 PetscInt c, i; 176 177 if (b->field != f) continue; 178 PetscCall(PetscViewerASCIIPushTab(viewer)); 179 PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type])); 180 if (!b->Nc) { 181 PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n")); 182 } else { 183 PetscCall(PetscViewerASCIIPrintf(viewer, " components: ")); 184 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 185 for (c = 0; c < b->Nc; ++c) { 186 if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 187 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c])); 188 } 189 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 190 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 191 } 192 PetscCall(PetscViewerASCIIPrintf(viewer, " values: ")); 193 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 194 for (i = 0; i < b->Nv; ++i) { 195 if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 196 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i])); 197 } 198 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 199 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 200 #if defined(__clang__) 201 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat-pedantic"); 202 #elif defined(__GNUC__) || defined(__GNUG__) 203 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat"); 204 #endif 205 if (b->func) { 206 PetscCall(PetscDLAddr(b->func, &name)); 207 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name)); 208 else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func)); 209 PetscCall(PetscFree(name)); 210 } 211 if (b->func_t) { 212 PetscCall(PetscDLAddr(b->func_t, &name)); 213 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name)); 214 else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t)); 215 PetscCall(PetscFree(name)); 216 } 217 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END(); 218 PetscCall(PetscWeakFormView(b->wf, viewer)); 219 PetscCall(PetscViewerASCIIPopTab(viewer)); 220 } 221 } 222 PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 223 if (numConstants) { 224 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants)); 225 PetscCall(PetscViewerASCIIPushTab(viewer)); 226 for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f]))); 227 PetscCall(PetscViewerASCIIPopTab(viewer)); 228 } 229 PetscCall(PetscWeakFormView(ds->wf, viewer)); 230 PetscCall(PetscViewerASCIIPopTab(viewer)); 231 PetscFunctionReturn(PETSC_SUCCESS); 232 } 233 234 /*@C 235 PetscDSViewFromOptions - View a `PetscDS` based on values in the options database 236 237 Collective 238 239 Input Parameters: 240 + A - the `PetscDS` object 241 . obj - Optional object that provides the options prefix used in the search 242 - name - command line option 243 244 Level: intermediate 245 246 .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()` 247 @*/ 248 PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[]) 249 { 250 PetscFunctionBegin; 251 PetscValidHeaderSpecific(A, PETSCDS_CLASSID, 1); 252 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 253 PetscFunctionReturn(PETSC_SUCCESS); 254 } 255 256 /*@C 257 PetscDSView - Views a `PetscDS` 258 259 Collective 260 261 Input Parameters: 262 + prob - the `PetscDS` object to view 263 - v - the viewer 264 265 Level: developer 266 267 .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`, `PetscDSViewFromOptions()` 268 @*/ 269 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v) 270 { 271 PetscBool iascii; 272 273 PetscFunctionBegin; 274 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 275 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v)); 276 else PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 277 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &iascii)); 278 if (iascii) PetscCall(PetscDSView_Ascii(prob, v)); 279 PetscTryTypeMethod(prob, view, v); 280 PetscFunctionReturn(PETSC_SUCCESS); 281 } 282 283 /*@ 284 PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database 285 286 Collective 287 288 Input Parameter: 289 . prob - the `PetscDS` object to set options for 290 291 Options Database Keys: 292 + -petscds_type <type> - Set the `PetscDS` type 293 . -petscds_view <view opt> - View the `PetscDS` 294 . -petscds_jac_pre - Turn formation of a separate Jacobian preconditioner on or off 295 . -bc_<name> <ids> - Specify a list of label ids for a boundary condition 296 - -bc_<name>_comp <comps> - Specify a list of field components to constrain for a boundary condition 297 298 Level: intermediate 299 300 .seealso: `PetscDS`, `PetscDSView()` 301 @*/ 302 PetscErrorCode PetscDSSetFromOptions(PetscDS prob) 303 { 304 DSBoundary b; 305 const char *defaultType; 306 char name[256]; 307 PetscBool flg; 308 309 PetscFunctionBegin; 310 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 311 if (!((PetscObject)prob)->type_name) { 312 defaultType = PETSCDSBASIC; 313 } else { 314 defaultType = ((PetscObject)prob)->type_name; 315 } 316 PetscCall(PetscDSRegisterAll()); 317 318 PetscObjectOptionsBegin((PetscObject)prob); 319 for (b = prob->boundary; b; b = b->next) { 320 char optname[1024]; 321 PetscInt ids[1024], len = 1024; 322 PetscBool flg; 323 324 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name)); 325 PetscCall(PetscMemzero(ids, sizeof(ids))); 326 PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg)); 327 if (flg) { 328 b->Nv = len; 329 PetscCall(PetscFree(b->values)); 330 PetscCall(PetscMalloc1(len, &b->values)); 331 PetscCall(PetscArraycpy(b->values, ids, len)); 332 PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values)); 333 } 334 len = 1024; 335 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name)); 336 PetscCall(PetscMemzero(ids, sizeof(ids))); 337 PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg)); 338 if (flg) { 339 b->Nc = len; 340 PetscCall(PetscFree(b->comps)); 341 PetscCall(PetscMalloc1(len, &b->comps)); 342 PetscCall(PetscArraycpy(b->comps, ids, len)); 343 } 344 } 345 PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg)); 346 if (flg) { 347 PetscCall(PetscDSSetType(prob, name)); 348 } else if (!((PetscObject)prob)->type_name) { 349 PetscCall(PetscDSSetType(prob, defaultType)); 350 } 351 PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg)); 352 PetscCall(PetscOptionsBool("-petscds_force_quad", "Discrete System", "PetscDSSetForceQuad", prob->forceQuad, &prob->forceQuad, &flg)); 353 PetscTryTypeMethod(prob, setfromoptions); 354 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 355 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject)); 356 PetscOptionsEnd(); 357 if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view")); 358 PetscFunctionReturn(PETSC_SUCCESS); 359 } 360 361 /*@C 362 PetscDSSetUp - Construct data structures for the `PetscDS` 363 364 Collective 365 366 Input Parameter: 367 . prob - the `PetscDS` object to setup 368 369 Level: developer 370 371 .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()` 372 @*/ 373 PetscErrorCode PetscDSSetUp(PetscDS prob) 374 { 375 const PetscInt Nf = prob->Nf; 376 PetscBool hasH = PETSC_FALSE; 377 PetscInt maxOrder[4] = {-1, -1, -1, -1}; 378 PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f; 379 380 PetscFunctionBegin; 381 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 382 if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS); 383 /* Calculate sizes */ 384 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 385 PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed)); 386 prob->totDim = prob->totComp = 0; 387 PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb)); 388 PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer)); 389 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])); 390 PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf)); 391 if (prob->forceQuad) { 392 // Note: This assumes we have one kind of cell at each dimension. 393 // We can fix this by having quadrature hold the celltype 394 PetscQuadrature maxQuad[4] = {NULL, NULL, NULL, NULL}; 395 396 for (f = 0; f < Nf; ++f) { 397 PetscObject obj; 398 PetscClassId id; 399 PetscQuadrature q = NULL, fq = NULL; 400 PetscInt dim = -1, order = -1, forder = -1; 401 402 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 403 if (!obj) continue; 404 PetscCall(PetscObjectGetClassId(obj, &id)); 405 if (id == PETSCFE_CLASSID) { 406 PetscFE fe = (PetscFE)obj; 407 408 PetscCall(PetscFEGetQuadrature(fe, &q)); 409 PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 410 } else if (id == PETSCFV_CLASSID) { 411 PetscFV fv = (PetscFV)obj; 412 413 PetscCall(PetscFVGetQuadrature(fv, &q)); 414 } 415 if (q) { 416 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 417 PetscCall(PetscQuadratureGetOrder(q, &order)); 418 if (order > maxOrder[dim]) { 419 maxOrder[dim] = order; 420 maxQuad[dim] = q; 421 } 422 } 423 if (fq) { 424 PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL)); 425 PetscCall(PetscQuadratureGetOrder(fq, &forder)); 426 if (forder > maxOrder[dim]) { 427 maxOrder[dim] = forder; 428 maxQuad[dim] = fq; 429 } 430 } 431 } 432 for (f = 0; f < Nf; ++f) { 433 PetscObject obj; 434 PetscClassId id; 435 PetscQuadrature q; 436 PetscInt dim; 437 438 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 439 if (!obj) continue; 440 PetscCall(PetscObjectGetClassId(obj, &id)); 441 if (id == PETSCFE_CLASSID) { 442 PetscFE fe = (PetscFE)obj; 443 444 PetscCall(PetscFEGetQuadrature(fe, &q)); 445 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 446 PetscCall(PetscFESetQuadrature(fe, maxQuad[dim])); 447 PetscCall(PetscFESetFaceQuadrature(fe, maxQuad[dim - 1])); 448 } else if (id == PETSCFV_CLASSID) { 449 PetscFV fv = (PetscFV)obj; 450 451 PetscCall(PetscFVGetQuadrature(fv, &q)); 452 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 453 PetscCall(PetscFVSetQuadrature(fv, maxQuad[dim])); 454 } 455 } 456 } 457 for (f = 0; f < Nf; ++f) { 458 PetscObject obj; 459 PetscClassId id; 460 PetscQuadrature q = NULL; 461 PetscInt Nq = 0, Nb, Nc; 462 463 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 464 if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE; 465 if (!obj) { 466 /* Empty mesh */ 467 Nb = Nc = 0; 468 prob->T[f] = prob->Tf[f] = NULL; 469 } else { 470 PetscCall(PetscObjectGetClassId(obj, &id)); 471 if (id == PETSCFE_CLASSID) { 472 PetscFE fe = (PetscFE)obj; 473 474 PetscCall(PetscFEGetQuadrature(fe, &q)); 475 { 476 PetscQuadrature fq; 477 PetscInt dim, order; 478 479 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 480 PetscCall(PetscQuadratureGetOrder(q, &order)); 481 if (maxOrder[dim] < 0) maxOrder[dim] = order; 482 PetscCheck(order == maxOrder[dim], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " cell quadrature order %" PetscInt_FMT " != %" PetscInt_FMT " DS cell quadrature order", f, order, maxOrder[dim]); 483 PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 484 if (fq) { 485 PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL)); 486 PetscCall(PetscQuadratureGetOrder(fq, &order)); 487 if (maxOrder[dim] < 0) maxOrder[dim] = order; 488 PetscCheck(order == maxOrder[dim], PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Field %" PetscInt_FMT " face quadrature order %" PetscInt_FMT " != %" PetscInt_FMT " DS face quadrature order", f, order, maxOrder[dim]); 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 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 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 PetscValidBoolPointer(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 of `f0` and `f1`: 1300 .vb 1301 void 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 of `f0` and `f1`: 1357 .vb 1358 void 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 of `f0` and `f1`: 1413 .vb 1414 void 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 of `g0`, `g1`, `g2` and `g3`: 1552 .vb 1553 void 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 of `g0`, `g1`, `g2` and `g3`: 1617 .vb 1618 void 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 of `g0`, `g1`, `g2` and `g3`: 1728 .vb 1729 void 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 of `g0`, `g1`, `g2` and `g3`: 1794 .vb 1795 void 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 of `g0`, `g1`, `g2` and `g3`: 1881 .vb 1882 void 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 of `g0`, `g1`, `g2` and `g3`: 1946 .vb 1947 void 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 of `r`: 2006 .vb 2007 void 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 of `r`: 2049 .vb 2050 void 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 of `update`: 2090 .vb 2091 void 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 of `update`: 2139 .vb 2140 void 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 of `f0` and `f1`: 2210 .vb 2211 void 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 of `f0` and `f1`: 2269 .vb 2270 void 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 of `g0`, `g1`, `g2` and `g3`: 2352 .vb 2353 void 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 of `g0`, `g1`, `g2` and `g3`: 2418 .vb 2419 void 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; No Fortran Support 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 of `g0`, `g1`, `g2` and `g3`: 2507 .vb 2508 void 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 .seealso: `PetscDS`, `PetscDSSetBdJacobianPreconditioner()` 2541 @*/ 2542 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[])) 2543 { 2544 PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3; 2545 PetscInt n0, n1, n2, n3; 2546 2547 PetscFunctionBegin; 2548 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2549 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); 2550 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); 2551 PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 2552 *g0 = tmp0 ? tmp0[0] : NULL; 2553 *g1 = tmp1 ? tmp1[0] : NULL; 2554 *g2 = tmp2 ? tmp2[0] : NULL; 2555 *g3 = tmp3 ? tmp3[0] : NULL; 2556 PetscFunctionReturn(PETSC_SUCCESS); 2557 } 2558 2559 /*@C 2560 PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field 2561 2562 Not Collective; No Fortran Support 2563 2564 Input Parameters: 2565 + ds - The `PetscDS` 2566 . f - The test field number 2567 . g - The field number 2568 . g0 - integrand for the test and basis function term 2569 . g1 - integrand for the test function and basis function gradient term 2570 . g2 - integrand for the test function gradient and basis function term 2571 - g3 - integrand for the test function gradient and basis function gradient term 2572 2573 Calling sequence of `g0`, `g1`, `g2` and `g3`: 2574 .vb 2575 void g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2576 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2577 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2578 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 2579 .ve 2580 + dim - the spatial dimension 2581 . Nf - the number of fields 2582 . NfAux - the number of auxiliary fields 2583 . uOff - the offset into u[] and u_t[] for each field 2584 . uOff_x - the offset into u_x[] for each field 2585 . u - each field evaluated at the current point 2586 . u_t - the time derivative of each field evaluated at the current point 2587 . u_x - the gradient of each field evaluated at the current point 2588 . aOff - the offset into a[] and a_t[] for each auxiliary field 2589 . aOff_x - the offset into a_x[] for each auxiliary field 2590 . a - each auxiliary field evaluated at the current point 2591 . a_t - the time derivative of each auxiliary field evaluated at the current point 2592 . a_x - the gradient of auxiliary each field evaluated at the current point 2593 . t - current time 2594 . u_tShift - the multiplier a for dF/dU_t 2595 . x - coordinates of the current point 2596 . n - normal at the current point 2597 . numConstants - number of constant parameters 2598 . constants - constant parameters 2599 - g0 - output values at the current point 2600 2601 Level: intermediate 2602 2603 Note: 2604 We are using a first order FEM model for the weak form: 2605 \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 2606 2607 .seealso: `PetscDS`, `PetscDSGetBdJacobianPreconditioner()` 2608 @*/ 2609 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[])) 2610 { 2611 PetscFunctionBegin; 2612 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2613 if (g0) PetscValidFunction(g0, 4); 2614 if (g1) PetscValidFunction(g1, 5); 2615 if (g2) PetscValidFunction(g2, 6); 2616 if (g3) PetscValidFunction(g3, 7); 2617 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2618 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 2619 PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 2620 PetscFunctionReturn(PETSC_SUCCESS); 2621 } 2622 2623 /*@C 2624 PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field 2625 2626 Not Collective 2627 2628 Input Parameters: 2629 + prob - The PetscDS 2630 - f - The test field number 2631 2632 Output Parameters: 2633 + exactSol - exact solution for the test field 2634 - exactCtx - exact solution context 2635 2636 Calling sequence of `exactSol`: 2637 .vb 2638 PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2639 .ve 2640 + dim - the spatial dimension 2641 . t - current time 2642 . x - coordinates of the current point 2643 . Nc - the number of field components 2644 . u - the solution field evaluated at the current point 2645 - ctx - a user context 2646 2647 Level: intermediate 2648 2649 .seealso: `PetscDS`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()` 2650 @*/ 2651 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2652 { 2653 PetscFunctionBegin; 2654 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2655 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); 2656 if (sol) { 2657 PetscValidPointer(sol, 3); 2658 *sol = prob->exactSol[f]; 2659 } 2660 if (ctx) { 2661 PetscValidPointer(ctx, 4); 2662 *ctx = prob->exactCtx[f]; 2663 } 2664 PetscFunctionReturn(PETSC_SUCCESS); 2665 } 2666 2667 /*@C 2668 PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field 2669 2670 Not Collective 2671 2672 Input Parameters: 2673 + prob - The `PetscDS` 2674 . f - The test field number 2675 . sol - solution function for the test fields 2676 - ctx - solution context or `NULL` 2677 2678 Calling sequence of `sol`: 2679 .vb 2680 PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2681 .ve 2682 + dim - the spatial dimension 2683 . t - current time 2684 . x - coordinates of the current point 2685 . Nc - the number of field components 2686 . u - the solution field evaluated at the current point 2687 - ctx - a user context 2688 2689 Level: intermediate 2690 2691 .seealso: `PetscDS`, `PetscDSGetExactSolution()` 2692 @*/ 2693 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2694 { 2695 PetscFunctionBegin; 2696 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2697 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2698 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2699 if (sol) { 2700 PetscValidFunction(sol, 3); 2701 prob->exactSol[f] = sol; 2702 } 2703 if (ctx) { 2704 PetscValidFunction(ctx, 4); 2705 prob->exactCtx[f] = ctx; 2706 } 2707 PetscFunctionReturn(PETSC_SUCCESS); 2708 } 2709 2710 /*@C 2711 PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field 2712 2713 Not Collective 2714 2715 Input Parameters: 2716 + prob - The `PetscDS` 2717 - f - The test field number 2718 2719 Output Parameters: 2720 + exactSol - time derivative of the exact solution for the test field 2721 - exactCtx - time derivative of the exact solution context 2722 2723 Calling sequence of `exactSol`: 2724 .vb 2725 PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2726 .ve 2727 + dim - the spatial dimension 2728 . t - current time 2729 . x - coordinates of the current point 2730 . Nc - the number of field components 2731 . u - the solution field evaluated at the current point 2732 - ctx - a user context 2733 2734 Level: intermediate 2735 2736 .seealso: `PetscDS`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()` 2737 @*/ 2738 PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2739 { 2740 PetscFunctionBegin; 2741 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2742 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); 2743 if (sol) { 2744 PetscValidPointer(sol, 3); 2745 *sol = prob->exactSol_t[f]; 2746 } 2747 if (ctx) { 2748 PetscValidPointer(ctx, 4); 2749 *ctx = prob->exactCtx_t[f]; 2750 } 2751 PetscFunctionReturn(PETSC_SUCCESS); 2752 } 2753 2754 /*@C 2755 PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field 2756 2757 Not Collective 2758 2759 Input Parameters: 2760 + prob - The `PetscDS` 2761 . f - The test field number 2762 . sol - time derivative of the solution function for the test fields 2763 - ctx - time derivative of the solution context or `NULL` 2764 2765 Calling sequence of `sol`: 2766 .vb 2767 PetscErrorCode sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2768 .ve 2769 + dim - the spatial dimension 2770 . t - current time 2771 . x - coordinates of the current point 2772 . Nc - the number of field components 2773 . u - the solution field evaluated at the current point 2774 - ctx - a user context 2775 2776 Level: intermediate 2777 2778 .seealso: `PetscDS`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()` 2779 @*/ 2780 PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2781 { 2782 PetscFunctionBegin; 2783 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2784 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2785 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2786 if (sol) { 2787 PetscValidFunction(sol, 3); 2788 prob->exactSol_t[f] = sol; 2789 } 2790 if (ctx) { 2791 PetscValidFunction(ctx, 4); 2792 prob->exactCtx_t[f] = ctx; 2793 } 2794 PetscFunctionReturn(PETSC_SUCCESS); 2795 } 2796 2797 /*@C 2798 PetscDSGetConstants - Returns the array of constants passed to point functions 2799 2800 Not Collective 2801 2802 Input Parameter: 2803 . prob - The `PetscDS` object 2804 2805 Output Parameters: 2806 + numConstants - The number of constants 2807 - constants - The array of constants, NULL if there are none 2808 2809 Level: intermediate 2810 2811 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()` 2812 @*/ 2813 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[]) 2814 { 2815 PetscFunctionBegin; 2816 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2817 if (numConstants) { 2818 PetscValidIntPointer(numConstants, 2); 2819 *numConstants = prob->numConstants; 2820 } 2821 if (constants) { 2822 PetscValidPointer(constants, 3); 2823 *constants = prob->constants; 2824 } 2825 PetscFunctionReturn(PETSC_SUCCESS); 2826 } 2827 2828 /*@C 2829 PetscDSSetConstants - Set the array of constants passed to point functions 2830 2831 Not Collective 2832 2833 Input Parameters: 2834 + prob - The `PetscDS` object 2835 . numConstants - The number of constants 2836 - constants - The array of constants, NULL if there are none 2837 2838 Level: intermediate 2839 2840 .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()` 2841 @*/ 2842 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[]) 2843 { 2844 PetscFunctionBegin; 2845 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2846 if (numConstants != prob->numConstants) { 2847 PetscCall(PetscFree(prob->constants)); 2848 prob->numConstants = numConstants; 2849 if (prob->numConstants) { 2850 PetscCall(PetscMalloc1(prob->numConstants, &prob->constants)); 2851 } else { 2852 prob->constants = NULL; 2853 } 2854 } 2855 if (prob->numConstants) { 2856 PetscValidScalarPointer(constants, 3); 2857 PetscCall(PetscArraycpy(prob->constants, constants, prob->numConstants)); 2858 } 2859 PetscFunctionReturn(PETSC_SUCCESS); 2860 } 2861 2862 /*@ 2863 PetscDSGetFieldIndex - Returns the index of the given field 2864 2865 Not Collective 2866 2867 Input Parameters: 2868 + prob - The `PetscDS` object 2869 - disc - The discretization object 2870 2871 Output Parameter: 2872 . f - The field number 2873 2874 Level: beginner 2875 2876 .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2877 @*/ 2878 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2879 { 2880 PetscInt g; 2881 2882 PetscFunctionBegin; 2883 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2884 PetscValidIntPointer(f, 3); 2885 *f = -1; 2886 for (g = 0; g < prob->Nf; ++g) { 2887 if (disc == prob->disc[g]) break; 2888 } 2889 PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2890 *f = g; 2891 PetscFunctionReturn(PETSC_SUCCESS); 2892 } 2893 2894 /*@ 2895 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2896 2897 Not Collective 2898 2899 Input Parameters: 2900 + prob - The `PetscDS` object 2901 - f - The field number 2902 2903 Output Parameter: 2904 . size - The size 2905 2906 Level: beginner 2907 2908 .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2909 @*/ 2910 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2911 { 2912 PetscFunctionBegin; 2913 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2914 PetscValidIntPointer(size, 3); 2915 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); 2916 PetscCall(PetscDSSetUp(prob)); 2917 *size = prob->Nb[f]; 2918 PetscFunctionReturn(PETSC_SUCCESS); 2919 } 2920 2921 /*@ 2922 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2923 2924 Not Collective 2925 2926 Input Parameters: 2927 + prob - The `PetscDS` object 2928 - f - The field number 2929 2930 Output Parameter: 2931 . off - The offset 2932 2933 Level: beginner 2934 2935 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2936 @*/ 2937 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2938 { 2939 PetscInt size, g; 2940 2941 PetscFunctionBegin; 2942 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2943 PetscValidIntPointer(off, 3); 2944 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); 2945 *off = 0; 2946 for (g = 0; g < f; ++g) { 2947 PetscCall(PetscDSGetFieldSize(prob, g, &size)); 2948 *off += size; 2949 } 2950 PetscFunctionReturn(PETSC_SUCCESS); 2951 } 2952 2953 /*@ 2954 PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell 2955 2956 Not Collective 2957 2958 Input Parameters: 2959 + prob - The `PetscDS` object 2960 - f - The field number 2961 2962 Output Parameter: 2963 . off - The offset 2964 2965 Level: beginner 2966 2967 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2968 @*/ 2969 PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off) 2970 { 2971 PetscInt size, g; 2972 2973 PetscFunctionBegin; 2974 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2975 PetscValidIntPointer(off, 3); 2976 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); 2977 *off = 0; 2978 for (g = 0; g < f; ++g) { 2979 PetscBool cohesive; 2980 2981 PetscCall(PetscDSGetCohesive(ds, g, &cohesive)); 2982 PetscCall(PetscDSGetFieldSize(ds, g, &size)); 2983 *off += cohesive ? size : size * 2; 2984 } 2985 PetscFunctionReturn(PETSC_SUCCESS); 2986 } 2987 2988 /*@ 2989 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 2990 2991 Not Collective 2992 2993 Input Parameter: 2994 . prob - The `PetscDS` object 2995 2996 Output Parameter: 2997 . dimensions - The number of dimensions 2998 2999 Level: beginner 3000 3001 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3002 @*/ 3003 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 3004 { 3005 PetscFunctionBegin; 3006 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3007 PetscCall(PetscDSSetUp(prob)); 3008 PetscValidPointer(dimensions, 2); 3009 *dimensions = prob->Nb; 3010 PetscFunctionReturn(PETSC_SUCCESS); 3011 } 3012 3013 /*@ 3014 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 3015 3016 Not Collective 3017 3018 Input Parameter: 3019 . prob - The `PetscDS` object 3020 3021 Output Parameter: 3022 . components - The number of components 3023 3024 Level: beginner 3025 3026 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3027 @*/ 3028 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 3029 { 3030 PetscFunctionBegin; 3031 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3032 PetscCall(PetscDSSetUp(prob)); 3033 PetscValidPointer(components, 2); 3034 *components = prob->Nc; 3035 PetscFunctionReturn(PETSC_SUCCESS); 3036 } 3037 3038 /*@ 3039 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 3040 3041 Not Collective 3042 3043 Input Parameters: 3044 + prob - The `PetscDS` object 3045 - f - The field number 3046 3047 Output Parameter: 3048 . off - The offset 3049 3050 Level: beginner 3051 3052 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3053 @*/ 3054 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 3055 { 3056 PetscFunctionBegin; 3057 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3058 PetscValidIntPointer(off, 3); 3059 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); 3060 PetscCall(PetscDSSetUp(prob)); 3061 *off = prob->off[f]; 3062 PetscFunctionReturn(PETSC_SUCCESS); 3063 } 3064 3065 /*@ 3066 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 3067 3068 Not Collective 3069 3070 Input Parameter: 3071 . prob - The `PetscDS` object 3072 3073 Output Parameter: 3074 . offsets - The offsets 3075 3076 Level: beginner 3077 3078 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3079 @*/ 3080 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 3081 { 3082 PetscFunctionBegin; 3083 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3084 PetscValidPointer(offsets, 2); 3085 PetscCall(PetscDSSetUp(prob)); 3086 *offsets = prob->off; 3087 PetscFunctionReturn(PETSC_SUCCESS); 3088 } 3089 3090 /*@ 3091 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 3092 3093 Not Collective 3094 3095 Input Parameter: 3096 . prob - The `PetscDS` object 3097 3098 Output Parameter: 3099 . offsets - The offsets 3100 3101 Level: beginner 3102 3103 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3104 @*/ 3105 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 3106 { 3107 PetscFunctionBegin; 3108 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3109 PetscValidPointer(offsets, 2); 3110 PetscCall(PetscDSSetUp(prob)); 3111 *offsets = prob->offDer; 3112 PetscFunctionReturn(PETSC_SUCCESS); 3113 } 3114 3115 /*@ 3116 PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point 3117 3118 Not Collective 3119 3120 Input Parameters: 3121 + ds - The `PetscDS` object 3122 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3123 3124 Output Parameter: 3125 . offsets - The offsets 3126 3127 Level: beginner 3128 3129 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3130 @*/ 3131 PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3132 { 3133 PetscFunctionBegin; 3134 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3135 PetscValidPointer(offsets, 3); 3136 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3137 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3138 PetscCall(PetscDSSetUp(ds)); 3139 *offsets = ds->offCohesive[s]; 3140 PetscFunctionReturn(PETSC_SUCCESS); 3141 } 3142 3143 /*@ 3144 PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point 3145 3146 Not Collective 3147 3148 Input Parameters: 3149 + ds - The `PetscDS` object 3150 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3151 3152 Output Parameter: 3153 . offsets - The offsets 3154 3155 Level: beginner 3156 3157 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3158 @*/ 3159 PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3160 { 3161 PetscFunctionBegin; 3162 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3163 PetscValidPointer(offsets, 3); 3164 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3165 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3166 PetscCall(PetscDSSetUp(ds)); 3167 *offsets = ds->offDerCohesive[s]; 3168 PetscFunctionReturn(PETSC_SUCCESS); 3169 } 3170 3171 /*@C 3172 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 3173 3174 Not Collective 3175 3176 Input Parameter: 3177 . prob - The `PetscDS` object 3178 3179 Output Parameter: 3180 . T - The basis function and derivatives tabulation at quadrature points for each field 3181 3182 Level: intermediate 3183 3184 .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()` 3185 @*/ 3186 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) 3187 { 3188 PetscFunctionBegin; 3189 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3190 PetscValidPointer(T, 2); 3191 PetscCall(PetscDSSetUp(prob)); 3192 *T = prob->T; 3193 PetscFunctionReturn(PETSC_SUCCESS); 3194 } 3195 3196 /*@C 3197 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 3198 3199 Not Collective 3200 3201 Input Parameter: 3202 . prob - The `PetscDS` object 3203 3204 Output Parameter: 3205 . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field 3206 3207 Level: intermediate 3208 3209 .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()` 3210 @*/ 3211 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 3212 { 3213 PetscFunctionBegin; 3214 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3215 PetscValidPointer(Tf, 2); 3216 PetscCall(PetscDSSetUp(prob)); 3217 *Tf = prob->Tf; 3218 PetscFunctionReturn(PETSC_SUCCESS); 3219 } 3220 3221 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x) 3222 { 3223 PetscFunctionBegin; 3224 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3225 PetscCall(PetscDSSetUp(prob)); 3226 if (u) { 3227 PetscValidPointer(u, 2); 3228 *u = prob->u; 3229 } 3230 if (u_t) { 3231 PetscValidPointer(u_t, 3); 3232 *u_t = prob->u_t; 3233 } 3234 if (u_x) { 3235 PetscValidPointer(u_x, 4); 3236 *u_x = prob->u_x; 3237 } 3238 PetscFunctionReturn(PETSC_SUCCESS); 3239 } 3240 3241 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3) 3242 { 3243 PetscFunctionBegin; 3244 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3245 PetscCall(PetscDSSetUp(prob)); 3246 if (f0) { 3247 PetscValidPointer(f0, 2); 3248 *f0 = prob->f0; 3249 } 3250 if (f1) { 3251 PetscValidPointer(f1, 3); 3252 *f1 = prob->f1; 3253 } 3254 if (g0) { 3255 PetscValidPointer(g0, 4); 3256 *g0 = prob->g0; 3257 } 3258 if (g1) { 3259 PetscValidPointer(g1, 5); 3260 *g1 = prob->g1; 3261 } 3262 if (g2) { 3263 PetscValidPointer(g2, 6); 3264 *g2 = prob->g2; 3265 } 3266 if (g3) { 3267 PetscValidPointer(g3, 7); 3268 *g3 = prob->g3; 3269 } 3270 PetscFunctionReturn(PETSC_SUCCESS); 3271 } 3272 3273 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 3274 { 3275 PetscFunctionBegin; 3276 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3277 PetscCall(PetscDSSetUp(prob)); 3278 if (x) { 3279 PetscValidPointer(x, 2); 3280 *x = prob->x; 3281 } 3282 if (basisReal) { 3283 PetscValidPointer(basisReal, 3); 3284 *basisReal = prob->basisReal; 3285 } 3286 if (basisDerReal) { 3287 PetscValidPointer(basisDerReal, 4); 3288 *basisDerReal = prob->basisDerReal; 3289 } 3290 if (testReal) { 3291 PetscValidPointer(testReal, 5); 3292 *testReal = prob->testReal; 3293 } 3294 if (testDerReal) { 3295 PetscValidPointer(testDerReal, 6); 3296 *testDerReal = prob->testDerReal; 3297 } 3298 PetscFunctionReturn(PETSC_SUCCESS); 3299 } 3300 3301 /*@C 3302 PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3303 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 3304 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3305 3306 Collective 3307 3308 Input Parameters: 3309 + ds - The PetscDS object 3310 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3311 . name - The BC name 3312 . label - The label defining constrained points 3313 . Nv - The number of `DMLabel` values for constrained points 3314 . values - An array of label values for constrained points 3315 . field - The field to constrain 3316 . Nc - The number of constrained field components (0 will constrain all fields) 3317 . comps - An array of constrained component numbers 3318 . bcFunc - A pointwise function giving boundary values 3319 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3320 - ctx - An optional user context for bcFunc 3321 3322 Output Parameters: 3323 - bd - The boundary number 3324 3325 Options Database Keys: 3326 + -bc_<boundary name> <num> - Overrides the boundary ids 3327 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3328 3329 Level: developer 3330 3331 Note: 3332 Both `bcFunc` and `bcFunc_t` will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, Then the calling sequence is: 3333 3334 $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3335 3336 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is: 3337 .vb 3338 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3339 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3340 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3341 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3342 .ve 3343 + dim - the spatial dimension 3344 . Nf - the number of fields 3345 . uOff - the offset into u[] and u_t[] for each field 3346 . uOff_x - the offset into u_x[] for each field 3347 . u - each field evaluated at the current point 3348 . u_t - the time derivative of each field evaluated at the current point 3349 . u_x - the gradient of each field evaluated at the current point 3350 . aOff - the offset into a[] and a_t[] for each auxiliary field 3351 . aOff_x - the offset into a_x[] for each auxiliary field 3352 . a - each auxiliary field evaluated at the current point 3353 . a_t - the time derivative of each auxiliary field evaluated at the current point 3354 . a_x - the gradient of auxiliary each field evaluated at the current point 3355 . t - current time 3356 . x - coordinates of the current point 3357 . numConstants - number of constant parameters 3358 . constants - constant parameters 3359 - bcval - output values at the current point 3360 3361 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3362 @*/ 3363 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) 3364 { 3365 DSBoundary head = ds->boundary, b; 3366 PetscInt n = 0; 3367 const char *lname; 3368 3369 PetscFunctionBegin; 3370 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3371 PetscValidLogicalCollectiveEnum(ds, type, 2); 3372 PetscValidCharPointer(name, 3); 3373 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 3374 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3375 PetscValidLogicalCollectiveInt(ds, field, 7); 3376 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3377 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); 3378 if (Nc > 0) { 3379 PetscInt *fcomps; 3380 PetscInt c; 3381 3382 PetscCall(PetscDSGetComponents(ds, &fcomps)); 3383 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); 3384 for (c = 0; c < Nc; ++c) { 3385 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); 3386 } 3387 } 3388 PetscCall(PetscNew(&b)); 3389 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3390 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3391 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3392 PetscCall(PetscMalloc1(Nv, &b->values)); 3393 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3394 PetscCall(PetscMalloc1(Nc, &b->comps)); 3395 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3396 PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 3397 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3398 b->type = type; 3399 b->label = label; 3400 b->Nv = Nv; 3401 b->field = field; 3402 b->Nc = Nc; 3403 b->func = bcFunc; 3404 b->func_t = bcFunc_t; 3405 b->ctx = ctx; 3406 b->next = NULL; 3407 /* Append to linked list so that we can preserve the order */ 3408 if (!head) ds->boundary = b; 3409 while (head) { 3410 if (!head->next) { 3411 head->next = b; 3412 head = b; 3413 } 3414 head = head->next; 3415 ++n; 3416 } 3417 if (bd) { 3418 PetscValidIntPointer(bd, 13); 3419 *bd = n; 3420 } 3421 PetscFunctionReturn(PETSC_SUCCESS); 3422 } 3423 3424 /*@C 3425 PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3426 In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that 3427 boundary integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3428 3429 Collective 3430 3431 Input Parameters: 3432 + ds - The `PetscDS` object 3433 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3434 . name - The BC name 3435 . lname - The naem of the label defining constrained points 3436 . Nv - The number of `DMLabel` values for constrained points 3437 . values - An array of label values for constrained points 3438 . field - The field to constrain 3439 . Nc - The number of constrained field components (0 will constrain all fields) 3440 . comps - An array of constrained component numbers 3441 . bcFunc - A pointwise function giving boundary values 3442 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3443 - ctx - An optional user context for bcFunc 3444 3445 Output Parameters: 3446 - bd - The boundary number 3447 3448 Options Database Keys: 3449 + -bc_<boundary name> <num> - Overrides the boundary ids 3450 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3451 3452 Calling Sequence of `bcFunc` and `bcFunc_t`: 3453 If the type is `DM_BC_ESSENTIAL` 3454 .vb 3455 void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3456 .ve 3457 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, 3458 .vb 3459 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3460 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3461 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3462 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3463 .ve 3464 + dim - the spatial dimension 3465 . Nf - the number of fields 3466 . uOff - the offset into u[] and u_t[] for each field 3467 . uOff_x - the offset into u_x[] for each field 3468 . u - each field evaluated at the current point 3469 . u_t - the time derivative of each field evaluated at the current point 3470 . u_x - the gradient of each field evaluated at the current point 3471 . aOff - the offset into a[] and a_t[] for each auxiliary field 3472 . aOff_x - the offset into a_x[] for each auxiliary field 3473 . a - each auxiliary field evaluated at the current point 3474 . a_t - the time derivative of each auxiliary field evaluated at the current point 3475 . a_x - the gradient of auxiliary each field evaluated at the current point 3476 . t - current time 3477 . x - coordinates of the current point 3478 . numConstants - number of constant parameters 3479 . constants - constant parameters 3480 - bcval - output values at the current point 3481 3482 Level: developer 3483 3484 Note: 3485 This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built. 3486 3487 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3488 @*/ 3489 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) 3490 { 3491 DSBoundary head = ds->boundary, b; 3492 PetscInt n = 0; 3493 3494 PetscFunctionBegin; 3495 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3496 PetscValidLogicalCollectiveEnum(ds, type, 2); 3497 PetscValidCharPointer(name, 3); 3498 PetscValidCharPointer(lname, 4); 3499 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3500 PetscValidLogicalCollectiveInt(ds, field, 7); 3501 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3502 PetscCall(PetscNew(&b)); 3503 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3504 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3505 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3506 PetscCall(PetscMalloc1(Nv, &b->values)); 3507 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3508 PetscCall(PetscMalloc1(Nc, &b->comps)); 3509 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3510 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3511 b->type = type; 3512 b->label = NULL; 3513 b->Nv = Nv; 3514 b->field = field; 3515 b->Nc = Nc; 3516 b->func = bcFunc; 3517 b->func_t = bcFunc_t; 3518 b->ctx = ctx; 3519 b->next = NULL; 3520 /* Append to linked list so that we can preserve the order */ 3521 if (!head) ds->boundary = b; 3522 while (head) { 3523 if (!head->next) { 3524 head->next = b; 3525 head = b; 3526 } 3527 head = head->next; 3528 ++n; 3529 } 3530 if (bd) { 3531 PetscValidIntPointer(bd, 13); 3532 *bd = n; 3533 } 3534 PetscFunctionReturn(PETSC_SUCCESS); 3535 } 3536 3537 /*@C 3538 PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3539 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 3540 should be performed, using the kernels from `PetscDSSetBdResidual()`. 3541 3542 Input Parameters: 3543 + ds - The `PetscDS` object 3544 . bd - The boundary condition number 3545 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3546 . name - The BC name 3547 . label - The label defining constrained points 3548 . Nv - The number of `DMLabel` ids for constrained points 3549 . values - An array of ids for constrained points 3550 . field - The field to constrain 3551 . Nc - The number of constrained field components 3552 . comps - An array of constrained component numbers 3553 . bcFunc - A pointwise function giving boundary values 3554 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3555 - ctx - An optional user context for bcFunc 3556 3557 Level: developer 3558 3559 Note: 3560 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`. 3561 See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks. 3562 3563 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel` 3564 @*/ 3565 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) 3566 { 3567 DSBoundary b = ds->boundary; 3568 PetscInt n = 0; 3569 3570 PetscFunctionBegin; 3571 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3572 while (b) { 3573 if (n == bd) break; 3574 b = b->next; 3575 ++n; 3576 } 3577 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3578 if (name) { 3579 PetscCall(PetscFree(b->name)); 3580 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3581 } 3582 b->type = type; 3583 if (label) { 3584 const char *name; 3585 3586 b->label = label; 3587 PetscCall(PetscFree(b->lname)); 3588 PetscCall(PetscObjectGetName((PetscObject)label, &name)); 3589 PetscCall(PetscStrallocpy(name, (char **)&b->lname)); 3590 } 3591 if (Nv >= 0) { 3592 b->Nv = Nv; 3593 PetscCall(PetscFree(b->values)); 3594 PetscCall(PetscMalloc1(Nv, &b->values)); 3595 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3596 } 3597 if (field >= 0) b->field = field; 3598 if (Nc >= 0) { 3599 b->Nc = Nc; 3600 PetscCall(PetscFree(b->comps)); 3601 PetscCall(PetscMalloc1(Nc, &b->comps)); 3602 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3603 } 3604 if (bcFunc) b->func = bcFunc; 3605 if (bcFunc_t) b->func_t = bcFunc_t; 3606 if (ctx) b->ctx = ctx; 3607 PetscFunctionReturn(PETSC_SUCCESS); 3608 } 3609 3610 /*@ 3611 PetscDSGetNumBoundary - Get the number of registered BC 3612 3613 Input Parameters: 3614 . ds - The `PetscDS` object 3615 3616 Output Parameters: 3617 . numBd - The number of BC 3618 3619 Level: intermediate 3620 3621 .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()` 3622 @*/ 3623 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3624 { 3625 DSBoundary b = ds->boundary; 3626 3627 PetscFunctionBegin; 3628 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3629 PetscValidIntPointer(numBd, 2); 3630 *numBd = 0; 3631 while (b) { 3632 ++(*numBd); 3633 b = b->next; 3634 } 3635 PetscFunctionReturn(PETSC_SUCCESS); 3636 } 3637 3638 /*@C 3639 PetscDSGetBoundary - Gets a boundary condition to the model 3640 3641 Input Parameters: 3642 + ds - The `PetscDS` object 3643 - bd - The BC number 3644 3645 Output Parameters: 3646 + wf - The `PetscWeakForm` holding the pointwise functions 3647 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3648 . name - The BC name 3649 . label - The label defining constrained points 3650 . Nv - The number of `DMLabel` ids for constrained points 3651 . values - An array of ids for constrained points 3652 . field - The field to constrain 3653 . Nc - The number of constrained field components 3654 . comps - An array of constrained component numbers 3655 . bcFunc - A pointwise function giving boundary values 3656 . bcFunc_t - A pointwise function giving the time derivative of the boundary values 3657 - ctx - An optional user context for bcFunc 3658 3659 Options Database Keys: 3660 + -bc_<boundary name> <num> - Overrides the boundary ids 3661 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3662 3663 Level: developer 3664 3665 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel` 3666 @*/ 3667 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) 3668 { 3669 DSBoundary b = ds->boundary; 3670 PetscInt n = 0; 3671 3672 PetscFunctionBegin; 3673 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3674 while (b) { 3675 if (n == bd) break; 3676 b = b->next; 3677 ++n; 3678 } 3679 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3680 if (wf) { 3681 PetscValidPointer(wf, 3); 3682 *wf = b->wf; 3683 } 3684 if (type) { 3685 PetscValidPointer(type, 4); 3686 *type = b->type; 3687 } 3688 if (name) { 3689 PetscValidPointer(name, 5); 3690 *name = b->name; 3691 } 3692 if (label) { 3693 PetscValidPointer(label, 6); 3694 *label = b->label; 3695 } 3696 if (Nv) { 3697 PetscValidIntPointer(Nv, 7); 3698 *Nv = b->Nv; 3699 } 3700 if (values) { 3701 PetscValidPointer(values, 8); 3702 *values = b->values; 3703 } 3704 if (field) { 3705 PetscValidIntPointer(field, 9); 3706 *field = b->field; 3707 } 3708 if (Nc) { 3709 PetscValidIntPointer(Nc, 10); 3710 *Nc = b->Nc; 3711 } 3712 if (comps) { 3713 PetscValidPointer(comps, 11); 3714 *comps = b->comps; 3715 } 3716 if (func) { 3717 PetscValidPointer(func, 12); 3718 *func = b->func; 3719 } 3720 if (func_t) { 3721 PetscValidPointer(func_t, 13); 3722 *func_t = b->func_t; 3723 } 3724 if (ctx) { 3725 PetscValidPointer(ctx, 14); 3726 *ctx = b->ctx; 3727 } 3728 PetscFunctionReturn(PETSC_SUCCESS); 3729 } 3730 3731 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3732 { 3733 PetscFunctionBegin; 3734 PetscCall(PetscNew(bNew)); 3735 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf)); 3736 PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf)); 3737 PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name))); 3738 PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname))); 3739 (*bNew)->type = b->type; 3740 (*bNew)->label = b->label; 3741 (*bNew)->Nv = b->Nv; 3742 PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values)); 3743 PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv)); 3744 (*bNew)->field = b->field; 3745 (*bNew)->Nc = b->Nc; 3746 PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps)); 3747 PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc)); 3748 (*bNew)->func = b->func; 3749 (*bNew)->func_t = b->func_t; 3750 (*bNew)->ctx = b->ctx; 3751 PetscFunctionReturn(PETSC_SUCCESS); 3752 } 3753 3754 /*@ 3755 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 3756 3757 Not Collective 3758 3759 Input Parameters: 3760 + ds - The source `PetscDS` object 3761 . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields 3762 - fields - The selected fields, or NULL for all fields 3763 3764 Output Parameter: 3765 . newds - The target `PetscDS`, now with a copy of the boundary conditions 3766 3767 Level: intermediate 3768 3769 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3770 @*/ 3771 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3772 { 3773 DSBoundary b, *lastnext; 3774 3775 PetscFunctionBegin; 3776 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3777 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3778 if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS); 3779 PetscCall(PetscDSDestroyBoundary(newds)); 3780 lastnext = &(newds->boundary); 3781 for (b = ds->boundary; b; b = b->next) { 3782 DSBoundary bNew; 3783 PetscInt fieldNew = -1; 3784 3785 if (numFields > 0 && fields) { 3786 PetscInt f; 3787 3788 for (f = 0; f < numFields; ++f) 3789 if (b->field == fields[f]) break; 3790 if (f == numFields) continue; 3791 fieldNew = f; 3792 } 3793 PetscCall(DSBoundaryDuplicate_Internal(b, &bNew)); 3794 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3795 *lastnext = bNew; 3796 lastnext = &(bNew->next); 3797 } 3798 PetscFunctionReturn(PETSC_SUCCESS); 3799 } 3800 3801 /*@ 3802 PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS` 3803 3804 Not Collective 3805 3806 Input Parameter: 3807 . ds - The `PetscDS` object 3808 3809 Level: intermediate 3810 3811 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()` 3812 @*/ 3813 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3814 { 3815 DSBoundary next = ds->boundary; 3816 3817 PetscFunctionBegin; 3818 while (next) { 3819 DSBoundary b = next; 3820 3821 next = b->next; 3822 PetscCall(PetscWeakFormDestroy(&b->wf)); 3823 PetscCall(PetscFree(b->name)); 3824 PetscCall(PetscFree(b->lname)); 3825 PetscCall(PetscFree(b->values)); 3826 PetscCall(PetscFree(b->comps)); 3827 PetscCall(PetscFree(b)); 3828 } 3829 PetscFunctionReturn(PETSC_SUCCESS); 3830 } 3831 3832 /*@ 3833 PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout 3834 3835 Not Collective 3836 3837 Input Parameters: 3838 + prob - The `PetscDS` object 3839 . numFields - Number of new fields 3840 - fields - Old field number for each new field 3841 3842 Output Parameter: 3843 . newprob - The `PetscDS` copy 3844 3845 Level: intermediate 3846 3847 .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3848 @*/ 3849 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3850 { 3851 PetscInt Nf, Nfn, fn; 3852 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3855 if (fields) PetscValidIntPointer(fields, 3); 3856 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3857 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3858 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3859 numFields = numFields < 0 ? Nf : numFields; 3860 for (fn = 0; fn < numFields; ++fn) { 3861 const PetscInt f = fields ? fields[fn] : fn; 3862 PetscObject disc; 3863 3864 if (f >= Nf) continue; 3865 PetscCall(PetscDSGetDiscretization(prob, f, &disc)); 3866 PetscCall(PetscDSSetDiscretization(newprob, fn, disc)); 3867 } 3868 PetscFunctionReturn(PETSC_SUCCESS); 3869 } 3870 3871 /*@ 3872 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 3873 3874 Not Collective 3875 3876 Input Parameters: 3877 + prob - The `PetscDS` object 3878 . numFields - Number of new fields 3879 - fields - Old field number for each new field 3880 3881 Output Parameter: 3882 . newprob - The `PetscDS` copy 3883 3884 Level: intermediate 3885 3886 .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3887 @*/ 3888 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3889 { 3890 PetscInt Nf, Nfn, fn, gn; 3891 3892 PetscFunctionBegin; 3893 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3894 if (fields) PetscValidIntPointer(fields, 3); 3895 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3896 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3897 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3898 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); 3899 for (fn = 0; fn < numFields; ++fn) { 3900 const PetscInt f = fields ? fields[fn] : fn; 3901 PetscPointFunc obj; 3902 PetscPointFunc f0, f1; 3903 PetscBdPointFunc f0Bd, f1Bd; 3904 PetscRiemannFunc r; 3905 3906 if (f >= Nf) continue; 3907 PetscCall(PetscDSGetObjective(prob, f, &obj)); 3908 PetscCall(PetscDSGetResidual(prob, f, &f0, &f1)); 3909 PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd)); 3910 PetscCall(PetscDSGetRiemannSolver(prob, f, &r)); 3911 PetscCall(PetscDSSetObjective(newprob, fn, obj)); 3912 PetscCall(PetscDSSetResidual(newprob, fn, f0, f1)); 3913 PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd)); 3914 PetscCall(PetscDSSetRiemannSolver(newprob, fn, r)); 3915 for (gn = 0; gn < numFields; ++gn) { 3916 const PetscInt g = fields ? fields[gn] : gn; 3917 PetscPointJac g0, g1, g2, g3; 3918 PetscPointJac g0p, g1p, g2p, g3p; 3919 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3920 3921 if (g >= Nf) continue; 3922 PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3)); 3923 PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p)); 3924 PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd)); 3925 PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3)); 3926 PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p)); 3927 PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd)); 3928 } 3929 } 3930 PetscFunctionReturn(PETSC_SUCCESS); 3931 } 3932 3933 /*@ 3934 PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS` 3935 3936 Not Collective 3937 3938 Input Parameter: 3939 . prob - The `PetscDS` object 3940 3941 Output Parameter: 3942 . newprob - The `PetscDS` copy 3943 3944 Level: intermediate 3945 3946 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3947 @*/ 3948 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3949 { 3950 PetscWeakForm wf, newwf; 3951 PetscInt Nf, Ng; 3952 3953 PetscFunctionBegin; 3954 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3955 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3956 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3957 PetscCall(PetscDSGetNumFields(newprob, &Ng)); 3958 PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng); 3959 PetscCall(PetscDSGetWeakForm(prob, &wf)); 3960 PetscCall(PetscDSGetWeakForm(newprob, &newwf)); 3961 PetscCall(PetscWeakFormCopy(wf, newwf)); 3962 PetscFunctionReturn(PETSC_SUCCESS); 3963 } 3964 3965 /*@ 3966 PetscDSCopyConstants - Copy all constants to another `PetscDS` 3967 3968 Not Collective 3969 3970 Input Parameter: 3971 . prob - The `PetscDS` object 3972 3973 Output Parameter: 3974 . newprob - The `PetscDS` copy 3975 3976 Level: intermediate 3977 3978 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3979 @*/ 3980 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3981 { 3982 PetscInt Nc; 3983 const PetscScalar *constants; 3984 3985 PetscFunctionBegin; 3986 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3987 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3988 PetscCall(PetscDSGetConstants(prob, &Nc, &constants)); 3989 PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants)); 3990 PetscFunctionReturn(PETSC_SUCCESS); 3991 } 3992 3993 /*@ 3994 PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS` 3995 3996 Not Collective 3997 3998 Input Parameter: 3999 . ds - The `PetscDS` object 4000 4001 Output Parameter: 4002 . newds - The `PetscDS` copy 4003 4004 Level: intermediate 4005 4006 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 4007 @*/ 4008 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 4009 { 4010 PetscSimplePointFunc sol; 4011 void *ctx; 4012 PetscInt Nf, f; 4013 4014 PetscFunctionBegin; 4015 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4016 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 4017 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4018 for (f = 0; f < Nf; ++f) { 4019 PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx)); 4020 PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx)); 4021 PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx)); 4022 PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx)); 4023 } 4024 PetscFunctionReturn(PETSC_SUCCESS); 4025 } 4026 4027 PetscErrorCode PetscDSCopy(PetscDS ds, DM dmNew, PetscDS dsNew) 4028 { 4029 DSBoundary b; 4030 PetscInt cdim, Nf, f, d; 4031 PetscBool isCohesive; 4032 void *ctx; 4033 4034 PetscFunctionBegin; 4035 PetscCall(PetscDSCopyConstants(ds, dsNew)); 4036 PetscCall(PetscDSCopyExactSolutions(ds, dsNew)); 4037 PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew)); 4038 PetscCall(PetscDSCopyEquations(ds, dsNew)); 4039 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4040 for (f = 0; f < Nf; ++f) { 4041 PetscCall(PetscDSGetContext(ds, f, &ctx)); 4042 PetscCall(PetscDSSetContext(dsNew, f, ctx)); 4043 PetscCall(PetscDSGetCohesive(ds, f, &isCohesive)); 4044 PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive)); 4045 PetscCall(PetscDSGetJetDegree(ds, f, &d)); 4046 PetscCall(PetscDSSetJetDegree(dsNew, f, d)); 4047 } 4048 if (Nf) { 4049 PetscCall(PetscDSGetCoordinateDimension(ds, &cdim)); 4050 PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim)); 4051 } 4052 PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew)); 4053 for (b = dsNew->boundary; b; b = b->next) { 4054 PetscCall(DMGetLabel(dmNew, b->lname, &b->label)); 4055 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 4056 //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 4057 } 4058 PetscFunctionReturn(PETSC_SUCCESS); 4059 } 4060 4061 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 4062 { 4063 PetscInt dim, Nf, f; 4064 4065 PetscFunctionBegin; 4066 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 4067 PetscValidPointer(subprob, 3); 4068 if (height == 0) { 4069 *subprob = prob; 4070 PetscFunctionReturn(PETSC_SUCCESS); 4071 } 4072 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4073 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 4074 PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height); 4075 if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs)); 4076 if (!prob->subprobs[height - 1]) { 4077 PetscInt cdim; 4078 4079 PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1])); 4080 PetscCall(PetscDSGetCoordinateDimension(prob, &cdim)); 4081 PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim)); 4082 for (f = 0; f < Nf; ++f) { 4083 PetscFE subfe; 4084 PetscObject obj; 4085 PetscClassId id; 4086 4087 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 4088 PetscCall(PetscObjectGetClassId(obj, &id)); 4089 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe)); 4090 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f); 4091 PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe)); 4092 } 4093 } 4094 *subprob = prob->subprobs[height - 1]; 4095 PetscFunctionReturn(PETSC_SUCCESS); 4096 } 4097 4098 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 4099 { 4100 PetscObject obj; 4101 PetscClassId id; 4102 PetscInt Nf; 4103 4104 PetscFunctionBegin; 4105 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4106 PetscValidPointer(disctype, 3); 4107 *disctype = PETSC_DISC_NONE; 4108 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4109 PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf); 4110 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 4111 if (obj) { 4112 PetscCall(PetscObjectGetClassId(obj, &id)); 4113 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 4114 else *disctype = PETSC_DISC_FV; 4115 } 4116 PetscFunctionReturn(PETSC_SUCCESS); 4117 } 4118 4119 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 4120 { 4121 PetscFunctionBegin; 4122 PetscCall(PetscFree(ds->data)); 4123 PetscFunctionReturn(PETSC_SUCCESS); 4124 } 4125 4126 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 4127 { 4128 PetscFunctionBegin; 4129 ds->ops->setfromoptions = NULL; 4130 ds->ops->setup = NULL; 4131 ds->ops->view = NULL; 4132 ds->ops->destroy = PetscDSDestroy_Basic; 4133 PetscFunctionReturn(PETSC_SUCCESS); 4134 } 4135 4136 /*MC 4137 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 4138 4139 Level: intermediate 4140 4141 .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()` 4142 M*/ 4143 4144 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 4145 { 4146 PetscDS_Basic *b; 4147 4148 PetscFunctionBegin; 4149 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4150 PetscCall(PetscNew(&b)); 4151 ds->data = b; 4152 4153 PetscCall(PetscDSInitialize_Basic(ds)); 4154 PetscFunctionReturn(PETSC_SUCCESS); 4155 } 4156