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