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