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