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