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