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