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