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