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