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