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 /*@C 9 PetscDSRegister - Adds a new `PetscDS` implementation 10 11 Not Collective; No Fortran Support 12 13 Input Parameters: 14 + sname - The name of a new user-defined creation routine 15 - function - The creation routine itself 16 17 Example Usage: 18 .vb 19 PetscDSRegister("my_ds", MyPetscDSCreate); 20 .ve 21 22 Then, your PetscDS type can be chosen with the procedural interface via 23 .vb 24 PetscDSCreate(MPI_Comm, PetscDS *); 25 PetscDSSetType(PetscDS, "my_ds"); 26 .ve 27 or at runtime via the option 28 .vb 29 -petscds_type my_ds 30 .ve 31 32 Level: advanced 33 34 Note: 35 `PetscDSRegister()` may be called multiple times to add several user-defined `PetscDSs` 36 37 .seealso: `PetscDSType`, `PetscDS`, `PetscDSRegisterAll()`, `PetscDSRegisterDestroy()` 38 @*/ 39 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS)) 40 { 41 PetscFunctionBegin; 42 PetscCall(PetscFunctionListAdd(&PetscDSList, sname, function)); 43 PetscFunctionReturn(PETSC_SUCCESS); 44 } 45 46 /*@ 47 PetscDSSetType - Builds a particular `PetscDS` 48 49 Collective; No Fortran Support 50 51 Input Parameters: 52 + prob - The `PetscDS` object 53 - name - The `PetscDSType` 54 55 Options Database Key: 56 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types 57 58 Level: intermediate 59 60 .seealso: `PetscDSType`, `PetscDS`, `PetscDSGetType()`, `PetscDSCreate()` 61 @*/ 62 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name) 63 { 64 PetscErrorCode (*r)(PetscDS); 65 PetscBool match; 66 67 PetscFunctionBegin; 68 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 69 PetscCall(PetscObjectTypeCompare((PetscObject)prob, name, &match)); 70 if (match) PetscFunctionReturn(PETSC_SUCCESS); 71 72 PetscCall(PetscDSRegisterAll()); 73 PetscCall(PetscFunctionListFind(PetscDSList, name, &r)); 74 PetscCheck(r, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name); 75 76 PetscTryTypeMethod(prob, destroy); 77 prob->ops->destroy = NULL; 78 79 PetscCall((*r)(prob)); 80 PetscCall(PetscObjectChangeTypeName((PetscObject)prob, name)); 81 PetscFunctionReturn(PETSC_SUCCESS); 82 } 83 84 /*@ 85 PetscDSGetType - Gets the `PetscDSType` name (as a string) from the `PetscDS` 86 87 Not Collective; No Fortran Support 88 89 Input Parameter: 90 . prob - The `PetscDS` 91 92 Output Parameter: 93 . name - The `PetscDSType` name 94 95 Level: intermediate 96 97 .seealso: `PetscDSType`, `PetscDS`, `PetscDSSetType()`, `PetscDSCreate()` 98 @*/ 99 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name) 100 { 101 PetscFunctionBegin; 102 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 103 PetscAssertPointer(name, 2); 104 PetscCall(PetscDSRegisterAll()); 105 *name = ((PetscObject)prob)->type_name; 106 PetscFunctionReturn(PETSC_SUCCESS); 107 } 108 109 static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer) 110 { 111 PetscViewerFormat format; 112 const PetscScalar *constants; 113 PetscInt Nf, numConstants, f; 114 115 PetscFunctionBegin; 116 PetscCall(PetscDSGetNumFields(ds, &Nf)); 117 PetscCall(PetscViewerGetFormat(viewer, &format)); 118 PetscCall(PetscViewerASCIIPrintf(viewer, "Discrete System with %" PetscInt_FMT " fields\n", Nf)); 119 PetscCall(PetscViewerASCIIPushTab(viewer)); 120 PetscCall(PetscViewerASCIIPrintf(viewer, " cell total dim %" PetscInt_FMT " total comp %" PetscInt_FMT "\n", ds->totDim, ds->totComp)); 121 if (ds->isCohesive) PetscCall(PetscViewerASCIIPrintf(viewer, " cohesive cell\n")); 122 for (f = 0; f < Nf; ++f) { 123 DSBoundary b; 124 PetscObject obj; 125 PetscClassId id; 126 PetscQuadrature q; 127 const char *name; 128 PetscInt Nc, Nq, Nqc; 129 130 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 131 PetscCall(PetscObjectGetClassId(obj, &id)); 132 PetscCall(PetscObjectGetName(obj, &name)); 133 PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>")); 134 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 135 if (id == PETSCFE_CLASSID) { 136 PetscCall(PetscFEGetNumComponents((PetscFE)obj, &Nc)); 137 PetscCall(PetscFEGetQuadrature((PetscFE)obj, &q)); 138 PetscCall(PetscViewerASCIIPrintf(viewer, " FEM")); 139 } else if (id == PETSCFV_CLASSID) { 140 PetscCall(PetscFVGetNumComponents((PetscFV)obj, &Nc)); 141 PetscCall(PetscFVGetQuadrature((PetscFV)obj, &q)); 142 PetscCall(PetscViewerASCIIPrintf(viewer, " FVM")); 143 } else SETERRQ(PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 144 if (Nc > 1) PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " components", Nc)); 145 else PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT " component ", Nc)); 146 if (ds->implicit[f]) PetscCall(PetscViewerASCIIPrintf(viewer, " (implicit)")); 147 else PetscCall(PetscViewerASCIIPrintf(viewer, " (explicit)")); 148 if (q) { 149 PetscCall(PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL)); 150 PetscCall(PetscViewerASCIIPrintf(viewer, " (Nq %" PetscInt_FMT " Nqc %" PetscInt_FMT ")", Nq, Nqc)); 151 } 152 PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "-jet", ds->jetDegree[f])); 153 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 154 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 155 PetscCall(PetscViewerASCIIPushTab(viewer)); 156 if (id == PETSCFE_CLASSID) PetscCall(PetscFEView((PetscFE)obj, viewer)); 157 else if (id == PETSCFV_CLASSID) PetscCall(PetscFVView((PetscFV)obj, viewer)); 158 PetscCall(PetscViewerASCIIPopTab(viewer)); 159 160 for (b = ds->boundary; b; b = b->next) { 161 char *name; 162 PetscInt c, i; 163 164 if (b->field != f) continue; 165 PetscCall(PetscViewerASCIIPushTab(viewer)); 166 PetscCall(PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type])); 167 if (!b->Nc) { 168 PetscCall(PetscViewerASCIIPrintf(viewer, " all components\n")); 169 } else { 170 PetscCall(PetscViewerASCIIPrintf(viewer, " components: ")); 171 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 172 for (c = 0; c < b->Nc; ++c) { 173 if (c > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 174 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->comps[c])); 175 } 176 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 177 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 178 } 179 PetscCall(PetscViewerASCIIPrintf(viewer, " values: ")); 180 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE)); 181 for (i = 0; i < b->Nv; ++i) { 182 if (i > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", ")); 183 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT, b->values[i])); 184 } 185 PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 186 PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE)); 187 #if defined(__clang__) 188 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat-pedantic") 189 #elif defined(__GNUC__) || defined(__GNUG__) 190 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_BEGIN("-Wformat") 191 #endif 192 if (b->func) { 193 PetscCall(PetscDLAddr(b->func, &name)); 194 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func: %s\n", name)); 195 else PetscCall(PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func)); 196 PetscCall(PetscFree(name)); 197 } 198 if (b->func_t) { 199 PetscCall(PetscDLAddr(b->func_t, &name)); 200 if (name) PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name)); 201 else PetscCall(PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t)); 202 PetscCall(PetscFree(name)); 203 } 204 PETSC_PRAGMA_DIAGNOSTIC_IGNORED_END() 205 PetscCall(PetscWeakFormView(b->wf, viewer)); 206 PetscCall(PetscViewerASCIIPopTab(viewer)); 207 } 208 } 209 PetscCall(PetscDSGetConstants(ds, &numConstants, &constants)); 210 if (numConstants) { 211 PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " constants\n", numConstants)); 212 PetscCall(PetscViewerASCIIPushTab(viewer)); 213 for (f = 0; f < numConstants; ++f) PetscCall(PetscViewerASCIIPrintf(viewer, "%g\n", (double)PetscRealPart(constants[f]))); 214 PetscCall(PetscViewerASCIIPopTab(viewer)); 215 } 216 PetscCall(PetscWeakFormView(ds->wf, viewer)); 217 PetscCall(PetscViewerASCIIPopTab(viewer)); 218 PetscFunctionReturn(PETSC_SUCCESS); 219 } 220 221 /*@ 222 PetscDSViewFromOptions - View a `PetscDS` based on values in the options database 223 224 Collective 225 226 Input Parameters: 227 + A - the `PetscDS` object 228 . obj - Optional object that provides the options prefix used in the search of the options database 229 - name - command line option 230 231 Level: intermediate 232 233 .seealso: `PetscDSType`, `PetscDS`, `PetscDSView()`, `PetscObjectViewFromOptions()`, `PetscDSCreate()` 234 @*/ 235 PetscErrorCode PetscDSViewFromOptions(PetscDS A, PetscObject obj, const char name[]) 236 { 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(A, PETSCDS_CLASSID, 1); 239 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 240 PetscFunctionReturn(PETSC_SUCCESS); 241 } 242 243 /*@ 244 PetscDSView - Views a `PetscDS` 245 246 Collective 247 248 Input Parameters: 249 + prob - the `PetscDS` object to view 250 - v - the viewer 251 252 Level: developer 253 254 .seealso: `PetscDSType`, `PetscDS`, `PetscViewer`, `PetscDSDestroy()`, `PetscDSViewFromOptions()` 255 @*/ 256 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v) 257 { 258 PetscBool isascii; 259 260 PetscFunctionBegin; 261 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 262 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)prob), &v)); 263 else PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 264 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii)); 265 if (isascii) PetscCall(PetscDSView_Ascii(prob, v)); 266 PetscTryTypeMethod(prob, view, v); 267 PetscFunctionReturn(PETSC_SUCCESS); 268 } 269 270 /*@ 271 PetscDSSetFromOptions - sets parameters in a `PetscDS` from the options database 272 273 Collective 274 275 Input Parameter: 276 . prob - the `PetscDS` object to set options for 277 278 Options Database Keys: 279 + -petscds_type <type> - Set the `PetscDS` type 280 . -petscds_view <view opt> - View the `PetscDS` 281 . -petscds_jac_pre - Turn formation of a separate Jacobian preconditioner on or off 282 . -bc_<name> <ids> - Specify a list of label ids for a boundary condition 283 - -bc_<name>_comp <comps> - Specify a list of field components to constrain for a boundary condition 284 285 Level: intermediate 286 287 .seealso: `PetscDS`, `PetscDSView()` 288 @*/ 289 PetscErrorCode PetscDSSetFromOptions(PetscDS prob) 290 { 291 DSBoundary b; 292 const char *defaultType; 293 char name[256]; 294 PetscBool flg; 295 296 PetscFunctionBegin; 297 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 298 if (!((PetscObject)prob)->type_name) { 299 defaultType = PETSCDSBASIC; 300 } else { 301 defaultType = ((PetscObject)prob)->type_name; 302 } 303 PetscCall(PetscDSRegisterAll()); 304 305 PetscObjectOptionsBegin((PetscObject)prob); 306 for (b = prob->boundary; b; b = b->next) { 307 char optname[1024]; 308 PetscInt ids[1024], len = 1024; 309 PetscBool flg; 310 311 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name)); 312 PetscCall(PetscMemzero(ids, sizeof(ids))); 313 PetscCall(PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg)); 314 if (flg) { 315 b->Nv = len; 316 PetscCall(PetscFree(b->values)); 317 PetscCall(PetscMalloc1(len, &b->values)); 318 PetscCall(PetscArraycpy(b->values, ids, len)); 319 PetscCall(PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values)); 320 } 321 len = 1024; 322 PetscCall(PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name)); 323 PetscCall(PetscMemzero(ids, sizeof(ids))); 324 PetscCall(PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg)); 325 if (flg) { 326 b->Nc = len; 327 PetscCall(PetscFree(b->comps)); 328 PetscCall(PetscMalloc1(len, &b->comps)); 329 PetscCall(PetscArraycpy(b->comps, ids, len)); 330 } 331 } 332 PetscCall(PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg)); 333 if (flg) { 334 PetscCall(PetscDSSetType(prob, name)); 335 } else if (!((PetscObject)prob)->type_name) { 336 PetscCall(PetscDSSetType(prob, defaultType)); 337 } 338 PetscCall(PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg)); 339 PetscCall(PetscOptionsBool("-petscds_force_quad", "Discrete System", "PetscDSSetForceQuad", prob->forceQuad, &prob->forceQuad, &flg)); 340 PetscCall(PetscOptionsInt("-petscds_print_integrate", "Discrete System", "", prob->printIntegrate, &prob->printIntegrate, NULL)); 341 PetscTryTypeMethod(prob, setfromoptions); 342 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 343 PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)prob, PetscOptionsObject)); 344 PetscOptionsEnd(); 345 if (prob->Nf) PetscCall(PetscDSViewFromOptions(prob, NULL, "-petscds_view")); 346 PetscFunctionReturn(PETSC_SUCCESS); 347 } 348 349 /*@ 350 PetscDSSetUp - Construct data structures for the `PetscDS` 351 352 Collective 353 354 Input Parameter: 355 . prob - the `PetscDS` object to setup 356 357 Level: developer 358 359 .seealso: `PetscDS`, `PetscDSView()`, `PetscDSDestroy()` 360 @*/ 361 PetscErrorCode PetscDSSetUp(PetscDS prob) 362 { 363 const PetscInt Nf = prob->Nf; 364 PetscBool hasH = PETSC_FALSE; 365 PetscInt maxOrder[4] = {-2, -2, -2, -2}; 366 PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f; 367 368 PetscFunctionBegin; 369 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 370 if (prob->setup) PetscFunctionReturn(PETSC_SUCCESS); 371 /* Calculate sizes */ 372 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 373 PetscCall(PetscDSGetCoordinateDimension(prob, &dimEmbed)); 374 prob->totDim = prob->totComp = 0; 375 PetscCall(PetscMalloc2(Nf, &prob->Nc, Nf, &prob->Nb)); 376 PetscCall(PetscCalloc2(Nf + 1, &prob->off, Nf + 1, &prob->offDer)); 377 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])); 378 PetscCall(PetscMalloc2(Nf, &prob->T, Nf, &prob->Tf)); 379 if (prob->forceQuad) { 380 // Note: This assumes we have one kind of cell at each dimension. 381 // We can fix this by having quadrature hold the celltype 382 PetscQuadrature maxQuad[4] = {NULL, NULL, NULL, NULL}; 383 384 for (f = 0; f < Nf; ++f) { 385 PetscObject obj; 386 PetscClassId id; 387 PetscQuadrature q = NULL, fq = NULL; 388 PetscInt dim = -1, order = -1, forder = -1; 389 390 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 391 if (!obj) continue; 392 PetscCall(PetscObjectGetClassId(obj, &id)); 393 if (id == PETSCFE_CLASSID) { 394 PetscFE fe = (PetscFE)obj; 395 396 PetscCall(PetscFEGetQuadrature(fe, &q)); 397 PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 398 } else if (id == PETSCFV_CLASSID) { 399 PetscFV fv = (PetscFV)obj; 400 401 PetscCall(PetscFVGetQuadrature(fv, &q)); 402 } 403 if (q) { 404 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 405 PetscCall(PetscQuadratureGetOrder(q, &order)); 406 if (order > maxOrder[dim]) { 407 maxOrder[dim] = order; 408 maxQuad[dim] = q; 409 } 410 } 411 if (fq) { 412 PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL)); 413 PetscCall(PetscQuadratureGetOrder(fq, &forder)); 414 if (forder > maxOrder[dim]) { 415 maxOrder[dim] = forder; 416 maxQuad[dim] = fq; 417 } 418 } 419 } 420 for (f = 0; f < Nf; ++f) { 421 PetscObject obj; 422 PetscClassId id; 423 PetscQuadrature q; 424 PetscInt dim; 425 426 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 427 if (!obj) continue; 428 PetscCall(PetscObjectGetClassId(obj, &id)); 429 if (id == PETSCFE_CLASSID) { 430 PetscFE fe = (PetscFE)obj; 431 432 PetscCall(PetscFEGetQuadrature(fe, &q)); 433 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 434 PetscCall(PetscFESetQuadrature(fe, maxQuad[dim])); 435 PetscCall(PetscFESetFaceQuadrature(fe, dim ? maxQuad[dim - 1] : NULL)); 436 } else if (id == PETSCFV_CLASSID) { 437 PetscFV fv = (PetscFV)obj; 438 439 PetscCall(PetscFVGetQuadrature(fv, &q)); 440 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 441 PetscCall(PetscFVSetQuadrature(fv, maxQuad[dim])); 442 } 443 } 444 } 445 for (f = 0; f < Nf; ++f) { 446 PetscObject obj; 447 PetscClassId id; 448 PetscQuadrature q = NULL; 449 PetscInt Nq = 0, Nb, Nc; 450 451 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 452 if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE; 453 if (!obj) { 454 /* Empty mesh */ 455 Nb = Nc = 0; 456 prob->T[f] = prob->Tf[f] = NULL; 457 } else { 458 PetscCall(PetscObjectGetClassId(obj, &id)); 459 if (id == PETSCFE_CLASSID) { 460 PetscFE fe = (PetscFE)obj; 461 462 PetscCall(PetscFEGetQuadrature(fe, &q)); 463 { 464 PetscQuadrature fq; 465 PetscInt dim, order; 466 467 PetscCall(PetscQuadratureGetData(q, &dim, NULL, NULL, NULL, NULL)); 468 PetscCall(PetscQuadratureGetOrder(q, &order)); 469 if (maxOrder[dim] < 0) maxOrder[dim] = order; 470 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]); 471 PetscCall(PetscFEGetFaceQuadrature(fe, &fq)); 472 if (fq) { 473 PetscCall(PetscQuadratureGetData(fq, &dim, NULL, NULL, NULL, NULL)); 474 PetscCall(PetscQuadratureGetOrder(fq, &order)); 475 if (maxOrder[dim] < 0) maxOrder[dim] = order; 476 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]); 477 } 478 } 479 PetscCall(PetscFEGetDimension(fe, &Nb)); 480 PetscCall(PetscFEGetNumComponents(fe, &Nc)); 481 PetscCall(PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f])); 482 PetscCall(PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f])); 483 } else if (id == PETSCFV_CLASSID) { 484 PetscFV fv = (PetscFV)obj; 485 486 PetscCall(PetscFVGetQuadrature(fv, &q)); 487 PetscCall(PetscFVGetNumComponents(fv, &Nc)); 488 Nb = Nc; 489 PetscCall(PetscFVGetCellTabulation(fv, &prob->T[f])); 490 /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */ 491 } else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %" PetscInt_FMT, f); 492 } 493 prob->Nc[f] = Nc; 494 prob->Nb[f] = Nb; 495 prob->off[f + 1] = Nc + prob->off[f]; 496 prob->offDer[f + 1] = Nc * dim + prob->offDer[f]; 497 prob->offCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[0][f]; 498 prob->offDerCohesive[0][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[0][f]; 499 prob->offCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) + prob->offCohesive[0][f]; 500 prob->offDerCohesive[1][f] = (prob->cohesive[f] ? 0 : Nc) * dimEmbed + prob->offDerCohesive[0][f]; 501 prob->offCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) + prob->offCohesive[2][f]; 502 prob->offDerCohesive[2][f + 1] = (prob->cohesive[f] ? Nc : Nc * 2) * dimEmbed + prob->offDerCohesive[2][f]; 503 if (q) PetscCall(PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL)); 504 NqMax = PetscMax(NqMax, Nq); 505 NbMax = PetscMax(NbMax, Nb); 506 NcMax = PetscMax(NcMax, Nc); 507 prob->totDim += Nb; 508 prob->totComp += Nc; 509 /* There are two faces for all fields on a cohesive cell, except for cohesive fields */ 510 if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb; 511 } 512 prob->offCohesive[1][Nf] = prob->offCohesive[0][Nf]; 513 prob->offDerCohesive[1][Nf] = prob->offDerCohesive[0][Nf]; 514 /* Allocate works space */ 515 NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */ 516 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)); 517 PetscCall(PetscMalloc5(dimEmbed, &prob->x, NbMax * NcMax, &prob->basisReal, NbMax * NcMax * dimEmbed, &prob->basisDerReal, NbMax * NcMax, &prob->testReal, NbMax * NcMax * dimEmbed, &prob->testDerReal)); 518 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, 519 &prob->g2, NsMax * NsMax * NqMax * NcMax * NcMax * dimEmbed * dimEmbed, &prob->g3)); 520 PetscTryTypeMethod(prob, setup); 521 prob->setup = PETSC_TRUE; 522 PetscFunctionReturn(PETSC_SUCCESS); 523 } 524 525 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob) 526 { 527 PetscFunctionBegin; 528 PetscCall(PetscFree2(prob->Nc, prob->Nb)); 529 PetscCall(PetscFree2(prob->off, prob->offDer)); 530 PetscCall(PetscFree6(prob->offCohesive[0], prob->offCohesive[1], prob->offCohesive[2], prob->offDerCohesive[0], prob->offDerCohesive[1], prob->offDerCohesive[2])); 531 PetscCall(PetscFree2(prob->T, prob->Tf)); 532 PetscCall(PetscFree3(prob->u, prob->u_t, prob->u_x)); 533 PetscCall(PetscFree5(prob->x, prob->basisReal, prob->basisDerReal, prob->testReal, prob->testDerReal)); 534 PetscCall(PetscFree6(prob->f0, prob->f1, prob->g0, prob->g1, prob->g2, prob->g3)); 535 PetscFunctionReturn(PETSC_SUCCESS); 536 } 537 538 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew) 539 { 540 PetscObject *tmpd; 541 PetscBool *tmpi; 542 PetscInt *tmpk; 543 PetscBool *tmpc; 544 PetscPointFn **tmpup; 545 PetscSimplePointFn **tmpexactSol, **tmpexactSol_t, **tmplowerBound, **tmpupperBound; 546 void **tmpexactCtx, **tmpexactCtx_t, **tmplowerCtx, **tmpupperCtx; 547 void **tmpctx; 548 PetscInt Nf = prob->Nf, f; 549 550 PetscFunctionBegin; 551 if (Nf >= NfNew) PetscFunctionReturn(PETSC_SUCCESS); 552 prob->setup = PETSC_FALSE; 553 PetscCall(PetscDSDestroyStructs_Static(prob)); 554 PetscCall(PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk)); 555 for (f = 0; f < Nf; ++f) { 556 tmpd[f] = prob->disc[f]; 557 tmpi[f] = prob->implicit[f]; 558 tmpc[f] = prob->cohesive[f]; 559 tmpk[f] = prob->jetDegree[f]; 560 } 561 for (f = Nf; f < NfNew; ++f) { 562 tmpd[f] = NULL; 563 tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE; 564 tmpk[f] = 1; 565 } 566 PetscCall(PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree)); 567 PetscCall(PetscWeakFormSetNumFields(prob->wf, NfNew)); 568 prob->Nf = NfNew; 569 prob->disc = tmpd; 570 prob->implicit = tmpi; 571 prob->cohesive = tmpc; 572 prob->jetDegree = tmpk; 573 PetscCall(PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx)); 574 for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f]; 575 for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f]; 576 for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL; 577 for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL; 578 PetscCall(PetscFree2(prob->update, prob->ctx)); 579 prob->update = tmpup; 580 prob->ctx = tmpctx; 581 PetscCall(PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t)); 582 PetscCall(PetscCalloc4(NfNew, &tmplowerBound, NfNew, &tmplowerCtx, NfNew, &tmpupperBound, NfNew, &tmpupperCtx)); 583 for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f]; 584 for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f]; 585 for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f]; 586 for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f]; 587 for (f = 0; f < Nf; ++f) tmplowerBound[f] = prob->lowerBound[f]; 588 for (f = 0; f < Nf; ++f) tmplowerCtx[f] = prob->lowerCtx[f]; 589 for (f = 0; f < Nf; ++f) tmpupperBound[f] = prob->upperBound[f]; 590 for (f = 0; f < Nf; ++f) tmpupperCtx[f] = prob->upperCtx[f]; 591 for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL; 592 for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL; 593 for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL; 594 for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL; 595 for (f = Nf; f < NfNew; ++f) tmplowerBound[f] = NULL; 596 for (f = Nf; f < NfNew; ++f) tmplowerCtx[f] = NULL; 597 for (f = Nf; f < NfNew; ++f) tmpupperBound[f] = NULL; 598 for (f = Nf; f < NfNew; ++f) tmpupperCtx[f] = NULL; 599 PetscCall(PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t)); 600 PetscCall(PetscFree4(prob->lowerBound, prob->lowerCtx, prob->upperBound, prob->upperCtx)); 601 prob->exactSol = tmpexactSol; 602 prob->exactCtx = tmpexactCtx; 603 prob->exactSol_t = tmpexactSol_t; 604 prob->exactCtx_t = tmpexactCtx_t; 605 prob->lowerBound = tmplowerBound; 606 prob->lowerCtx = tmplowerCtx; 607 prob->upperBound = tmpupperBound; 608 prob->upperCtx = tmpupperCtx; 609 PetscFunctionReturn(PETSC_SUCCESS); 610 } 611 612 /*@ 613 PetscDSDestroy - Destroys a `PetscDS` object 614 615 Collective 616 617 Input Parameter: 618 . ds - the `PetscDS` object to destroy 619 620 Level: developer 621 622 .seealso: `PetscDSView()` 623 @*/ 624 PetscErrorCode PetscDSDestroy(PetscDS *ds) 625 { 626 PetscInt f; 627 628 PetscFunctionBegin; 629 if (!*ds) PetscFunctionReturn(PETSC_SUCCESS); 630 PetscValidHeaderSpecific(*ds, PETSCDS_CLASSID, 1); 631 632 if (--((PetscObject)*ds)->refct > 0) { 633 *ds = NULL; 634 PetscFunctionReturn(PETSC_SUCCESS); 635 } 636 ((PetscObject)*ds)->refct = 0; 637 if ((*ds)->subprobs) { 638 PetscInt dim, d; 639 640 PetscCall(PetscDSGetSpatialDimension(*ds, &dim)); 641 for (d = 0; d < dim; ++d) PetscCall(PetscDSDestroy(&(*ds)->subprobs[d])); 642 } 643 PetscCall(PetscFree((*ds)->subprobs)); 644 PetscCall(PetscDSDestroyStructs_Static(*ds)); 645 for (f = 0; f < (*ds)->Nf; ++f) PetscCall(PetscObjectDereference((*ds)->disc[f])); 646 PetscCall(PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree)); 647 PetscCall(PetscWeakFormDestroy(&(*ds)->wf)); 648 PetscCall(PetscFree2((*ds)->update, (*ds)->ctx)); 649 PetscCall(PetscFree4((*ds)->exactSol, (*ds)->exactCtx, (*ds)->exactSol_t, (*ds)->exactCtx_t)); 650 PetscCall(PetscFree4((*ds)->lowerBound, (*ds)->lowerCtx, (*ds)->upperBound, (*ds)->upperCtx)); 651 PetscTryTypeMethod(*ds, destroy); 652 PetscCall(PetscDSDestroyBoundary(*ds)); 653 PetscCall(PetscFree((*ds)->constants)); 654 for (PetscInt c = 0; c < DM_NUM_POLYTOPES; ++c) { 655 const PetscInt Na = DMPolytopeTypeGetNumArrangements((DMPolytopeType)c); 656 if ((*ds)->quadPerm[c]) 657 for (PetscInt o = 0; o < Na; ++o) PetscCall(ISDestroy(&(*ds)->quadPerm[c][o])); 658 PetscCall(PetscFree((*ds)->quadPerm[c])); 659 (*ds)->quadPerm[c] = NULL; 660 } 661 PetscCall(PetscHeaderDestroy(ds)); 662 PetscFunctionReturn(PETSC_SUCCESS); 663 } 664 665 /*@ 666 PetscDSCreate - Creates an empty `PetscDS` object. The type can then be set with `PetscDSSetType()`. 667 668 Collective 669 670 Input Parameter: 671 . comm - The communicator for the `PetscDS` object 672 673 Output Parameter: 674 . ds - The `PetscDS` object 675 676 Level: beginner 677 678 .seealso: `PetscDS`, `PetscDSSetType()`, `PETSCDSBASIC`, `PetscDSType`, `PetscDSDestroy()` 679 @*/ 680 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds) 681 { 682 PetscDS p; 683 684 PetscFunctionBegin; 685 PetscAssertPointer(ds, 2); 686 PetscCall(PetscDSInitializePackage()); 687 688 PetscCall(PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView)); 689 p->Nf = 0; 690 p->setup = PETSC_FALSE; 691 p->numConstants = 0; 692 p->numFuncConstants = 3; // Row and col fields, cell size 693 p->dimEmbed = -1; 694 p->useJacPre = PETSC_TRUE; 695 p->forceQuad = PETSC_TRUE; 696 PetscCall(PetscMalloc1(p->numConstants + p->numFuncConstants, &p->constants)); 697 PetscCall(PetscWeakFormCreate(comm, &p->wf)); 698 PetscCall(PetscArrayzero(p->quadPerm, DM_NUM_POLYTOPES)); 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, this can be a `PetscFE` or a `PetscFV` 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, this can be a `PetscFE` or a `PetscFV` 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 from within the `PetscDS` 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 to be used by the `PetscDS` 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 discretization object, this can be a `PetscFE` or `PetscFV` 1130 1131 Level: beginner 1132 1133 .seealso: `PetscWeakForm`, `PetscFE`, `PetscFV`, `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 `TSARKIMEX` 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: `TSARKIMEX`, `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 `TSARKIMEX` 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: `TSARKIMEX`, `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 that was provided with `PetscDSSetObjective()` 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, see `PetscPointFn` 1282 1283 Level: intermediate 1284 1285 Note: 1286 We are using a first order FEM model for the weak form\: $ \int_\Omega \phi\,\mathrm{obj}(u, u_t, \nabla u, x, t)$ 1287 1288 .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetObjective()`, `PetscDSGetResidual()` 1289 @*/ 1290 PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f, PetscPointFn **obj) 1291 { 1292 PetscPointFn **tmp; 1293 PetscInt n; 1294 1295 PetscFunctionBegin; 1296 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1297 PetscAssertPointer(obj, 3); 1298 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); 1299 PetscCall(PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp)); 1300 *obj = tmp ? tmp[0] : NULL; 1301 PetscFunctionReturn(PETSC_SUCCESS); 1302 } 1303 1304 /*@C 1305 PetscDSSetObjective - Set the pointwise objective function for a given test field 1306 1307 Not Collective 1308 1309 Input Parameters: 1310 + ds - The `PetscDS` 1311 . f - The test field number 1312 - obj - integrand for the test function term, see `PetscPointFn` 1313 1314 Level: intermediate 1315 1316 Note: 1317 We are using a first order FEM model for the weak form\: $ \int_\Omega \phi\,\mathrm{obj}(u, u_t, \nabla u, x, t)$ 1318 1319 .seealso: `PetscPointFn`, `PetscDS`, `PetscDSGetObjective()`, `PetscDSSetResidual()` 1320 @*/ 1321 PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f, PetscPointFn *obj) 1322 { 1323 PetscFunctionBegin; 1324 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1325 if (obj) PetscValidFunction(obj, 3); 1326 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1327 PetscCall(PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj)); 1328 PetscFunctionReturn(PETSC_SUCCESS); 1329 } 1330 1331 /*@C 1332 PetscDSGetResidual - Get the pointwise residual function for a given test field 1333 1334 Not Collective 1335 1336 Input Parameters: 1337 + ds - The `PetscDS` 1338 - f - The test field number 1339 1340 Output Parameters: 1341 + f0 - integrand for the test function term, see `PetscPointFn` 1342 - f1 - integrand for the test function gradient term, see `PetscPointFn` 1343 1344 Level: intermediate 1345 1346 Note: 1347 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)$ 1348 1349 .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetResidual()` 1350 @*/ 1351 PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f, PetscPointFn **f0, PetscPointFn **f1) 1352 { 1353 PetscPointFn **tmp0, **tmp1; 1354 PetscInt n0, n1; 1355 1356 PetscFunctionBegin; 1357 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1358 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); 1359 PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1)); 1360 *f0 = tmp0 ? tmp0[0] : NULL; 1361 *f1 = tmp1 ? tmp1[0] : NULL; 1362 PetscFunctionReturn(PETSC_SUCCESS); 1363 } 1364 1365 /*@C 1366 PetscDSSetResidual - Set the pointwise residual function for a given test field 1367 1368 Not Collective 1369 1370 Input Parameters: 1371 + ds - The `PetscDS` 1372 . f - The test field number 1373 . f0 - integrand for the test function term, see `PetscPointFn` 1374 - f1 - integrand for the test function gradient term, see `PetscPointFn` 1375 1376 Level: intermediate 1377 1378 Note: 1379 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)$ 1380 1381 .seealso: `PetscPointFn`, `PetscDS`, `PetscDSGetResidual()` 1382 @*/ 1383 PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f, PetscPointFn *f0, PetscPointFn *f1) 1384 { 1385 PetscFunctionBegin; 1386 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1387 if (f0) PetscValidFunction(f0, 3); 1388 if (f1) PetscValidFunction(f1, 4); 1389 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1390 PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1)); 1391 PetscFunctionReturn(PETSC_SUCCESS); 1392 } 1393 1394 /*@C 1395 PetscDSGetRHSResidual - Get the pointwise RHS residual function for explicit timestepping for a given test field 1396 1397 Not Collective 1398 1399 Input Parameters: 1400 + ds - The `PetscDS` 1401 - f - The test field number 1402 1403 Output Parameters: 1404 + f0 - integrand for the test function term, see `PetscPointFn` 1405 - f1 - integrand for the test function gradient term, see `PetscPointFn` 1406 1407 Level: intermediate 1408 1409 Note: 1410 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)$ 1411 1412 .seealso: `PetscPointFn`, `PetscDS`, `PetscDSSetRHSResidual()` 1413 @*/ 1414 PetscErrorCode PetscDSGetRHSResidual(PetscDS ds, PetscInt f, PetscPointFn **f0, PetscPointFn **f1) 1415 { 1416 PetscPointFn **tmp0, **tmp1; 1417 PetscInt n0, n1; 1418 1419 PetscFunctionBegin; 1420 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1421 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); 1422 PetscCall(PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 100, &n0, &tmp0, &n1, &tmp1)); 1423 *f0 = tmp0 ? tmp0[0] : NULL; 1424 *f1 = tmp1 ? tmp1[0] : NULL; 1425 PetscFunctionReturn(PETSC_SUCCESS); 1426 } 1427 1428 /*@C 1429 PetscDSSetRHSResidual - Set the pointwise residual function for explicit timestepping for a given test field 1430 1431 Not Collective 1432 1433 Input Parameters: 1434 + ds - The `PetscDS` 1435 . f - The test field number 1436 . f0 - integrand for the test function term, see `PetscPointFn` 1437 - f1 - integrand for the test function gradient term, see `PetscPointFn` 1438 1439 Level: intermediate 1440 1441 Note: 1442 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)$ 1443 1444 .seealso: `PetscDS`, `PetscDSGetResidual()` 1445 @*/ 1446 PetscErrorCode PetscDSSetRHSResidual(PetscDS ds, PetscInt f, PetscPointFn *f0, PetscPointFn *f1) 1447 { 1448 PetscFunctionBegin; 1449 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1450 if (f0) PetscValidFunction(f0, 3); 1451 if (f1) PetscValidFunction(f1, 4); 1452 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1453 PetscCall(PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 100, 0, f0, 0, f1)); 1454 PetscFunctionReturn(PETSC_SUCCESS); 1455 } 1456 1457 /*@ 1458 PetscDSHasJacobian - Checks that the Jacobian functions have been set 1459 1460 Not Collective 1461 1462 Input Parameter: 1463 . ds - The `PetscDS` 1464 1465 Output Parameter: 1466 . hasJac - flag that indicates the pointwise function for the Jacobian has been set 1467 1468 Level: intermediate 1469 1470 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1471 @*/ 1472 PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac) 1473 { 1474 PetscFunctionBegin; 1475 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1476 PetscCall(PetscWeakFormHasJacobian(ds->wf, hasJac)); 1477 PetscFunctionReturn(PETSC_SUCCESS); 1478 } 1479 1480 /*@C 1481 PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field 1482 1483 Not Collective 1484 1485 Input Parameters: 1486 + ds - The `PetscDS` 1487 . f - The test field number 1488 - g - The field number 1489 1490 Output Parameters: 1491 + g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1492 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1493 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1494 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1495 1496 Level: intermediate 1497 1498 Note: 1499 We are using a first order FEM model for the weak form\: 1500 1501 $$ 1502 \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 1503 + \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 1504 $$ 1505 1506 .seealso: `PetscDS`, `PetscDSSetJacobian()`, `PetscPointJacFn` 1507 @*/ 1508 PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3) 1509 { 1510 PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3; 1511 PetscInt n0, n1, n2, n3; 1512 1513 PetscFunctionBegin; 1514 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1515 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); 1516 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); 1517 PetscCall(PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1518 *g0 = tmp0 ? tmp0[0] : NULL; 1519 *g1 = tmp1 ? tmp1[0] : NULL; 1520 *g2 = tmp2 ? tmp2[0] : NULL; 1521 *g3 = tmp3 ? tmp3[0] : NULL; 1522 PetscFunctionReturn(PETSC_SUCCESS); 1523 } 1524 1525 /*@C 1526 PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields 1527 1528 Not Collective 1529 1530 Input Parameters: 1531 + ds - The `PetscDS` 1532 . f - The test field number 1533 . g - The field number 1534 . g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1535 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1536 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1537 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1538 1539 Level: intermediate 1540 1541 Note: 1542 We are using a first order FEM model for the weak form\: 1543 1544 $$ 1545 \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 1546 + \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 1547 $$ 1548 1549 .seealso: `PetscDS`, `PetscDSGetJacobian()`, `PetscPointJacFn` 1550 @*/ 1551 PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3) 1552 { 1553 PetscFunctionBegin; 1554 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1555 if (g0) PetscValidFunction(g0, 4); 1556 if (g1) PetscValidFunction(g1, 5); 1557 if (g2) PetscValidFunction(g2, 6); 1558 if (g3) PetscValidFunction(g3, 7); 1559 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1560 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1561 PetscCall(PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1562 PetscFunctionReturn(PETSC_SUCCESS); 1563 } 1564 1565 /*@ 1566 PetscDSUseJacobianPreconditioner - Set whether to construct a Jacobian preconditioner 1567 1568 Not Collective 1569 1570 Input Parameters: 1571 + prob - The `PetscDS` 1572 - useJacPre - flag that enables construction of a Jacobian preconditioner 1573 1574 Level: intermediate 1575 1576 Developer Note: 1577 Should be called `PetscDSSetUseJacobianPreconditioner()` 1578 1579 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1580 @*/ 1581 PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre) 1582 { 1583 PetscFunctionBegin; 1584 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1585 prob->useJacPre = useJacPre; 1586 PetscFunctionReturn(PETSC_SUCCESS); 1587 } 1588 1589 /*@ 1590 PetscDSHasJacobianPreconditioner - Checks if a Jacobian matrix for constructing a preconditioner has been set 1591 1592 Not Collective 1593 1594 Input Parameter: 1595 . ds - The `PetscDS` 1596 1597 Output Parameter: 1598 . hasJacPre - the flag 1599 1600 Level: intermediate 1601 1602 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()` 1603 @*/ 1604 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre) 1605 { 1606 PetscFunctionBegin; 1607 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1608 *hasJacPre = PETSC_FALSE; 1609 if (!ds->useJacPre) PetscFunctionReturn(PETSC_SUCCESS); 1610 PetscCall(PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre)); 1611 PetscFunctionReturn(PETSC_SUCCESS); 1612 } 1613 1614 /*@C 1615 PetscDSGetJacobianPreconditioner - Get the pointwise Jacobian function for given test and basis field that constructs the matrix used 1616 to compute the preconditioner. If this is missing, the system matrix is used to build the preconditioner. 1617 1618 Not Collective 1619 1620 Input Parameters: 1621 + ds - The `PetscDS` 1622 . f - The test field number 1623 - g - The field number 1624 1625 Output Parameters: 1626 + g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1627 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1628 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1629 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1630 1631 Level: intermediate 1632 1633 Note: 1634 We are using a first order FEM model for the weak form\: 1635 1636 $$ 1637 \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 1638 + \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 1639 $$ 1640 1641 Developer Note: 1642 The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner. 1643 1644 .seealso: `PetscDS`, `PetscDSSetJacobianPreconditioner()`, `PetscDSGetJacobian()`, `PetscPointJacFn` 1645 @*/ 1646 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3) 1647 { 1648 PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3; 1649 PetscInt n0, n1, n2, n3; 1650 1651 PetscFunctionBegin; 1652 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1653 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); 1654 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); 1655 PetscCall(PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1656 *g0 = tmp0 ? tmp0[0] : NULL; 1657 *g1 = tmp1 ? tmp1[0] : NULL; 1658 *g2 = tmp2 ? tmp2[0] : NULL; 1659 *g3 = tmp3 ? tmp3[0] : NULL; 1660 PetscFunctionReturn(PETSC_SUCCESS); 1661 } 1662 1663 /*@C 1664 PetscDSSetJacobianPreconditioner - Set the pointwise Jacobian function for given test and basis fields that constructs the matrix used 1665 to compute the preconditioner. If this is missing, the system matrix is used to build the preconditioner. 1666 1667 Not Collective 1668 1669 Input Parameters: 1670 + ds - The `PetscDS` 1671 . f - The test field number 1672 . g - The field number 1673 . g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1674 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1675 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1676 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1677 1678 Level: intermediate 1679 1680 Note: 1681 We are using a first order FEM model for the weak form\: 1682 1683 $$ 1684 \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 1685 + \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 1686 $$ 1687 1688 Developer Note: 1689 The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner. 1690 1691 .seealso: `PetscDS`, `PetscDSGetJacobianPreconditioner()`, `PetscDSSetJacobian()`, `PetscPointJacFn` 1692 @*/ 1693 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3) 1694 { 1695 PetscFunctionBegin; 1696 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1697 if (g0) PetscValidFunction(g0, 4); 1698 if (g1) PetscValidFunction(g1, 5); 1699 if (g2) PetscValidFunction(g2, 6); 1700 if (g3) PetscValidFunction(g3, 7); 1701 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1702 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1703 PetscCall(PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1704 PetscFunctionReturn(PETSC_SUCCESS); 1705 } 1706 1707 /*@ 1708 PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, $dF/du_t$, has been set 1709 1710 Not Collective 1711 1712 Input Parameter: 1713 . ds - The `PetscDS` 1714 1715 Output Parameter: 1716 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set 1717 1718 Level: intermediate 1719 1720 .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscDSGetJacobian()` 1721 @*/ 1722 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac) 1723 { 1724 PetscFunctionBegin; 1725 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1726 PetscCall(PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac)); 1727 PetscFunctionReturn(PETSC_SUCCESS); 1728 } 1729 1730 /*@C 1731 PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, $dF/du_t$, function for given test and basis field 1732 1733 Not Collective 1734 1735 Input Parameters: 1736 + ds - The `PetscDS` 1737 . f - The test field number 1738 - g - The field number 1739 1740 Output Parameters: 1741 + g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1742 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1743 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1744 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1745 1746 Level: intermediate 1747 1748 Note: 1749 We are using a first order FEM model for the weak form\: 1750 1751 $$ 1752 \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 1753 + \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 1754 $$ 1755 1756 .seealso: `PetscDS`, `PetscDSSetJacobian()`, `PetscDSSetDynamicJacobian()`, `PetscPointJacFn` 1757 @*/ 1758 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn **g0, PetscPointJacFn **g1, PetscPointJacFn **g2, PetscPointJacFn **g3) 1759 { 1760 PetscPointJacFn **tmp0, **tmp1, **tmp2, **tmp3; 1761 PetscInt n0, n1, n2, n3; 1762 1763 PetscFunctionBegin; 1764 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1765 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); 1766 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); 1767 PetscCall(PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 1768 *g0 = tmp0 ? tmp0[0] : NULL; 1769 *g1 = tmp1 ? tmp1[0] : NULL; 1770 *g2 = tmp2 ? tmp2[0] : NULL; 1771 *g3 = tmp3 ? tmp3[0] : NULL; 1772 PetscFunctionReturn(PETSC_SUCCESS); 1773 } 1774 1775 /*@C 1776 PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, $dF/du_t$, function for given test and basis fields 1777 1778 Not Collective 1779 1780 Input Parameters: 1781 + ds - The `PetscDS` 1782 . f - The test field number 1783 . g - The field number 1784 . g0 - integrand for the test and basis function term, see `PetscPointJacFn` 1785 . g1 - integrand for the test function and basis function gradient term, see `PetscPointJacFn` 1786 . g2 - integrand for the test function gradient and basis function term, see `PetscPointJacFn` 1787 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscPointJacFn` 1788 1789 Level: intermediate 1790 1791 Note: 1792 We are using a first order FEM model for the weak form\: 1793 1794 $$ 1795 \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 1796 + \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 1797 $$ 1798 1799 .seealso: `PetscDS`, `PetscDSGetDynamicJacobian()`, `PetscDSGetJacobian()`, `PetscPointJacFn` 1800 @*/ 1801 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscPointJacFn *g0, PetscPointJacFn *g1, PetscPointJacFn *g2, PetscPointJacFn *g3) 1802 { 1803 PetscFunctionBegin; 1804 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1805 if (g0) PetscValidFunction(g0, 4); 1806 if (g1) PetscValidFunction(g1, 5); 1807 if (g2) PetscValidFunction(g2, 6); 1808 if (g3) PetscValidFunction(g3, 7); 1809 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1810 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 1811 PetscCall(PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 1812 PetscFunctionReturn(PETSC_SUCCESS); 1813 } 1814 1815 /*@C 1816 PetscDSGetRiemannSolver - Returns the Riemann solver for the given field 1817 1818 Not Collective 1819 1820 Input Parameters: 1821 + ds - The `PetscDS` object 1822 - f - The field number 1823 1824 Output Parameter: 1825 . r - Riemann solver, see `PetscRiemannFn` 1826 1827 Level: intermediate 1828 1829 .seealso: `PetscDS`, `PetscRiemannFn`, `PetscDSSetRiemannSolver()` 1830 @*/ 1831 PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, PetscRiemannFn **r) 1832 { 1833 PetscRiemannFn **tmp; 1834 PetscInt n; 1835 1836 PetscFunctionBegin; 1837 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1838 PetscAssertPointer(r, 3); 1839 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); 1840 PetscCall(PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp)); 1841 *r = tmp ? tmp[0] : NULL; 1842 PetscFunctionReturn(PETSC_SUCCESS); 1843 } 1844 1845 /*@C 1846 PetscDSSetRiemannSolver - Sets the Riemann solver for the given field 1847 1848 Not Collective 1849 1850 Input Parameters: 1851 + ds - The `PetscDS` object 1852 . f - The field number 1853 - r - Riemann solver, see `PetscRiemannFn` 1854 1855 Level: intermediate 1856 1857 .seealso: `PetscDS`, `PetscRiemannFn`, `PetscDSGetRiemannSolver()` 1858 @*/ 1859 PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, PetscRiemannFn *r) 1860 { 1861 PetscFunctionBegin; 1862 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1863 if (r) PetscValidFunction(r, 3); 1864 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1865 PetscCall(PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r)); 1866 PetscFunctionReturn(PETSC_SUCCESS); 1867 } 1868 1869 /*@C 1870 PetscDSGetUpdate - Get the pointwise update function for a given field 1871 1872 Not Collective 1873 1874 Input Parameters: 1875 + ds - The `PetscDS` 1876 - f - The field number 1877 1878 Output Parameter: 1879 . update - update function, see `PetscPointFn` 1880 1881 Level: intermediate 1882 1883 .seealso: `PetscDS`, `PetscPointFn`, `PetscDSSetUpdate()`, `PetscDSSetResidual()` 1884 @*/ 1885 PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, PetscPointFn **update) 1886 { 1887 PetscFunctionBegin; 1888 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1889 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); 1890 if (update) { 1891 PetscAssertPointer(update, 3); 1892 *update = ds->update[f]; 1893 } 1894 PetscFunctionReturn(PETSC_SUCCESS); 1895 } 1896 1897 /*@C 1898 PetscDSSetUpdate - Set the pointwise update function for a given field 1899 1900 Not Collective 1901 1902 Input Parameters: 1903 + ds - The `PetscDS` 1904 . f - The field number 1905 - update - update function, see `PetscPointFn` 1906 1907 Level: intermediate 1908 1909 .seealso: `PetscDS`, `PetscPointFn`, `PetscDSGetResidual()` 1910 @*/ 1911 PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, PetscPointFn *update) 1912 { 1913 PetscFunctionBegin; 1914 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1915 if (update) PetscValidFunction(update, 3); 1916 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1917 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 1918 ds->update[f] = update; 1919 PetscFunctionReturn(PETSC_SUCCESS); 1920 } 1921 1922 /*@C 1923 PetscDSGetContext - Returns the context that was passed by `PetscDSSetContext()` 1924 1925 Not Collective 1926 1927 Input Parameters: 1928 + ds - The `PetscDS` 1929 . f - The field number 1930 - ctx - the context 1931 1932 Level: intermediate 1933 1934 .seealso: `PetscDS`, `PetscPointFn`, `PetscDSSetContext()` 1935 @*/ 1936 PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx) 1937 { 1938 PetscFunctionBegin; 1939 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1940 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); 1941 PetscAssertPointer(ctx, 3); 1942 *(void **)ctx = ds->ctx[f]; 1943 PetscFunctionReturn(PETSC_SUCCESS); 1944 } 1945 1946 /*@C 1947 PetscDSSetContext - Sets the context that is passed back to some of the pointwise function callbacks used by this `PetscDS` 1948 1949 Not Collective 1950 1951 Input Parameters: 1952 + ds - The `PetscDS` 1953 . f - The field number 1954 - ctx - the context 1955 1956 Level: intermediate 1957 1958 .seealso: `PetscDS`, `PetscPointFn`, `PetscDSGetContext()` 1959 @*/ 1960 PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx) 1961 { 1962 PetscFunctionBegin; 1963 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1964 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 1965 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 1966 ds->ctx[f] = ctx; 1967 PetscFunctionReturn(PETSC_SUCCESS); 1968 } 1969 1970 /*@C 1971 PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field 1972 1973 Not Collective 1974 1975 Input Parameters: 1976 + ds - The PetscDS 1977 - f - The test field number 1978 1979 Output Parameters: 1980 + f0 - boundary integrand for the test function term, see `PetscBdPointFn` 1981 - f1 - boundary integrand for the test function gradient term, see `PetscBdPointFn` 1982 1983 Level: intermediate 1984 1985 Note: 1986 We are using a first order FEM model for the weak form\: 1987 1988 $$ 1989 \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 1990 $$ 1991 1992 .seealso: `PetscDS`, `PetscBdPointFn`, `PetscDSSetBdResidual()` 1993 @*/ 1994 PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, PetscBdPointFn **f0, PetscBdPointFn **f1) 1995 { 1996 PetscBdPointFn **tmp0, **tmp1; 1997 PetscInt n0, n1; 1998 1999 PetscFunctionBegin; 2000 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2001 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); 2002 PetscCall(PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1)); 2003 *f0 = tmp0 ? tmp0[0] : NULL; 2004 *f1 = tmp1 ? tmp1[0] : NULL; 2005 PetscFunctionReturn(PETSC_SUCCESS); 2006 } 2007 2008 /*@C 2009 PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field 2010 2011 Not Collective 2012 2013 Input Parameters: 2014 + ds - The `PetscDS` 2015 . f - The test field number 2016 . f0 - boundary integrand for the test function term, see `PetscBdPointFn` 2017 - f1 - boundary integrand for the test function gradient term, see `PetscBdPointFn` 2018 2019 Level: intermediate 2020 2021 Note: 2022 We are using a first order FEM model for the weak form\: 2023 2024 $$ 2025 \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 2026 $$ 2027 2028 .seealso: `PetscDS`, `PetscBdPointFn`, `PetscDSGetBdResidual()` 2029 @*/ 2030 PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, PetscBdPointFn *f0, PetscBdPointFn *f1) 2031 { 2032 PetscFunctionBegin; 2033 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2034 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2035 PetscCall(PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1)); 2036 PetscFunctionReturn(PETSC_SUCCESS); 2037 } 2038 2039 /*@ 2040 PetscDSHasBdJacobian - Indicates that boundary Jacobian functions have been set 2041 2042 Not Collective 2043 2044 Input Parameter: 2045 . ds - The `PetscDS` 2046 2047 Output Parameter: 2048 . hasBdJac - flag that pointwise function for the boundary Jacobian has been set 2049 2050 Level: intermediate 2051 2052 .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()` 2053 @*/ 2054 PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac) 2055 { 2056 PetscFunctionBegin; 2057 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2058 PetscAssertPointer(hasBdJac, 2); 2059 PetscCall(PetscWeakFormHasBdJacobian(ds->wf, hasBdJac)); 2060 PetscFunctionReturn(PETSC_SUCCESS); 2061 } 2062 2063 /*@C 2064 PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field 2065 2066 Not Collective 2067 2068 Input Parameters: 2069 + ds - The `PetscDS` 2070 . f - The test field number 2071 - g - The field number 2072 2073 Output Parameters: 2074 + g0 - integrand for the test and basis function term, see `PetscBdPointJacFn` 2075 . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn` 2076 . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn` 2077 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn` 2078 2079 Level: intermediate 2080 2081 Note: 2082 We are using a first order FEM model for the weak form\: 2083 2084 $$ 2085 \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 2086 + \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 2087 $$ 2088 2089 .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSSetBdJacobian()` 2090 @*/ 2091 PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn **g0, PetscBdPointJacFn **g1, PetscBdPointJacFn **g2, PetscBdPointJacFn **g3) 2092 { 2093 PetscBdPointJacFn **tmp0, **tmp1, **tmp2, **tmp3; 2094 PetscInt n0, n1, n2, n3; 2095 2096 PetscFunctionBegin; 2097 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2098 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); 2099 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); 2100 PetscCall(PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 2101 *g0 = tmp0 ? tmp0[0] : NULL; 2102 *g1 = tmp1 ? tmp1[0] : NULL; 2103 *g2 = tmp2 ? tmp2[0] : NULL; 2104 *g3 = tmp3 ? tmp3[0] : NULL; 2105 PetscFunctionReturn(PETSC_SUCCESS); 2106 } 2107 2108 /*@C 2109 PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field 2110 2111 Not Collective 2112 2113 Input Parameters: 2114 + ds - The PetscDS 2115 . f - The test field number 2116 . g - The field number 2117 . g0 - integrand for the test and basis function term, see `PetscBdPointJacFn` 2118 . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn` 2119 . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn` 2120 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn` 2121 2122 Level: intermediate 2123 2124 Note: 2125 We are using a first order FEM model for the weak form\: 2126 2127 $$ 2128 \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 2129 + \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 2130 $$ 2131 2132 .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSGetBdJacobian()` 2133 @*/ 2134 PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn *g0, PetscBdPointJacFn *g1, PetscBdPointJacFn *g2, PetscBdPointJacFn *g3) 2135 { 2136 PetscFunctionBegin; 2137 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2138 if (g0) PetscValidFunction(g0, 4); 2139 if (g1) PetscValidFunction(g1, 5); 2140 if (g2) PetscValidFunction(g2, 6); 2141 if (g3) PetscValidFunction(g3, 7); 2142 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2143 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 2144 PetscCall(PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 2145 PetscFunctionReturn(PETSC_SUCCESS); 2146 } 2147 2148 /*@ 2149 PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set with `PetscDSSetBdJacobianPreconditioner()` 2150 2151 Not Collective 2152 2153 Input Parameter: 2154 . ds - The `PetscDS` 2155 2156 Output Parameter: 2157 . hasBdJacPre - flag that pointwise function for the boundary Jacobian matrix to construct the preconditioner has been set 2158 2159 Level: intermediate 2160 2161 Developer Note: 2162 The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner. 2163 2164 .seealso: `PetscDS`, `PetscDSHasJacobian()`, `PetscDSSetBdJacobian()`, `PetscDSGetBdJacobian()` 2165 @*/ 2166 PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre) 2167 { 2168 PetscFunctionBegin; 2169 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2170 PetscAssertPointer(hasBdJacPre, 2); 2171 PetscCall(PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre)); 2172 PetscFunctionReturn(PETSC_SUCCESS); 2173 } 2174 2175 /*@C 2176 PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian function for given test and basis field that constructs the 2177 matrix used to construct the preconditioner 2178 2179 Not Collective; No Fortran Support 2180 2181 Input Parameters: 2182 + ds - The `PetscDS` 2183 . f - The test field number 2184 - g - The field number 2185 2186 Output Parameters: 2187 + g0 - integrand for the test and basis function term, see `PetscBdPointJacFn` 2188 . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn` 2189 . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn` 2190 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn` 2191 2192 Level: intermediate 2193 2194 Note: 2195 We are using a first order FEM model for the weak form\: 2196 2197 $$ 2198 \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 2199 + \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 2200 $$ 2201 2202 Developer Note: 2203 The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner. 2204 2205 .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSSetBdJacobianPreconditioner()` 2206 @*/ 2207 PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn **g0, PetscBdPointJacFn **g1, PetscBdPointJacFn **g2, PetscBdPointJacFn **g3) 2208 { 2209 PetscBdPointJacFn **tmp0, **tmp1, **tmp2, **tmp3; 2210 PetscInt n0, n1, n2, n3; 2211 2212 PetscFunctionBegin; 2213 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2214 PetscCheck(!(f < 0) && !(f >= ds->Nf), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, ds->Nf); 2215 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); 2216 PetscCall(PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3)); 2217 *g0 = tmp0 ? tmp0[0] : NULL; 2218 *g1 = tmp1 ? tmp1[0] : NULL; 2219 *g2 = tmp2 ? tmp2[0] : NULL; 2220 *g3 = tmp3 ? tmp3[0] : NULL; 2221 PetscFunctionReturn(PETSC_SUCCESS); 2222 } 2223 2224 /*@C 2225 PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field that constructs the 2226 matrix used to construct the preconditioner 2227 2228 Not Collective; No Fortran Support 2229 2230 Input Parameters: 2231 + ds - The `PetscDS` 2232 . f - The test field number 2233 . g - The field number 2234 . g0 - integrand for the test and basis function term, see `PetscBdPointJacFn` 2235 . g1 - integrand for the test function and basis function gradient term, see `PetscBdPointJacFn` 2236 . g2 - integrand for the test function gradient and basis function term, see `PetscBdPointJacFn` 2237 - g3 - integrand for the test function gradient and basis function gradient term, see `PetscBdPointJacFn` 2238 2239 Level: intermediate 2240 2241 Note: 2242 We are using a first order FEM model for the weak form\: 2243 2244 $$ 2245 \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 2246 + \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 2247 $$ 2248 2249 Developer Note: 2250 The name is confusing since the function computes a matrix used to construct the preconditioner, not a preconditioner. 2251 2252 .seealso: `PetscDS`, `PetscBdPointJacFn`, `PetscDSGetBdJacobianPreconditioner()` 2253 @*/ 2254 PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, PetscBdPointJacFn *g0, PetscBdPointJacFn *g1, PetscBdPointJacFn *g2, PetscBdPointJacFn *g3) 2255 { 2256 PetscFunctionBegin; 2257 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2258 if (g0) PetscValidFunction(g0, 4); 2259 if (g1) PetscValidFunction(g1, 5); 2260 if (g2) PetscValidFunction(g2, 6); 2261 if (g3) PetscValidFunction(g3, 7); 2262 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2263 PetscCheck(g >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", g); 2264 PetscCall(PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3)); 2265 PetscFunctionReturn(PETSC_SUCCESS); 2266 } 2267 2268 /*@C 2269 PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field 2270 2271 Not Collective 2272 2273 Input Parameters: 2274 + prob - The `PetscDS` 2275 - f - The test field number 2276 2277 Output Parameters: 2278 + sol - exact solution function for the test field, see `PetscPointExactSolutionFn` 2279 - ctx - exact solution context 2280 2281 Level: intermediate 2282 2283 .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSSetExactSolution()`, `PetscDSGetExactSolutionTimeDerivative()` 2284 @*/ 2285 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscPointExactSolutionFn **sol, void **ctx) 2286 { 2287 PetscFunctionBegin; 2288 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2289 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); 2290 if (sol) { 2291 PetscAssertPointer(sol, 3); 2292 *sol = prob->exactSol[f]; 2293 } 2294 if (ctx) { 2295 PetscAssertPointer(ctx, 4); 2296 *ctx = prob->exactCtx[f]; 2297 } 2298 PetscFunctionReturn(PETSC_SUCCESS); 2299 } 2300 2301 /*@C 2302 PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field 2303 2304 Not Collective 2305 2306 Input Parameters: 2307 + prob - The `PetscDS` 2308 . f - The test field number 2309 . sol - solution function for the test fields, see `PetscPointExactSolutionFn` 2310 - ctx - solution context or `NULL` 2311 2312 Level: intermediate 2313 2314 .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSGetExactSolution()` 2315 @*/ 2316 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscPointExactSolutionFn *sol, void *ctx) 2317 { 2318 PetscFunctionBegin; 2319 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2320 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2321 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2322 if (sol) { 2323 PetscValidFunction(sol, 3); 2324 prob->exactSol[f] = sol; 2325 } 2326 if (ctx) { 2327 PetscValidFunction(ctx, 4); 2328 prob->exactCtx[f] = ctx; 2329 } 2330 PetscFunctionReturn(PETSC_SUCCESS); 2331 } 2332 2333 /*@C 2334 PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field 2335 2336 Not Collective 2337 2338 Input Parameters: 2339 + prob - The `PetscDS` 2340 - f - The test field number 2341 2342 Output Parameters: 2343 + sol - time derivative of the exact solution for the test field, see `PetscPointExactSolutionFn` 2344 - ctx - the exact solution context 2345 2346 Level: intermediate 2347 2348 .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSSetExactSolutionTimeDerivative()`, `PetscDSGetExactSolution()` 2349 @*/ 2350 PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscPointExactSolutionFn **sol, void **ctx) 2351 { 2352 PetscFunctionBegin; 2353 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2354 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); 2355 if (sol) { 2356 PetscAssertPointer(sol, 3); 2357 *sol = prob->exactSol_t[f]; 2358 } 2359 if (ctx) { 2360 PetscAssertPointer(ctx, 4); 2361 *ctx = prob->exactCtx_t[f]; 2362 } 2363 PetscFunctionReturn(PETSC_SUCCESS); 2364 } 2365 2366 /*@C 2367 PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field 2368 2369 Not Collective 2370 2371 Input Parameters: 2372 + prob - The `PetscDS` 2373 . f - The test field number 2374 . sol - time derivative of the solution function for the test fields, see `PetscPointExactSolutionFn` 2375 - ctx - the solution context or `NULL` 2376 2377 Level: intermediate 2378 2379 .seealso: `PetscDS`, `PetscPointExactSolutionFn`, `PetscDSGetExactSolutionTimeDerivative()`, `PetscDSSetExactSolution()` 2380 @*/ 2381 PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscPointExactSolutionFn *sol, void *ctx) 2382 { 2383 PetscFunctionBegin; 2384 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2385 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2386 PetscCall(PetscDSEnlarge_Static(prob, f + 1)); 2387 if (sol) { 2388 PetscValidFunction(sol, 3); 2389 prob->exactSol_t[f] = sol; 2390 } 2391 if (ctx) { 2392 PetscValidFunction(ctx, 4); 2393 prob->exactCtx_t[f] = ctx; 2394 } 2395 PetscFunctionReturn(PETSC_SUCCESS); 2396 } 2397 2398 /*@C 2399 PetscDSGetLowerBound - Get the pointwise lower bound function for a given field 2400 2401 Not Collective 2402 2403 Input Parameters: 2404 + ds - The PetscDS 2405 - f - The field number 2406 2407 Output Parameters: 2408 + lb - lower bound function for the field, see `PetscPointBoundFn` 2409 - ctx - lower bound context that was set with `PetscDSSetLowerBound()` 2410 2411 Level: intermediate 2412 2413 .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSSetLowerBound()`, `PetscDSGetUpperBound()`, `PetscDSGetExactSolution()` 2414 @*/ 2415 PetscErrorCode PetscDSGetLowerBound(PetscDS ds, PetscInt f, PetscPointBoundFn **lb, void **ctx) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2419 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); 2420 if (lb) { 2421 PetscAssertPointer(lb, 3); 2422 *lb = ds->lowerBound[f]; 2423 } 2424 if (ctx) { 2425 PetscAssertPointer(ctx, 4); 2426 *ctx = ds->lowerCtx[f]; 2427 } 2428 PetscFunctionReturn(PETSC_SUCCESS); 2429 } 2430 2431 /*@C 2432 PetscDSSetLowerBound - Set the pointwise lower bound function for a given field 2433 2434 Not Collective 2435 2436 Input Parameters: 2437 + ds - The `PetscDS` 2438 . f - The field number 2439 . lb - lower bound function for the test fields, see `PetscPointBoundFn` 2440 - ctx - lower bound context or `NULL` which will be passed to `lb` 2441 2442 Level: intermediate 2443 2444 .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSGetLowerBound()`, `PetscDSGetUpperBound()`, `PetscDSGetExactSolution()` 2445 @*/ 2446 PetscErrorCode PetscDSSetLowerBound(PetscDS ds, PetscInt f, PetscPointBoundFn *lb, void *ctx) 2447 { 2448 PetscFunctionBegin; 2449 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2450 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2451 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 2452 if (lb) { 2453 PetscValidFunction(lb, 3); 2454 ds->lowerBound[f] = lb; 2455 } 2456 if (ctx) { 2457 PetscValidFunction(ctx, 4); 2458 ds->lowerCtx[f] = ctx; 2459 } 2460 PetscFunctionReturn(PETSC_SUCCESS); 2461 } 2462 2463 /*@C 2464 PetscDSGetUpperBound - Get the pointwise upper bound function for a given field 2465 2466 Not Collective 2467 2468 Input Parameters: 2469 + ds - The `PetscDS` 2470 - f - The field number 2471 2472 Output Parameters: 2473 + ub - upper bound function for the field, see `PetscPointBoundFn` 2474 - ctx - upper bound context that was set with `PetscDSSetUpperBound()` 2475 2476 Level: intermediate 2477 2478 .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSSetUpperBound()`, `PetscDSGetLowerBound()`, `PetscDSGetExactSolution()` 2479 @*/ 2480 PetscErrorCode PetscDSGetUpperBound(PetscDS ds, PetscInt f, PetscPointBoundFn **ub, void **ctx) 2481 { 2482 PetscFunctionBegin; 2483 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2484 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); 2485 if (ub) { 2486 PetscAssertPointer(ub, 3); 2487 *ub = ds->upperBound[f]; 2488 } 2489 if (ctx) { 2490 PetscAssertPointer(ctx, 4); 2491 *ctx = ds->upperCtx[f]; 2492 } 2493 PetscFunctionReturn(PETSC_SUCCESS); 2494 } 2495 2496 /*@C 2497 PetscDSSetUpperBound - Set the pointwise upper bound function for a given field 2498 2499 Not Collective 2500 2501 Input Parameters: 2502 + ds - The `PetscDS` 2503 . f - The field number 2504 . ub - upper bound function for the test fields, see `PetscPointBoundFn` 2505 - ctx - context or `NULL` that will be passed to `ub` 2506 2507 Level: intermediate 2508 2509 .seealso: `PetscDS`, `PetscPointBoundFn`, `PetscDSGetUpperBound()`, `PetscDSGetLowerBound()`, `PetscDSGetExactSolution()` 2510 @*/ 2511 PetscErrorCode PetscDSSetUpperBound(PetscDS ds, PetscInt f, PetscPointBoundFn *ub, void *ctx) 2512 { 2513 PetscFunctionBegin; 2514 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2515 PetscCheck(f >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %" PetscInt_FMT " must be non-negative", f); 2516 PetscCall(PetscDSEnlarge_Static(ds, f + 1)); 2517 if (ub) { 2518 PetscValidFunction(ub, 3); 2519 ds->upperBound[f] = ub; 2520 } 2521 if (ctx) { 2522 PetscValidFunction(ctx, 4); 2523 ds->upperCtx[f] = ctx; 2524 } 2525 PetscFunctionReturn(PETSC_SUCCESS); 2526 } 2527 2528 /*@C 2529 PetscDSGetConstants - Returns the array of constants passed to point functions from a `PetscDS` object 2530 2531 Not Collective 2532 2533 Input Parameter: 2534 . ds - The `PetscDS` object 2535 2536 Output Parameters: 2537 + numConstants - The number of constants, or pass in `NULL` if not required 2538 - constants - The array of constants, `NULL` if there are none 2539 2540 Level: intermediate 2541 2542 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSCreate()` 2543 @*/ 2544 PetscErrorCode PetscDSGetConstants(PetscDS ds, PeOp PetscInt *numConstants, PeOp const PetscScalar *constants[]) 2545 { 2546 PetscFunctionBegin; 2547 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2548 if (numConstants) { 2549 PetscAssertPointer(numConstants, 2); 2550 *numConstants = ds->numConstants; 2551 } 2552 if (constants) { 2553 PetscAssertPointer(constants, 3); 2554 *constants = ds->constants; 2555 } 2556 PetscFunctionReturn(PETSC_SUCCESS); 2557 } 2558 2559 /*@C 2560 PetscDSSetConstants - Set the array of constants passed to point functions from a `PetscDS` 2561 2562 Not Collective 2563 2564 Input Parameters: 2565 + ds - The `PetscDS` object 2566 . numConstants - The number of constants 2567 - constants - The array of constants, `NULL` if there are none 2568 2569 Level: intermediate 2570 2571 .seealso: `PetscDS`, `PetscDSGetConstants()`, `PetscDSCreate()` 2572 @*/ 2573 PetscErrorCode PetscDSSetConstants(PetscDS ds, PetscInt numConstants, PetscScalar constants[]) 2574 { 2575 PetscFunctionBegin; 2576 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2577 if (numConstants != ds->numConstants) { 2578 PetscCall(PetscFree(ds->constants)); 2579 ds->numConstants = numConstants; 2580 PetscCall(PetscMalloc1(ds->numConstants + ds->numFuncConstants, &ds->constants)); 2581 } 2582 if (ds->numConstants) { 2583 PetscAssertPointer(constants, 3); 2584 PetscCall(PetscArraycpy(ds->constants, constants, ds->numConstants)); 2585 } 2586 PetscFunctionReturn(PETSC_SUCCESS); 2587 } 2588 2589 /*@C 2590 PetscDSSetIntegrationParameters - Set the parameters for a particular integration 2591 2592 Not Collective 2593 2594 Input Parameters: 2595 + ds - The `PetscDS` object 2596 . fieldI - The test field for a given point function, or `PETSC_DETERMINE` 2597 - fieldJ - The basis field for a given point function, or `PETSC_DETERMINE` 2598 2599 Level: intermediate 2600 2601 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSGetConstants()`, `PetscDSCreate()` 2602 @*/ 2603 PetscErrorCode PetscDSSetIntegrationParameters(PetscDS ds, PetscInt fieldI, PetscInt fieldJ) 2604 { 2605 PetscFunctionBegin; 2606 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2607 ds->constants[ds->numConstants] = fieldI; 2608 ds->constants[ds->numConstants + 1] = fieldJ; 2609 PetscFunctionReturn(PETSC_SUCCESS); 2610 } 2611 2612 /*@C 2613 PetscDSSetCellParameters - Set the parameters for a particular cell 2614 2615 Not Collective 2616 2617 Input Parameters: 2618 + ds - The `PetscDS` object 2619 - volume - The cell volume 2620 2621 Level: intermediate 2622 2623 .seealso: `PetscDS`, `PetscDSSetConstants()`, `PetscDSGetConstants()`, `PetscDSCreate()` 2624 @*/ 2625 PetscErrorCode PetscDSSetCellParameters(PetscDS ds, PetscReal volume) 2626 { 2627 PetscFunctionBegin; 2628 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2629 ds->constants[ds->numConstants + 2] = volume; 2630 PetscFunctionReturn(PETSC_SUCCESS); 2631 } 2632 2633 /*@ 2634 PetscDSGetFieldIndex - Returns the index of the given field 2635 2636 Not Collective 2637 2638 Input Parameters: 2639 + prob - The `PetscDS` object 2640 - disc - The discretization object 2641 2642 Output Parameter: 2643 . f - The field number 2644 2645 Level: beginner 2646 2647 .seealso: `PetscDS`, `PetscGetDiscretization()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2648 @*/ 2649 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2650 { 2651 PetscInt g; 2652 2653 PetscFunctionBegin; 2654 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2655 PetscAssertPointer(f, 3); 2656 *f = -1; 2657 for (g = 0; g < prob->Nf; ++g) { 2658 if (disc == prob->disc[g]) break; 2659 } 2660 PetscCheck(g != prob->Nf, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2661 *f = g; 2662 PetscFunctionReturn(PETSC_SUCCESS); 2663 } 2664 2665 /*@ 2666 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2667 2668 Not Collective 2669 2670 Input Parameters: 2671 + prob - The `PetscDS` object 2672 - f - The field number 2673 2674 Output Parameter: 2675 . size - The size 2676 2677 Level: beginner 2678 2679 .seealso: `PetscDS`, `PetscDSGetFieldOffset()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2680 @*/ 2681 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2682 { 2683 PetscFunctionBegin; 2684 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2685 PetscAssertPointer(size, 3); 2686 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); 2687 PetscCall(PetscDSSetUp(prob)); 2688 *size = prob->Nb[f]; 2689 PetscFunctionReturn(PETSC_SUCCESS); 2690 } 2691 2692 /*@ 2693 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2694 2695 Not Collective 2696 2697 Input Parameters: 2698 + prob - The `PetscDS` object 2699 - f - The field number 2700 2701 Output Parameter: 2702 . off - The offset 2703 2704 Level: beginner 2705 2706 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2707 @*/ 2708 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2709 { 2710 PetscInt size, g; 2711 2712 PetscFunctionBegin; 2713 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2714 PetscAssertPointer(off, 3); 2715 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); 2716 *off = 0; 2717 for (g = 0; g < f; ++g) { 2718 PetscCall(PetscDSGetFieldSize(prob, g, &size)); 2719 *off += size; 2720 } 2721 PetscFunctionReturn(PETSC_SUCCESS); 2722 } 2723 2724 /*@ 2725 PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell 2726 2727 Not Collective 2728 2729 Input Parameters: 2730 + ds - The `PetscDS` object 2731 - f - The field number 2732 2733 Output Parameter: 2734 . off - The offset 2735 2736 Level: beginner 2737 2738 .seealso: `PetscDS`, `PetscDSGetFieldSize()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2739 @*/ 2740 PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off) 2741 { 2742 PetscInt size, g; 2743 2744 PetscFunctionBegin; 2745 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2746 PetscAssertPointer(off, 3); 2747 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); 2748 *off = 0; 2749 for (g = 0; g < f; ++g) { 2750 PetscBool cohesive; 2751 2752 PetscCall(PetscDSGetCohesive(ds, g, &cohesive)); 2753 PetscCall(PetscDSGetFieldSize(ds, g, &size)); 2754 *off += cohesive ? size : size * 2; 2755 } 2756 PetscFunctionReturn(PETSC_SUCCESS); 2757 } 2758 2759 /*@ 2760 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 2761 2762 Not Collective 2763 2764 Input Parameter: 2765 . prob - The `PetscDS` object 2766 2767 Output Parameter: 2768 . dimensions - The number of dimensions 2769 2770 Level: beginner 2771 2772 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2773 @*/ 2774 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 2775 { 2776 PetscFunctionBegin; 2777 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2778 PetscCall(PetscDSSetUp(prob)); 2779 PetscAssertPointer(dimensions, 2); 2780 *dimensions = prob->Nb; 2781 PetscFunctionReturn(PETSC_SUCCESS); 2782 } 2783 2784 /*@ 2785 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 2786 2787 Not Collective 2788 2789 Input Parameter: 2790 . prob - The `PetscDS` object 2791 2792 Output Parameter: 2793 . components - The number of components 2794 2795 Level: beginner 2796 2797 .seealso: `PetscDS`, `PetscDSGetComponentOffsets()`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2798 @*/ 2799 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 2800 { 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2803 PetscCall(PetscDSSetUp(prob)); 2804 PetscAssertPointer(components, 2); 2805 *components = prob->Nc; 2806 PetscFunctionReturn(PETSC_SUCCESS); 2807 } 2808 2809 /*@ 2810 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 2811 2812 Not Collective 2813 2814 Input Parameters: 2815 + prob - The `PetscDS` object 2816 - f - The field number 2817 2818 Output Parameter: 2819 . off - The offset 2820 2821 Level: beginner 2822 2823 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2824 @*/ 2825 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 2826 { 2827 PetscFunctionBegin; 2828 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2829 PetscAssertPointer(off, 3); 2830 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); 2831 PetscCall(PetscDSSetUp(prob)); 2832 *off = prob->off[f]; 2833 PetscFunctionReturn(PETSC_SUCCESS); 2834 } 2835 2836 /*@ 2837 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 2838 2839 Not Collective 2840 2841 Input Parameter: 2842 . prob - The `PetscDS` object 2843 2844 Output Parameter: 2845 . offsets - The offsets 2846 2847 Level: beginner 2848 2849 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2850 @*/ 2851 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 2852 { 2853 PetscFunctionBegin; 2854 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2855 PetscAssertPointer(offsets, 2); 2856 PetscCall(PetscDSSetUp(prob)); 2857 *offsets = prob->off; 2858 PetscFunctionReturn(PETSC_SUCCESS); 2859 } 2860 2861 /*@ 2862 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 2863 2864 Not Collective 2865 2866 Input Parameter: 2867 . prob - The `PetscDS` object 2868 2869 Output Parameter: 2870 . offsets - The offsets 2871 2872 Level: beginner 2873 2874 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2875 @*/ 2876 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 2877 { 2878 PetscFunctionBegin; 2879 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2880 PetscAssertPointer(offsets, 2); 2881 PetscCall(PetscDSSetUp(prob)); 2882 *offsets = prob->offDer; 2883 PetscFunctionReturn(PETSC_SUCCESS); 2884 } 2885 2886 /*@ 2887 PetscDSGetComponentOffsetsCohesive - Returns the offset of each field on an evaluation point 2888 2889 Not Collective 2890 2891 Input Parameters: 2892 + ds - The `PetscDS` object 2893 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 2894 2895 Output Parameter: 2896 . offsets - The offsets 2897 2898 Level: beginner 2899 2900 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2901 @*/ 2902 PetscErrorCode PetscDSGetComponentOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 2903 { 2904 PetscFunctionBegin; 2905 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2906 PetscAssertPointer(offsets, 3); 2907 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 2908 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 2909 PetscCall(PetscDSSetUp(ds)); 2910 *offsets = ds->offCohesive[s]; 2911 PetscFunctionReturn(PETSC_SUCCESS); 2912 } 2913 2914 /*@ 2915 PetscDSGetComponentDerivativeOffsetsCohesive - Returns the offset of each field derivative on an evaluation point 2916 2917 Not Collective 2918 2919 Input Parameters: 2920 + ds - The `PetscDS` object 2921 - s - The cohesive side, 0 for negative, 1 for positive, 2 for cohesive 2922 2923 Output Parameter: 2924 . offsets - The offsets 2925 2926 Level: beginner 2927 2928 .seealso: `PetscDS`, `PetscDSGetNumFields()`, `PetscDSCreate()` 2929 @*/ 2930 PetscErrorCode PetscDSGetComponentDerivativeOffsetsCohesive(PetscDS ds, PetscInt s, PetscInt *offsets[]) 2931 { 2932 PetscFunctionBegin; 2933 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2934 PetscAssertPointer(offsets, 3); 2935 PetscCheck(ds->isCohesive, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cohesive offsets are only valid for a cohesive DS"); 2936 PetscCheck(!(s < 0) && !(s > 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cohesive side %" PetscInt_FMT " is not in [0, 2]", s); 2937 PetscCall(PetscDSSetUp(ds)); 2938 *offsets = ds->offDerCohesive[s]; 2939 PetscFunctionReturn(PETSC_SUCCESS); 2940 } 2941 2942 /*@C 2943 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 2944 2945 Not Collective 2946 2947 Input Parameter: 2948 . prob - The `PetscDS` object 2949 2950 Output Parameter: 2951 . T - The basis function and derivatives tabulation at quadrature points for each field, see `PetscTabulation` for its details 2952 2953 Level: intermediate 2954 2955 Note: 2956 The tabulation is only valid so long as the `PetscDS` has not be destroyed. There is no `PetscDSRestoreTabulation()` in C. 2957 2958 Fortran Note: 2959 Use the declaration 2960 .vb 2961 PetscTabulation, pointer :: tab(:) 2962 .ve 2963 and access the values using, for example, 2964 .vb 2965 tab(i)%ptr%K 2966 tab(i)%ptr%T(j)%ptr 2967 .ve 2968 where $ i = 1, 2, ..., Nf $ and $ j = 1, 2, ..., tab(i)%ptr%K+1 $. 2969 2970 Use `PetscDSRestoreTabulation()` to restore the array 2971 2972 Developer Note: 2973 The Fortran language syntax does not directly support arrays of pointers, the '%ptr' notation allows mimicking their use in Fortran. 2974 2975 .seealso: `PetscDS`, `PetscTabulation`, `PetscDSCreate()` 2976 @*/ 2977 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) PeNS 2978 { 2979 PetscFunctionBegin; 2980 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2981 PetscAssertPointer(T, 2); 2982 PetscCall(PetscDSSetUp(prob)); 2983 *T = prob->T; 2984 PetscFunctionReturn(PETSC_SUCCESS); 2985 } 2986 2987 /*@C 2988 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 2989 2990 Not Collective 2991 2992 Input Parameter: 2993 . prob - The `PetscDS` object 2994 2995 Output Parameter: 2996 . Tf - The basis function and derivative tabulation on each local face at quadrature points for each field 2997 2998 Level: intermediate 2999 3000 Note: 3001 The tabulation is only valid so long as the `PetscDS` has not be destroyed. There is no `PetscDSRestoreFaceTabulation()` in C. 3002 3003 .seealso: `PetscTabulation`, `PetscDS`, `PetscDSGetTabulation()`, `PetscDSCreate()` 3004 @*/ 3005 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 3006 { 3007 PetscFunctionBegin; 3008 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3009 PetscAssertPointer(Tf, 2); 3010 PetscCall(PetscDSSetUp(prob)); 3011 *Tf = prob->Tf; 3012 PetscFunctionReturn(PETSC_SUCCESS); 3013 } 3014 3015 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar *u[], PetscScalar *u_t[], PetscScalar *u_x[]) 3016 { 3017 PetscFunctionBegin; 3018 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3019 PetscCall(PetscDSSetUp(prob)); 3020 if (u) { 3021 PetscAssertPointer(u, 2); 3022 *u = prob->u; 3023 } 3024 if (u_t) { 3025 PetscAssertPointer(u_t, 3); 3026 *u_t = prob->u_t; 3027 } 3028 if (u_x) { 3029 PetscAssertPointer(u_x, 4); 3030 *u_x = prob->u_x; 3031 } 3032 PetscFunctionReturn(PETSC_SUCCESS); 3033 } 3034 3035 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar *f0[], PetscScalar *f1[], PetscScalar *g0[], PetscScalar *g1[], PetscScalar *g2[], PetscScalar *g3[]) 3036 { 3037 PetscFunctionBegin; 3038 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3039 PetscCall(PetscDSSetUp(prob)); 3040 if (f0) { 3041 PetscAssertPointer(f0, 2); 3042 *f0 = prob->f0; 3043 } 3044 if (f1) { 3045 PetscAssertPointer(f1, 3); 3046 *f1 = prob->f1; 3047 } 3048 if (g0) { 3049 PetscAssertPointer(g0, 4); 3050 *g0 = prob->g0; 3051 } 3052 if (g1) { 3053 PetscAssertPointer(g1, 5); 3054 *g1 = prob->g1; 3055 } 3056 if (g2) { 3057 PetscAssertPointer(g2, 6); 3058 *g2 = prob->g2; 3059 } 3060 if (g3) { 3061 PetscAssertPointer(g3, 7); 3062 *g3 = prob->g3; 3063 } 3064 PetscFunctionReturn(PETSC_SUCCESS); 3065 } 3066 3067 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 3068 { 3069 PetscFunctionBegin; 3070 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3071 PetscCall(PetscDSSetUp(prob)); 3072 if (x) { 3073 PetscAssertPointer(x, 2); 3074 *x = prob->x; 3075 } 3076 if (basisReal) { 3077 PetscAssertPointer(basisReal, 3); 3078 *basisReal = prob->basisReal; 3079 } 3080 if (basisDerReal) { 3081 PetscAssertPointer(basisDerReal, 4); 3082 *basisDerReal = prob->basisDerReal; 3083 } 3084 if (testReal) { 3085 PetscAssertPointer(testReal, 5); 3086 *testReal = prob->testReal; 3087 } 3088 if (testDerReal) { 3089 PetscAssertPointer(testDerReal, 6); 3090 *testDerReal = prob->testDerReal; 3091 } 3092 PetscFunctionReturn(PETSC_SUCCESS); 3093 } 3094 3095 /*@C 3096 PetscDSAddBoundary - Add a boundary condition to the model. 3097 3098 Collective 3099 3100 Input Parameters: 3101 + ds - The `PetscDS` object 3102 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3103 . name - The name for the boundary condition 3104 . label - The label defining constrained points 3105 . Nv - The number of `DMLabel` values for constrained points 3106 . values - An array of label values for constrained points 3107 . field - The field to constrain 3108 . Nc - The number of constrained field components (0 will constrain all fields) 3109 . comps - An array of constrained component numbers 3110 . bcFunc - A pointwise function giving boundary values 3111 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL` 3112 - ctx - An optional user context for `bcFunc` 3113 3114 Output Parameter: 3115 . bd - The boundary number 3116 3117 Options Database Keys: 3118 + -bc_<boundary name> <num> - Overrides the boundary ids 3119 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3120 3121 Level: developer 3122 3123 Note: 3124 Both `bcFunc` and `bcFunc_t` will depend on the boundary condition type. If the type if `DM_BC_ESSENTIAL`, then the calling sequence is\: 3125 .vb 3126 void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3127 .ve 3128 3129 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, then the calling sequence is\: 3130 .vb 3131 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3132 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3133 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3134 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3135 .ve 3136 + dim - the coordinate dimension 3137 . Nf - the number of fields 3138 . uOff - the offset into u[] and u_t[] for each field 3139 . uOff_x - the offset into u_x[] for each field 3140 . u - each field evaluated at the current point 3141 . u_t - the time derivative of each field evaluated at the current point 3142 . u_x - the gradient of each field evaluated at the current point 3143 . aOff - the offset into a[] and a_t[] for each auxiliary field 3144 . aOff_x - the offset into a_x[] for each auxiliary field 3145 . a - each auxiliary field evaluated at the current point 3146 . a_t - the time derivative of each auxiliary field evaluated at the current point 3147 . a_x - the gradient of auxiliary each field evaluated at the current point 3148 . t - current time 3149 . x - coordinates of the current point 3150 . numConstants - number of constant parameters 3151 . constants - constant parameters 3152 - bcval - output values at the current point 3153 3154 Notes: 3155 The pointwise functions are used to provide boundary values for essential boundary 3156 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3157 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3158 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3159 3160 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundaryByName()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3161 @*/ 3162 PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, void *ctx, PetscInt *bd) 3163 { 3164 DSBoundary head = ds->boundary, b; 3165 PetscInt n = 0; 3166 const char *lname; 3167 3168 PetscFunctionBegin; 3169 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3170 PetscValidLogicalCollectiveEnum(ds, type, 2); 3171 PetscAssertPointer(name, 3); 3172 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 3173 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3174 PetscValidLogicalCollectiveInt(ds, field, 7); 3175 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3176 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); 3177 if (Nc > 0) { 3178 PetscInt *fcomps; 3179 PetscInt c; 3180 3181 PetscCall(PetscDSGetComponents(ds, &fcomps)); 3182 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); 3183 for (c = 0; c < Nc; ++c) { 3184 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); 3185 } 3186 } 3187 PetscCall(PetscNew(&b)); 3188 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3189 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3190 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3191 PetscCall(PetscMalloc1(Nv, &b->values)); 3192 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3193 PetscCall(PetscMalloc1(Nc, &b->comps)); 3194 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3195 PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 3196 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3197 b->type = type; 3198 b->label = label; 3199 b->Nv = Nv; 3200 b->field = field; 3201 b->Nc = Nc; 3202 b->func = bcFunc; 3203 b->func_t = bcFunc_t; 3204 b->ctx = ctx; 3205 b->next = NULL; 3206 /* Append to linked list so that we can preserve the order */ 3207 if (!head) ds->boundary = b; 3208 while (head) { 3209 if (!head->next) { 3210 head->next = b; 3211 head = b; 3212 } 3213 head = head->next; 3214 ++n; 3215 } 3216 if (bd) { 3217 PetscAssertPointer(bd, 13); 3218 *bd = n; 3219 } 3220 PetscFunctionReturn(PETSC_SUCCESS); 3221 } 3222 3223 // PetscClangLinter pragma ignore: -fdoc-section-header-unknown 3224 /*@C 3225 PetscDSAddBoundaryByName - Add a boundary condition to the model. 3226 3227 Collective 3228 3229 Input Parameters: 3230 + ds - The `PetscDS` object 3231 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3232 . name - The boundary condition name 3233 . lname - The name of the label defining constrained points 3234 . Nv - The number of `DMLabel` values for constrained points 3235 . values - An array of label values for constrained points 3236 . field - The field to constrain 3237 . Nc - The number of constrained field components (0 will constrain all fields) 3238 . comps - An array of constrained component numbers 3239 . bcFunc - A pointwise function giving boundary values 3240 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL` 3241 - ctx - An optional user context for `bcFunc` 3242 3243 Output Parameter: 3244 . bd - The boundary number 3245 3246 Options Database Keys: 3247 + -bc_<boundary name> <num> - Overrides the boundary ids 3248 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3249 3250 Calling Sequence of `bcFunc` and `bcFunc_t`: 3251 If the type is `DM_BC_ESSENTIAL` 3252 .vb 3253 void bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3254 .ve 3255 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, 3256 .vb 3257 void bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3258 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3259 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3260 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3261 .ve 3262 + dim - the coordinate dimension 3263 . Nf - the number of fields 3264 . uOff - the offset into `u`[] and `u_t`[] for each field 3265 . uOff_x - the offset into `u_x`[] for each field 3266 . u - each field evaluated at the current point 3267 . u_t - the time derivative of each field evaluated at the current point 3268 . u_x - the gradient of each field evaluated at the current point 3269 . aOff - the offset into `a`[] and `a_t`[] for each auxiliary field 3270 . aOff_x - the offset into `a_x`[] for each auxiliary field 3271 . a - each auxiliary field evaluated at the current point 3272 . a_t - the time derivative of each auxiliary field evaluated at the current point 3273 . a_x - the gradient of auxiliary each field evaluated at the current point 3274 . t - current time 3275 . x - coordinates of the current point 3276 . numConstants - number of constant parameters 3277 . constants - constant parameters 3278 - bcval - output values at the current point 3279 3280 Level: developer 3281 3282 Notes: 3283 The pointwise functions are used to provide boundary values for essential boundary 3284 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3285 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3286 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3287 3288 This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built. 3289 3290 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3291 @*/ 3292 PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, void *ctx, PetscInt *bd) 3293 { 3294 DSBoundary head = ds->boundary, b; 3295 PetscInt n = 0; 3296 3297 PetscFunctionBegin; 3298 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3299 PetscValidLogicalCollectiveEnum(ds, type, 2); 3300 PetscAssertPointer(name, 3); 3301 PetscAssertPointer(lname, 4); 3302 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3303 PetscValidLogicalCollectiveInt(ds, field, 7); 3304 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3305 PetscCall(PetscNew(&b)); 3306 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3307 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3308 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3309 PetscCall(PetscMalloc1(Nv, &b->values)); 3310 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3311 PetscCall(PetscMalloc1(Nc, &b->comps)); 3312 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3313 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3314 b->type = type; 3315 b->label = NULL; 3316 b->Nv = Nv; 3317 b->field = field; 3318 b->Nc = Nc; 3319 b->func = bcFunc; 3320 b->func_t = bcFunc_t; 3321 b->ctx = ctx; 3322 b->next = NULL; 3323 /* Append to linked list so that we can preserve the order */ 3324 if (!head) ds->boundary = b; 3325 while (head) { 3326 if (!head->next) { 3327 head->next = b; 3328 head = b; 3329 } 3330 head = head->next; 3331 ++n; 3332 } 3333 if (bd) { 3334 PetscAssertPointer(bd, 13); 3335 *bd = n; 3336 } 3337 PetscFunctionReturn(PETSC_SUCCESS); 3338 } 3339 3340 /*@C 3341 PetscDSUpdateBoundary - Change a boundary condition for the model. 3342 3343 Input Parameters: 3344 + ds - The `PetscDS` object 3345 . bd - The boundary condition number 3346 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3347 . name - The boundary condition name 3348 . label - The label defining constrained points 3349 . Nv - The number of `DMLabel` ids for constrained points 3350 . values - An array of ids for constrained points 3351 . field - The field to constrain 3352 . Nc - The number of constrained field components 3353 . comps - An array of constrained component numbers 3354 . bcFunc - A pointwise function giving boundary values 3355 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or `NULL` 3356 - ctx - An optional user context for `bcFunc` 3357 3358 Level: developer 3359 3360 Notes: 3361 The pointwise functions are used to provide boundary values for essential boundary 3362 conditions. In FEM, they are acting upon by dual basis functionals to generate FEM 3363 coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary 3364 integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3365 3366 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`. 3367 See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks. 3368 3369 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel` 3370 @*/ 3371 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[], PetscVoidFn *bcFunc, PetscVoidFn *bcFunc_t, void *ctx) 3372 { 3373 DSBoundary b = ds->boundary; 3374 PetscInt n = 0; 3375 3376 PetscFunctionBegin; 3377 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3378 while (b) { 3379 if (n == bd) break; 3380 b = b->next; 3381 ++n; 3382 } 3383 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3384 if (name) { 3385 PetscCall(PetscFree(b->name)); 3386 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3387 } 3388 b->type = type; 3389 if (label) { 3390 const char *name; 3391 3392 b->label = label; 3393 PetscCall(PetscFree(b->lname)); 3394 PetscCall(PetscObjectGetName((PetscObject)label, &name)); 3395 PetscCall(PetscStrallocpy(name, (char **)&b->lname)); 3396 } 3397 if (Nv >= 0) { 3398 b->Nv = Nv; 3399 PetscCall(PetscFree(b->values)); 3400 PetscCall(PetscMalloc1(Nv, &b->values)); 3401 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3402 } 3403 if (field >= 0) b->field = field; 3404 if (Nc >= 0) { 3405 b->Nc = Nc; 3406 PetscCall(PetscFree(b->comps)); 3407 PetscCall(PetscMalloc1(Nc, &b->comps)); 3408 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3409 } 3410 if (bcFunc) b->func = bcFunc; 3411 if (bcFunc_t) b->func_t = bcFunc_t; 3412 if (ctx) b->ctx = ctx; 3413 PetscFunctionReturn(PETSC_SUCCESS); 3414 } 3415 3416 /*@ 3417 PetscDSGetNumBoundary - Get the number of registered boundary conditions 3418 3419 Input Parameter: 3420 . ds - The `PetscDS` object 3421 3422 Output Parameter: 3423 . numBd - The number of boundary conditions 3424 3425 Level: intermediate 3426 3427 .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()` 3428 @*/ 3429 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3430 { 3431 DSBoundary b = ds->boundary; 3432 3433 PetscFunctionBegin; 3434 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3435 PetscAssertPointer(numBd, 2); 3436 *numBd = 0; 3437 while (b) { 3438 ++(*numBd); 3439 b = b->next; 3440 } 3441 PetscFunctionReturn(PETSC_SUCCESS); 3442 } 3443 3444 /*@C 3445 PetscDSGetBoundary - Gets a boundary condition from the model 3446 3447 Input Parameters: 3448 + ds - The `PetscDS` object 3449 - bd - The boundary condition number 3450 3451 Output Parameters: 3452 + wf - The `PetscWeakForm` holding the pointwise functions 3453 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3454 . name - The boundary condition name 3455 . label - The label defining constrained points 3456 . Nv - The number of `DMLabel` ids for constrained points 3457 . values - An array of ids for constrained points 3458 . field - The field to constrain 3459 . Nc - The number of constrained field components 3460 . comps - An array of constrained component numbers 3461 . func - A pointwise function giving boundary values 3462 . func_t - A pointwise function giving the time derivative of the boundary values 3463 - ctx - An optional user context for `bcFunc` 3464 3465 Options Database Keys: 3466 + -bc_<boundary name> <num> - Overrides the boundary ids 3467 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3468 3469 Level: developer 3470 3471 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel` 3472 @*/ 3473 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[], PetscVoidFn **func, PetscVoidFn **func_t, void **ctx) 3474 { 3475 DSBoundary b = ds->boundary; 3476 PetscInt n = 0; 3477 3478 PetscFunctionBegin; 3479 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3480 while (b) { 3481 if (n == bd) break; 3482 b = b->next; 3483 ++n; 3484 } 3485 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3486 if (wf) { 3487 PetscAssertPointer(wf, 3); 3488 *wf = b->wf; 3489 } 3490 if (type) { 3491 PetscAssertPointer(type, 4); 3492 *type = b->type; 3493 } 3494 if (name) { 3495 PetscAssertPointer(name, 5); 3496 *name = b->name; 3497 } 3498 if (label) { 3499 PetscAssertPointer(label, 6); 3500 *label = b->label; 3501 } 3502 if (Nv) { 3503 PetscAssertPointer(Nv, 7); 3504 *Nv = b->Nv; 3505 } 3506 if (values) { 3507 PetscAssertPointer(values, 8); 3508 *values = b->values; 3509 } 3510 if (field) { 3511 PetscAssertPointer(field, 9); 3512 *field = b->field; 3513 } 3514 if (Nc) { 3515 PetscAssertPointer(Nc, 10); 3516 *Nc = b->Nc; 3517 } 3518 if (comps) { 3519 PetscAssertPointer(comps, 11); 3520 *comps = b->comps; 3521 } 3522 if (func) { 3523 PetscAssertPointer(func, 12); 3524 *func = b->func; 3525 } 3526 if (func_t) { 3527 PetscAssertPointer(func_t, 13); 3528 *func_t = b->func_t; 3529 } 3530 if (ctx) { 3531 PetscAssertPointer(ctx, 14); 3532 *ctx = b->ctx; 3533 } 3534 PetscFunctionReturn(PETSC_SUCCESS); 3535 } 3536 3537 /*@ 3538 PetscDSUpdateBoundaryLabels - Update `DMLabel` in each boundary condition using the label name and the input `DM` 3539 3540 Not Collective 3541 3542 Input Parameters: 3543 + ds - The source `PetscDS` object 3544 - dm - The `DM` holding labels 3545 3546 Level: intermediate 3547 3548 .seealso: `PetscDS`, `DMBoundary`, `DM`, `PetscDSCopyBoundary()`, `PetscDSCreate()`, `DMGetLabel()` 3549 @*/ 3550 PetscErrorCode PetscDSUpdateBoundaryLabels(PetscDS ds, DM dm) 3551 { 3552 DSBoundary b; 3553 3554 PetscFunctionBegin; 3555 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3556 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 3557 for (b = ds->boundary; b; b = b->next) { 3558 if (b->lname) PetscCall(DMGetLabel(dm, b->lname, &b->label)); 3559 } 3560 PetscFunctionReturn(PETSC_SUCCESS); 3561 } 3562 3563 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3564 { 3565 PetscFunctionBegin; 3566 PetscCall(PetscNew(bNew)); 3567 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf)); 3568 PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf)); 3569 PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name))); 3570 PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname))); 3571 (*bNew)->type = b->type; 3572 (*bNew)->label = b->label; 3573 (*bNew)->Nv = b->Nv; 3574 PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values)); 3575 PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv)); 3576 (*bNew)->field = b->field; 3577 (*bNew)->Nc = b->Nc; 3578 PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps)); 3579 PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc)); 3580 (*bNew)->func = b->func; 3581 (*bNew)->func_t = b->func_t; 3582 (*bNew)->ctx = b->ctx; 3583 PetscFunctionReturn(PETSC_SUCCESS); 3584 } 3585 3586 /*@ 3587 PetscDSCopyBoundary - Copy all boundary condition objects to the new `PetscDS` 3588 3589 Not Collective 3590 3591 Input Parameters: 3592 + ds - The source `PetscDS` object 3593 . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields 3594 - fields - The selected fields, or `NULL` for all fields 3595 3596 Output Parameter: 3597 . newds - The target `PetscDS`, now with a copy of the boundary conditions 3598 3599 Level: intermediate 3600 3601 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3602 @*/ 3603 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3604 { 3605 DSBoundary b, *lastnext; 3606 3607 PetscFunctionBegin; 3608 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3609 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3610 if (ds == newds) PetscFunctionReturn(PETSC_SUCCESS); 3611 PetscCall(PetscDSDestroyBoundary(newds)); 3612 lastnext = &newds->boundary; 3613 for (b = ds->boundary; b; b = b->next) { 3614 DSBoundary bNew; 3615 PetscInt fieldNew = -1; 3616 3617 if (numFields > 0 && fields) { 3618 PetscInt f; 3619 3620 for (f = 0; f < numFields; ++f) 3621 if (b->field == fields[f]) break; 3622 if (f == numFields) continue; 3623 fieldNew = f; 3624 } 3625 PetscCall(DSBoundaryDuplicate_Internal(b, &bNew)); 3626 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3627 *lastnext = bNew; 3628 lastnext = &bNew->next; 3629 } 3630 PetscFunctionReturn(PETSC_SUCCESS); 3631 } 3632 3633 /*@ 3634 PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS` 3635 3636 Not Collective 3637 3638 Input Parameter: 3639 . ds - The `PetscDS` object 3640 3641 Level: intermediate 3642 3643 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()` 3644 @*/ 3645 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3646 { 3647 DSBoundary next = ds->boundary; 3648 3649 PetscFunctionBegin; 3650 while (next) { 3651 DSBoundary b = next; 3652 3653 next = b->next; 3654 PetscCall(PetscWeakFormDestroy(&b->wf)); 3655 PetscCall(PetscFree(b->name)); 3656 PetscCall(PetscFree(b->lname)); 3657 PetscCall(PetscFree(b->values)); 3658 PetscCall(PetscFree(b->comps)); 3659 PetscCall(PetscFree(b)); 3660 } 3661 PetscFunctionReturn(PETSC_SUCCESS); 3662 } 3663 3664 /*@ 3665 PetscDSSelectDiscretizations - Copy discretizations to the new `PetscDS` with different field layout 3666 3667 Not Collective 3668 3669 Input Parameters: 3670 + prob - The `PetscDS` object 3671 . numFields - Number of new fields 3672 . fields - Old field number for each new field 3673 . minDegree - Minimum degree for a discretization, or `PETSC_DETERMINE` for no limit 3674 - maxDegree - Maximum degree for a discretization, or `PETSC_DETERMINE` for no limit 3675 3676 Output Parameter: 3677 . newprob - The `PetscDS` copy 3678 3679 Level: intermediate 3680 3681 .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3682 @*/ 3683 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscInt minDegree, PetscInt maxDegree, PetscDS newprob) 3684 { 3685 PetscInt Nf, Nfn, fn; 3686 3687 PetscFunctionBegin; 3688 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3689 if (fields) PetscAssertPointer(fields, 3); 3690 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 6); 3691 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3692 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3693 numFields = numFields < 0 ? Nf : numFields; 3694 for (fn = 0; fn < numFields; ++fn) { 3695 const PetscInt f = fields ? fields[fn] : fn; 3696 PetscObject disc; 3697 PetscClassId id; 3698 3699 if (f >= Nf) continue; 3700 PetscCall(PetscDSGetDiscretization(prob, f, &disc)); 3701 PetscCallContinue(PetscObjectGetClassId(disc, &id)); 3702 if (id == PETSCFE_CLASSID) { 3703 PetscFE fe; 3704 3705 PetscCall(PetscFELimitDegree((PetscFE)disc, minDegree, maxDegree, &fe)); 3706 PetscCall(PetscDSSetDiscretization(newprob, fn, (PetscObject)fe)); 3707 PetscCall(PetscFEDestroy(&fe)); 3708 } else { 3709 PetscCall(PetscDSSetDiscretization(newprob, fn, disc)); 3710 } 3711 } 3712 PetscFunctionReturn(PETSC_SUCCESS); 3713 } 3714 3715 /*@ 3716 PetscDSSelectEquations - Copy pointwise function pointers to the new `PetscDS` with different field layout 3717 3718 Not Collective 3719 3720 Input Parameters: 3721 + prob - The `PetscDS` object 3722 . numFields - Number of new fields 3723 - fields - Old field number for each new field 3724 3725 Output Parameter: 3726 . newprob - The `PetscDS` copy 3727 3728 Level: intermediate 3729 3730 .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3731 @*/ 3732 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3733 { 3734 PetscInt Nf, Nfn, fn, gn; 3735 3736 PetscFunctionBegin; 3737 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3738 if (fields) PetscAssertPointer(fields, 3); 3739 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3740 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3741 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3742 PetscCheck(numFields <= Nfn, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields %" PetscInt_FMT " to transfer must not be greater than the total number of fields %" PetscInt_FMT, numFields, Nfn); 3743 for (fn = 0; fn < numFields; ++fn) { 3744 const PetscInt f = fields ? fields[fn] : fn; 3745 PetscPointFn *obj; 3746 PetscPointFn *f0, *f1; 3747 PetscBdPointFn *f0Bd, *f1Bd; 3748 PetscRiemannFn *r; 3749 3750 if (f >= Nf) continue; 3751 PetscCall(PetscDSGetObjective(prob, f, &obj)); 3752 PetscCall(PetscDSGetResidual(prob, f, &f0, &f1)); 3753 PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd)); 3754 PetscCall(PetscDSGetRiemannSolver(prob, f, &r)); 3755 PetscCall(PetscDSSetObjective(newprob, fn, obj)); 3756 PetscCall(PetscDSSetResidual(newprob, fn, f0, f1)); 3757 PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd)); 3758 PetscCall(PetscDSSetRiemannSolver(newprob, fn, r)); 3759 for (gn = 0; gn < numFields; ++gn) { 3760 const PetscInt g = fields ? fields[gn] : gn; 3761 PetscPointJacFn *g0, *g1, *g2, *g3; 3762 PetscPointJacFn *g0p, *g1p, *g2p, *g3p; 3763 PetscBdPointJacFn *g0Bd, *g1Bd, *g2Bd, *g3Bd; 3764 3765 if (g >= Nf) continue; 3766 PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3)); 3767 PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p)); 3768 PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd)); 3769 PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3)); 3770 PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p)); 3771 PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd)); 3772 } 3773 } 3774 PetscFunctionReturn(PETSC_SUCCESS); 3775 } 3776 3777 /*@ 3778 PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS` 3779 3780 Not Collective 3781 3782 Input Parameter: 3783 . prob - The `PetscDS` object 3784 3785 Output Parameter: 3786 . newprob - The `PetscDS` copy 3787 3788 Level: intermediate 3789 3790 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3791 @*/ 3792 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3793 { 3794 PetscWeakForm wf, newwf; 3795 PetscInt Nf, Ng; 3796 3797 PetscFunctionBegin; 3798 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3799 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3800 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3801 PetscCall(PetscDSGetNumFields(newprob, &Ng)); 3802 PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng); 3803 PetscCall(PetscDSGetWeakForm(prob, &wf)); 3804 PetscCall(PetscDSGetWeakForm(newprob, &newwf)); 3805 PetscCall(PetscWeakFormCopy(wf, newwf)); 3806 PetscFunctionReturn(PETSC_SUCCESS); 3807 } 3808 3809 /*@ 3810 PetscDSCopyConstants - Copy all constants set with `PetscDSSetConstants()` to another `PetscDS` 3811 3812 Not Collective 3813 3814 Input Parameter: 3815 . prob - The `PetscDS` object 3816 3817 Output Parameter: 3818 . newprob - The `PetscDS` copy 3819 3820 Level: intermediate 3821 3822 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3823 @*/ 3824 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3825 { 3826 PetscInt Nc; 3827 const PetscScalar *constants; 3828 3829 PetscFunctionBegin; 3830 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3831 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3832 PetscCall(PetscDSGetConstants(prob, &Nc, &constants)); 3833 PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants)); 3834 PetscFunctionReturn(PETSC_SUCCESS); 3835 } 3836 3837 /*@ 3838 PetscDSCopyExactSolutions - Copy all exact solutions set with `PetscDSSetExactSolution()` and `PetscDSSetExactSolutionTimeDerivative()` to another `PetscDS` 3839 3840 Not Collective 3841 3842 Input Parameter: 3843 . ds - The `PetscDS` object 3844 3845 Output Parameter: 3846 . newds - The `PetscDS` copy 3847 3848 Level: intermediate 3849 3850 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSCopyBounds()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3851 @*/ 3852 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 3853 { 3854 PetscSimplePointFn *sol; 3855 void *ctx; 3856 PetscInt Nf, f; 3857 3858 PetscFunctionBegin; 3859 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3860 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 3861 PetscCall(PetscDSGetNumFields(ds, &Nf)); 3862 for (f = 0; f < Nf; ++f) { 3863 PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx)); 3864 PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx)); 3865 PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx)); 3866 PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx)); 3867 } 3868 PetscFunctionReturn(PETSC_SUCCESS); 3869 } 3870 3871 /*@ 3872 PetscDSCopyBounds - Copy lower and upper solution bounds set with `PetscDSSetLowerBound()` and `PetscDSSetLowerBound()` to another `PetscDS` 3873 3874 Not Collective 3875 3876 Input Parameter: 3877 . ds - The `PetscDS` object 3878 3879 Output Parameter: 3880 . newds - The `PetscDS` copy 3881 3882 Level: intermediate 3883 3884 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSCopyExactSolutions()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3885 @*/ 3886 PetscErrorCode PetscDSCopyBounds(PetscDS ds, PetscDS newds) 3887 { 3888 PetscSimplePointFn *bound; 3889 void *ctx; 3890 PetscInt Nf, f; 3891 3892 PetscFunctionBegin; 3893 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3894 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 3895 PetscCall(PetscDSGetNumFields(ds, &Nf)); 3896 for (f = 0; f < Nf; ++f) { 3897 PetscCall(PetscDSGetLowerBound(ds, f, &bound, &ctx)); 3898 PetscCall(PetscDSSetLowerBound(newds, f, bound, ctx)); 3899 PetscCall(PetscDSGetUpperBound(ds, f, &bound, &ctx)); 3900 PetscCall(PetscDSSetUpperBound(newds, f, bound, ctx)); 3901 } 3902 PetscFunctionReturn(PETSC_SUCCESS); 3903 } 3904 3905 PetscErrorCode PetscDSCopy(PetscDS ds, PetscInt minDegree, PetscInt maxDegree, DM dmNew, PetscDS dsNew) 3906 { 3907 DSBoundary b; 3908 PetscInt cdim, Nf, f, d; 3909 PetscBool isCohesive; 3910 void *ctx; 3911 3912 PetscFunctionBegin; 3913 PetscCall(PetscDSCopyConstants(ds, dsNew)); 3914 PetscCall(PetscDSCopyExactSolutions(ds, dsNew)); 3915 PetscCall(PetscDSCopyBounds(ds, dsNew)); 3916 PetscCall(PetscDSSelectDiscretizations(ds, PETSC_DETERMINE, NULL, minDegree, maxDegree, dsNew)); 3917 PetscCall(PetscDSCopyEquations(ds, dsNew)); 3918 PetscCall(PetscDSGetNumFields(ds, &Nf)); 3919 for (f = 0; f < Nf; ++f) { 3920 PetscCall(PetscDSGetContext(ds, f, &ctx)); 3921 PetscCall(PetscDSSetContext(dsNew, f, ctx)); 3922 PetscCall(PetscDSGetCohesive(ds, f, &isCohesive)); 3923 PetscCall(PetscDSSetCohesive(dsNew, f, isCohesive)); 3924 PetscCall(PetscDSGetJetDegree(ds, f, &d)); 3925 PetscCall(PetscDSSetJetDegree(dsNew, f, d)); 3926 } 3927 if (Nf) { 3928 PetscCall(PetscDSGetCoordinateDimension(ds, &cdim)); 3929 PetscCall(PetscDSSetCoordinateDimension(dsNew, cdim)); 3930 } 3931 PetscCall(PetscDSCopyBoundary(ds, PETSC_DETERMINE, NULL, dsNew)); 3932 for (b = dsNew->boundary; b; b = b->next) { 3933 PetscCall(DMGetLabel(dmNew, b->lname, &b->label)); 3934 /* Do not check if label exists here, since p4est calls this for the reference tree which does not have the labels */ 3935 //PetscCheck(b->label,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Label %s missing in new DM", name); 3936 } 3937 PetscFunctionReturn(PETSC_SUCCESS); 3938 } 3939 3940 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 3941 { 3942 PetscInt dim, Nf, f; 3943 3944 PetscFunctionBegin; 3945 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3946 PetscAssertPointer(subprob, 3); 3947 if (height == 0) { 3948 *subprob = prob; 3949 PetscFunctionReturn(PETSC_SUCCESS); 3950 } 3951 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3952 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 3953 PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height); 3954 if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs)); 3955 if (!prob->subprobs[height - 1]) { 3956 PetscInt cdim; 3957 3958 PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1])); 3959 PetscCall(PetscDSGetCoordinateDimension(prob, &cdim)); 3960 PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim)); 3961 for (f = 0; f < Nf; ++f) { 3962 PetscFE subfe; 3963 PetscObject obj; 3964 PetscClassId id; 3965 3966 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 3967 PetscCall(PetscObjectGetClassId(obj, &id)); 3968 PetscCheck(id == PETSCFE_CLASSID, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f); 3969 PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe)); 3970 PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe)); 3971 } 3972 } 3973 *subprob = prob->subprobs[height - 1]; 3974 PetscFunctionReturn(PETSC_SUCCESS); 3975 } 3976 3977 PetscErrorCode PetscDSPermuteQuadPoint(PetscDS ds, PetscInt ornt, PetscInt field, PetscInt q, PetscInt *qperm) 3978 { 3979 IS permIS; 3980 PetscQuadrature quad; 3981 DMPolytopeType ct; 3982 const PetscInt *perm; 3983 PetscInt Na, Nq; 3984 3985 PetscFunctionBeginHot; 3986 PetscCall(PetscFEGetQuadrature((PetscFE)ds->disc[field], &quad)); 3987 PetscCall(PetscQuadratureGetData(quad, NULL, NULL, &Nq, NULL, NULL)); 3988 PetscCall(PetscQuadratureGetCellType(quad, &ct)); 3989 PetscCheck(q >= 0 && q < Nq, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Quadrature point %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", q, Nq); 3990 Na = DMPolytopeTypeGetNumArrangements(ct) / 2; 3991 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); 3992 if (!ds->quadPerm[(PetscInt)ct]) PetscCall(PetscQuadratureComputePermutations(quad, NULL, &ds->quadPerm[(PetscInt)ct])); 3993 permIS = ds->quadPerm[(PetscInt)ct][ornt + Na]; 3994 PetscCall(ISGetIndices(permIS, &perm)); 3995 *qperm = perm[q]; 3996 PetscCall(ISRestoreIndices(permIS, &perm)); 3997 PetscFunctionReturn(PETSC_SUCCESS); 3998 } 3999 4000 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 4001 { 4002 PetscObject obj; 4003 PetscClassId id; 4004 PetscInt Nf; 4005 4006 PetscFunctionBegin; 4007 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4008 PetscAssertPointer(disctype, 3); 4009 *disctype = PETSC_DISC_NONE; 4010 PetscCall(PetscDSGetNumFields(ds, &Nf)); 4011 PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf); 4012 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 4013 if (obj) { 4014 PetscCall(PetscObjectGetClassId(obj, &id)); 4015 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 4016 else *disctype = PETSC_DISC_FV; 4017 } 4018 PetscFunctionReturn(PETSC_SUCCESS); 4019 } 4020 4021 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 4022 { 4023 PetscFunctionBegin; 4024 PetscCall(PetscFree(ds->data)); 4025 PetscFunctionReturn(PETSC_SUCCESS); 4026 } 4027 4028 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 4029 { 4030 PetscFunctionBegin; 4031 ds->ops->setfromoptions = NULL; 4032 ds->ops->setup = NULL; 4033 ds->ops->view = NULL; 4034 ds->ops->destroy = PetscDSDestroy_Basic; 4035 PetscFunctionReturn(PETSC_SUCCESS); 4036 } 4037 4038 /*MC 4039 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 4040 4041 Level: intermediate 4042 4043 .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()` 4044 M*/ 4045 4046 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 4047 { 4048 PetscDS_Basic *b; 4049 4050 PetscFunctionBegin; 4051 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4052 PetscCall(PetscNew(&b)); 4053 ds->data = b; 4054 4055 PetscCall(PetscDSInitialize_Basic(ds)); 4056 PetscFunctionReturn(PETSC_SUCCESS); 4057 } 4058