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