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 PetscCheck(field >= 0 && field < ds->Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_OUTOFRANGE, "Field %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", field, ds->Nf); 3266 if (Nc > 0) { 3267 PetscInt *fcomps; 3268 PetscInt c; 3269 3270 PetscCall(PetscDSGetComponents(ds, &fcomps)); 3271 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); 3272 for (c = 0; c < Nc; ++c) { 3273 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); 3274 } 3275 } 3276 PetscCall(PetscNew(&b)); 3277 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3278 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3279 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3280 PetscCall(PetscMalloc1(Nv, &b->values)); 3281 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3282 PetscCall(PetscMalloc1(Nc, &b->comps)); 3283 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3284 PetscCall(PetscObjectGetName((PetscObject)label, &lname)); 3285 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3286 b->type = type; 3287 b->label = label; 3288 b->Nv = Nv; 3289 b->field = field; 3290 b->Nc = Nc; 3291 b->func = bcFunc; 3292 b->func_t = bcFunc_t; 3293 b->ctx = ctx; 3294 b->next = NULL; 3295 /* Append to linked list so that we can preserve the order */ 3296 if (!head) ds->boundary = b; 3297 while (head) { 3298 if (!head->next) { 3299 head->next = b; 3300 head = b; 3301 } 3302 head = head->next; 3303 ++n; 3304 } 3305 if (bd) { 3306 PetscValidIntPointer(bd, 13); 3307 *bd = n; 3308 } 3309 PetscFunctionReturn(0); 3310 } 3311 3312 /*@C 3313 PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3314 In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that 3315 boundary integrals should be performed, using the kernels from `PetscDSSetBdResidual()`. 3316 3317 Collective on ds 3318 3319 Input Parameters: 3320 + ds - The `PetscDS` object 3321 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3322 . name - The BC name 3323 . lname - The naem of the label defining constrained points 3324 . Nv - The number of `DMLabel` values for constrained points 3325 . values - An array of label values for constrained points 3326 . field - The field to constrain 3327 . Nc - The number of constrained field components (0 will constrain all fields) 3328 . comps - An array of constrained component numbers 3329 . bcFunc - A pointwise function giving boundary values 3330 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3331 - ctx - An optional user context for bcFunc 3332 3333 Output Parameters: 3334 - bd - The boundary number 3335 3336 Options Database Keys: 3337 + -bc_<boundary name> <num> - Overrides the boundary ids 3338 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3339 3340 Calling Sequence of bcFunc() and bcFunc_t(): 3341 If the type is `DM_BC_ESSENTIAL` 3342 .vb 3343 bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3344 .ve 3345 If the type is `DM_BC_ESSENTIAL_FIELD` or other _FIELD value, 3346 .vb 3347 bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3348 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3349 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3350 PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3351 .ve 3352 + dim - the spatial dimension 3353 . Nf - the number of fields 3354 . uOff - the offset into u[] and u_t[] for each field 3355 . uOff_x - the offset into u_x[] for each field 3356 . u - each field evaluated at the current point 3357 . u_t - the time derivative of each field evaluated at the current point 3358 . u_x - the gradient of each field evaluated at the current point 3359 . aOff - the offset into a[] and a_t[] for each auxiliary field 3360 . aOff_x - the offset into a_x[] for each auxiliary field 3361 . a - each auxiliary field evaluated at the current point 3362 . a_t - the time derivative of each auxiliary field evaluated at the current point 3363 . a_x - the gradient of auxiliary each field evaluated at the current point 3364 . t - current time 3365 . x - coordinates of the current point 3366 . numConstants - number of constant parameters 3367 . constants - constant parameters 3368 - bcval - output values at the current point 3369 3370 Level: developer 3371 3372 Note: 3373 This function should only be used with `DMFOREST` currently, since labels cannot be defined before the underlying `DMPLEX` is built. 3374 3375 .seealso: `PetscDS`, `PetscWeakForm`, `DMLabel`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSSetResidual()`, `PetscDSSetBdResidual()` 3376 @*/ 3377 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) 3378 { 3379 DSBoundary head = ds->boundary, b; 3380 PetscInt n = 0; 3381 3382 PetscFunctionBegin; 3383 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3384 PetscValidLogicalCollectiveEnum(ds, type, 2); 3385 PetscValidCharPointer(name, 3); 3386 PetscValidCharPointer(lname, 4); 3387 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3388 PetscValidLogicalCollectiveInt(ds, field, 7); 3389 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3390 PetscCall(PetscNew(&b)); 3391 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3392 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf)); 3393 PetscCall(PetscWeakFormSetNumFields(b->wf, ds->Nf)); 3394 PetscCall(PetscMalloc1(Nv, &b->values)); 3395 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3396 PetscCall(PetscMalloc1(Nc, &b->comps)); 3397 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3398 PetscCall(PetscStrallocpy(lname, (char **)&b->lname)); 3399 b->type = type; 3400 b->label = NULL; 3401 b->Nv = Nv; 3402 b->field = field; 3403 b->Nc = Nc; 3404 b->func = bcFunc; 3405 b->func_t = bcFunc_t; 3406 b->ctx = ctx; 3407 b->next = NULL; 3408 /* Append to linked list so that we can preserve the order */ 3409 if (!head) ds->boundary = b; 3410 while (head) { 3411 if (!head->next) { 3412 head->next = b; 3413 head = b; 3414 } 3415 head = head->next; 3416 ++n; 3417 } 3418 if (bd) { 3419 PetscValidIntPointer(bd, 13); 3420 *bd = n; 3421 } 3422 PetscFunctionReturn(0); 3423 } 3424 3425 /*@C 3426 PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. 3427 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 3428 should be performed, using the kernels from `PetscDSSetBdResidual()`. 3429 3430 Input Parameters: 3431 + ds - The `PetscDS` object 3432 . bd - The boundary condition number 3433 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3434 . name - The BC name 3435 . label - The label defining constrained points 3436 . Nv - The number of `DMLabel` ids for constrained points 3437 . values - An array of ids for constrained points 3438 . field - The field to constrain 3439 . Nc - The number of constrained field components 3440 . comps - An array of constrained component numbers 3441 . bcFunc - A pointwise function giving boundary values 3442 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3443 - ctx - An optional user context for bcFunc 3444 3445 Level: developer 3446 3447 Note: 3448 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from `PetscDSGetNumBoundary()`. 3449 See `PetscDSAddBoundary()` for a description of the calling sequences for the callbacks. 3450 3451 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()`, `PetscDSGetNumBoundary()`, `DMLabel` 3452 @*/ 3453 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) 3454 { 3455 DSBoundary b = ds->boundary; 3456 PetscInt n = 0; 3457 3458 PetscFunctionBegin; 3459 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3460 while (b) { 3461 if (n == bd) break; 3462 b = b->next; 3463 ++n; 3464 } 3465 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3466 if (name) { 3467 PetscCall(PetscFree(b->name)); 3468 PetscCall(PetscStrallocpy(name, (char **)&b->name)); 3469 } 3470 b->type = type; 3471 if (label) { 3472 const char *name; 3473 3474 b->label = label; 3475 PetscCall(PetscFree(b->lname)); 3476 PetscCall(PetscObjectGetName((PetscObject)label, &name)); 3477 PetscCall(PetscStrallocpy(name, (char **)&b->lname)); 3478 } 3479 if (Nv >= 0) { 3480 b->Nv = Nv; 3481 PetscCall(PetscFree(b->values)); 3482 PetscCall(PetscMalloc1(Nv, &b->values)); 3483 if (Nv) PetscCall(PetscArraycpy(b->values, values, Nv)); 3484 } 3485 if (field >= 0) b->field = field; 3486 if (Nc >= 0) { 3487 b->Nc = Nc; 3488 PetscCall(PetscFree(b->comps)); 3489 PetscCall(PetscMalloc1(Nc, &b->comps)); 3490 if (Nc) PetscCall(PetscArraycpy(b->comps, comps, Nc)); 3491 } 3492 if (bcFunc) b->func = bcFunc; 3493 if (bcFunc_t) b->func_t = bcFunc_t; 3494 if (ctx) b->ctx = ctx; 3495 PetscFunctionReturn(0); 3496 } 3497 3498 /*@ 3499 PetscDSGetNumBoundary - Get the number of registered BC 3500 3501 Input Parameters: 3502 . ds - The `PetscDS` object 3503 3504 Output Parameters: 3505 . numBd - The number of BC 3506 3507 Level: intermediate 3508 3509 .seealso: `PetscDS`, `PetscDSAddBoundary()`, `PetscDSGetBoundary()` 3510 @*/ 3511 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3512 { 3513 DSBoundary b = ds->boundary; 3514 3515 PetscFunctionBegin; 3516 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3517 PetscValidIntPointer(numBd, 2); 3518 *numBd = 0; 3519 while (b) { 3520 ++(*numBd); 3521 b = b->next; 3522 } 3523 PetscFunctionReturn(0); 3524 } 3525 3526 /*@C 3527 PetscDSGetBoundary - Gets a boundary condition to the model 3528 3529 Input Parameters: 3530 + ds - The `PetscDS` object 3531 - bd - The BC number 3532 3533 Output Parameters: 3534 + wf - The `PetscWeakForm` holding the pointwise functions 3535 . type - The type of condition, e.g. `DM_BC_ESSENTIAL`/`DM_BC_ESSENTIAL_FIELD` (Dirichlet), or `DM_BC_NATURAL` (Neumann) 3536 . name - The BC name 3537 . label - The label defining constrained points 3538 . Nv - The number of `DMLabel` ids for constrained points 3539 . values - An array of ids for constrained points 3540 . field - The field to constrain 3541 . Nc - The number of constrained field components 3542 . comps - An array of constrained component numbers 3543 . bcFunc - A pointwise function giving boundary values 3544 . bcFunc_t - A pointwise function giving the time derivative of the boundary values 3545 - ctx - An optional user context for bcFunc 3546 3547 Options Database Keys: 3548 + -bc_<boundary name> <num> - Overrides the boundary ids 3549 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3550 3551 Level: developer 3552 3553 .seealso: `PetscDS`, `PetscWeakForm`, `DMBoundaryConditionType`, `PetscDSAddBoundary()`, `DMLabel` 3554 @*/ 3555 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) 3556 { 3557 DSBoundary b = ds->boundary; 3558 PetscInt n = 0; 3559 3560 PetscFunctionBegin; 3561 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3562 while (b) { 3563 if (n == bd) break; 3564 b = b->next; 3565 ++n; 3566 } 3567 PetscCheck(b, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %" PetscInt_FMT " is not in [0, %" PetscInt_FMT ")", bd, n); 3568 if (wf) { 3569 PetscValidPointer(wf, 3); 3570 *wf = b->wf; 3571 } 3572 if (type) { 3573 PetscValidPointer(type, 4); 3574 *type = b->type; 3575 } 3576 if (name) { 3577 PetscValidPointer(name, 5); 3578 *name = b->name; 3579 } 3580 if (label) { 3581 PetscValidPointer(label, 6); 3582 *label = b->label; 3583 } 3584 if (Nv) { 3585 PetscValidIntPointer(Nv, 7); 3586 *Nv = b->Nv; 3587 } 3588 if (values) { 3589 PetscValidPointer(values, 8); 3590 *values = b->values; 3591 } 3592 if (field) { 3593 PetscValidIntPointer(field, 9); 3594 *field = b->field; 3595 } 3596 if (Nc) { 3597 PetscValidIntPointer(Nc, 10); 3598 *Nc = b->Nc; 3599 } 3600 if (comps) { 3601 PetscValidPointer(comps, 11); 3602 *comps = b->comps; 3603 } 3604 if (func) { 3605 PetscValidPointer(func, 12); 3606 *func = b->func; 3607 } 3608 if (func_t) { 3609 PetscValidPointer(func_t, 13); 3610 *func_t = b->func_t; 3611 } 3612 if (ctx) { 3613 PetscValidPointer(ctx, 14); 3614 *ctx = b->ctx; 3615 } 3616 PetscFunctionReturn(0); 3617 } 3618 3619 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3620 { 3621 PetscFunctionBegin; 3622 PetscCall(PetscNew(bNew)); 3623 PetscCall(PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf)); 3624 PetscCall(PetscWeakFormCopy(b->wf, (*bNew)->wf)); 3625 PetscCall(PetscStrallocpy(b->name, (char **)&((*bNew)->name))); 3626 PetscCall(PetscStrallocpy(b->lname, (char **)&((*bNew)->lname))); 3627 (*bNew)->type = b->type; 3628 (*bNew)->label = b->label; 3629 (*bNew)->Nv = b->Nv; 3630 PetscCall(PetscMalloc1(b->Nv, &(*bNew)->values)); 3631 PetscCall(PetscArraycpy((*bNew)->values, b->values, b->Nv)); 3632 (*bNew)->field = b->field; 3633 (*bNew)->Nc = b->Nc; 3634 PetscCall(PetscMalloc1(b->Nc, &(*bNew)->comps)); 3635 PetscCall(PetscArraycpy((*bNew)->comps, b->comps, b->Nc)); 3636 (*bNew)->func = b->func; 3637 (*bNew)->func_t = b->func_t; 3638 (*bNew)->ctx = b->ctx; 3639 PetscFunctionReturn(0); 3640 } 3641 3642 /*@ 3643 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 3644 3645 Not collective 3646 3647 Input Parameters: 3648 + ds - The source `PetscDS` object 3649 . numFields - The number of selected fields, or `PETSC_DEFAULT` for all fields 3650 - fields - The selected fields, or NULL for all fields 3651 3652 Output Parameter: 3653 . newds - The target `PetscDS`, now with a copy of the boundary conditions 3654 3655 Level: intermediate 3656 3657 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3658 @*/ 3659 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3660 { 3661 DSBoundary b, *lastnext; 3662 3663 PetscFunctionBegin; 3664 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3665 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3666 if (ds == newds) PetscFunctionReturn(0); 3667 PetscCall(PetscDSDestroyBoundary(newds)); 3668 lastnext = &(newds->boundary); 3669 for (b = ds->boundary; b; b = b->next) { 3670 DSBoundary bNew; 3671 PetscInt fieldNew = -1; 3672 3673 if (numFields > 0 && fields) { 3674 PetscInt f; 3675 3676 for (f = 0; f < numFields; ++f) 3677 if (b->field == fields[f]) break; 3678 if (f == numFields) continue; 3679 fieldNew = f; 3680 } 3681 PetscCall(DSBoundaryDuplicate_Internal(b, &bNew)); 3682 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3683 *lastnext = bNew; 3684 lastnext = &(bNew->next); 3685 } 3686 PetscFunctionReturn(0); 3687 } 3688 3689 /*@ 3690 PetscDSDestroyBoundary - Remove all `DMBoundary` objects from the `PetscDS` 3691 3692 Not collective 3693 3694 Input Parameter: 3695 . ds - The `PetscDS` object 3696 3697 Level: intermediate 3698 3699 .seealso: `PetscDS`, `DMBoundary`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()` 3700 @*/ 3701 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3702 { 3703 DSBoundary next = ds->boundary; 3704 3705 PetscFunctionBegin; 3706 while (next) { 3707 DSBoundary b = next; 3708 3709 next = b->next; 3710 PetscCall(PetscWeakFormDestroy(&b->wf)); 3711 PetscCall(PetscFree(b->name)); 3712 PetscCall(PetscFree(b->lname)); 3713 PetscCall(PetscFree(b->values)); 3714 PetscCall(PetscFree(b->comps)); 3715 PetscCall(PetscFree(b)); 3716 } 3717 PetscFunctionReturn(0); 3718 } 3719 3720 /*@ 3721 PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout 3722 3723 Not collective 3724 3725 Input Parameters: 3726 + prob - The `PetscDS` object 3727 . numFields - Number of new fields 3728 - fields - Old field number for each new field 3729 3730 Output Parameter: 3731 . newprob - The `PetscDS` copy 3732 3733 Level: intermediate 3734 3735 .seealso: `PetscDS`, `PetscDSSelectEquations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3736 @*/ 3737 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3738 { 3739 PetscInt Nf, Nfn, fn; 3740 3741 PetscFunctionBegin; 3742 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3743 if (fields) PetscValidIntPointer(fields, 3); 3744 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3745 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3746 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3747 numFields = numFields < 0 ? Nf : numFields; 3748 for (fn = 0; fn < numFields; ++fn) { 3749 const PetscInt f = fields ? fields[fn] : fn; 3750 PetscObject disc; 3751 3752 if (f >= Nf) continue; 3753 PetscCall(PetscDSGetDiscretization(prob, f, &disc)); 3754 PetscCall(PetscDSSetDiscretization(newprob, fn, disc)); 3755 } 3756 PetscFunctionReturn(0); 3757 } 3758 3759 /*@ 3760 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 3761 3762 Not collective 3763 3764 Input Parameters: 3765 + prob - The `PetscDS` object 3766 . numFields - Number of new fields 3767 - fields - Old field number for each new field 3768 3769 Output Parameter: 3770 . newprob - The `PetscDS` copy 3771 3772 Level: intermediate 3773 3774 .seealso: `PetscDS`, `PetscDSSelectDiscretizations()`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3775 @*/ 3776 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3777 { 3778 PetscInt Nf, Nfn, fn, gn; 3779 3780 PetscFunctionBegin; 3781 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3782 if (fields) PetscValidIntPointer(fields, 3); 3783 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3784 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3785 PetscCall(PetscDSGetNumFields(newprob, &Nfn)); 3786 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); 3787 for (fn = 0; fn < numFields; ++fn) { 3788 const PetscInt f = fields ? fields[fn] : fn; 3789 PetscPointFunc obj; 3790 PetscPointFunc f0, f1; 3791 PetscBdPointFunc f0Bd, f1Bd; 3792 PetscRiemannFunc r; 3793 3794 if (f >= Nf) continue; 3795 PetscCall(PetscDSGetObjective(prob, f, &obj)); 3796 PetscCall(PetscDSGetResidual(prob, f, &f0, &f1)); 3797 PetscCall(PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd)); 3798 PetscCall(PetscDSGetRiemannSolver(prob, f, &r)); 3799 PetscCall(PetscDSSetObjective(newprob, fn, obj)); 3800 PetscCall(PetscDSSetResidual(newprob, fn, f0, f1)); 3801 PetscCall(PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd)); 3802 PetscCall(PetscDSSetRiemannSolver(newprob, fn, r)); 3803 for (gn = 0; gn < numFields; ++gn) { 3804 const PetscInt g = fields ? fields[gn] : gn; 3805 PetscPointJac g0, g1, g2, g3; 3806 PetscPointJac g0p, g1p, g2p, g3p; 3807 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3808 3809 if (g >= Nf) continue; 3810 PetscCall(PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3)); 3811 PetscCall(PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p)); 3812 PetscCall(PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd)); 3813 PetscCall(PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3)); 3814 PetscCall(PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p)); 3815 PetscCall(PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd)); 3816 } 3817 } 3818 PetscFunctionReturn(0); 3819 } 3820 3821 /*@ 3822 PetscDSCopyEquations - Copy all pointwise function pointers to another `PetscDS` 3823 3824 Not collective 3825 3826 Input Parameter: 3827 . prob - The `PetscDS` object 3828 3829 Output Parameter: 3830 . newprob - The `PetscDS` copy 3831 3832 Level: intermediate 3833 3834 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3835 @*/ 3836 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3837 { 3838 PetscWeakForm wf, newwf; 3839 PetscInt Nf, Ng; 3840 3841 PetscFunctionBegin; 3842 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3843 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3844 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3845 PetscCall(PetscDSGetNumFields(newprob, &Ng)); 3846 PetscCheck(Nf == Ng, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %" PetscInt_FMT " != %" PetscInt_FMT, Nf, Ng); 3847 PetscCall(PetscDSGetWeakForm(prob, &wf)); 3848 PetscCall(PetscDSGetWeakForm(newprob, &newwf)); 3849 PetscCall(PetscWeakFormCopy(wf, newwf)); 3850 PetscFunctionReturn(0); 3851 } 3852 3853 /*@ 3854 PetscDSCopyConstants - Copy all constants to another `PetscDS` 3855 3856 Not collective 3857 3858 Input Parameter: 3859 . prob - The `PetscDS` object 3860 3861 Output Parameter: 3862 . newprob - The `PetscDS` copy 3863 3864 Level: intermediate 3865 3866 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3867 @*/ 3868 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3869 { 3870 PetscInt Nc; 3871 const PetscScalar *constants; 3872 3873 PetscFunctionBegin; 3874 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3875 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3876 PetscCall(PetscDSGetConstants(prob, &Nc, &constants)); 3877 PetscCall(PetscDSSetConstants(newprob, Nc, (PetscScalar *)constants)); 3878 PetscFunctionReturn(0); 3879 } 3880 3881 /*@ 3882 PetscDSCopyExactSolutions - Copy all exact solutions to another `PetscDS` 3883 3884 Not collective 3885 3886 Input Parameter: 3887 . ds - The `PetscDS` object 3888 3889 Output Parameter: 3890 . newds - The `PetscDS` copy 3891 3892 Level: intermediate 3893 3894 .seealso: `PetscDS`, `PetscDSCopyBoundary()`, `PetscDSCopyEquations()`, `PetscDSSetResidual()`, `PetscDSSetJacobian()`, `PetscDSSetRiemannSolver()`, `PetscDSSetBdResidual()`, `PetscDSSetBdJacobian()`, `PetscDSCreate()` 3895 @*/ 3896 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 3897 { 3898 PetscSimplePointFunc sol; 3899 void *ctx; 3900 PetscInt Nf, f; 3901 3902 PetscFunctionBegin; 3903 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3904 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 3905 PetscCall(PetscDSGetNumFields(ds, &Nf)); 3906 for (f = 0; f < Nf; ++f) { 3907 PetscCall(PetscDSGetExactSolution(ds, f, &sol, &ctx)); 3908 PetscCall(PetscDSSetExactSolution(newds, f, sol, ctx)); 3909 PetscCall(PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx)); 3910 PetscCall(PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx)); 3911 } 3912 PetscFunctionReturn(0); 3913 } 3914 3915 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 3916 { 3917 PetscInt dim, Nf, f; 3918 3919 PetscFunctionBegin; 3920 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3921 PetscValidPointer(subprob, 3); 3922 if (height == 0) { 3923 *subprob = prob; 3924 PetscFunctionReturn(0); 3925 } 3926 PetscCall(PetscDSGetNumFields(prob, &Nf)); 3927 PetscCall(PetscDSGetSpatialDimension(prob, &dim)); 3928 PetscCheck(height <= dim, PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %" PetscInt_FMT "], not %" PetscInt_FMT, dim, height); 3929 if (!prob->subprobs) PetscCall(PetscCalloc1(dim, &prob->subprobs)); 3930 if (!prob->subprobs[height - 1]) { 3931 PetscInt cdim; 3932 3933 PetscCall(PetscDSCreate(PetscObjectComm((PetscObject)prob), &prob->subprobs[height - 1])); 3934 PetscCall(PetscDSGetCoordinateDimension(prob, &cdim)); 3935 PetscCall(PetscDSSetCoordinateDimension(prob->subprobs[height - 1], cdim)); 3936 for (f = 0; f < Nf; ++f) { 3937 PetscFE subfe; 3938 PetscObject obj; 3939 PetscClassId id; 3940 3941 PetscCall(PetscDSGetDiscretization(prob, f, &obj)); 3942 PetscCall(PetscObjectGetClassId(obj, &id)); 3943 if (id == PETSCFE_CLASSID) PetscCall(PetscFEGetHeightSubspace((PetscFE)obj, height, &subfe)); 3944 else SETERRQ(PetscObjectComm((PetscObject)prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %" PetscInt_FMT, f); 3945 PetscCall(PetscDSSetDiscretization(prob->subprobs[height - 1], f, (PetscObject)subfe)); 3946 } 3947 } 3948 *subprob = prob->subprobs[height - 1]; 3949 PetscFunctionReturn(0); 3950 } 3951 3952 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 3953 { 3954 PetscObject obj; 3955 PetscClassId id; 3956 PetscInt Nf; 3957 3958 PetscFunctionBegin; 3959 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3960 PetscValidPointer(disctype, 3); 3961 *disctype = PETSC_DISC_NONE; 3962 PetscCall(PetscDSGetNumFields(ds, &Nf)); 3963 PetscCheck(f < Nf, PetscObjectComm((PetscObject)ds), PETSC_ERR_ARG_SIZ, "Field %" PetscInt_FMT " must be in [0, %" PetscInt_FMT ")", f, Nf); 3964 PetscCall(PetscDSGetDiscretization(ds, f, &obj)); 3965 if (obj) { 3966 PetscCall(PetscObjectGetClassId(obj, &id)); 3967 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 3968 else *disctype = PETSC_DISC_FV; 3969 } 3970 PetscFunctionReturn(0); 3971 } 3972 3973 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 3974 { 3975 PetscFunctionBegin; 3976 PetscCall(PetscFree(ds->data)); 3977 PetscFunctionReturn(0); 3978 } 3979 3980 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 3981 { 3982 PetscFunctionBegin; 3983 ds->ops->setfromoptions = NULL; 3984 ds->ops->setup = NULL; 3985 ds->ops->view = NULL; 3986 ds->ops->destroy = PetscDSDestroy_Basic; 3987 PetscFunctionReturn(0); 3988 } 3989 3990 /*MC 3991 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 3992 3993 Level: intermediate 3994 3995 .seealso: `PetscDSType`, `PetscDSCreate()`, `PetscDSSetType()` 3996 M*/ 3997 3998 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 3999 { 4000 PetscDS_Basic *b; 4001 4002 PetscFunctionBegin; 4003 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4004 PetscCall(PetscNew(&b)); 4005 ds->data = b; 4006 4007 PetscCall(PetscDSInitialize_Basic(ds)); 4008 PetscFunctionReturn(0); 4009 } 4010