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