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