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