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