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