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