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