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