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