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