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