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