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->numFuncConstants = 2; // Row and col fields 691 p->dimEmbed = -1; 692 p->useJacPre = PETSC_TRUE; 693 p->forceQuad = PETSC_TRUE; 694 PetscCall(PetscMalloc1(p->numConstants + p->numFuncConstants, &p->constants)); 695 PetscCall(PetscWeakFormCreate(comm, &p->wf)); 696 PetscCall(PetscArrayzero(p->quadPerm, DM_NUM_POLYTOPES)); 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 . ds - 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 ds, PetscInt *numConstants, const PetscScalar *constants[]) 2828 { 2829 PetscFunctionBegin; 2830 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2831 if (numConstants) { 2832 PetscAssertPointer(numConstants, 2); 2833 *numConstants = ds->numConstants; 2834 } 2835 if (constants) { 2836 PetscAssertPointer(constants, 3); 2837 *constants = ds->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 + ds - 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 ds, PetscInt numConstants, PetscScalar constants[]) 2857 { 2858 PetscFunctionBegin; 2859 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2860 if (numConstants != ds->numConstants) { 2861 PetscCall(PetscFree(ds->constants)); 2862 ds->numConstants = numConstants; 2863 if (ds->numConstants) { 2864 PetscCall(PetscMalloc1(ds->numConstants + ds->numFuncConstants, &ds->constants)); 2865 } else { 2866 ds->constants = NULL; 2867 } 2868 } 2869 if (ds->numConstants) { 2870 PetscAssertPointer(constants, 3); 2871 PetscCall(PetscArraycpy(ds->constants, constants, ds->numConstants)); 2872 } 2873 PetscFunctionReturn(PETSC_SUCCESS); 2874 } 2875 2876 /*@C 2877 PetscDSSetIntegrationParameters - Set the parameters for a particular integration 2878 2879 Not Collective 2880 2881 Input Parameters: 2882 + ds - The `PetscDS` object 2883 . fieldI - The test field for a given point function, or PETSC_DETERMINE 2884 - fieldJ - The basis field for a given point function, or PETSC_DETERMINE 2885 2886 Level: intermediate 2887 2888 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSGetConstants()`, `PetscDSCreate()` 2889 @*/ 2890 PetscErrorCode PetscDSSetIntegrationParameters(PetscDS ds, PetscInt fieldI, PetscInt fieldJ) 2891 { 2892 PetscFunctionBegin; 2893 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2894 ds->constants[ds->numConstants] = fieldI; 2895 ds->constants[ds->numConstants + 1] = fieldJ; 2896 PetscFunctionReturn(PETSC_SUCCESS); 2897 } 2898 2899 /*@ 2900 PetscDSGetFieldIndex - Returns the index of the given field 2901 2902 Not Collective 2903 2904 Input Parameters: 2905 + prob - The `PetscDS` object 2906 - disc - The discretization object 2907 2908 Output Parameter: 2909 . f - The field number 2910 2911 Level: beginner 2912 2913 .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2914 @*/ 2915 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2916 { 2917 PetscInt g; 2918 2919 PetscFunctionBegin; 2920 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2921 PetscAssertPointer(f, 3); 2922 *f = -1; 2923 for (g = 0; g < prob->Nf; ++g) { 2924 if (disc == prob->disc[g]) break; 2925 } 2926 PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2927 *f = g; 2928 PetscFunctionReturn(PETSC_SUCCESS); 2929 } 2930 2931 /*@ 2932 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2933 2934 Not Collective 2935 2936 Input Parameters: 2937 + prob - The `PetscDS` object 2938 - f - The field number 2939 2940 Output Parameter: 2941 . size - The size 2942 2943 Level: beginner 2944 2945 .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2946 @*/ 2947 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2948 { 2949 PetscFunctionBegin; 2950 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2951 PetscAssertPointer(size, 3); 2952 PetscCheck(!(f < 0) && !(f >= prob->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, prob->Nf); 2953 PetscCall(PetscDSSetUp(prob)); 2954 *size = prob->Nb[f]; 2955 PetscFunctionReturn(PETSC_SUCCESS); 2956 } 2957 2958 /*@ 2959 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2960 2961 Not Collective 2962 2963 Input Parameters: 2964 + prob - The `PetscDS` object 2965 - f - The field number 2966 2967 Output Parameter: 2968 . off - The offset 2969 2970 Level: beginner 2971 2972 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2973 @*/ 2974 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2975 { 2976 PetscInt size, g; 2977 2978 PetscFunctionBegin; 2979 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2980 PetscAssertPointer(off, 3); 2981 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); 2982 *off = 0; 2983 for (g = 0; g < f; ++g) { 2984 PetscCall(PetscDSGetFieldSize(prob, g, &size)); 2985 *off += size; 2986 } 2987 PetscFunctionReturn(PETSC_SUCCESS); 2988 } 2989 2990 /*@ 2991 PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell 2992 2993 Not Collective 2994 2995 Input Parameters: 2996 + ds - The `PetscDS` object 2997 - f - The field number 2998 2999 Output Parameter: 3000 . off - The offset 3001 3002 Level: beginner 3003 3004 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3005 @*/ 3006 PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off) 3007 { 3008 PetscInt size, g; 3009 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3012 PetscAssertPointer(off, 3); 3013 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); 3014 *off = 0; 3015 for (g = 0; g < f; ++g) { 3016 PetscBool cohesive; 3017 3018 PetscCall(PetscDSGetCohesive(ds, g, &cohesive)); 3019 PetscCall(PetscDSGetFieldSize(ds, g, &size)); 3020 *off += cohesive ? size : size * 2; 3021 } 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@ 3026 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 3027 3028 Not Collective 3029 3030 Input Parameter: 3031 . prob - The `PetscDS` object 3032 3033 Output Parameter: 3034 . dimensions - The number of dimensions 3035 3036 Level: beginner 3037 3038 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3039 @*/ 3040 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 3041 { 3042 PetscFunctionBegin; 3043 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3044 PetscCall(PetscDSSetUp(prob)); 3045 PetscAssertPointer(dimensions, 2); 3046 *dimensions = prob->Nb; 3047 PetscFunctionReturn(PETSC_SUCCESS); 3048 } 3049 3050 /*@ 3051 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 3052 3053 Not Collective 3054 3055 Input Parameter: 3056 . prob - The `PetscDS` object 3057 3058 Output Parameter: 3059 . components - The number of components 3060 3061 Level: beginner 3062 3063 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3064 @*/ 3065 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 3066 { 3067 PetscFunctionBegin; 3068 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3069 PetscCall(PetscDSSetUp(prob)); 3070 PetscAssertPointer(components, 2); 3071 *components = prob->Nc; 3072 PetscFunctionReturn(PETSC_SUCCESS); 3073 } 3074 3075 /*@ 3076 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 3077 3078 Not Collective 3079 3080 Input Parameters: 3081 + prob - The `PetscDS` object 3082 - f - The field number 3083 3084 Output Parameter: 3085 . off - The offset 3086 3087 Level: beginner 3088 3089 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3090 @*/ 3091 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 3092 { 3093 PetscFunctionBegin; 3094 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3095 PetscAssertPointer(off, 3); 3096 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); 3097 PetscCall(PetscDSSetUp(prob)); 3098 *off = prob->off[f]; 3099 PetscFunctionReturn(PETSC_SUCCESS); 3100 } 3101 3102 /*@ 3103 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 3104 3105 Not Collective 3106 3107 Input Parameter: 3108 . prob - The `PetscDS` object 3109 3110 Output Parameter: 3111 . offsets - The offsets 3112 3113 Level: beginner 3114 3115 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3116 @*/ 3117 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 3118 { 3119 PetscFunctionBegin; 3120 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3121 PetscAssertPointer(offsets, 2); 3122 PetscCall(PetscDSSetUp(prob)); 3123 *offsets = prob->off; 3124 PetscFunctionReturn(PETSC_SUCCESS); 3125 } 3126 3127 /*@ 3128 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 3129 3130 Not Collective 3131 3132 Input Parameter: 3133 . prob - The `PetscDS` object 3134 3135 Output Parameter: 3136 . offsets - The offsets 3137 3138 Level: beginner 3139 3140 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3141 @*/ 3142 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 3143 { 3144 PetscFunctionBegin; 3145 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3146 PetscAssertPointer(offsets, 2); 3147 PetscCall(PetscDSSetUp(prob)); 3148 *offsets = prob->offDer; 3149 PetscFunctionReturn(PETSC_SUCCESS); 3150 } 3151 3152 /*@ 3153 PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point 3154 3155 Not Collective 3156 3157 Input Parameters: 3158 + ds - The `PetscDS` object 3159 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3160 3161 Output Parameter: 3162 . offsets - The offsets 3163 3164 Level: beginner 3165 3166 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3167 @*/ 3168 PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3169 { 3170 PetscFunctionBegin; 3171 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3172 PetscAssertPointer(offsets, 3); 3173 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3174 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3175 PetscCall(PetscDSSetUp(ds)); 3176 *offsets = ds->offCohesive[s]; 3177 PetscFunctionReturn(PETSC_SUCCESS); 3178 } 3179 3180 /*@ 3181 PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point 3182 3183 Not Collective 3184 3185 Input Parameters: 3186 + ds - The `PetscDS` object 3187 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 3188 3189 Output Parameter: 3190 . offsets - The offsets 3191 3192 Level: beginner 3193 3194 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 3195 @*/ 3196 PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 3197 { 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3200 PetscAssertPointer(offsets, 3); 3201 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 3202 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 3203 PetscCall(PetscDSSetUp(ds)); 3204 *offsets = ds->offDerCohesive[s]; 3205 PetscFunctionReturn(PETSC_SUCCESS); 3206 } 3207 3208 /*@C 3209 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 3210 3211 Not Collective 3212 3213 Input Parameter: 3214 . prob - The `PetscDS` object 3215 3216 Output Parameter: 3217 . T - The basis function and derivatives tabulation at quadrature points for each field 3218 3219 Level: intermediate 3220 3221 .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()` 3222 @*/ 3223 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) 3224 { 3225 PetscFunctionBegin; 3226 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3227 PetscAssertPointer(T, 2); 3228 PetscCall(PetscDSSetUp(prob)); 3229 *T = prob->T; 3230 PetscFunctionReturn(PETSC_SUCCESS); 3231 } 3232 3233 /*@C 3234 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 3235 3236 Not Collective 3237 3238 Input Parameter: 3239 . prob - The `PetscDS` object 3240 3241 Output Parameter: 3242 . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field 3243 3244 Level: intermediate 3245 3246 .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()` 3247 @*/ 3248 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 3249 { 3250 PetscFunctionBegin; 3251 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3252 PetscAssertPointer(Tf, 2); 3253 PetscCall(PetscDSSetUp(prob)); 3254 *Tf = prob->Tf; 3255 PetscFunctionReturn(PETSC_SUCCESS); 3256 } 3257 3258 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x) 3259 { 3260 PetscFunctionBegin; 3261 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3262 PetscCall(PetscDSSetUp(prob)); 3263 if (u) { 3264 PetscAssertPointer(u, 2); 3265 *u = prob->u; 3266 } 3267 if (u_t) { 3268 PetscAssertPointer(u_t, 3); 3269 *u_t = prob->u_t; 3270 } 3271 if (u_x) { 3272 PetscAssertPointer(u_x, 4); 3273 *u_x = prob->u_x; 3274 } 3275 PetscFunctionReturn(PETSC_SUCCESS); 3276 } 3277 3278 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3) 3279 { 3280 PetscFunctionBegin; 3281 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3282 PetscCall(PetscDSSetUp(prob)); 3283 if (f0) { 3284 PetscAssertPointer(f0, 2); 3285 *f0 = prob->f0; 3286 } 3287 if (f1) { 3288 PetscAssertPointer(f1, 3); 3289 *f1 = prob->f1; 3290 } 3291 if (g0) { 3292 PetscAssertPointer(g0, 4); 3293 *g0 = prob->g0; 3294 } 3295 if (g1) { 3296 PetscAssertPointer(g1, 5); 3297 *g1 = prob->g1; 3298 } 3299 if (g2) { 3300 PetscAssertPointer(g2, 6); 3301 *g2 = prob->g2; 3302 } 3303 if (g3) { 3304 PetscAssertPointer(g3, 7); 3305 *g3 = prob->g3; 3306 } 3307 PetscFunctionReturn(PETSC_SUCCESS); 3308 } 3309 3310 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 3311 { 3312 PetscFunctionBegin; 3313 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3314 PetscCall(PetscDSSetUp(prob)); 3315 if (x) { 3316 PetscAssertPointer(x, 2); 3317 *x = prob->x; 3318 } 3319 if (basisReal) { 3320 PetscAssertPointer(basisReal, 3); 3321 *basisReal = prob->basisReal; 3322 } 3323 if (basisDerReal) { 3324 PetscAssertPointer(basisDerReal, 4); 3325 *basisDerReal = prob->basisDerReal; 3326 } 3327 if (testReal) { 3328 PetscAssertPointer(testReal, 5); 3329 *testReal = prob->testReal; 3330 } 3331 if (testDerReal) { 3332 PetscAssertPointer(testDerReal, 6); 3333 *testDerReal = prob->testDerReal; 3334 } 3335 PetscFunctionReturn(PETSC_SUCCESS); 3336 } 3337 3338 /*@C 3339 PetscDSAddBoundary - Add a boundary condition to the model. 3340 3341 Collective 3342 3343 Input Parameters: 3344 + ds - The PetscDS object 3345 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3346 . name - The BC name 3347 . label - The label defining constrained points 3348 . Nv - The number of `DMLabel` values for constrained points 3349 . values - An array of label values for constrained points 3350 . field - The field to constrain 3351 . Nc - The number of constrained field components (0 will constrain all fields) 3352 . comps - An array of constrained component numbers 3353 . bcFunc - A pointwise function giving boundary values 3354 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3355 - ctx - An optional user context for bcFunc 3356 3357 Output Parameter: 3358 . bd - The boundary number 3359 3360 Options Database Keys: 3361 + -bc_<boundary name> <num> - Overrides the boundary ids 3362 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3363 3364 Level: developer 3365 3366 Note: 3367 Both `bcFunc` and `bcFunc_t` will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\: 3368 3369 $ void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3370 3371 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\: 3372 .vb 3373 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3374 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3375 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3376 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3377 .ve 3378 + dim - the spatial dimension 3379 . Nf - the number of fields 3380 . uOff - the offset into u[] and u_t[] for each field 3381 . uOff_x - the offset into u_x[] for each field 3382 . u - each field evaluated at the current point 3383 . u_t - the time derivative of each field evaluated at the current point 3384 . u_x - the gradient of each field evaluated at the current point 3385 . aOff - the offset into a[] and a_t[] for each auxiliary field 3386 . aOff_x - the offset into a_x[] for each auxiliary field 3387 . a - each auxiliary field evaluated at the current point 3388 . a_t - the time derivative of each auxiliary field evaluated at the current point 3389 . a_x - the gradient of auxiliary each field evaluated at the current point 3390 . t - current time 3391 . x - coordinates of the current point 3392 . numConstants - number of constant parameters 3393 . constants - constant parameters 3394 - bcval - output values at the current point 3395 3396 Notes: 3397 The pointwise functions are used to provide boundary values for essential boundary 3398 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3399 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3400 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3401 3402 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3403 @*/ 3404 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) 3405 { 3406 DSBoundary head = ds->boundary, b; 3407 PetscInt n = 0; 3408 const char *lname; 3409 3410 PetscFunctionBegin; 3411 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3412 PetscValidLogicalCollectiveEnum(ds, type, 2); 3413 PetscAssertPointer(name, 3); 3414 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 3415 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3416 PetscValidLogicalCollectiveInt(ds, field, 7); 3417 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3418 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); 3419 if (Nc > 0) { 3420 PetscInt *fcomps; 3421 PetscInt c; 3422 3423 PetscCall(PetscDSGetComponents(ds, &fcomps)); 3424 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); 3425 for (c = 0; c < Nc; ++c) { 3426 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); 3427 } 3428 } 3429 PetscCall(PetscNew(&b)); 3430 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3431 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3432 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3433 PetscCall(PetscMalloc1(Nv, &b->values)); 3434 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3435 PetscCall(PetscMalloc1(Nc, &b->comps)); 3436 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3437 PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 3438 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3439 b->type = type; 3440 b->label = label; 3441 b->Nv = Nv; 3442 b->field = field; 3443 b->Nc = Nc; 3444 b->func = bcFunc; 3445 b->func_t = bcFunc_t; 3446 b->ctx = ctx; 3447 b->next = NULL; 3448 /* Append to linked list so that we can preserve the order */ 3449 if (!head) ds->boundary = b; 3450 while (head) { 3451 if (!head->next) { 3452 head->next = b; 3453 head = b; 3454 } 3455 head = head->next; 3456 ++n; 3457 } 3458 if (bd) { 3459 PetscAssertPointer(bd, 13); 3460 *bd = n; 3461 } 3462 PetscFunctionReturn(PETSC_SUCCESS); 3463 } 3464 3465 // PetscClangLinter pragma ignore: -fdoc-section-header-unknown 3466 /*@C 3467 PetscDSAddBoundaryByName - Add a boundary condition to the model. 3468 3469 Collective 3470 3471 Input Parameters: 3472 + ds - The `PetscDS` object 3473 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3474 . name - The BC name 3475 . lname - The naem of the label defining constrained points 3476 . Nv - The number of `DMLabel` values for constrained points 3477 . values - An array of label values for constrained points 3478 . field - The field to constrain 3479 . Nc - The number of constrained field components (0 will constrain all fields) 3480 . comps - An array of constrained component numbers 3481 . bcFunc - A pointwise function giving boundary values 3482 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3483 - ctx - An optional user context for bcFunc 3484 3485 Output Parameter: 3486 . bd - The boundary number 3487 3488 Options Database Keys: 3489 + -bc_<boundary name> <num> - Overrides the boundary ids 3490 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3491 3492 Calling Sequence of `bcFunc` and `bcFunc_t`: 3493 If the type is `DM_BC_ESSENTIAL` 3494 .vb 3495 void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3496 .ve 3497 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, 3498 .vb 3499 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3500 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3501 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3502 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3503 .ve 3504 + dim - the spatial dimension 3505 . Nf - the number of fields 3506 . uOff - the offset into u[] and u_t[] for each field 3507 . uOff_x - the offset into u_x[] for each field 3508 . u - each field evaluated at the current point 3509 . u_t - the time derivative of each field evaluated at the current point 3510 . u_x - the gradient of each field evaluated at the current point 3511 . aOff - the offset into a[] and a_t[] for each auxiliary field 3512 . aOff_x - the offset into a_x[] for each auxiliary field 3513 . a - each auxiliary field evaluated at the current point 3514 . a_t - the time derivative of each auxiliary field evaluated at the current point 3515 . a_x - the gradient of auxiliary each field evaluated at the current point 3516 . t - current time 3517 . x - coordinates of the current point 3518 . numConstants - number of constant parameters 3519 . constants - constant parameters 3520 - bcval - output values at the current point 3521 3522 Level: developer 3523 3524 Notes: 3525 The pointwise functions are used to provide boundary values for essential boundary 3526 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3527 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3528 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3529 3530 This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built. 3531 3532 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3533 @*/ 3534 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) 3535 { 3536 DSBoundary head = ds->boundary, b; 3537 PetscInt n = 0; 3538 3539 PetscFunctionBegin; 3540 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3541 PetscValidLogicalCollectiveEnum(ds, type, 2); 3542 PetscAssertPointer(name, 3); 3543 PetscAssertPointer(lname, 4); 3544 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3545 PetscValidLogicalCollectiveInt(ds, field, 7); 3546 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3547 PetscCall(PetscNew(&b)); 3548 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3549 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3550 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3551 PetscCall(PetscMalloc1(Nv, &b->values)); 3552 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3553 PetscCall(PetscMalloc1(Nc, &b->comps)); 3554 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3555 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3556 b->type = type; 3557 b->label = NULL; 3558 b->Nv = Nv; 3559 b->field = field; 3560 b->Nc = Nc; 3561 b->func = bcFunc; 3562 b->func_t = bcFunc_t; 3563 b->ctx = ctx; 3564 b->next = NULL; 3565 /* Append to linked list so that we can preserve the order */ 3566 if (!head) ds->boundary = b; 3567 while (head) { 3568 if (!head->next) { 3569 head->next = b; 3570 head = b; 3571 } 3572 head = head->next; 3573 ++n; 3574 } 3575 if (bd) { 3576 PetscAssertPointer(bd, 13); 3577 *bd = n; 3578 } 3579 PetscFunctionReturn(PETSC_SUCCESS); 3580 } 3581 3582 /*@C 3583 PetscDSUpdateBoundary - Change a boundary condition for the model. 3584 3585 Input Parameters: 3586 + ds - The `PetscDS` object 3587 . bd - The boundary condition number 3588 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3589 . name - The BC name 3590 . label - The label defining constrained points 3591 . Nv - The number of `DMLabel` ids for constrained points 3592 . values - An array of ids for constrained points 3593 . field - The field to constrain 3594 . Nc - The number of constrained field components 3595 . comps - An array of constrained component numbers 3596 . bcFunc - A pointwise function giving boundary values 3597 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3598 - ctx - An optional user context for bcFunc 3599 3600 Level: developer 3601 3602 Notes: 3603 The pointwise functions are used to provide boundary values for essential boundary 3604 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3605 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3606 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3607 3608 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`. 3609 See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks. 3610 3611 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel` 3612 @*/ 3613 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) 3614 { 3615 DSBoundary b = ds->boundary; 3616 PetscInt n = 0; 3617 3618 PetscFunctionBegin; 3619 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3620 while (b) { 3621 if (n == bd) break; 3622 b = b->next; 3623 ++n; 3624 } 3625 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3626 if (name) { 3627 PetscCall(PetscFree(b->name)); 3628 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3629 } 3630 b->type = type; 3631 if (label) { 3632 const char *name; 3633 3634 b->label = label; 3635 PetscCall(PetscFree(b->lname)); 3636 PetscCall(PetscObjectGetName((PetscObject)label, &name)); 3637 PetscCall(PetscStrallocpy(name, (char **)&b->lname)); 3638 } 3639 if (Nv >= 0) { 3640 b->Nv = Nv; 3641 PetscCall(PetscFree(b->values)); 3642 PetscCall(PetscMalloc1(Nv, &b->values)); 3643 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3644 } 3645 if (field >= 0) b->field = field; 3646 if (Nc >= 0) { 3647 b->Nc = Nc; 3648 PetscCall(PetscFree(b->comps)); 3649 PetscCall(PetscMalloc1(Nc, &b->comps)); 3650 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3651 } 3652 if (bcFunc) b->func = bcFunc; 3653 if (bcFunc_t) b->func_t = bcFunc_t; 3654 if (ctx) b->ctx = ctx; 3655 PetscFunctionReturn(PETSC_SUCCESS); 3656 } 3657 3658 /*@ 3659 PetscDSGetNumBoundary - Get the number of registered BC 3660 3661 Input Parameter: 3662 . ds - The `PetscDS` object 3663 3664 Output Parameter: 3665 . numBd - The number of BC 3666 3667 Level: intermediate 3668 3669 .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()` 3670 @*/ 3671 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3672 { 3673 DSBoundary b = ds->boundary; 3674 3675 PetscFunctionBegin; 3676 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3677 PetscAssertPointer(numBd, 2); 3678 *numBd = 0; 3679 while (b) { 3680 ++(*numBd); 3681 b = b->next; 3682 } 3683 PetscFunctionReturn(PETSC_SUCCESS); 3684 } 3685 3686 /*@C 3687 PetscDSGetBoundary - Gets a boundary condition to the model 3688 3689 Input Parameters: 3690 + ds - The `PetscDS` object 3691 - bd - The BC number 3692 3693 Output Parameters: 3694 + wf - The `PetscWeakForm` holding the pointwise functions 3695 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3696 . name - The BC name 3697 . label - The label defining constrained points 3698 . Nv - The number of `DMLabel` ids for constrained points 3699 . values - An array of ids for constrained points 3700 . field - The field to constrain 3701 . Nc - The number of constrained field components 3702 . comps - An array of constrained component numbers 3703 . func - A pointwise function giving boundary values 3704 . func_t - A pointwise function giving the time derivative of the boundary values 3705 - ctx - An optional user context for bcFunc 3706 3707 Options Database Keys: 3708 + -bc_<boundary name> <num> - Overrides the boundary ids 3709 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3710 3711 Level: developer 3712 3713 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel` 3714 @*/ 3715 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) 3716 { 3717 DSBoundary b = ds->boundary; 3718 PetscInt n = 0; 3719 3720 PetscFunctionBegin; 3721 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3722 while (b) { 3723 if (n == bd) break; 3724 b = b->next; 3725 ++n; 3726 } 3727 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3728 if (wf) { 3729 PetscAssertPointer(wf, 3); 3730 *wf = b->wf; 3731 } 3732 if (type) { 3733 PetscAssertPointer(type, 4); 3734 *type = b->type; 3735 } 3736 if (name) { 3737 PetscAssertPointer(name, 5); 3738 *name = b->name; 3739 } 3740 if (label) { 3741 PetscAssertPointer(label, 6); 3742 *label = b->label; 3743 } 3744 if (Nv) { 3745 PetscAssertPointer(Nv, 7); 3746 *Nv = b->Nv; 3747 } 3748 if (values) { 3749 PetscAssertPointer(values, 8); 3750 *values = b->values; 3751 } 3752 if (field) { 3753 PetscAssertPointer(field, 9); 3754 *field = b->field; 3755 } 3756 if (Nc) { 3757 PetscAssertPointer(Nc, 10); 3758 *Nc = b->Nc; 3759 } 3760 if (comps) { 3761 PetscAssertPointer(comps, 11); 3762 *comps = b->comps; 3763 } 3764 if (func) { 3765 PetscAssertPointer(func, 12); 3766 *func = b->func; 3767 } 3768 if (func_t) { 3769 PetscAssertPointer(func_t, 13); 3770 *func_t = b->func_t; 3771 } 3772 if (ctx) { 3773 PetscAssertPointer(ctx, 14); 3774 *ctx = b->ctx; 3775 } 3776 PetscFunctionReturn(PETSC_SUCCESS); 3777 } 3778 3779 /*@ 3780 PetscDSUpdateBoundaryLabels - Update `DMLabel` in each boundary condition using the label name and the input `DM` 3781 3782 Not Collective 3783 3784 Input Parameters: 3785 + ds - The source `PetscDS` object 3786 - dm - The `DM` holding labels 3787 3788 Level: intermediate 3789 3790 .seealso: `PetscDS`, `DMBoundary`, `DM`, `PetscDSCopyBoundary()`, `PetscDSCreate()`, `DMGetLabel()` 3791 @*/ 3792 PetscErrorCode PetscDSUpdateBoundaryLabels(PetscDS ds, DM dm) 3793 { 3794 DSBoundary b; 3795 3796 PetscFunctionBegin; 3797 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3798 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 3799 for (b = ds->boundary; b; b = b->next) { 3800 if (b->lname) PetscCall(DMGetLabel(dm, b->lname, &b->label)); 3801 } 3802 PetscFunctionReturn(PETSC_SUCCESS); 3803 } 3804 3805 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3806 { 3807 PetscFunctionBegin; 3808 PetscCall(PetscNew(bNew)); 3809 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf)); 3810 PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf)); 3811 PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name))); 3812 PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname))); 3813 (*bNew)->type = b->type; 3814 (*bNew)->label = b->label; 3815 (*bNew)->Nv = b->Nv; 3816 PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values)); 3817 PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv)); 3818 (*bNew)->field = b->field; 3819 (*bNew)->Nc = b->Nc; 3820 PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps)); 3821 PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc)); 3822 (*bNew)->func = b->func; 3823 (*bNew)->func_t = b->func_t; 3824 (*bNew)->ctx = b->ctx; 3825 PetscFunctionReturn(PETSC_SUCCESS); 3826 } 3827 3828 /*@ 3829 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 3830 3831 Not Collective 3832 3833 Input Parameters: 3834 + ds - The source `PetscDS` object 3835 . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields 3836 - fields - The selected fields, or NULL for all fields 3837 3838 Output Parameter: 3839 . newds - The target `PetscDS`, now with a copy of the boundary conditions 3840 3841 Level: intermediate 3842 3843 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3844 @*/ 3845 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3846 { 3847 DSBoundary b, *lastnext; 3848 3849 PetscFunctionBegin; 3850 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3851 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3852 if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS); 3853 PetscCall(PetscDSDestroyBoundary(newds)); 3854 lastnext = &newds->boundary; 3855 for (b = ds->boundary; b; b = b->next) { 3856 DSBoundary bNew; 3857 PetscInt fieldNew = -1; 3858 3859 if (numFields > 0 && fields) { 3860 PetscInt f; 3861 3862 for (f = 0; f < numFields; ++f) 3863 if (b->field == fields[f]) break; 3864 if (f == numFields) continue; 3865 fieldNew = f; 3866 } 3867 PetscCall(DSBoundaryDuplicate_Internal(b, &bNew)); 3868 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3869 *lastnext = bNew; 3870 lastnext = &bNew->next; 3871 } 3872 PetscFunctionReturn(PETSC_SUCCESS); 3873 } 3874 3875 /*@ 3876 PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS` 3877 3878 Not Collective 3879 3880 Input Parameter: 3881 . ds - The `PetscDS` object 3882 3883 Level: intermediate 3884 3885 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()` 3886 @*/ 3887 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3888 { 3889 DSBoundary next = ds->boundary; 3890 3891 PetscFunctionBegin; 3892 while (next) { 3893 DSBoundary b = next; 3894 3895 next = b->next; 3896 PetscCall(PetscWeakFormDestroy(&b->wf)); 3897 PetscCall(PetscFree(b->name)); 3898 PetscCall(PetscFree(b->lname)); 3899 PetscCall(PetscFree(b->values)); 3900 PetscCall(PetscFree(b->comps)); 3901 PetscCall(PetscFree(b)); 3902 } 3903 PetscFunctionReturn(PETSC_SUCCESS); 3904 } 3905 3906 /*@ 3907 PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout 3908 3909 Not Collective 3910 3911 Input Parameters: 3912 + prob - The `PetscDS` object 3913 . numFields - Number of new fields 3914 - fields - Old field number for each new field 3915 3916 Output Parameter: 3917 . newprob - The `PetscDS` copy 3918 3919 Level: intermediate 3920 3921 .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3922 @*/ 3923 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3924 { 3925 PetscInt Nf, Nfn, fn; 3926 3927 PetscFunctionBegin; 3928 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3929 if (fields) PetscAssertPointer(fields, 3); 3930 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3931 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3932 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3933 numFields = numFields < 0 ? Nf : numFields; 3934 for (fn = 0; fn < numFields; ++fn) { 3935 const PetscInt f = fields ? fields[fn] : fn; 3936 PetscObject disc; 3937 3938 if (f >= Nf) continue; 3939 PetscCall(PetscDSGetDiscretization(prob, f, &disc)); 3940 PetscCall(PetscDSSetDiscretization(newprob, fn, disc)); 3941 } 3942 PetscFunctionReturn(PETSC_SUCCESS); 3943 } 3944 3945 /*@ 3946 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 3947 3948 Not Collective 3949 3950 Input Parameters: 3951 + prob - The `PetscDS` object 3952 . numFields - Number of new fields 3953 - fields - Old field number for each new field 3954 3955 Output Parameter: 3956 . newprob - The `PetscDS` copy 3957 3958 Level: intermediate 3959 3960 .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3961 @*/ 3962 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3963 { 3964 PetscInt Nf, Nfn, fn, gn; 3965 3966 PetscFunctionBegin; 3967 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3968 if (fields) PetscAssertPointer(fields, 3); 3969 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3970 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3971 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3972 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); 3973 for (fn = 0; fn < numFields; ++fn) { 3974 const PetscInt f = fields ? fields[fn] : fn; 3975 PetscPointFunc obj; 3976 PetscPointFunc f0, f1; 3977 PetscBdPointFunc f0Bd, f1Bd; 3978 PetscRiemannFunc r; 3979 3980 if (f >= Nf) continue; 3981 PetscCall(PetscDSGetObjective(prob, f, &obj)); 3982 PetscCall(PetscDSGetResidual(prob, f, &f0, &f1)); 3983 PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd)); 3984 PetscCall(PetscDSGetRiemannSolver(prob, f, &r)); 3985 PetscCall(PetscDSSetObjective(newprob, fn, obj)); 3986 PetscCall(PetscDSSetResidual(newprob, fn, f0, f1)); 3987 PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd)); 3988 PetscCall(PetscDSSetRiemannSolver(newprob, fn, r)); 3989 for (gn = 0; gn < numFields; ++gn) { 3990 const PetscInt g = fields ? fields[gn] : gn; 3991 PetscPointJac g0, g1, g2, g3; 3992 PetscPointJac g0p, g1p, g2p, g3p; 3993 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3994 3995 if (g >= Nf) continue; 3996 PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3)); 3997 PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p)); 3998 PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd)); 3999 PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3)); 4000 PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p)); 4001 PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd)); 4002 } 4003 } 4004 PetscFunctionReturn(PETSC_SUCCESS); 4005 } 4006 4007 /*@ 4008 PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS` 4009 4010 Not Collective 4011 4012 Input Parameter: 4013 . prob - The `PetscDS` object 4014 4015 Output Parameter: 4016 . newprob - The `PetscDS` copy 4017 4018 Level: intermediate 4019 4020 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 4021 @*/ 4022 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 4023 { 4024 PetscWeakForm wf, newwf; 4025 PetscInt Nf, Ng; 4026 4027 PetscFunctionBegin; 4028 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 4029 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 4030 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4031 PetscCall(PetscDSGetNumFields(newprob, &Ng)); 4032 PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng); 4033 PetscCall(PetscDSGetWeakForm(prob, &wf)); 4034 PetscCall(PetscDSGetWeakForm(newprob, &newwf)); 4035 PetscCall(PetscWeakFormCopy(wf, newwf)); 4036 PetscFunctionReturn(PETSC_SUCCESS); 4037 } 4038 4039 /*@ 4040 PetscDSCopyConstants - Copy all constants to another `PetscDS` 4041 4042 Not Collective 4043 4044 Input Parameter: 4045 . prob - The `PetscDS` object 4046 4047 Output Parameter: 4048 . newprob - The `PetscDS` copy 4049 4050 Level: intermediate 4051 4052 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 4053 @*/ 4054 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 4055 { 4056 PetscInt Nc; 4057 const PetscScalar *constants; 4058 4059 PetscFunctionBegin; 4060 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 4061 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 4062 PetscCall(PetscDSGetConstants(prob, &Nc, &constants)); 4063 PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants)); 4064 PetscFunctionReturn(PETSC_SUCCESS); 4065 } 4066 4067 /*@ 4068 PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS` 4069 4070 Not Collective 4071 4072 Input Parameter: 4073 . ds - The `PetscDS` object 4074 4075 Output Parameter: 4076 . newds - The `PetscDS` copy 4077 4078 Level: intermediate 4079 4080 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 4081 @*/ 4082 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 4083 { 4084 PetscSimplePointFn *sol; 4085 void *ctx; 4086 PetscInt Nf, f; 4087 4088 PetscFunctionBegin; 4089 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4090 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 4091 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4092 for (f = 0; f < Nf; ++f) { 4093 PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx)); 4094 PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx)); 4095 PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx)); 4096 PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx)); 4097 } 4098 PetscFunctionReturn(PETSC_SUCCESS); 4099 } 4100 4101 PetscErrorCode PetscDSCopy(PetscDS ds, DM dmNew, PetscDS dsNew) 4102 { 4103 DSBoundary b; 4104 PetscInt cdim, Nf, f, d; 4105 PetscBool isCohesive; 4106 void *ctx; 4107 4108 PetscFunctionBegin; 4109 PetscCall(PetscDSCopyConstants(ds, dsNew)); 4110 PetscCall(PetscDSCopyExactSolutions(ds, dsNew)); 4111 PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, dsNew)); 4112 PetscCall(PetscDSCopyEquations(ds, dsNew)); 4113 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4114 for (f = 0; f < Nf; ++f) { 4115 PetscCall(PetscDSGetContext(ds, f, &ctx)); 4116 PetscCall(PetscDSSetContext(dsNew, f, ctx)); 4117 PetscCall(PetscDSGetCohesive(ds, f, &isCohesive)); 4118 PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive)); 4119 PetscCall(PetscDSGetJetDegree(ds, f, &d)); 4120 PetscCall(PetscDSSetJetDegree(dsNew, f, d)); 4121 } 4122 if (Nf) { 4123 PetscCall(PetscDSGetCoordinateDimension(ds, &cdim)); 4124 PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim)); 4125 } 4126 PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew)); 4127 for (b = dsNew->boundary; b; b = b->next) { 4128 PetscCall(DMGetLabel(dmNew, b->lname, &b->label)); 4129 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 4130 //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 4131 } 4132 PetscFunctionReturn(PETSC_SUCCESS); 4133 } 4134 4135 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 4136 { 4137 PetscInt dim, Nf, f; 4138 4139 PetscFunctionBegin; 4140 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 4141 PetscAssertPointer(subprob, 3); 4142 if (height == 0) { 4143 *subprob = prob; 4144 PetscFunctionReturn(PETSC_SUCCESS); 4145 } 4146 PetscCall(PetscDSGetNumFields(prob, &Nf)); 4147 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 4148 PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height); 4149 if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs)); 4150 if (!prob->subprobs[height - 1]) { 4151 PetscInt cdim; 4152 4153 PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1])); 4154 PetscCall(PetscDSGetCoordinateDimension(prob, &cdim)); 4155 PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim)); 4156 for (f = 0; f < Nf; ++f) { 4157 PetscFE subfe; 4158 PetscObject obj; 4159 PetscClassId id; 4160 4161 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 4162 PetscCall(PetscObjectGetClassId(obj, &id)); 4163 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe)); 4164 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f); 4165 PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe)); 4166 } 4167 } 4168 *subprob = prob->subprobs[height - 1]; 4169 PetscFunctionReturn(PETSC_SUCCESS); 4170 } 4171 4172 PetscErrorCode PetscDSPermuteQuadPoint(PetscDS ds, PetscInt ornt, PetscInt field, PetscInt q, PetscInt *qperm) 4173 { 4174 IS permIS; 4175 PetscQuadrature quad; 4176 DMPolytopeType ct; 4177 const PetscInt *perm; 4178 PetscInt Na, Nq; 4179 4180 PetscFunctionBeginHot; 4181 PetscCall(PetscFEGetQuadrature((PetscFE)ds->disc[field], &quad)); 4182 PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL)); 4183 PetscCall(PetscQuadratureGetCellType(quad, &ct)); 4184 PetscCheck(q >= 0 && q < Nq, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Quadrature point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", q, Nq); 4185 Na = DMPolytopeTypeGetNumArrangements(ct) / 2; 4186 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); 4187 if (!ds->quadPerm[(PetscInt)ct]) PetscCall(PetscQuadratureComputePermutations(quad, NULL, &ds->quadPerm[(PetscInt)ct])); 4188 permIS = ds->quadPerm[(PetscInt)ct][ornt + Na]; 4189 PetscCall(ISGetIndices(permIS, &perm)); 4190 *qperm = perm[q]; 4191 PetscCall(ISRestoreIndices(permIS, &perm)); 4192 PetscFunctionReturn(PETSC_SUCCESS); 4193 } 4194 4195 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 4196 { 4197 PetscObject obj; 4198 PetscClassId id; 4199 PetscInt Nf; 4200 4201 PetscFunctionBegin; 4202 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4203 PetscAssertPointer(disctype, 3); 4204 *disctype = PETSC_DISC_NONE; 4205 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4206 PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf); 4207 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 4208 if (obj) { 4209 PetscCall(PetscObjectGetClassId(obj, &id)); 4210 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 4211 else *disctype = PETSC_DISC_FV; 4212 } 4213 PetscFunctionReturn(PETSC_SUCCESS); 4214 } 4215 4216 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 4217 { 4218 PetscFunctionBegin; 4219 PetscCall(PetscFree(ds->data)); 4220 PetscFunctionReturn(PETSC_SUCCESS); 4221 } 4222 4223 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 4224 { 4225 PetscFunctionBegin; 4226 ds->ops->setfromoptions = NULL; 4227 ds->ops->setup = NULL; 4228 ds->ops->view = NULL; 4229 ds->ops->destroy = PetscDSDestroy_Basic; 4230 PetscFunctionReturn(PETSC_SUCCESS); 4231 } 4232 4233 /*MC 4234 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 4235 4236 Level: intermediate 4237 4238 .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()` 4239 M*/ 4240 4241 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 4242 { 4243 PetscDS_Basic *b; 4244 4245 PetscFunctionBegin; 4246 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4247 PetscCall(PetscNew(&b)); 4248 ds->data = b; 4249 4250 PetscCall(PetscDSInitialize_Basic(ds)); 4251 PetscFunctionReturn(PETSC_SUCCESS); 4252 } 4253