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