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