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 PetscErrorCode ierr; 58 59 PetscFunctionBegin; 60 ierr = PetscFunctionListAdd(&PetscDSList, sname, function);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 /*@C 65 PetscDSSetType - Builds a particular PetscDS 66 67 Collective on prob 68 69 Input Parameters: 70 + prob - The PetscDS object 71 - name - The kind of system 72 73 Options Database Key: 74 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types 75 76 Level: intermediate 77 78 Not available from Fortran 79 80 .seealso: PetscDSGetType(), PetscDSCreate() 81 @*/ 82 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name) 83 { 84 PetscErrorCode (*r)(PetscDS); 85 PetscBool match; 86 PetscErrorCode ierr; 87 88 PetscFunctionBegin; 89 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 90 ierr = PetscObjectTypeCompare((PetscObject) prob, name, &match);CHKERRQ(ierr); 91 if (match) PetscFunctionReturn(0); 92 93 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 94 ierr = PetscFunctionListFind(PetscDSList, name, &r);CHKERRQ(ierr); 95 if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name); 96 97 if (prob->ops->destroy) { 98 ierr = (*prob->ops->destroy)(prob);CHKERRQ(ierr); 99 prob->ops->destroy = NULL; 100 } 101 ierr = (*r)(prob);CHKERRQ(ierr); 102 ierr = PetscObjectChangeTypeName((PetscObject) prob, name);CHKERRQ(ierr); 103 PetscFunctionReturn(0); 104 } 105 106 /*@C 107 PetscDSGetType - Gets the PetscDS type name (as a string) from the object. 108 109 Not Collective 110 111 Input Parameter: 112 . prob - The PetscDS 113 114 Output Parameter: 115 . name - The PetscDS type name 116 117 Level: intermediate 118 119 Not available from Fortran 120 121 .seealso: PetscDSSetType(), PetscDSCreate() 122 @*/ 123 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name) 124 { 125 PetscErrorCode ierr; 126 127 PetscFunctionBegin; 128 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 129 PetscValidPointer(name, 2); 130 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 131 *name = ((PetscObject) prob)->type_name; 132 PetscFunctionReturn(0); 133 } 134 135 static PetscErrorCode PetscDSView_Ascii(PetscDS prob, PetscViewer viewer) 136 { 137 PetscViewerFormat format; 138 const PetscScalar *constants; 139 PetscInt numConstants, f; 140 PetscErrorCode ierr; 141 142 PetscFunctionBegin; 143 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 144 ierr = PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", prob->Nf);CHKERRQ(ierr); 145 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 146 ierr = PetscViewerASCIIPrintf(viewer, " cell total dim %D total comp %D\n", prob->totDim, prob->totComp);CHKERRQ(ierr); 147 if (prob->isHybrid) {ierr = PetscViewerASCIIPrintf(viewer, " hybrid cell\n");CHKERRQ(ierr);} 148 for (f = 0; f < prob->Nf; ++f) { 149 DSBoundary b; 150 PetscObject obj; 151 PetscClassId id; 152 PetscQuadrature q; 153 const char *name; 154 PetscInt Nc, Nq, Nqc; 155 156 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 157 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 158 ierr = PetscObjectGetName(obj, &name);CHKERRQ(ierr); 159 ierr = PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");CHKERRQ(ierr); 160 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 161 if (id == PETSCFE_CLASSID) { 162 ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr); 163 ierr = PetscFEGetQuadrature((PetscFE) obj, &q);CHKERRQ(ierr); 164 ierr = PetscViewerASCIIPrintf(viewer, " FEM");CHKERRQ(ierr); 165 } else if (id == PETSCFV_CLASSID) { 166 ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr); 167 ierr = PetscFVGetQuadrature((PetscFV) obj, &q);CHKERRQ(ierr); 168 ierr = PetscViewerASCIIPrintf(viewer, " FVM");CHKERRQ(ierr); 169 } 170 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 171 if (Nc > 1) {ierr = PetscViewerASCIIPrintf(viewer, "%D components", Nc);CHKERRQ(ierr);} 172 else {ierr = PetscViewerASCIIPrintf(viewer, "%D component ", Nc);CHKERRQ(ierr);} 173 if (prob->implicit[f]) {ierr = PetscViewerASCIIPrintf(viewer, " (implicit)");CHKERRQ(ierr);} 174 else {ierr = PetscViewerASCIIPrintf(viewer, " (explicit)");CHKERRQ(ierr);} 175 if (q) { 176 ierr = PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);CHKERRQ(ierr); 177 ierr = PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);CHKERRQ(ierr); 178 } 179 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 180 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 181 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 182 if (id == PETSCFE_CLASSID) {ierr = PetscFEView((PetscFE) obj, viewer);CHKERRQ(ierr);} 183 else if (id == PETSCFV_CLASSID) {ierr = PetscFVView((PetscFV) obj, viewer);CHKERRQ(ierr);} 184 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 185 186 for (b = prob->boundary; b; b = b->next) { 187 PetscInt c, i; 188 189 if (b->field != f) continue; 190 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 191 ierr = PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->labelname, DMBoundaryConditionTypes[b->type]);CHKERRQ(ierr); 192 if (!b->numcomps) { 193 ierr = PetscViewerASCIIPrintf(viewer, " all components\n");CHKERRQ(ierr); 194 } else { 195 ierr = PetscViewerASCIIPrintf(viewer, " components: ");CHKERRQ(ierr); 196 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 197 for (c = 0; c < b->numcomps; ++c) { 198 if (c > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 199 ierr = PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);CHKERRQ(ierr); 200 } 201 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 202 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, " ids: ");CHKERRQ(ierr); 205 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 206 for (i = 0; i < b->numids; ++i) { 207 if (i > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 208 ierr = PetscViewerASCIIPrintf(viewer, "%D", b->ids[i]);CHKERRQ(ierr); 209 } 210 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 211 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 212 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 213 } 214 } 215 ierr = PetscDSGetConstants(prob, &numConstants, &constants);CHKERRQ(ierr); 216 if (numConstants) { 217 ierr = PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);CHKERRQ(ierr); 218 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 219 for (f = 0; f < numConstants; ++f) {ierr = PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));CHKERRQ(ierr);} 220 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 221 } 222 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 223 PetscFunctionReturn(0); 224 } 225 226 /*@C 227 PetscDSViewFromOptions - View from Options 228 229 Collective on PetscDS 230 231 Input Parameters: 232 + A - the PetscDS object 233 . obj - Optional object 234 - name - command line option 235 236 Level: intermediate 237 .seealso: PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate() 238 @*/ 239 PetscErrorCode PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[]) 240 { 241 PetscErrorCode ierr; 242 243 PetscFunctionBegin; 244 PetscValidHeaderSpecific(A,PETSCDS_CLASSID,1); 245 ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 246 PetscFunctionReturn(0); 247 } 248 249 /*@C 250 PetscDSView - Views a PetscDS 251 252 Collective on prob 253 254 Input Parameter: 255 + prob - the PetscDS object to view 256 - v - the viewer 257 258 Level: developer 259 260 .seealso PetscDSDestroy() 261 @*/ 262 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v) 263 { 264 PetscBool iascii; 265 PetscErrorCode ierr; 266 267 PetscFunctionBegin; 268 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 269 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);CHKERRQ(ierr);} 270 else {PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);} 271 ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 272 if (iascii) {ierr = PetscDSView_Ascii(prob, v);CHKERRQ(ierr);} 273 if (prob->ops->view) {ierr = (*prob->ops->view)(prob, v);CHKERRQ(ierr);} 274 PetscFunctionReturn(0); 275 } 276 277 /*@ 278 PetscDSSetFromOptions - sets parameters in a PetscDS from the options database 279 280 Collective on prob 281 282 Input Parameter: 283 . prob - the PetscDS object to set options for 284 285 Options Database: 286 + -petscds_type <type> : Set the DS type 287 . -petscds_view <view opt> : View the DS 288 . -petscds_jac_pre : Turn formation of a separate Jacobian preconditioner on and off 289 . -bc_<name> <ids> : Specify a list of label ids for a boundary condition 290 - -bc_<name>_comp <comps> : Specify a list of field components to constrain for a boundary condition 291 292 Level: developer 293 294 .seealso PetscDSView() 295 @*/ 296 PetscErrorCode PetscDSSetFromOptions(PetscDS prob) 297 { 298 DSBoundary b; 299 const char *defaultType; 300 char name[256]; 301 PetscBool flg; 302 PetscErrorCode ierr; 303 304 PetscFunctionBegin; 305 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 306 if (!((PetscObject) prob)->type_name) { 307 defaultType = PETSCDSBASIC; 308 } else { 309 defaultType = ((PetscObject) prob)->type_name; 310 } 311 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 312 313 ierr = PetscObjectOptionsBegin((PetscObject) prob);CHKERRQ(ierr); 314 for (b = prob->boundary; b; b = b->next) { 315 char optname[1024]; 316 PetscInt ids[1024], len = 1024; 317 PetscBool flg; 318 319 ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);CHKERRQ(ierr); 320 ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr); 321 ierr = PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);CHKERRQ(ierr); 322 if (flg) { 323 b->numids = len; 324 ierr = PetscFree(b->ids);CHKERRQ(ierr); 325 ierr = PetscMalloc1(len, &b->ids);CHKERRQ(ierr); 326 ierr = PetscArraycpy(b->ids, ids, len);CHKERRQ(ierr); 327 } 328 len = 1024; 329 ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);CHKERRQ(ierr); 330 ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr); 331 ierr = PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);CHKERRQ(ierr); 332 if (flg) { 333 b->numcomps = len; 334 ierr = PetscFree(b->comps);CHKERRQ(ierr); 335 ierr = PetscMalloc1(len, &b->comps);CHKERRQ(ierr); 336 ierr = PetscArraycpy(b->comps, ids, len);CHKERRQ(ierr); 337 } 338 } 339 ierr = PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);CHKERRQ(ierr); 340 if (flg) { 341 ierr = PetscDSSetType(prob, name);CHKERRQ(ierr); 342 } else if (!((PetscObject) prob)->type_name) { 343 ierr = PetscDSSetType(prob, defaultType);CHKERRQ(ierr); 344 } 345 ierr = PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg);CHKERRQ(ierr); 346 if (prob->ops->setfromoptions) {ierr = (*prob->ops->setfromoptions)(prob);CHKERRQ(ierr);} 347 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 348 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);CHKERRQ(ierr); 349 ierr = PetscOptionsEnd();CHKERRQ(ierr); 350 if (prob->Nf) {ierr = PetscDSViewFromOptions(prob, NULL, "-petscds_view");CHKERRQ(ierr);} 351 PetscFunctionReturn(0); 352 } 353 354 /*@C 355 PetscDSSetUp - Construct data structures for the PetscDS 356 357 Collective on prob 358 359 Input Parameter: 360 . prob - the PetscDS object to setup 361 362 Level: developer 363 364 .seealso PetscDSView(), PetscDSDestroy() 365 @*/ 366 PetscErrorCode PetscDSSetUp(PetscDS prob) 367 { 368 const PetscInt Nf = prob->Nf; 369 PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f; 370 PetscErrorCode ierr; 371 372 PetscFunctionBegin; 373 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 374 if (prob->setup) PetscFunctionReturn(0); 375 /* Calculate sizes */ 376 ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr); 377 ierr = PetscDSGetCoordinateDimension(prob, &dimEmbed);CHKERRQ(ierr); 378 prob->totDim = prob->totComp = 0; 379 ierr = PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);CHKERRQ(ierr); 380 ierr = PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);CHKERRQ(ierr); 381 ierr = PetscMalloc2(Nf,&prob->T,Nf,&prob->Tf);CHKERRQ(ierr); 382 for (f = 0; f < Nf; ++f) { 383 PetscObject obj; 384 PetscClassId id; 385 PetscQuadrature q; 386 PetscInt Nq = 0, Nb, Nc; 387 388 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 389 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 390 if (id == PETSCFE_CLASSID) { 391 PetscFE fe = (PetscFE) obj; 392 393 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 394 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 395 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 396 ierr = PetscFEGetCellTabulation(fe, &prob->T[f]);CHKERRQ(ierr); 397 ierr = PetscFEGetFaceTabulation(fe, &prob->Tf[f]);CHKERRQ(ierr); 398 } else if (id == PETSCFV_CLASSID) { 399 PetscFV fv = (PetscFV) obj; 400 401 ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr); 402 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 403 Nb = Nc; 404 ierr = PetscFVGetCellTabulation(fv, &prob->T[f]);CHKERRQ(ierr); 405 /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */ 406 } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 407 prob->Nc[f] = Nc; 408 prob->Nb[f] = Nb; 409 prob->off[f+1] = Nc + prob->off[f]; 410 prob->offDer[f+1] = Nc*dim + prob->offDer[f]; 411 if (q) {ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);} 412 NqMax = PetscMax(NqMax, Nq); 413 NbMax = PetscMax(NbMax, Nb); 414 NcMax = PetscMax(NcMax, Nc); 415 prob->totDim += Nb; 416 prob->totComp += Nc; 417 /* There are two faces for all fields but the cohesive field on a hybrid cell */ 418 if (prob->isHybrid && (f < Nf-1)) prob->totDim += Nb; 419 } 420 /* Allocate works space */ 421 if (prob->isHybrid) NsMax = 2; 422 ierr = PetscMalloc3(NsMax*prob->totComp,&prob->u,NsMax*prob->totComp,&prob->u_t,NsMax*prob->totComp*dimEmbed,&prob->u_x);CHKERRQ(ierr); 423 ierr = PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);CHKERRQ(ierr); 424 ierr = PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dim,&prob->f1, 425 NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dim,&prob->g1, 426 NsMax*NsMax*NqMax*NcMax*NcMax*dim,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dim*dim,&prob->g3);CHKERRQ(ierr); 427 if (prob->ops->setup) {ierr = (*prob->ops->setup)(prob);CHKERRQ(ierr);} 428 prob->setup = PETSC_TRUE; 429 PetscFunctionReturn(0); 430 } 431 432 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob) 433 { 434 PetscErrorCode ierr; 435 436 PetscFunctionBegin; 437 ierr = PetscFree2(prob->Nc,prob->Nb);CHKERRQ(ierr); 438 ierr = PetscFree2(prob->off,prob->offDer);CHKERRQ(ierr); 439 ierr = PetscFree2(prob->T,prob->Tf);CHKERRQ(ierr); 440 ierr = PetscFree3(prob->u,prob->u_t,prob->u_x);CHKERRQ(ierr); 441 ierr = PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);CHKERRQ(ierr); 442 ierr = PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);CHKERRQ(ierr); 443 PetscFunctionReturn(0); 444 } 445 446 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew) 447 { 448 PetscObject *tmpd; 449 PetscBool *tmpi; 450 PetscPointFunc *tmpobj, *tmpf, *tmpup; 451 PetscPointJac *tmpg, *tmpgp, *tmpgt; 452 PetscBdPointFunc *tmpfbd; 453 PetscBdPointJac *tmpgbd; 454 PetscRiemannFunc *tmpr; 455 PetscSimplePointFunc *tmpexactSol; 456 void **tmpexactCtx; 457 void **tmpctx; 458 PetscInt Nf = prob->Nf, f; 459 PetscErrorCode ierr; 460 461 PetscFunctionBegin; 462 if (Nf >= NfNew) PetscFunctionReturn(0); 463 prob->setup = PETSC_FALSE; 464 ierr = PetscDSDestroyStructs_Static(prob);CHKERRQ(ierr); 465 ierr = PetscMalloc2(NfNew, &tmpd, NfNew, &tmpi);CHKERRQ(ierr); 466 for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f];} 467 for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE;} 468 ierr = PetscFree2(prob->disc, prob->implicit);CHKERRQ(ierr); 469 prob->Nf = NfNew; 470 prob->disc = tmpd; 471 prob->implicit = tmpi; 472 ierr = PetscCalloc7(NfNew, &tmpobj, NfNew*2, &tmpf, NfNew*NfNew*4, &tmpg, NfNew*NfNew*4, &tmpgp, NfNew*NfNew*4, &tmpgt, NfNew, &tmpr, NfNew, &tmpctx);CHKERRQ(ierr); 473 ierr = PetscCalloc1(NfNew, &tmpup);CHKERRQ(ierr); 474 for (f = 0; f < Nf; ++f) tmpobj[f] = prob->obj[f]; 475 for (f = 0; f < Nf*2; ++f) tmpf[f] = prob->f[f]; 476 for (f = 0; f < Nf*Nf*4; ++f) tmpg[f] = prob->g[f]; 477 for (f = 0; f < Nf*Nf*4; ++f) tmpgp[f] = prob->gp[f]; 478 for (f = 0; f < Nf; ++f) tmpr[f] = prob->r[f]; 479 for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f]; 480 for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f]; 481 for (f = Nf; f < NfNew; ++f) tmpobj[f] = NULL; 482 for (f = Nf*2; f < NfNew*2; ++f) tmpf[f] = NULL; 483 for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpg[f] = NULL; 484 for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgp[f] = NULL; 485 for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgt[f] = NULL; 486 for (f = Nf; f < NfNew; ++f) tmpr[f] = NULL; 487 for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL; 488 for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL; 489 ierr = PetscFree7(prob->obj, prob->f, prob->g, prob->gp, prob->gt, prob->r, prob->ctx);CHKERRQ(ierr); 490 ierr = PetscFree(prob->update);CHKERRQ(ierr); 491 prob->obj = tmpobj; 492 prob->f = tmpf; 493 prob->g = tmpg; 494 prob->gp = tmpgp; 495 prob->gt = tmpgt; 496 prob->r = tmpr; 497 prob->update = tmpup; 498 prob->ctx = tmpctx; 499 ierr = PetscCalloc4(NfNew*2, &tmpfbd, NfNew*NfNew*4, &tmpgbd, NfNew, &tmpexactSol, NfNew, &tmpexactCtx);CHKERRQ(ierr); 500 for (f = 0; f < Nf*2; ++f) tmpfbd[f] = prob->fBd[f]; 501 for (f = 0; f < Nf*Nf*4; ++f) tmpgbd[f] = prob->gBd[f]; 502 for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f]; 503 for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f]; 504 for (f = Nf*2; f < NfNew*2; ++f) tmpfbd[f] = NULL; 505 for (f = Nf*Nf*4; f < NfNew*NfNew*4; ++f) tmpgbd[f] = NULL; 506 for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL; 507 for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL; 508 ierr = PetscFree4(prob->fBd, prob->gBd, prob->exactSol, prob->exactCtx);CHKERRQ(ierr); 509 prob->fBd = tmpfbd; 510 prob->gBd = tmpgbd; 511 prob->exactSol = tmpexactSol; 512 prob->exactCtx = tmpexactCtx; 513 PetscFunctionReturn(0); 514 } 515 516 /*@ 517 PetscDSDestroy - Destroys a PetscDS object 518 519 Collective on prob 520 521 Input Parameter: 522 . prob - the PetscDS object to destroy 523 524 Level: developer 525 526 .seealso PetscDSView() 527 @*/ 528 PetscErrorCode PetscDSDestroy(PetscDS *prob) 529 { 530 PetscInt f; 531 DSBoundary next; 532 PetscErrorCode ierr; 533 534 PetscFunctionBegin; 535 if (!*prob) PetscFunctionReturn(0); 536 PetscValidHeaderSpecific((*prob), PETSCDS_CLASSID, 1); 537 538 if (--((PetscObject)(*prob))->refct > 0) {*prob = 0; PetscFunctionReturn(0);} 539 ((PetscObject) (*prob))->refct = 0; 540 if ((*prob)->subprobs) { 541 PetscInt dim, d; 542 543 ierr = PetscDSGetSpatialDimension(*prob, &dim);CHKERRQ(ierr); 544 for (d = 0; d < dim; ++d) {ierr = PetscDSDestroy(&(*prob)->subprobs[d]);CHKERRQ(ierr);} 545 } 546 ierr = PetscFree((*prob)->subprobs);CHKERRQ(ierr); 547 ierr = PetscDSDestroyStructs_Static(*prob);CHKERRQ(ierr); 548 for (f = 0; f < (*prob)->Nf; ++f) { 549 ierr = PetscObjectDereference((*prob)->disc[f]);CHKERRQ(ierr); 550 } 551 ierr = PetscFree2((*prob)->disc, (*prob)->implicit);CHKERRQ(ierr); 552 ierr = PetscFree7((*prob)->obj,(*prob)->f,(*prob)->g,(*prob)->gp,(*prob)->gt,(*prob)->r,(*prob)->ctx);CHKERRQ(ierr); 553 ierr = PetscFree((*prob)->update);CHKERRQ(ierr); 554 ierr = PetscFree4((*prob)->fBd,(*prob)->gBd,(*prob)->exactSol,(*prob)->exactCtx);CHKERRQ(ierr); 555 if ((*prob)->ops->destroy) {ierr = (*(*prob)->ops->destroy)(*prob);CHKERRQ(ierr);} 556 next = (*prob)->boundary; 557 while (next) { 558 DSBoundary b = next; 559 560 next = b->next; 561 ierr = PetscFree(b->comps);CHKERRQ(ierr); 562 ierr = PetscFree(b->ids);CHKERRQ(ierr); 563 ierr = PetscFree(b->name);CHKERRQ(ierr); 564 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 565 ierr = PetscFree(b);CHKERRQ(ierr); 566 } 567 ierr = PetscFree((*prob)->constants);CHKERRQ(ierr); 568 ierr = PetscHeaderDestroy(prob);CHKERRQ(ierr); 569 PetscFunctionReturn(0); 570 } 571 572 /*@ 573 PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType(). 574 575 Collective 576 577 Input Parameter: 578 . comm - The communicator for the PetscDS object 579 580 Output Parameter: 581 . prob - The PetscDS object 582 583 Level: beginner 584 585 .seealso: PetscDSSetType(), PETSCDSBASIC 586 @*/ 587 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *prob) 588 { 589 PetscDS p; 590 PetscErrorCode ierr; 591 592 PetscFunctionBegin; 593 PetscValidPointer(prob, 2); 594 *prob = NULL; 595 ierr = PetscDSInitializePackage();CHKERRQ(ierr); 596 597 ierr = PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);CHKERRQ(ierr); 598 599 p->Nf = 0; 600 p->setup = PETSC_FALSE; 601 p->numConstants = 0; 602 p->constants = NULL; 603 p->dimEmbed = -1; 604 p->useJacPre = PETSC_TRUE; 605 606 *prob = p; 607 PetscFunctionReturn(0); 608 } 609 610 /*@ 611 PetscDSGetNumFields - Returns the number of fields in the DS 612 613 Not collective 614 615 Input Parameter: 616 . prob - The PetscDS object 617 618 Output Parameter: 619 . Nf - The number of fields 620 621 Level: beginner 622 623 .seealso: PetscDSGetSpatialDimension(), PetscDSCreate() 624 @*/ 625 PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf) 626 { 627 PetscFunctionBegin; 628 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 629 PetscValidPointer(Nf, 2); 630 *Nf = prob->Nf; 631 PetscFunctionReturn(0); 632 } 633 634 /*@ 635 PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations 636 637 Not collective 638 639 Input Parameter: 640 . prob - The PetscDS object 641 642 Output Parameter: 643 . dim - The spatial dimension 644 645 Level: beginner 646 647 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate() 648 @*/ 649 PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim) 650 { 651 PetscErrorCode ierr; 652 653 PetscFunctionBegin; 654 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 655 PetscValidPointer(dim, 2); 656 *dim = 0; 657 if (prob->Nf) { 658 PetscObject obj; 659 PetscClassId id; 660 661 ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr); 662 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 663 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetSpatialDimension((PetscFE) obj, dim);CHKERRQ(ierr);} 664 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetSpatialDimension((PetscFV) obj, dim);CHKERRQ(ierr);} 665 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0); 666 } 667 PetscFunctionReturn(0); 668 } 669 670 /*@ 671 PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded 672 673 Not collective 674 675 Input Parameter: 676 . prob - The PetscDS object 677 678 Output Parameter: 679 . dimEmbed - The coordinate dimension 680 681 Level: beginner 682 683 .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate() 684 @*/ 685 PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed) 686 { 687 PetscFunctionBegin; 688 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 689 PetscValidPointer(dimEmbed, 2); 690 if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS"); 691 *dimEmbed = prob->dimEmbed; 692 PetscFunctionReturn(0); 693 } 694 695 /*@ 696 PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded 697 698 Logically collective on prob 699 700 Input Parameters: 701 + prob - The PetscDS object 702 - dimEmbed - The coordinate dimension 703 704 Level: beginner 705 706 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate() 707 @*/ 708 PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed) 709 { 710 PetscFunctionBegin; 711 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 712 if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed); 713 prob->dimEmbed = dimEmbed; 714 PetscFunctionReturn(0); 715 } 716 717 /*@ 718 PetscDSGetHybrid - Returns the flag for a hybrid (cohesive) cell 719 720 Not collective 721 722 Input Parameter: 723 . prob - The PetscDS object 724 725 Output Parameter: 726 . isHybrid - The flag 727 728 Level: developer 729 730 .seealso: PetscDSSetHybrid(), PetscDSCreate() 731 @*/ 732 PetscErrorCode PetscDSGetHybrid(PetscDS prob, PetscBool *isHybrid) 733 { 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 736 PetscValidPointer(isHybrid, 2); 737 *isHybrid = prob->isHybrid; 738 PetscFunctionReturn(0); 739 } 740 741 /*@ 742 PetscDSSetHybrid - Set the flag for a hybrid (cohesive) cell 743 744 Not collective 745 746 Input Parameters: 747 + prob - The PetscDS object 748 - isHybrid - The flag 749 750 Level: developer 751 752 .seealso: PetscDSGetHybrid(), PetscDSCreate() 753 @*/ 754 PetscErrorCode PetscDSSetHybrid(PetscDS prob, PetscBool isHybrid) 755 { 756 PetscFunctionBegin; 757 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 758 prob->isHybrid = isHybrid; 759 PetscFunctionReturn(0); 760 } 761 762 /*@ 763 PetscDSGetTotalDimension - Returns the total size of the approximation space for this system 764 765 Not collective 766 767 Input Parameter: 768 . prob - The PetscDS object 769 770 Output Parameter: 771 . dim - The total problem dimension 772 773 Level: beginner 774 775 .seealso: PetscDSGetNumFields(), PetscDSCreate() 776 @*/ 777 PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim) 778 { 779 PetscErrorCode ierr; 780 781 PetscFunctionBegin; 782 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 783 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 784 PetscValidPointer(dim, 2); 785 *dim = prob->totDim; 786 PetscFunctionReturn(0); 787 } 788 789 /*@ 790 PetscDSGetTotalComponents - Returns the total number of components in this system 791 792 Not collective 793 794 Input Parameter: 795 . prob - The PetscDS object 796 797 Output Parameter: 798 . dim - The total number of components 799 800 Level: beginner 801 802 .seealso: PetscDSGetNumFields(), PetscDSCreate() 803 @*/ 804 PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc) 805 { 806 PetscErrorCode ierr; 807 808 PetscFunctionBegin; 809 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 810 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 811 PetscValidPointer(Nc, 2); 812 *Nc = prob->totComp; 813 PetscFunctionReturn(0); 814 } 815 816 /*@ 817 PetscDSGetDiscretization - Returns the discretization object for the given field 818 819 Not collective 820 821 Input Parameters: 822 + prob - The PetscDS object 823 - f - The field number 824 825 Output Parameter: 826 . disc - The discretization object 827 828 Level: beginner 829 830 .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 831 @*/ 832 PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc) 833 { 834 PetscFunctionBegin; 835 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 836 PetscValidPointer(disc, 3); 837 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 838 *disc = prob->disc[f]; 839 PetscFunctionReturn(0); 840 } 841 842 /*@ 843 PetscDSSetDiscretization - Sets the discretization object for the given field 844 845 Not collective 846 847 Input Parameters: 848 + prob - The PetscDS object 849 . f - The field number 850 - disc - The discretization object 851 852 Level: beginner 853 854 .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 855 @*/ 856 PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc) 857 { 858 PetscErrorCode ierr; 859 860 PetscFunctionBegin; 861 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 862 PetscValidPointer(disc, 3); 863 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 864 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 865 ierr = PetscObjectDereference(prob->disc[f]);CHKERRQ(ierr); 866 prob->disc[f] = disc; 867 ierr = PetscObjectReference(disc);CHKERRQ(ierr); 868 { 869 PetscClassId id; 870 871 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 872 if (id == PETSCFE_CLASSID) { 873 ierr = PetscDSSetImplicit(prob, f, PETSC_TRUE);CHKERRQ(ierr); 874 } else if (id == PETSCFV_CLASSID) { 875 ierr = PetscDSSetImplicit(prob, f, PETSC_FALSE);CHKERRQ(ierr); 876 } 877 } 878 PetscFunctionReturn(0); 879 } 880 881 /*@ 882 PetscDSAddDiscretization - Adds a discretization object 883 884 Not collective 885 886 Input Parameters: 887 + prob - The PetscDS object 888 - disc - The boundary discretization object 889 890 Level: beginner 891 892 .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 893 @*/ 894 PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc) 895 { 896 PetscErrorCode ierr; 897 898 PetscFunctionBegin; 899 ierr = PetscDSSetDiscretization(prob, prob->Nf, disc);CHKERRQ(ierr); 900 PetscFunctionReturn(0); 901 } 902 903 /*@ 904 PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX 905 906 Not collective 907 908 Input Parameters: 909 + prob - The PetscDS object 910 - f - The field number 911 912 Output Parameter: 913 . implicit - The flag indicating what kind of solve to use for this field 914 915 Level: developer 916 917 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 918 @*/ 919 PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit) 920 { 921 PetscFunctionBegin; 922 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 923 PetscValidPointer(implicit, 3); 924 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 925 *implicit = prob->implicit[f]; 926 PetscFunctionReturn(0); 927 } 928 929 /*@ 930 PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX 931 932 Not collective 933 934 Input Parameters: 935 + prob - The PetscDS object 936 . f - The field number 937 - implicit - The flag indicating what kind of solve to use for this field 938 939 Level: developer 940 941 .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 942 @*/ 943 PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit) 944 { 945 PetscFunctionBegin; 946 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 947 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 948 prob->implicit[f] = implicit; 949 PetscFunctionReturn(0); 950 } 951 952 PetscErrorCode PetscDSGetObjective(PetscDS prob, PetscInt f, 953 void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 954 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 955 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 956 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 957 { 958 PetscFunctionBegin; 959 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 960 PetscValidPointer(obj, 2); 961 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 962 *obj = prob->obj[f]; 963 PetscFunctionReturn(0); 964 } 965 966 PetscErrorCode PetscDSSetObjective(PetscDS prob, PetscInt f, 967 void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 968 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 969 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 970 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 971 { 972 PetscErrorCode ierr; 973 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 976 if (obj) PetscValidFunction(obj, 2); 977 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 978 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 979 prob->obj[f] = obj; 980 PetscFunctionReturn(0); 981 } 982 983 /*@C 984 PetscDSGetResidual - Get the pointwise residual function for a given test field 985 986 Not collective 987 988 Input Parameters: 989 + prob - The PetscDS 990 - f - The test field number 991 992 Output Parameters: 993 + f0 - integrand for the test function term 994 - f1 - integrand for the test function gradient term 995 996 Note: We are using a first order FEM model for the weak form: 997 998 \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) 999 1000 The calling sequence for the callbacks f0 and f1 is given by: 1001 1002 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1003 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1004 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1005 $ PetscReal t, const PetscReal x[], PetscScalar f0[]) 1006 1007 + dim - the spatial dimension 1008 . Nf - the number of fields 1009 . uOff - the offset into u[] and u_t[] for each field 1010 . uOff_x - the offset into u_x[] for each field 1011 . u - each field evaluated at the current point 1012 . u_t - the time derivative of each field evaluated at the current point 1013 . u_x - the gradient of each field evaluated at the current point 1014 . aOff - the offset into a[] and a_t[] for each auxiliary field 1015 . aOff_x - the offset into a_x[] for each auxiliary field 1016 . a - each auxiliary field evaluated at the current point 1017 . a_t - the time derivative of each auxiliary field evaluated at the current point 1018 . a_x - the gradient of auxiliary each field evaluated at the current point 1019 . t - current time 1020 . x - coordinates of the current point 1021 . numConstants - number of constant parameters 1022 . constants - constant parameters 1023 - f0 - output values at the current point 1024 1025 Level: intermediate 1026 1027 .seealso: PetscDSSetResidual() 1028 @*/ 1029 PetscErrorCode PetscDSGetResidual(PetscDS prob, PetscInt f, 1030 void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1031 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1032 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1033 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 1034 void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1035 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1036 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1037 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1038 { 1039 PetscFunctionBegin; 1040 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1041 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1042 if (f0) {PetscValidPointer(f0, 3); *f0 = prob->f[f*2+0];} 1043 if (f1) {PetscValidPointer(f1, 4); *f1 = prob->f[f*2+1];} 1044 PetscFunctionReturn(0); 1045 } 1046 1047 /*@C 1048 PetscDSSetResidual - Set the pointwise residual function for a given test field 1049 1050 Not collective 1051 1052 Input Parameters: 1053 + prob - The PetscDS 1054 . f - The test field number 1055 . f0 - integrand for the test function term 1056 - f1 - integrand for the test function gradient term 1057 1058 Note: We are using a first order FEM model for the weak form: 1059 1060 \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) 1061 1062 The calling sequence for the callbacks f0 and f1 is given by: 1063 1064 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1065 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1066 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1067 $ PetscReal t, const PetscReal x[], PetscScalar f0[]) 1068 1069 + dim - the spatial dimension 1070 . Nf - the number of fields 1071 . uOff - the offset into u[] and u_t[] for each field 1072 . uOff_x - the offset into u_x[] for each field 1073 . u - each field evaluated at the current point 1074 . u_t - the time derivative of each field evaluated at the current point 1075 . u_x - the gradient of each field evaluated at the current point 1076 . aOff - the offset into a[] and a_t[] for each auxiliary field 1077 . aOff_x - the offset into a_x[] for each auxiliary field 1078 . a - each auxiliary field evaluated at the current point 1079 . a_t - the time derivative of each auxiliary field evaluated at the current point 1080 . a_x - the gradient of auxiliary each field evaluated at the current point 1081 . t - current time 1082 . x - coordinates of the current point 1083 . numConstants - number of constant parameters 1084 . constants - constant parameters 1085 - f0 - output values at the current point 1086 1087 Level: intermediate 1088 1089 .seealso: PetscDSGetResidual() 1090 @*/ 1091 PetscErrorCode PetscDSSetResidual(PetscDS prob, PetscInt f, 1092 void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1093 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1094 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1095 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 1096 void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1097 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1098 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1099 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1100 { 1101 PetscErrorCode ierr; 1102 1103 PetscFunctionBegin; 1104 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1105 if (f0) PetscValidFunction(f0, 3); 1106 if (f1) PetscValidFunction(f1, 4); 1107 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1108 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 1109 prob->f[f*2+0] = f0; 1110 prob->f[f*2+1] = f1; 1111 PetscFunctionReturn(0); 1112 } 1113 1114 /*@C 1115 PetscDSHasJacobian - Signals that Jacobian functions have been set 1116 1117 Not collective 1118 1119 Input Parameter: 1120 . prob - The PetscDS 1121 1122 Output Parameter: 1123 . hasJac - flag that pointwise function for the Jacobian has been set 1124 1125 Level: intermediate 1126 1127 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1128 @*/ 1129 PetscErrorCode PetscDSHasJacobian(PetscDS prob, PetscBool *hasJac) 1130 { 1131 PetscInt f, g, h; 1132 1133 PetscFunctionBegin; 1134 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1135 *hasJac = PETSC_FALSE; 1136 for (f = 0; f < prob->Nf; ++f) { 1137 for (g = 0; g < prob->Nf; ++g) { 1138 for (h = 0; h < 4; ++h) { 1139 if (prob->g[(f*prob->Nf + g)*4+h]) *hasJac = PETSC_TRUE; 1140 } 1141 } 1142 } 1143 PetscFunctionReturn(0); 1144 } 1145 1146 /*@C 1147 PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field 1148 1149 Not collective 1150 1151 Input Parameters: 1152 + prob - The PetscDS 1153 . f - The test field number 1154 - g - The field number 1155 1156 Output Parameters: 1157 + g0 - integrand for the test and basis function term 1158 . g1 - integrand for the test function and basis function gradient term 1159 . g2 - integrand for the test function gradient and basis function term 1160 - g3 - integrand for the test function gradient and basis function gradient term 1161 1162 Note: We are using a first order FEM model for the weak form: 1163 1164 \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 1165 1166 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1167 1168 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1169 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1170 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1171 $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1172 1173 + dim - the spatial dimension 1174 . Nf - the number of fields 1175 . uOff - the offset into u[] and u_t[] for each field 1176 . uOff_x - the offset into u_x[] for each field 1177 . u - each field evaluated at the current point 1178 . u_t - the time derivative of each field evaluated at the current point 1179 . u_x - the gradient of each field evaluated at the current point 1180 . aOff - the offset into a[] and a_t[] for each auxiliary field 1181 . aOff_x - the offset into a_x[] for each auxiliary field 1182 . a - each auxiliary field evaluated at the current point 1183 . a_t - the time derivative of each auxiliary field evaluated at the current point 1184 . a_x - the gradient of auxiliary each field evaluated at the current point 1185 . t - current time 1186 . u_tShift - the multiplier a for dF/dU_t 1187 . x - coordinates of the current point 1188 . numConstants - number of constant parameters 1189 . constants - constant parameters 1190 - g0 - output values at the current point 1191 1192 Level: intermediate 1193 1194 .seealso: PetscDSSetJacobian() 1195 @*/ 1196 PetscErrorCode PetscDSGetJacobian(PetscDS prob, PetscInt f, PetscInt g, 1197 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1198 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1199 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1200 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1201 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1202 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1203 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1204 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1205 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1206 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1207 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1208 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1209 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1210 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1211 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1212 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1213 { 1214 PetscFunctionBegin; 1215 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1216 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1217 if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf); 1218 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g[(f*prob->Nf + g)*4+0];} 1219 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g[(f*prob->Nf + g)*4+1];} 1220 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g[(f*prob->Nf + g)*4+2];} 1221 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g[(f*prob->Nf + g)*4+3];} 1222 PetscFunctionReturn(0); 1223 } 1224 1225 /*@C 1226 PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields 1227 1228 Not collective 1229 1230 Input Parameters: 1231 + prob - The PetscDS 1232 . f - The test field number 1233 . g - The field number 1234 . g0 - integrand for the test and basis function term 1235 . g1 - integrand for the test function and basis function gradient term 1236 . g2 - integrand for the test function gradient and basis function term 1237 - g3 - integrand for the test function gradient and basis function gradient term 1238 1239 Note: We are using a first order FEM model for the weak form: 1240 1241 \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 1242 1243 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1244 1245 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1246 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1247 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1248 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1249 1250 + dim - the spatial dimension 1251 . Nf - the number of fields 1252 . uOff - the offset into u[] and u_t[] for each field 1253 . uOff_x - the offset into u_x[] for each field 1254 . u - each field evaluated at the current point 1255 . u_t - the time derivative of each field evaluated at the current point 1256 . u_x - the gradient of each field evaluated at the current point 1257 . aOff - the offset into a[] and a_t[] for each auxiliary field 1258 . aOff_x - the offset into a_x[] for each auxiliary field 1259 . a - each auxiliary field evaluated at the current point 1260 . a_t - the time derivative of each auxiliary field evaluated at the current point 1261 . a_x - the gradient of auxiliary each field evaluated at the current point 1262 . t - current time 1263 . u_tShift - the multiplier a for dF/dU_t 1264 . x - coordinates of the current point 1265 . numConstants - number of constant parameters 1266 . constants - constant parameters 1267 - g0 - output values at the current point 1268 1269 Level: intermediate 1270 1271 .seealso: PetscDSGetJacobian() 1272 @*/ 1273 PetscErrorCode PetscDSSetJacobian(PetscDS prob, PetscInt f, PetscInt g, 1274 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1275 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1276 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1277 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1278 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1279 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1280 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1281 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1282 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1283 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1284 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1285 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1286 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1287 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1288 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1289 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1290 { 1291 PetscErrorCode ierr; 1292 1293 PetscFunctionBegin; 1294 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1295 if (g0) PetscValidFunction(g0, 4); 1296 if (g1) PetscValidFunction(g1, 5); 1297 if (g2) PetscValidFunction(g2, 6); 1298 if (g3) PetscValidFunction(g3, 7); 1299 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1300 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1301 ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr); 1302 prob->g[(f*prob->Nf + g)*4+0] = g0; 1303 prob->g[(f*prob->Nf + g)*4+1] = g1; 1304 prob->g[(f*prob->Nf + g)*4+2] = g2; 1305 prob->g[(f*prob->Nf + g)*4+3] = g3; 1306 PetscFunctionReturn(0); 1307 } 1308 1309 /*@C 1310 PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner 1311 1312 Not collective 1313 1314 Input Parameters: 1315 + prob - The PetscDS 1316 - useJacPre - flag that enables construction of a Jacobian preconditioner 1317 1318 Level: intermediate 1319 1320 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1321 @*/ 1322 PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre) 1323 { 1324 PetscFunctionBegin; 1325 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1326 prob->useJacPre = useJacPre; 1327 PetscFunctionReturn(0); 1328 } 1329 1330 /*@C 1331 PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set 1332 1333 Not collective 1334 1335 Input Parameter: 1336 . prob - The PetscDS 1337 1338 Output Parameter: 1339 . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set 1340 1341 Level: intermediate 1342 1343 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1344 @*/ 1345 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS prob, PetscBool *hasJacPre) 1346 { 1347 PetscInt f, g, h; 1348 1349 PetscFunctionBegin; 1350 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1351 *hasJacPre = PETSC_FALSE; 1352 if (!prob->useJacPre) PetscFunctionReturn(0); 1353 for (f = 0; f < prob->Nf; ++f) { 1354 for (g = 0; g < prob->Nf; ++g) { 1355 for (h = 0; h < 4; ++h) { 1356 if (prob->gp[(f*prob->Nf + g)*4+h]) *hasJacPre = PETSC_TRUE; 1357 } 1358 } 1359 } 1360 PetscFunctionReturn(0); 1361 } 1362 1363 /*@C 1364 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. 1365 1366 Not collective 1367 1368 Input Parameters: 1369 + prob - The PetscDS 1370 . f - The test field number 1371 - g - The field number 1372 1373 Output Parameters: 1374 + g0 - integrand for the test and basis function term 1375 . g1 - integrand for the test function and basis function gradient term 1376 . g2 - integrand for the test function gradient and basis function term 1377 - g3 - integrand for the test function gradient and basis function gradient term 1378 1379 Note: We are using a first order FEM model for the weak form: 1380 1381 \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 1382 1383 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1384 1385 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1386 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1387 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1388 $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1389 1390 + dim - the spatial dimension 1391 . Nf - the number of fields 1392 . uOff - the offset into u[] and u_t[] for each field 1393 . uOff_x - the offset into u_x[] for each field 1394 . u - each field evaluated at the current point 1395 . u_t - the time derivative of each field evaluated at the current point 1396 . u_x - the gradient of each field evaluated at the current point 1397 . aOff - the offset into a[] and a_t[] for each auxiliary field 1398 . aOff_x - the offset into a_x[] for each auxiliary field 1399 . a - each auxiliary field evaluated at the current point 1400 . a_t - the time derivative of each auxiliary field evaluated at the current point 1401 . a_x - the gradient of auxiliary each field evaluated at the current point 1402 . t - current time 1403 . u_tShift - the multiplier a for dF/dU_t 1404 . x - coordinates of the current point 1405 . numConstants - number of constant parameters 1406 . constants - constant parameters 1407 - g0 - output values at the current point 1408 1409 Level: intermediate 1410 1411 .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1412 @*/ 1413 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g, 1414 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1415 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1416 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1417 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1418 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1419 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1420 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1421 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1422 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1423 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1424 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1425 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1426 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1427 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1428 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1429 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1430 { 1431 PetscFunctionBegin; 1432 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1433 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1434 if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf); 1435 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gp[(f*prob->Nf + g)*4+0];} 1436 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gp[(f*prob->Nf + g)*4+1];} 1437 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gp[(f*prob->Nf + g)*4+2];} 1438 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gp[(f*prob->Nf + g)*4+3];} 1439 PetscFunctionReturn(0); 1440 } 1441 1442 /*@C 1443 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. 1444 1445 Not collective 1446 1447 Input Parameters: 1448 + prob - The PetscDS 1449 . f - The test field number 1450 . g - The field number 1451 . g0 - integrand for the test and basis function term 1452 . g1 - integrand for the test function and basis function gradient term 1453 . g2 - integrand for the test function gradient and basis function term 1454 - g3 - integrand for the test function gradient and basis function gradient term 1455 1456 Note: We are using a first order FEM model for the weak form: 1457 1458 \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 1459 1460 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1461 1462 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1463 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1464 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1465 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1466 1467 + dim - the spatial dimension 1468 . Nf - the number of fields 1469 . uOff - the offset into u[] and u_t[] for each field 1470 . uOff_x - the offset into u_x[] for each field 1471 . u - each field evaluated at the current point 1472 . u_t - the time derivative of each field evaluated at the current point 1473 . u_x - the gradient of each field evaluated at the current point 1474 . aOff - the offset into a[] and a_t[] for each auxiliary field 1475 . aOff_x - the offset into a_x[] for each auxiliary field 1476 . a - each auxiliary field evaluated at the current point 1477 . a_t - the time derivative of each auxiliary field evaluated at the current point 1478 . a_x - the gradient of auxiliary each field evaluated at the current point 1479 . t - current time 1480 . u_tShift - the multiplier a for dF/dU_t 1481 . x - coordinates of the current point 1482 . numConstants - number of constant parameters 1483 . constants - constant parameters 1484 - g0 - output values at the current point 1485 1486 Level: intermediate 1487 1488 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian() 1489 @*/ 1490 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS prob, PetscInt f, PetscInt g, 1491 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1492 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1493 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1494 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1495 void (*g1)(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 g1[]), 1499 void (*g2)(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 g2[]), 1503 void (*g3)(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 g3[])) 1507 { 1508 PetscErrorCode ierr; 1509 1510 PetscFunctionBegin; 1511 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1512 if (g0) PetscValidFunction(g0, 4); 1513 if (g1) PetscValidFunction(g1, 5); 1514 if (g2) PetscValidFunction(g2, 6); 1515 if (g3) PetscValidFunction(g3, 7); 1516 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1517 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1518 ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr); 1519 prob->gp[(f*prob->Nf + g)*4+0] = g0; 1520 prob->gp[(f*prob->Nf + g)*4+1] = g1; 1521 prob->gp[(f*prob->Nf + g)*4+2] = g2; 1522 prob->gp[(f*prob->Nf + g)*4+3] = g3; 1523 PetscFunctionReturn(0); 1524 } 1525 1526 /*@C 1527 PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set 1528 1529 Not collective 1530 1531 Input Parameter: 1532 . prob - The PetscDS 1533 1534 Output Parameter: 1535 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set 1536 1537 Level: intermediate 1538 1539 .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian() 1540 @*/ 1541 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS prob, PetscBool *hasDynJac) 1542 { 1543 PetscInt f, g, h; 1544 1545 PetscFunctionBegin; 1546 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1547 *hasDynJac = PETSC_FALSE; 1548 for (f = 0; f < prob->Nf; ++f) { 1549 for (g = 0; g < prob->Nf; ++g) { 1550 for (h = 0; h < 4; ++h) { 1551 if (prob->gt[(f*prob->Nf + g)*4+h]) *hasDynJac = PETSC_TRUE; 1552 } 1553 } 1554 } 1555 PetscFunctionReturn(0); 1556 } 1557 1558 /*@C 1559 PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field 1560 1561 Not collective 1562 1563 Input Parameters: 1564 + prob - The PetscDS 1565 . f - The test field number 1566 - g - The field number 1567 1568 Output Parameters: 1569 + g0 - integrand for the test and basis function term 1570 . g1 - integrand for the test function and basis function gradient term 1571 . g2 - integrand for the test function gradient and basis function term 1572 - g3 - integrand for the test function gradient and basis function gradient term 1573 1574 Note: We are using a first order FEM model for the weak form: 1575 1576 \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 1577 1578 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1579 1580 $ g0(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, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1584 1585 + dim - the spatial dimension 1586 . Nf - the number of fields 1587 . uOff - the offset into u[] and u_t[] for each field 1588 . uOff_x - the offset into u_x[] for each field 1589 . u - each field evaluated at the current point 1590 . u_t - the time derivative of each field evaluated at the current point 1591 . u_x - the gradient of each field evaluated at the current point 1592 . aOff - the offset into a[] and a_t[] for each auxiliary field 1593 . aOff_x - the offset into a_x[] for each auxiliary field 1594 . a - each auxiliary field evaluated at the current point 1595 . a_t - the time derivative of each auxiliary field evaluated at the current point 1596 . a_x - the gradient of auxiliary each field evaluated at the current point 1597 . t - current time 1598 . u_tShift - the multiplier a for dF/dU_t 1599 . x - coordinates of the current point 1600 . numConstants - number of constant parameters 1601 . constants - constant parameters 1602 - g0 - output values at the current point 1603 1604 Level: intermediate 1605 1606 .seealso: PetscDSSetJacobian() 1607 @*/ 1608 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g, 1609 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1610 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1611 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1612 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1613 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1614 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1615 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1616 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1617 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1618 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1619 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1620 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1621 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1622 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1623 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1624 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1625 { 1626 PetscFunctionBegin; 1627 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1628 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1629 if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf); 1630 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gt[(f*prob->Nf + g)*4+0];} 1631 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gt[(f*prob->Nf + g)*4+1];} 1632 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gt[(f*prob->Nf + g)*4+2];} 1633 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gt[(f*prob->Nf + g)*4+3];} 1634 PetscFunctionReturn(0); 1635 } 1636 1637 /*@C 1638 PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields 1639 1640 Not collective 1641 1642 Input Parameters: 1643 + prob - The PetscDS 1644 . f - The test field number 1645 . g - The field number 1646 . g0 - integrand for the test and basis function term 1647 . g1 - integrand for the test function and basis function gradient term 1648 . g2 - integrand for the test function gradient and basis function term 1649 - g3 - integrand for the test function gradient and basis function gradient term 1650 1651 Note: We are using a first order FEM model for the weak form: 1652 1653 \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 1654 1655 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1656 1657 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1658 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1659 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1660 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1661 1662 + dim - the spatial dimension 1663 . Nf - the number of fields 1664 . uOff - the offset into u[] and u_t[] for each field 1665 . uOff_x - the offset into u_x[] for each field 1666 . u - each field evaluated at the current point 1667 . u_t - the time derivative of each field evaluated at the current point 1668 . u_x - the gradient of each field evaluated at the current point 1669 . aOff - the offset into a[] and a_t[] for each auxiliary field 1670 . aOff_x - the offset into a_x[] for each auxiliary field 1671 . a - each auxiliary field evaluated at the current point 1672 . a_t - the time derivative of each auxiliary field evaluated at the current point 1673 . a_x - the gradient of auxiliary each field evaluated at the current point 1674 . t - current time 1675 . u_tShift - the multiplier a for dF/dU_t 1676 . x - coordinates of the current point 1677 . numConstants - number of constant parameters 1678 . constants - constant parameters 1679 - g0 - output values at the current point 1680 1681 Level: intermediate 1682 1683 .seealso: PetscDSGetJacobian() 1684 @*/ 1685 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS prob, PetscInt f, PetscInt g, 1686 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1687 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1688 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1689 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1690 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1691 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1692 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1693 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1694 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1695 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1696 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1697 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1698 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1699 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1700 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1701 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1702 { 1703 PetscErrorCode ierr; 1704 1705 PetscFunctionBegin; 1706 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1707 if (g0) PetscValidFunction(g0, 4); 1708 if (g1) PetscValidFunction(g1, 5); 1709 if (g2) PetscValidFunction(g2, 6); 1710 if (g3) PetscValidFunction(g3, 7); 1711 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1712 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1713 ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr); 1714 prob->gt[(f*prob->Nf + g)*4+0] = g0; 1715 prob->gt[(f*prob->Nf + g)*4+1] = g1; 1716 prob->gt[(f*prob->Nf + g)*4+2] = g2; 1717 prob->gt[(f*prob->Nf + g)*4+3] = g3; 1718 PetscFunctionReturn(0); 1719 } 1720 1721 /*@C 1722 PetscDSGetRiemannSolver - Returns the Riemann solver for the given field 1723 1724 Not collective 1725 1726 Input Arguments: 1727 + prob - The PetscDS object 1728 - f - The field number 1729 1730 Output Argument: 1731 . r - Riemann solver 1732 1733 Calling sequence for r: 1734 1735 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 1736 1737 + dim - The spatial dimension 1738 . Nf - The number of fields 1739 . x - The coordinates at a point on the interface 1740 . n - The normal vector to the interface 1741 . uL - The state vector to the left of the interface 1742 . uR - The state vector to the right of the interface 1743 . flux - output array of flux through the interface 1744 . numConstants - number of constant parameters 1745 . constants - constant parameters 1746 - ctx - optional user context 1747 1748 Level: intermediate 1749 1750 .seealso: PetscDSSetRiemannSolver() 1751 @*/ 1752 PetscErrorCode PetscDSGetRiemannSolver(PetscDS prob, PetscInt f, 1753 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)) 1754 { 1755 PetscFunctionBegin; 1756 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1757 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1758 PetscValidPointer(r, 3); 1759 *r = prob->r[f]; 1760 PetscFunctionReturn(0); 1761 } 1762 1763 /*@C 1764 PetscDSSetRiemannSolver - Sets the Riemann solver for the given field 1765 1766 Not collective 1767 1768 Input Arguments: 1769 + prob - The PetscDS object 1770 . f - The field number 1771 - r - Riemann solver 1772 1773 Calling sequence for r: 1774 1775 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 1776 1777 + dim - The spatial dimension 1778 . Nf - The number of fields 1779 . x - The coordinates at a point on the interface 1780 . n - The normal vector to the interface 1781 . uL - The state vector to the left of the interface 1782 . uR - The state vector to the right of the interface 1783 . flux - output array of flux through the interface 1784 . numConstants - number of constant parameters 1785 . constants - constant parameters 1786 - ctx - optional user context 1787 1788 Level: intermediate 1789 1790 .seealso: PetscDSGetRiemannSolver() 1791 @*/ 1792 PetscErrorCode PetscDSSetRiemannSolver(PetscDS prob, PetscInt f, 1793 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)) 1794 { 1795 PetscErrorCode ierr; 1796 1797 PetscFunctionBegin; 1798 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1799 if (r) PetscValidFunction(r, 3); 1800 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1801 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 1802 prob->r[f] = r; 1803 PetscFunctionReturn(0); 1804 } 1805 1806 /*@C 1807 PetscDSGetUpdate - Get the pointwise update function for a given field 1808 1809 Not collective 1810 1811 Input Parameters: 1812 + prob - The PetscDS 1813 - f - The field number 1814 1815 Output Parameters: 1816 . update - update function 1817 1818 Note: The calling sequence for the callback update is given by: 1819 1820 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1821 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1822 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1823 $ PetscReal t, const PetscReal x[], PetscScalar uNew[]) 1824 1825 + dim - the spatial dimension 1826 . Nf - the number of fields 1827 . uOff - the offset into u[] and u_t[] for each field 1828 . uOff_x - the offset into u_x[] for each field 1829 . u - each field evaluated at the current point 1830 . u_t - the time derivative of each field evaluated at the current point 1831 . u_x - the gradient of each field evaluated at the current point 1832 . aOff - the offset into a[] and a_t[] for each auxiliary field 1833 . aOff_x - the offset into a_x[] for each auxiliary field 1834 . a - each auxiliary field evaluated at the current point 1835 . a_t - the time derivative of each auxiliary field evaluated at the current point 1836 . a_x - the gradient of auxiliary each field evaluated at the current point 1837 . t - current time 1838 . x - coordinates of the current point 1839 - uNew - new value for field at the current point 1840 1841 Level: intermediate 1842 1843 .seealso: PetscDSSetUpdate(), PetscDSSetResidual() 1844 @*/ 1845 PetscErrorCode PetscDSGetUpdate(PetscDS prob, PetscInt f, 1846 void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1847 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1848 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1849 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 1850 { 1851 PetscFunctionBegin; 1852 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1853 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1854 if (update) {PetscValidPointer(update, 3); *update = prob->update[f];} 1855 PetscFunctionReturn(0); 1856 } 1857 1858 /*@C 1859 PetscDSSetUpdate - Set the pointwise update function for a given field 1860 1861 Not collective 1862 1863 Input Parameters: 1864 + prob - The PetscDS 1865 . f - The field number 1866 - update - update function 1867 1868 Note: The calling sequence for the callback update is given by: 1869 1870 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1871 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1872 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1873 $ PetscReal t, const PetscReal x[], PetscScalar uNew[]) 1874 1875 + dim - the spatial dimension 1876 . Nf - the number of fields 1877 . uOff - the offset into u[] and u_t[] for each field 1878 . uOff_x - the offset into u_x[] for each field 1879 . u - each field evaluated at the current point 1880 . u_t - the time derivative of each field evaluated at the current point 1881 . u_x - the gradient of each field evaluated at the current point 1882 . aOff - the offset into a[] and a_t[] for each auxiliary field 1883 . aOff_x - the offset into a_x[] for each auxiliary field 1884 . a - each auxiliary field evaluated at the current point 1885 . a_t - the time derivative of each auxiliary field evaluated at the current point 1886 . a_x - the gradient of auxiliary each field evaluated at the current point 1887 . t - current time 1888 . x - coordinates of the current point 1889 - uNew - new field values at the current point 1890 1891 Level: intermediate 1892 1893 .seealso: PetscDSGetResidual() 1894 @*/ 1895 PetscErrorCode PetscDSSetUpdate(PetscDS prob, PetscInt f, 1896 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1897 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1898 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1899 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 1900 { 1901 PetscErrorCode ierr; 1902 1903 PetscFunctionBegin; 1904 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1905 if (update) PetscValidFunction(update, 3); 1906 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1907 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 1908 prob->update[f] = update; 1909 PetscFunctionReturn(0); 1910 } 1911 1912 PetscErrorCode PetscDSGetContext(PetscDS prob, PetscInt f, void **ctx) 1913 { 1914 PetscFunctionBegin; 1915 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1916 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1917 PetscValidPointer(ctx, 3); 1918 *ctx = prob->ctx[f]; 1919 PetscFunctionReturn(0); 1920 } 1921 1922 PetscErrorCode PetscDSSetContext(PetscDS prob, PetscInt f, void *ctx) 1923 { 1924 PetscErrorCode ierr; 1925 1926 PetscFunctionBegin; 1927 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1928 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1929 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 1930 prob->ctx[f] = ctx; 1931 PetscFunctionReturn(0); 1932 } 1933 1934 /*@C 1935 PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field 1936 1937 Not collective 1938 1939 Input Parameters: 1940 + prob - The PetscDS 1941 - f - The test field number 1942 1943 Output Parameters: 1944 + f0 - boundary integrand for the test function term 1945 - f1 - boundary integrand for the test function gradient term 1946 1947 Note: We are using a first order FEM model for the weak form: 1948 1949 \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 1950 1951 The calling sequence for the callbacks f0 and f1 is given by: 1952 1953 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1954 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1955 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1956 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 1957 1958 + dim - the spatial dimension 1959 . Nf - the number of fields 1960 . uOff - the offset into u[] and u_t[] for each field 1961 . uOff_x - the offset into u_x[] for each field 1962 . u - each field evaluated at the current point 1963 . u_t - the time derivative of each field evaluated at the current point 1964 . u_x - the gradient of each field evaluated at the current point 1965 . aOff - the offset into a[] and a_t[] for each auxiliary field 1966 . aOff_x - the offset into a_x[] for each auxiliary field 1967 . a - each auxiliary field evaluated at the current point 1968 . a_t - the time derivative of each auxiliary field evaluated at the current point 1969 . a_x - the gradient of auxiliary each field evaluated at the current point 1970 . t - current time 1971 . x - coordinates of the current point 1972 . n - unit normal at the current point 1973 . numConstants - number of constant parameters 1974 . constants - constant parameters 1975 - f0 - output values at the current point 1976 1977 Level: intermediate 1978 1979 .seealso: PetscDSSetBdResidual() 1980 @*/ 1981 PetscErrorCode PetscDSGetBdResidual(PetscDS prob, PetscInt f, 1982 void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1983 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1984 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1985 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 1986 void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1987 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1988 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1989 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1990 { 1991 PetscFunctionBegin; 1992 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1993 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 1994 if (f0) {PetscValidPointer(f0, 3); *f0 = prob->fBd[f*2+0];} 1995 if (f1) {PetscValidPointer(f1, 4); *f1 = prob->fBd[f*2+1];} 1996 PetscFunctionReturn(0); 1997 } 1998 1999 /*@C 2000 PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field 2001 2002 Not collective 2003 2004 Input Parameters: 2005 + prob - The PetscDS 2006 . f - The test field number 2007 . f0 - boundary integrand for the test function term 2008 - f1 - boundary integrand for the test function gradient term 2009 2010 Note: We are using a first order FEM model for the weak form: 2011 2012 \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 2013 2014 The calling sequence for the callbacks f0 and f1 is given by: 2015 2016 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2017 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2018 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2019 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 2020 2021 + dim - the spatial dimension 2022 . Nf - the number of fields 2023 . uOff - the offset into u[] and u_t[] for each field 2024 . uOff_x - the offset into u_x[] for each field 2025 . u - each field evaluated at the current point 2026 . u_t - the time derivative of each field evaluated at the current point 2027 . u_x - the gradient of each field evaluated at the current point 2028 . aOff - the offset into a[] and a_t[] for each auxiliary field 2029 . aOff_x - the offset into a_x[] for each auxiliary field 2030 . a - each auxiliary field evaluated at the current point 2031 . a_t - the time derivative of each auxiliary field evaluated at the current point 2032 . a_x - the gradient of auxiliary each field evaluated at the current point 2033 . t - current time 2034 . x - coordinates of the current point 2035 . n - unit normal at the current point 2036 . numConstants - number of constant parameters 2037 . constants - constant parameters 2038 - f0 - output values at the current point 2039 2040 Level: intermediate 2041 2042 .seealso: PetscDSGetBdResidual() 2043 @*/ 2044 PetscErrorCode PetscDSSetBdResidual(PetscDS prob, PetscInt f, 2045 void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2046 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2047 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2048 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 2049 void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2050 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2051 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2052 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 2053 { 2054 PetscErrorCode ierr; 2055 2056 PetscFunctionBegin; 2057 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2058 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2059 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 2060 if (f0) {PetscValidFunction(f0, 3); prob->fBd[f*2+0] = f0;} 2061 if (f1) {PetscValidFunction(f1, 4); prob->fBd[f*2+1] = f1;} 2062 PetscFunctionReturn(0); 2063 } 2064 2065 /*@C 2066 PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field 2067 2068 Not collective 2069 2070 Input Parameters: 2071 + prob - The PetscDS 2072 . f - The test field number 2073 - g - The field number 2074 2075 Output Parameters: 2076 + g0 - integrand for the test and basis function term 2077 . g1 - integrand for the test function and basis function gradient term 2078 . g2 - integrand for the test function gradient and basis function term 2079 - g3 - integrand for the test function gradient and basis function gradient term 2080 2081 Note: We are using a first order FEM model for the weak form: 2082 2083 \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 2084 2085 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2086 2087 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2088 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2089 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2090 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2091 2092 + dim - the spatial dimension 2093 . Nf - the number of fields 2094 . uOff - the offset into u[] and u_t[] for each field 2095 . uOff_x - the offset into u_x[] for each field 2096 . u - each field evaluated at the current point 2097 . u_t - the time derivative of each field evaluated at the current point 2098 . u_x - the gradient of each field evaluated at the current point 2099 . aOff - the offset into a[] and a_t[] for each auxiliary field 2100 . aOff_x - the offset into a_x[] for each auxiliary field 2101 . a - each auxiliary field evaluated at the current point 2102 . a_t - the time derivative of each auxiliary field evaluated at the current point 2103 . a_x - the gradient of auxiliary each field evaluated at the current point 2104 . t - current time 2105 . u_tShift - the multiplier a for dF/dU_t 2106 . x - coordinates of the current point 2107 . n - normal at the current point 2108 . numConstants - number of constant parameters 2109 . constants - constant parameters 2110 - g0 - output values at the current point 2111 2112 Level: intermediate 2113 2114 .seealso: PetscDSSetBdJacobian() 2115 @*/ 2116 PetscErrorCode PetscDSGetBdJacobian(PetscDS prob, PetscInt f, PetscInt g, 2117 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2118 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2119 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2120 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2121 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2122 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2123 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2124 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2125 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2126 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2127 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2128 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2129 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2130 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2131 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2132 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2133 { 2134 PetscFunctionBegin; 2135 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2136 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 2137 if ((g < 0) || (g >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, prob->Nf); 2138 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->gBd[(f*prob->Nf + g)*4+0];} 2139 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->gBd[(f*prob->Nf + g)*4+1];} 2140 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->gBd[(f*prob->Nf + g)*4+2];} 2141 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->gBd[(f*prob->Nf + g)*4+3];} 2142 PetscFunctionReturn(0); 2143 } 2144 2145 /*@C 2146 PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field 2147 2148 Not collective 2149 2150 Input Parameters: 2151 + prob - The PetscDS 2152 . f - The test field number 2153 . g - The field number 2154 . g0 - integrand for the test and basis function term 2155 . g1 - integrand for the test function and basis function gradient term 2156 . g2 - integrand for the test function gradient and basis function term 2157 - g3 - integrand for the test function gradient and basis function gradient term 2158 2159 Note: We are using a first order FEM model for the weak form: 2160 2161 \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 2162 2163 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2164 2165 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2166 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2167 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2168 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2169 2170 + dim - the spatial dimension 2171 . Nf - the number of fields 2172 . uOff - the offset into u[] and u_t[] for each field 2173 . uOff_x - the offset into u_x[] for each field 2174 . u - each field evaluated at the current point 2175 . u_t - the time derivative of each field evaluated at the current point 2176 . u_x - the gradient of each field evaluated at the current point 2177 . aOff - the offset into a[] and a_t[] for each auxiliary field 2178 . aOff_x - the offset into a_x[] for each auxiliary field 2179 . a - each auxiliary field evaluated at the current point 2180 . a_t - the time derivative of each auxiliary field evaluated at the current point 2181 . a_x - the gradient of auxiliary each field evaluated at the current point 2182 . t - current time 2183 . u_tShift - the multiplier a for dF/dU_t 2184 . x - coordinates of the current point 2185 . n - normal at the current point 2186 . numConstants - number of constant parameters 2187 . constants - constant parameters 2188 - g0 - output values at the current point 2189 2190 Level: intermediate 2191 2192 .seealso: PetscDSGetBdJacobian() 2193 @*/ 2194 PetscErrorCode PetscDSSetBdJacobian(PetscDS prob, PetscInt f, PetscInt g, 2195 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2196 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2197 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2198 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2199 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2200 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2201 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2202 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2203 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2204 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2205 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2206 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2207 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2208 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2209 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2210 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2211 { 2212 PetscErrorCode ierr; 2213 2214 PetscFunctionBegin; 2215 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2216 if (g0) PetscValidFunction(g0, 4); 2217 if (g1) PetscValidFunction(g1, 5); 2218 if (g2) PetscValidFunction(g2, 6); 2219 if (g3) PetscValidFunction(g3, 7); 2220 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2221 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 2222 ierr = PetscDSEnlarge_Static(prob, PetscMax(f, g)+1);CHKERRQ(ierr); 2223 prob->gBd[(f*prob->Nf + g)*4+0] = g0; 2224 prob->gBd[(f*prob->Nf + g)*4+1] = g1; 2225 prob->gBd[(f*prob->Nf + g)*4+2] = g2; 2226 prob->gBd[(f*prob->Nf + g)*4+3] = g3; 2227 PetscFunctionReturn(0); 2228 } 2229 2230 /*@C 2231 PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field 2232 2233 Not collective 2234 2235 Input Parameters: 2236 + prob - The PetscDS 2237 - f - The test field number 2238 2239 Output Parameter: 2240 + exactSol - exact solution for the test field 2241 - exactCtx - exact solution context 2242 2243 Note: The calling sequence for the solution functions is given by: 2244 2245 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2246 2247 + dim - the spatial dimension 2248 . t - current time 2249 . x - coordinates of the current point 2250 . Nc - the number of field components 2251 . u - the solution field evaluated at the current point 2252 - ctx - a user context 2253 2254 Level: intermediate 2255 2256 .seealso: PetscDSSetExactSolution() 2257 @*/ 2258 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2259 { 2260 PetscFunctionBegin; 2261 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2262 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 2263 if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol[f];} 2264 if (ctx) {PetscValidPointer(ctx, 4); *ctx = prob->exactCtx[f];} 2265 PetscFunctionReturn(0); 2266 } 2267 2268 /*@C 2269 PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field 2270 2271 Not collective 2272 2273 Input Parameters: 2274 + prob - The PetscDS 2275 . f - The test field number 2276 . sol - solution function for the test fields 2277 - ctx - solution context or NULL 2278 2279 Note: The calling sequence for solution functions is given by: 2280 2281 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2282 2283 + dim - the spatial dimension 2284 . t - current time 2285 . x - coordinates of the current point 2286 . Nc - the number of field components 2287 . u - the solution field evaluated at the current point 2288 - ctx - a user context 2289 2290 Level: intermediate 2291 2292 .seealso: PetscDSGetExactSolution() 2293 @*/ 2294 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2295 { 2296 PetscErrorCode ierr; 2297 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2300 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2301 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 2302 if (sol) {PetscValidFunction(sol, 3); prob->exactSol[f] = sol;} 2303 if (ctx) {PetscValidFunction(ctx, 4); prob->exactCtx[f] = ctx;} 2304 PetscFunctionReturn(0); 2305 } 2306 2307 /*@C 2308 PetscDSGetConstants - Returns the array of constants passed to point functions 2309 2310 Not collective 2311 2312 Input Parameter: 2313 . prob - The PetscDS object 2314 2315 Output Parameters: 2316 + numConstants - The number of constants 2317 - constants - The array of constants, NULL if there are none 2318 2319 Level: intermediate 2320 2321 .seealso: PetscDSSetConstants(), PetscDSCreate() 2322 @*/ 2323 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[]) 2324 { 2325 PetscFunctionBegin; 2326 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2327 if (numConstants) {PetscValidPointer(numConstants, 2); *numConstants = prob->numConstants;} 2328 if (constants) {PetscValidPointer(constants, 3); *constants = prob->constants;} 2329 PetscFunctionReturn(0); 2330 } 2331 2332 /*@C 2333 PetscDSSetConstants - Set the array of constants passed to point functions 2334 2335 Not collective 2336 2337 Input Parameters: 2338 + prob - The PetscDS object 2339 . numConstants - The number of constants 2340 - constants - The array of constants, NULL if there are none 2341 2342 Level: intermediate 2343 2344 .seealso: PetscDSGetConstants(), PetscDSCreate() 2345 @*/ 2346 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[]) 2347 { 2348 PetscErrorCode ierr; 2349 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2352 if (numConstants != prob->numConstants) { 2353 ierr = PetscFree(prob->constants);CHKERRQ(ierr); 2354 prob->numConstants = numConstants; 2355 if (prob->numConstants) { 2356 ierr = PetscMalloc1(prob->numConstants, &prob->constants);CHKERRQ(ierr); 2357 } else { 2358 prob->constants = NULL; 2359 } 2360 } 2361 if (prob->numConstants) { 2362 PetscValidPointer(constants, 3); 2363 ierr = PetscArraycpy(prob->constants, constants, prob->numConstants);CHKERRQ(ierr); 2364 } 2365 PetscFunctionReturn(0); 2366 } 2367 2368 /*@ 2369 PetscDSGetFieldIndex - Returns the index of the given field 2370 2371 Not collective 2372 2373 Input Parameters: 2374 + prob - The PetscDS object 2375 - disc - The discretization object 2376 2377 Output Parameter: 2378 . f - The field number 2379 2380 Level: beginner 2381 2382 .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 2383 @*/ 2384 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2385 { 2386 PetscInt g; 2387 2388 PetscFunctionBegin; 2389 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2390 PetscValidPointer(f, 3); 2391 *f = -1; 2392 for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;} 2393 if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2394 *f = g; 2395 PetscFunctionReturn(0); 2396 } 2397 2398 /*@ 2399 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2400 2401 Not collective 2402 2403 Input Parameters: 2404 + prob - The PetscDS object 2405 - f - The field number 2406 2407 Output Parameter: 2408 . size - The size 2409 2410 Level: beginner 2411 2412 .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate() 2413 @*/ 2414 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2415 { 2416 PetscErrorCode ierr; 2417 2418 PetscFunctionBegin; 2419 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2420 PetscValidPointer(size, 3); 2421 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 2422 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2423 *size = prob->Nb[f]; 2424 PetscFunctionReturn(0); 2425 } 2426 2427 /*@ 2428 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2429 2430 Not collective 2431 2432 Input Parameters: 2433 + prob - The PetscDS object 2434 - f - The field number 2435 2436 Output Parameter: 2437 . off - The offset 2438 2439 Level: beginner 2440 2441 .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate() 2442 @*/ 2443 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2444 { 2445 PetscInt size, g; 2446 PetscErrorCode ierr; 2447 2448 PetscFunctionBegin; 2449 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2450 PetscValidPointer(off, 3); 2451 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 2452 *off = 0; 2453 for (g = 0; g < f; ++g) { 2454 ierr = PetscDSGetFieldSize(prob, g, &size);CHKERRQ(ierr); 2455 *off += size; 2456 } 2457 PetscFunctionReturn(0); 2458 } 2459 2460 /*@ 2461 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 2462 2463 Not collective 2464 2465 Input Parameter: 2466 . prob - The PetscDS object 2467 2468 Output Parameter: 2469 . dimensions - The number of dimensions 2470 2471 Level: beginner 2472 2473 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate() 2474 @*/ 2475 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 2476 { 2477 PetscErrorCode ierr; 2478 2479 PetscFunctionBegin; 2480 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2481 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2482 PetscValidPointer(dimensions, 2); 2483 *dimensions = prob->Nb; 2484 PetscFunctionReturn(0); 2485 } 2486 2487 /*@ 2488 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 2489 2490 Not collective 2491 2492 Input Parameter: 2493 . prob - The PetscDS object 2494 2495 Output Parameter: 2496 . components - The number of components 2497 2498 Level: beginner 2499 2500 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate() 2501 @*/ 2502 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 2503 { 2504 PetscErrorCode ierr; 2505 2506 PetscFunctionBegin; 2507 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2508 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2509 PetscValidPointer(components, 2); 2510 *components = prob->Nc; 2511 PetscFunctionReturn(0); 2512 } 2513 2514 /*@ 2515 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 2516 2517 Not collective 2518 2519 Input Parameters: 2520 + prob - The PetscDS object 2521 - f - The field number 2522 2523 Output Parameter: 2524 . off - The offset 2525 2526 Level: beginner 2527 2528 .seealso: PetscDSGetNumFields(), PetscDSCreate() 2529 @*/ 2530 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 2531 { 2532 PetscFunctionBegin; 2533 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2534 PetscValidPointer(off, 3); 2535 if ((f < 0) || (f >= prob->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, prob->Nf); 2536 *off = prob->off[f]; 2537 PetscFunctionReturn(0); 2538 } 2539 2540 /*@ 2541 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 2542 2543 Not collective 2544 2545 Input Parameter: 2546 . prob - The PetscDS object 2547 2548 Output Parameter: 2549 . offsets - The offsets 2550 2551 Level: beginner 2552 2553 .seealso: PetscDSGetNumFields(), PetscDSCreate() 2554 @*/ 2555 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 2556 { 2557 PetscFunctionBegin; 2558 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2559 PetscValidPointer(offsets, 2); 2560 *offsets = prob->off; 2561 PetscFunctionReturn(0); 2562 } 2563 2564 /*@ 2565 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 2566 2567 Not collective 2568 2569 Input Parameter: 2570 . prob - The PetscDS object 2571 2572 Output Parameter: 2573 . offsets - The offsets 2574 2575 Level: beginner 2576 2577 .seealso: PetscDSGetNumFields(), PetscDSCreate() 2578 @*/ 2579 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 2580 { 2581 PetscFunctionBegin; 2582 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2583 PetscValidPointer(offsets, 2); 2584 *offsets = prob->offDer; 2585 PetscFunctionReturn(0); 2586 } 2587 2588 /*@C 2589 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 2590 2591 Not collective 2592 2593 Input Parameter: 2594 . prob - The PetscDS object 2595 2596 Output Parameter: 2597 . T - The basis function and derivatives tabulation at quadrature points for each field 2598 2599 Level: intermediate 2600 2601 .seealso: PetscDSCreate() 2602 @*/ 2603 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) 2604 { 2605 PetscErrorCode ierr; 2606 2607 PetscFunctionBegin; 2608 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2609 PetscValidPointer(T, 2); 2610 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2611 *T = prob->T; 2612 PetscFunctionReturn(0); 2613 } 2614 2615 /*@C 2616 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 2617 2618 Not collective 2619 2620 Input Parameter: 2621 . prob - The PetscDS object 2622 2623 Output Parameter: 2624 . Tf - The basis function and derviative tabulation on each lcoal face at quadrature points for each and field 2625 2626 Level: intermediate 2627 2628 .seealso: PetscDSGetTabulation(), PetscDSCreate() 2629 @*/ 2630 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 2631 { 2632 PetscErrorCode ierr; 2633 2634 PetscFunctionBegin; 2635 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2636 PetscValidPointer(Tf, 2); 2637 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2638 *Tf = prob->Tf; 2639 PetscFunctionReturn(0); 2640 } 2641 2642 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x) 2643 { 2644 PetscErrorCode ierr; 2645 2646 PetscFunctionBegin; 2647 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2648 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2649 if (u) {PetscValidPointer(u, 2); *u = prob->u;} 2650 if (u_t) {PetscValidPointer(u_t, 3); *u_t = prob->u_t;} 2651 if (u_x) {PetscValidPointer(u_x, 4); *u_x = prob->u_x;} 2652 PetscFunctionReturn(0); 2653 } 2654 2655 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3) 2656 { 2657 PetscErrorCode ierr; 2658 2659 PetscFunctionBegin; 2660 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2661 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2662 if (f0) {PetscValidPointer(f0, 2); *f0 = prob->f0;} 2663 if (f1) {PetscValidPointer(f1, 3); *f1 = prob->f1;} 2664 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g0;} 2665 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g1;} 2666 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g2;} 2667 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g3;} 2668 PetscFunctionReturn(0); 2669 } 2670 2671 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 2672 { 2673 PetscErrorCode ierr; 2674 2675 PetscFunctionBegin; 2676 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2677 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2678 if (x) {PetscValidPointer(x, 2); *x = prob->x;} 2679 if (basisReal) {PetscValidPointer(basisReal, 3); *basisReal = prob->basisReal;} 2680 if (basisDerReal) {PetscValidPointer(basisDerReal, 4); *basisDerReal = prob->basisDerReal;} 2681 if (testReal) {PetscValidPointer(testReal, 5); *testReal = prob->testReal;} 2682 if (testDerReal) {PetscValidPointer(testDerReal, 6); *testDerReal = prob->testDerReal;} 2683 PetscFunctionReturn(0); 2684 } 2685 2686 /*@C 2687 PetscDSAddBoundary - Add a boundary condition to the model 2688 2689 Input Parameters: 2690 + ds - The PetscDS object 2691 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 2692 . name - The BC name 2693 . labelname - The label defining constrained points 2694 . field - The field to constrain 2695 . numcomps - The number of constrained field components (0 will constrain all fields) 2696 . comps - An array of constrained component numbers 2697 . bcFunc - A pointwise function giving boundary values 2698 . numids - The number of DMLabel ids for constrained points 2699 . ids - An array of ids for constrained points 2700 - ctx - An optional user context for bcFunc 2701 2702 Options Database Keys: 2703 + -bc_<boundary name> <num> - Overrides the boundary ids 2704 - -bc_<boundary name>_comp <num> - Overrides the boundary components 2705 2706 Level: developer 2707 2708 .seealso: PetscDSGetBoundary() 2709 @*/ 2710 PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx) 2711 { 2712 DSBoundary b; 2713 PetscErrorCode ierr; 2714 2715 PetscFunctionBegin; 2716 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2717 ierr = PetscNew(&b);CHKERRQ(ierr); 2718 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 2719 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 2720 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 2721 if (numcomps) {ierr = PetscArraycpy(b->comps, comps, numcomps);CHKERRQ(ierr);} 2722 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 2723 if (numids) {ierr = PetscArraycpy(b->ids, ids, numids);CHKERRQ(ierr);} 2724 b->type = type; 2725 b->field = field; 2726 b->numcomps = numcomps; 2727 b->func = bcFunc; 2728 b->numids = numids; 2729 b->ctx = ctx; 2730 b->next = ds->boundary; 2731 ds->boundary = b; 2732 PetscFunctionReturn(0); 2733 } 2734 2735 /*@C 2736 PetscDSUpdateBoundary - Change a boundary condition for the model 2737 2738 Input Parameters: 2739 + ds - The PetscDS object 2740 . bd - The boundary condition number 2741 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 2742 . name - The BC name 2743 . labelname - The label defining constrained points 2744 . field - The field to constrain 2745 . numcomps - The number of constrained field components 2746 . comps - An array of constrained component numbers 2747 . bcFunc - A pointwise function giving boundary values 2748 . numids - The number of DMLabel ids for constrained points 2749 . ids - An array of ids for constrained points 2750 - ctx - An optional user context for bcFunc 2751 2752 Note: The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from PetscDSGetNumBoundary(). 2753 2754 Level: developer 2755 2756 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary() 2757 @*/ 2758 PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], const char labelname[], PetscInt field, PetscInt numcomps, const PetscInt *comps, void (*bcFunc)(void), PetscInt numids, const PetscInt *ids, void *ctx) 2759 { 2760 DSBoundary b = ds->boundary; 2761 PetscInt n = 0; 2762 PetscErrorCode ierr; 2763 2764 PetscFunctionBegin; 2765 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2766 while (b) { 2767 if (n == bd) break; 2768 b = b->next; 2769 ++n; 2770 } 2771 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 2772 if (name) { 2773 ierr = PetscFree(b->name);CHKERRQ(ierr); 2774 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 2775 } 2776 if (labelname) { 2777 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 2778 ierr = PetscStrallocpy(labelname, (char **) &b->labelname);CHKERRQ(ierr); 2779 } 2780 if (numcomps >= 0 && numcomps != b->numcomps) { 2781 b->numcomps = numcomps; 2782 ierr = PetscFree(b->comps);CHKERRQ(ierr); 2783 ierr = PetscMalloc1(numcomps, &b->comps);CHKERRQ(ierr); 2784 if (numcomps) {ierr = PetscArraycpy(b->comps, comps, numcomps);CHKERRQ(ierr);} 2785 } 2786 if (numids >= 0 && numids != b->numids) { 2787 b->numids = numids; 2788 ierr = PetscFree(b->ids);CHKERRQ(ierr); 2789 ierr = PetscMalloc1(numids, &b->ids);CHKERRQ(ierr); 2790 if (numids) {ierr = PetscArraycpy(b->ids, ids, numids);CHKERRQ(ierr);} 2791 } 2792 b->type = type; 2793 if (field >= 0) {b->field = field;} 2794 if (bcFunc) {b->func = bcFunc;} 2795 if (ctx) {b->ctx = ctx;} 2796 PetscFunctionReturn(0); 2797 } 2798 2799 /*@ 2800 PetscDSGetNumBoundary - Get the number of registered BC 2801 2802 Input Parameters: 2803 . ds - The PetscDS object 2804 2805 Output Parameters: 2806 . numBd - The number of BC 2807 2808 Level: intermediate 2809 2810 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary() 2811 @*/ 2812 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 2813 { 2814 DSBoundary b = ds->boundary; 2815 2816 PetscFunctionBegin; 2817 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2818 PetscValidPointer(numBd, 2); 2819 *numBd = 0; 2820 while (b) {++(*numBd); b = b->next;} 2821 PetscFunctionReturn(0); 2822 } 2823 2824 /*@C 2825 PetscDSGetBoundary - Gets a boundary condition to the model 2826 2827 Input Parameters: 2828 + ds - The PetscDS object 2829 - bd - The BC number 2830 2831 Output Parameters: 2832 + type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 2833 . name - The BC name 2834 . labelname - The label defining constrained points 2835 . field - The field to constrain 2836 . numcomps - The number of constrained field components 2837 . comps - An array of constrained component numbers 2838 . bcFunc - A pointwise function giving boundary values 2839 . numids - The number of DMLabel ids for constrained points 2840 . ids - An array of ids for constrained points 2841 - ctx - An optional user context for bcFunc 2842 2843 Options Database Keys: 2844 + -bc_<boundary name> <num> - Overrides the boundary ids 2845 - -bc_<boundary name>_comp <num> - Overrides the boundary components 2846 2847 Level: developer 2848 2849 .seealso: PetscDSAddBoundary() 2850 @*/ 2851 PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType *type, const char **name, const char **labelname, PetscInt *field, PetscInt *numcomps, const PetscInt **comps, void (**func)(void), PetscInt *numids, const PetscInt **ids, void **ctx) 2852 { 2853 DSBoundary b = ds->boundary; 2854 PetscInt n = 0; 2855 2856 PetscFunctionBegin; 2857 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2858 while (b) { 2859 if (n == bd) break; 2860 b = b->next; 2861 ++n; 2862 } 2863 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 2864 if (type) { 2865 PetscValidPointer(type, 3); 2866 *type = b->type; 2867 } 2868 if (name) { 2869 PetscValidPointer(name, 4); 2870 *name = b->name; 2871 } 2872 if (labelname) { 2873 PetscValidPointer(labelname, 5); 2874 *labelname = b->labelname; 2875 } 2876 if (field) { 2877 PetscValidPointer(field, 6); 2878 *field = b->field; 2879 } 2880 if (numcomps) { 2881 PetscValidPointer(numcomps, 7); 2882 *numcomps = b->numcomps; 2883 } 2884 if (comps) { 2885 PetscValidPointer(comps, 8); 2886 *comps = b->comps; 2887 } 2888 if (func) { 2889 PetscValidPointer(func, 9); 2890 *func = b->func; 2891 } 2892 if (numids) { 2893 PetscValidPointer(numids, 10); 2894 *numids = b->numids; 2895 } 2896 if (ids) { 2897 PetscValidPointer(ids, 11); 2898 *ids = b->ids; 2899 } 2900 if (ctx) { 2901 PetscValidPointer(ctx, 12); 2902 *ctx = b->ctx; 2903 } 2904 PetscFunctionReturn(0); 2905 } 2906 2907 /*@ 2908 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 2909 2910 Not collective 2911 2912 Input Parameter: 2913 . prob - The PetscDS object 2914 2915 Output Parameter: 2916 . newprob - The PetscDS copy 2917 2918 Level: intermediate 2919 2920 .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 2921 @*/ 2922 PetscErrorCode PetscDSCopyBoundary(PetscDS probA, PetscDS probB) 2923 { 2924 DSBoundary b, next, *lastnext; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 PetscValidHeaderSpecific(probA, PETSCDS_CLASSID, 1); 2929 PetscValidHeaderSpecific(probB, PETSCDS_CLASSID, 2); 2930 if (probA == probB) PetscFunctionReturn(0); 2931 next = probB->boundary; 2932 while (next) { 2933 DSBoundary b = next; 2934 2935 next = b->next; 2936 ierr = PetscFree(b->comps);CHKERRQ(ierr); 2937 ierr = PetscFree(b->ids);CHKERRQ(ierr); 2938 ierr = PetscFree(b->name);CHKERRQ(ierr); 2939 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 2940 ierr = PetscFree(b);CHKERRQ(ierr); 2941 } 2942 lastnext = &(probB->boundary); 2943 for (b = probA->boundary; b; b = b->next) { 2944 DSBoundary bNew; 2945 2946 ierr = PetscNew(&bNew);CHKERRQ(ierr); 2947 bNew->numcomps = b->numcomps; 2948 ierr = PetscMalloc1(bNew->numcomps, &bNew->comps);CHKERRQ(ierr); 2949 ierr = PetscArraycpy(bNew->comps, b->comps, bNew->numcomps);CHKERRQ(ierr); 2950 bNew->numids = b->numids; 2951 ierr = PetscMalloc1(bNew->numids, &bNew->ids);CHKERRQ(ierr); 2952 ierr = PetscArraycpy(bNew->ids, b->ids, bNew->numids);CHKERRQ(ierr); 2953 ierr = PetscStrallocpy(b->labelname,(char **) &(bNew->labelname));CHKERRQ(ierr); 2954 ierr = PetscStrallocpy(b->name,(char **) &(bNew->name));CHKERRQ(ierr); 2955 bNew->ctx = b->ctx; 2956 bNew->type = b->type; 2957 bNew->field = b->field; 2958 bNew->func = b->func; 2959 2960 *lastnext = bNew; 2961 lastnext = &(bNew->next); 2962 } 2963 PetscFunctionReturn(0); 2964 } 2965 2966 /*@C 2967 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 2968 2969 Not collective 2970 2971 Input Parameter: 2972 + prob - The PetscDS object 2973 . numFields - Number of new fields 2974 - fields - Old field number for each new field 2975 2976 Output Parameter: 2977 . newprob - The PetscDS copy 2978 2979 Level: intermediate 2980 2981 .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 2982 @*/ 2983 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 2984 { 2985 PetscInt Nf, Nfn, fn, gn; 2986 PetscErrorCode ierr; 2987 2988 PetscFunctionBegin; 2989 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2990 if (fields) PetscValidPointer(fields, 3); 2991 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 2992 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 2993 ierr = PetscDSGetNumFields(newprob, &Nfn);CHKERRQ(ierr); 2994 if (numFields > Nfn) SETERRQ2(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); 2995 for (fn = 0; fn < numFields; ++fn) { 2996 const PetscInt f = fields ? fields[fn] : fn; 2997 PetscPointFunc obj; 2998 PetscPointFunc f0, f1; 2999 PetscBdPointFunc f0Bd, f1Bd; 3000 PetscRiemannFunc r; 3001 3002 if (f >= Nf) continue; 3003 ierr = PetscDSGetObjective(prob, f, &obj);CHKERRQ(ierr); 3004 ierr = PetscDSGetResidual(prob, f, &f0, &f1);CHKERRQ(ierr); 3005 ierr = PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);CHKERRQ(ierr); 3006 ierr = PetscDSGetRiemannSolver(prob, f, &r);CHKERRQ(ierr); 3007 ierr = PetscDSSetObjective(newprob, fn, obj);CHKERRQ(ierr); 3008 ierr = PetscDSSetResidual(newprob, fn, f0, f1);CHKERRQ(ierr); 3009 ierr = PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);CHKERRQ(ierr); 3010 ierr = PetscDSSetRiemannSolver(newprob, fn, r);CHKERRQ(ierr); 3011 for (gn = 0; gn < numFields; ++gn) { 3012 const PetscInt g = fields ? fields[gn] : gn; 3013 PetscPointJac g0, g1, g2, g3; 3014 PetscPointJac g0p, g1p, g2p, g3p; 3015 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3016 3017 if (g >= Nf) continue; 3018 ierr = PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);CHKERRQ(ierr); 3019 ierr = PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);CHKERRQ(ierr); 3020 ierr = PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);CHKERRQ(ierr); 3021 ierr = PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);CHKERRQ(ierr); 3022 ierr = PetscDSSetJacobianPreconditioner(prob, fn, gn, g0p, g1p, g2p, g3p);CHKERRQ(ierr); 3023 ierr = PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);CHKERRQ(ierr); 3024 } 3025 } 3026 PetscFunctionReturn(0); 3027 } 3028 3029 /*@ 3030 PetscDSCopyEquations - Copy all pointwise function pointers to the new problem 3031 3032 Not collective 3033 3034 Input Parameter: 3035 . prob - The PetscDS object 3036 3037 Output Parameter: 3038 . newprob - The PetscDS copy 3039 3040 Level: intermediate 3041 3042 .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3043 @*/ 3044 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3045 { 3046 PetscInt Nf, Ng; 3047 PetscErrorCode ierr; 3048 3049 PetscFunctionBegin; 3050 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3051 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3052 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3053 ierr = PetscDSGetNumFields(newprob, &Ng);CHKERRQ(ierr); 3054 if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng); 3055 ierr = PetscDSSelectEquations(prob, Nf, NULL, newprob);CHKERRQ(ierr); 3056 PetscFunctionReturn(0); 3057 } 3058 /*@ 3059 PetscDSCopyConstants - Copy all constants to the new problem 3060 3061 Not collective 3062 3063 Input Parameter: 3064 . prob - The PetscDS object 3065 3066 Output Parameter: 3067 . newprob - The PetscDS copy 3068 3069 Level: intermediate 3070 3071 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3072 @*/ 3073 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3074 { 3075 PetscInt Nc; 3076 const PetscScalar *constants; 3077 PetscErrorCode ierr; 3078 3079 PetscFunctionBegin; 3080 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3081 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3082 ierr = PetscDSGetConstants(prob, &Nc, &constants);CHKERRQ(ierr); 3083 ierr = PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);CHKERRQ(ierr); 3084 PetscFunctionReturn(0); 3085 } 3086 3087 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 3088 { 3089 PetscInt dim, Nf, f; 3090 PetscErrorCode ierr; 3091 3092 PetscFunctionBegin; 3093 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3094 PetscValidPointer(subprob, 3); 3095 if (height == 0) {*subprob = prob; PetscFunctionReturn(0);} 3096 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3097 ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr); 3098 if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height); 3099 if (!prob->subprobs) {ierr = PetscCalloc1(dim, &prob->subprobs);CHKERRQ(ierr);} 3100 if (!prob->subprobs[height-1]) { 3101 PetscInt cdim; 3102 3103 ierr = PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);CHKERRQ(ierr); 3104 ierr = PetscDSGetCoordinateDimension(prob, &cdim);CHKERRQ(ierr); 3105 ierr = PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);CHKERRQ(ierr); 3106 for (f = 0; f < Nf; ++f) { 3107 PetscFE subfe; 3108 PetscObject obj; 3109 PetscClassId id; 3110 3111 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 3112 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3113 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);CHKERRQ(ierr);} 3114 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f); 3115 ierr = PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);CHKERRQ(ierr); 3116 } 3117 } 3118 *subprob = prob->subprobs[height-1]; 3119 PetscFunctionReturn(0); 3120 } 3121 3122 PetscErrorCode PetscDSIsFE_Internal(PetscDS ds, PetscInt f, PetscBool *isFE) 3123 { 3124 PetscObject obj; 3125 PetscClassId id; 3126 PetscInt Nf; 3127 PetscErrorCode ierr; 3128 3129 PetscFunctionBegin; 3130 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3131 PetscValidPointer(isFE, 3); 3132 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 3133 if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf); 3134 ierr = PetscDSGetDiscretization(ds, f, &obj);CHKERRQ(ierr); 3135 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3136 if (id == PETSCFE_CLASSID) *isFE = PETSC_TRUE; 3137 else *isFE = PETSC_FALSE; 3138 PetscFunctionReturn(0); 3139 } 3140 3141 static PetscErrorCode PetscDSDestroy_Basic(PetscDS prob) 3142 { 3143 PetscErrorCode ierr; 3144 3145 PetscFunctionBegin; 3146 ierr = PetscFree(prob->data);CHKERRQ(ierr); 3147 PetscFunctionReturn(0); 3148 } 3149 3150 static PetscErrorCode PetscDSInitialize_Basic(PetscDS prob) 3151 { 3152 PetscFunctionBegin; 3153 prob->ops->setfromoptions = NULL; 3154 prob->ops->setup = NULL; 3155 prob->ops->view = NULL; 3156 prob->ops->destroy = PetscDSDestroy_Basic; 3157 PetscFunctionReturn(0); 3158 } 3159 3160 /*MC 3161 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 3162 3163 Level: intermediate 3164 3165 .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType() 3166 M*/ 3167 3168 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS prob) 3169 { 3170 PetscDS_Basic *b; 3171 PetscErrorCode ierr; 3172 3173 PetscFunctionBegin; 3174 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3175 ierr = PetscNewLog(prob, &b);CHKERRQ(ierr); 3176 prob->data = b; 3177 3178 ierr = PetscDSInitialize_Basic(prob);CHKERRQ(ierr); 3179 PetscFunctionReturn(0); 3180 } 3181