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