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