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 /* A PetscDS (Discrete System) encodes a set of equations posed in a discrete space, which represents a set of 9 nonlinear continuum equations. The equations can have multiple fields, each field having a different 10 discretization. In addition, different pieces of the domain can have different field combinations and equations. 11 12 The DS provides the user a description of the approximation space on any given cell. It also gives pointwise 13 functions representing the equations. 14 15 Each field is associated with a label, marking the cells on which it is supported. Note that a field can be 16 supported on the closure of a cell not in the label due to overlap of the boundary of neighboring cells. The DM 17 then creates a DS for each set of cells with identical approximation spaces. When assembling, the user asks for 18 the space associated with a given cell. DMPlex uses the labels associated with each DS in the default integration loop. 19 */ 20 21 /*@C 22 PetscDSRegister - Adds a new PetscDS implementation 23 24 Not Collective 25 26 Input Parameters: 27 + name - The name of a new user-defined creation routine 28 - create_func - The creation routine itself 29 30 Notes: 31 PetscDSRegister() may be called multiple times to add several user-defined PetscDSs 32 33 Sample usage: 34 .vb 35 PetscDSRegister("my_ds", MyPetscDSCreate); 36 .ve 37 38 Then, your PetscDS type can be chosen with the procedural interface via 39 .vb 40 PetscDSCreate(MPI_Comm, PetscDS *); 41 PetscDSSetType(PetscDS, "my_ds"); 42 .ve 43 or at runtime via the option 44 .vb 45 -petscds_type my_ds 46 .ve 47 48 Level: advanced 49 50 Not available from Fortran 51 52 .seealso: PetscDSRegisterAll(), PetscDSRegisterDestroy() 53 54 @*/ 55 PetscErrorCode PetscDSRegister(const char sname[], PetscErrorCode (*function)(PetscDS)) 56 { 57 PetscErrorCode ierr; 58 59 PetscFunctionBegin; 60 ierr = PetscFunctionListAdd(&PetscDSList, sname, function);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 /*@C 65 PetscDSSetType - Builds a particular PetscDS 66 67 Collective on prob 68 69 Input Parameters: 70 + prob - The PetscDS object 71 - name - The kind of system 72 73 Options Database Key: 74 . -petscds_type <type> - Sets the PetscDS type; use -help for a list of available types 75 76 Level: intermediate 77 78 Not available from Fortran 79 80 .seealso: PetscDSGetType(), PetscDSCreate() 81 @*/ 82 PetscErrorCode PetscDSSetType(PetscDS prob, PetscDSType name) 83 { 84 PetscErrorCode (*r)(PetscDS); 85 PetscBool match; 86 PetscErrorCode ierr; 87 88 PetscFunctionBegin; 89 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 90 ierr = PetscObjectTypeCompare((PetscObject) prob, name, &match);CHKERRQ(ierr); 91 if (match) PetscFunctionReturn(0); 92 93 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 94 ierr = PetscFunctionListFind(PetscDSList, name, &r);CHKERRQ(ierr); 95 if (!r) SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown PetscDS type: %s", name); 96 97 if (prob->ops->destroy) { 98 ierr = (*prob->ops->destroy)(prob);CHKERRQ(ierr); 99 prob->ops->destroy = NULL; 100 } 101 ierr = (*r)(prob);CHKERRQ(ierr); 102 ierr = PetscObjectChangeTypeName((PetscObject) prob, name);CHKERRQ(ierr); 103 PetscFunctionReturn(0); 104 } 105 106 /*@C 107 PetscDSGetType - Gets the PetscDS type name (as a string) from the object. 108 109 Not Collective 110 111 Input Parameter: 112 . prob - The PetscDS 113 114 Output Parameter: 115 . name - The PetscDS type name 116 117 Level: intermediate 118 119 Not available from Fortran 120 121 .seealso: PetscDSSetType(), PetscDSCreate() 122 @*/ 123 PetscErrorCode PetscDSGetType(PetscDS prob, PetscDSType *name) 124 { 125 PetscErrorCode ierr; 126 127 PetscFunctionBegin; 128 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 129 PetscValidPointer(name, 2); 130 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 131 *name = ((PetscObject) prob)->type_name; 132 PetscFunctionReturn(0); 133 } 134 135 static PetscErrorCode PetscDSView_Ascii(PetscDS ds, PetscViewer viewer) 136 { 137 PetscViewerFormat format; 138 const PetscScalar *constants; 139 PetscInt Nf, numConstants, f; 140 PetscErrorCode ierr; 141 142 PetscFunctionBegin; 143 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 144 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 145 ierr = PetscViewerASCIIPrintf(viewer, "Discrete System with %d fields\n", Nf);CHKERRQ(ierr); 146 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 147 ierr = PetscViewerASCIIPrintf(viewer, " cell total dim %D total comp %D\n", ds->totDim, ds->totComp);CHKERRQ(ierr); 148 if (ds->isCohesive) {ierr = PetscViewerASCIIPrintf(viewer, " cohesive cell\n");CHKERRQ(ierr);} 149 for (f = 0; f < Nf; ++f) { 150 DSBoundary b; 151 PetscObject obj; 152 PetscClassId id; 153 PetscQuadrature q; 154 const char *name; 155 PetscInt Nc, Nq, Nqc; 156 157 ierr = PetscDSGetDiscretization(ds, f, &obj);CHKERRQ(ierr); 158 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 159 ierr = PetscObjectGetName(obj, &name);CHKERRQ(ierr); 160 ierr = PetscViewerASCIIPrintf(viewer, "Field %s", name ? name : "<unknown>");CHKERRQ(ierr); 161 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 162 if (id == PETSCFE_CLASSID) { 163 ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr); 164 ierr = PetscFEGetQuadrature((PetscFE) obj, &q);CHKERRQ(ierr); 165 ierr = PetscViewerASCIIPrintf(viewer, " FEM");CHKERRQ(ierr); 166 } else if (id == PETSCFV_CLASSID) { 167 ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr); 168 ierr = PetscFVGetQuadrature((PetscFV) obj, &q);CHKERRQ(ierr); 169 ierr = PetscViewerASCIIPrintf(viewer, " FVM");CHKERRQ(ierr); 170 } 171 else SETERRQ1(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %D", f); 172 if (Nc > 1) {ierr = PetscViewerASCIIPrintf(viewer, " %D components", Nc);CHKERRQ(ierr);} 173 else {ierr = PetscViewerASCIIPrintf(viewer, " %D component ", Nc);CHKERRQ(ierr);} 174 if (ds->implicit[f]) {ierr = PetscViewerASCIIPrintf(viewer, " (implicit)");CHKERRQ(ierr);} 175 else {ierr = PetscViewerASCIIPrintf(viewer, " (explicit)");CHKERRQ(ierr);} 176 if (q) { 177 ierr = PetscQuadratureGetData(q, NULL, &Nqc, &Nq, NULL, NULL);CHKERRQ(ierr); 178 ierr = PetscViewerASCIIPrintf(viewer, " (Nq %D Nqc %D)", Nq, Nqc);CHKERRQ(ierr); 179 } 180 ierr = PetscViewerASCIIPrintf(viewer, " %D-jet", ds->jetDegree[f]);CHKERRQ(ierr); 181 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 182 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 183 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 184 if (id == PETSCFE_CLASSID) {ierr = PetscFEView((PetscFE) obj, viewer);CHKERRQ(ierr);} 185 else if (id == PETSCFV_CLASSID) {ierr = PetscFVView((PetscFV) obj, viewer);CHKERRQ(ierr);} 186 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 187 188 for (b = ds->boundary; b; b = b->next) { 189 char *name; 190 PetscInt c, i; 191 192 if (b->field != f) continue; 193 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 194 ierr = PetscViewerASCIIPrintf(viewer, "Boundary %s (%s) %s\n", b->name, b->lname, DMBoundaryConditionTypes[b->type]);CHKERRQ(ierr); 195 if (!b->Nc) { 196 ierr = PetscViewerASCIIPrintf(viewer, " all components\n");CHKERRQ(ierr); 197 } else { 198 ierr = PetscViewerASCIIPrintf(viewer, " components: ");CHKERRQ(ierr); 199 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 200 for (c = 0; c < b->Nc; ++c) { 201 if (c > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 202 ierr = PetscViewerASCIIPrintf(viewer, "%D", b->comps[c]);CHKERRQ(ierr); 203 } 204 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 205 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 206 } 207 ierr = PetscViewerASCIIPrintf(viewer, " values: ");CHKERRQ(ierr); 208 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr); 209 for (i = 0; i < b->Nv; ++i) { 210 if (i > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 211 ierr = PetscViewerASCIIPrintf(viewer, "%D", b->values[i]);CHKERRQ(ierr); 212 } 213 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 214 ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr); 215 if (b->func) { 216 ierr = PetscDLAddr(b->func, &name);CHKERRQ(ierr); 217 if (name) {ierr = PetscViewerASCIIPrintf(viewer, " func: %s\n", name);CHKERRQ(ierr);} 218 else {ierr = PetscViewerASCIIPrintf(viewer, " func: %p\n", b->func);CHKERRQ(ierr);} 219 ierr = PetscFree(name);CHKERRQ(ierr); 220 } 221 if (b->func_t) { 222 ierr = PetscDLAddr(b->func_t, &name);CHKERRQ(ierr); 223 if (name) {ierr = PetscViewerASCIIPrintf(viewer, " func_t: %s\n", name);CHKERRQ(ierr);} 224 else {ierr = PetscViewerASCIIPrintf(viewer, " func_t: %p\n", b->func_t);CHKERRQ(ierr);} 225 ierr = PetscFree(name);CHKERRQ(ierr); 226 } 227 ierr = PetscWeakFormView(b->wf, viewer);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 229 } 230 } 231 ierr = PetscDSGetConstants(ds, &numConstants, &constants);CHKERRQ(ierr); 232 if (numConstants) { 233 ierr = PetscViewerASCIIPrintf(viewer, "%D constants\n", numConstants);CHKERRQ(ierr); 234 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 235 for (f = 0; f < numConstants; ++f) {ierr = PetscViewerASCIIPrintf(viewer, "%g\n", (double) PetscRealPart(constants[f]));CHKERRQ(ierr);} 236 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 237 } 238 ierr = PetscWeakFormView(ds->wf, viewer);CHKERRQ(ierr); 239 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 240 PetscFunctionReturn(0); 241 } 242 243 /*@C 244 PetscDSViewFromOptions - View from Options 245 246 Collective on PetscDS 247 248 Input Parameters: 249 + A - the PetscDS object 250 . obj - Optional object 251 - name - command line option 252 253 Level: intermediate 254 .seealso: PetscDS, PetscDSView, PetscObjectViewFromOptions(), PetscDSCreate() 255 @*/ 256 PetscErrorCode PetscDSViewFromOptions(PetscDS A,PetscObject obj,const char name[]) 257 { 258 PetscErrorCode ierr; 259 260 PetscFunctionBegin; 261 PetscValidHeaderSpecific(A,PETSCDS_CLASSID,1); 262 ierr = PetscObjectViewFromOptions((PetscObject)A,obj,name);CHKERRQ(ierr); 263 PetscFunctionReturn(0); 264 } 265 266 /*@C 267 PetscDSView - Views a PetscDS 268 269 Collective on prob 270 271 Input Parameters: 272 + prob - the PetscDS object to view 273 - v - the viewer 274 275 Level: developer 276 277 .seealso PetscDSDestroy() 278 @*/ 279 PetscErrorCode PetscDSView(PetscDS prob, PetscViewer v) 280 { 281 PetscBool iascii; 282 PetscErrorCode ierr; 283 284 PetscFunctionBegin; 285 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 286 if (!v) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) prob), &v);CHKERRQ(ierr);} 287 else {PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2);} 288 ierr = PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 289 if (iascii) {ierr = PetscDSView_Ascii(prob, v);CHKERRQ(ierr);} 290 if (prob->ops->view) {ierr = (*prob->ops->view)(prob, v);CHKERRQ(ierr);} 291 PetscFunctionReturn(0); 292 } 293 294 /*@ 295 PetscDSSetFromOptions - sets parameters in a PetscDS from the options database 296 297 Collective on prob 298 299 Input Parameter: 300 . prob - the PetscDS object to set options for 301 302 Options Database: 303 + -petscds_type <type> : Set the DS type 304 . -petscds_view <view opt> : View the DS 305 . -petscds_jac_pre : Turn formation of a separate Jacobian preconditioner on and off 306 . -bc_<name> <ids> : Specify a list of label ids for a boundary condition 307 - -bc_<name>_comp <comps> : Specify a list of field components to constrain for a boundary condition 308 309 Level: developer 310 311 .seealso PetscDSView() 312 @*/ 313 PetscErrorCode PetscDSSetFromOptions(PetscDS prob) 314 { 315 DSBoundary b; 316 const char *defaultType; 317 char name[256]; 318 PetscBool flg; 319 PetscErrorCode ierr; 320 321 PetscFunctionBegin; 322 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 323 if (!((PetscObject) prob)->type_name) { 324 defaultType = PETSCDSBASIC; 325 } else { 326 defaultType = ((PetscObject) prob)->type_name; 327 } 328 ierr = PetscDSRegisterAll();CHKERRQ(ierr); 329 330 ierr = PetscObjectOptionsBegin((PetscObject) prob);CHKERRQ(ierr); 331 for (b = prob->boundary; b; b = b->next) { 332 char optname[1024]; 333 PetscInt ids[1024], len = 1024; 334 PetscBool flg; 335 336 ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s", b->name);CHKERRQ(ierr); 337 ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr); 338 ierr = PetscOptionsIntArray(optname, "List of boundary IDs", "", ids, &len, &flg);CHKERRQ(ierr); 339 if (flg) { 340 b->Nv = len; 341 ierr = PetscFree(b->values);CHKERRQ(ierr); 342 ierr = PetscMalloc1(len, &b->values);CHKERRQ(ierr); 343 ierr = PetscArraycpy(b->values, ids, len);CHKERRQ(ierr); 344 ierr = PetscWeakFormRewriteKeys(b->wf, b->label, len, b->values);CHKERRQ(ierr); 345 } 346 len = 1024; 347 ierr = PetscSNPrintf(optname, sizeof(optname), "-bc_%s_comp", b->name);CHKERRQ(ierr); 348 ierr = PetscMemzero(ids, sizeof(ids));CHKERRQ(ierr); 349 ierr = PetscOptionsIntArray(optname, "List of boundary field components", "", ids, &len, &flg);CHKERRQ(ierr); 350 if (flg) { 351 b->Nc = len; 352 ierr = PetscFree(b->comps);CHKERRQ(ierr); 353 ierr = PetscMalloc1(len, &b->comps);CHKERRQ(ierr); 354 ierr = PetscArraycpy(b->comps, ids, len);CHKERRQ(ierr); 355 } 356 } 357 ierr = PetscOptionsFList("-petscds_type", "Discrete System", "PetscDSSetType", PetscDSList, defaultType, name, 256, &flg);CHKERRQ(ierr); 358 if (flg) { 359 ierr = PetscDSSetType(prob, name);CHKERRQ(ierr); 360 } else if (!((PetscObject) prob)->type_name) { 361 ierr = PetscDSSetType(prob, defaultType);CHKERRQ(ierr); 362 } 363 ierr = PetscOptionsBool("-petscds_jac_pre", "Discrete System", "PetscDSUseJacobianPreconditioner", prob->useJacPre, &prob->useJacPre, &flg);CHKERRQ(ierr); 364 if (prob->ops->setfromoptions) {ierr = (*prob->ops->setfromoptions)(prob);CHKERRQ(ierr);} 365 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 366 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) prob);CHKERRQ(ierr); 367 ierr = PetscOptionsEnd();CHKERRQ(ierr); 368 if (prob->Nf) {ierr = PetscDSViewFromOptions(prob, NULL, "-petscds_view");CHKERRQ(ierr);} 369 PetscFunctionReturn(0); 370 } 371 372 /*@C 373 PetscDSSetUp - Construct data structures for the PetscDS 374 375 Collective on prob 376 377 Input Parameter: 378 . prob - the PetscDS object to setup 379 380 Level: developer 381 382 .seealso PetscDSView(), PetscDSDestroy() 383 @*/ 384 PetscErrorCode PetscDSSetUp(PetscDS prob) 385 { 386 const PetscInt Nf = prob->Nf; 387 PetscBool hasH = PETSC_FALSE; 388 PetscInt dim, dimEmbed, NbMax = 0, NcMax = 0, NqMax = 0, NsMax = 1, f; 389 PetscErrorCode ierr; 390 391 PetscFunctionBegin; 392 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 393 if (prob->setup) PetscFunctionReturn(0); 394 /* Calculate sizes */ 395 ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr); 396 ierr = PetscDSGetCoordinateDimension(prob, &dimEmbed);CHKERRQ(ierr); 397 prob->totDim = prob->totComp = 0; 398 ierr = PetscMalloc2(Nf,&prob->Nc,Nf,&prob->Nb);CHKERRQ(ierr); 399 ierr = PetscCalloc2(Nf+1,&prob->off,Nf+1,&prob->offDer);CHKERRQ(ierr); 400 ierr = PetscMalloc2(Nf,&prob->T,Nf,&prob->Tf);CHKERRQ(ierr); 401 for (f = 0; f < Nf; ++f) { 402 PetscObject obj; 403 PetscClassId id; 404 PetscQuadrature q = NULL; 405 PetscInt Nq = 0, Nb, Nc; 406 407 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 408 if (prob->jetDegree[f] > 1) hasH = PETSC_TRUE; 409 if (!obj) { 410 /* Empty mesh */ 411 Nb = Nc = 0; 412 prob->T[f] = prob->Tf[f] = NULL; 413 } else { 414 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 415 if (id == PETSCFE_CLASSID) { 416 PetscFE fe = (PetscFE) obj; 417 418 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 419 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 420 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 421 ierr = PetscFEGetCellTabulation(fe, prob->jetDegree[f], &prob->T[f]);CHKERRQ(ierr); 422 ierr = PetscFEGetFaceTabulation(fe, prob->jetDegree[f], &prob->Tf[f]);CHKERRQ(ierr); 423 } else if (id == PETSCFV_CLASSID) { 424 PetscFV fv = (PetscFV) obj; 425 426 ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr); 427 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 428 Nb = Nc; 429 ierr = PetscFVGetCellTabulation(fv, &prob->T[f]);CHKERRQ(ierr); 430 /* TODO: should PetscFV also have face tabulation? Otherwise there will be a null pointer in prob->basisFace */ 431 } else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 432 } 433 prob->Nc[f] = Nc; 434 prob->Nb[f] = Nb; 435 prob->off[f+1] = Nc + prob->off[f]; 436 prob->offDer[f+1] = Nc*dim + prob->offDer[f]; 437 if (q) {ierr = PetscQuadratureGetData(q, NULL, NULL, &Nq, NULL, NULL);CHKERRQ(ierr);} 438 NqMax = PetscMax(NqMax, Nq); 439 NbMax = PetscMax(NbMax, Nb); 440 NcMax = PetscMax(NcMax, Nc); 441 prob->totDim += Nb; 442 prob->totComp += Nc; 443 /* There are two faces for all fields on a cohesive cell, except for cohesive fields */ 444 if (prob->isCohesive && !prob->cohesive[f]) prob->totDim += Nb; 445 } 446 /* Allocate works space */ 447 NsMax = 2; /* A non-cohesive discretizations can be used on a cohesive cell, so we need this extra workspace for all DS */ 448 ierr = PetscMalloc3(NsMax*prob->totComp,&prob->u,NsMax*prob->totComp,&prob->u_t,NsMax*prob->totComp*dimEmbed + (hasH ? NsMax*prob->totComp*dimEmbed*dimEmbed : 0),&prob->u_x);CHKERRQ(ierr); 449 ierr = PetscMalloc5(dimEmbed,&prob->x,NbMax*NcMax,&prob->basisReal,NbMax*NcMax*dimEmbed,&prob->basisDerReal,NbMax*NcMax,&prob->testReal,NbMax*NcMax*dimEmbed,&prob->testDerReal);CHKERRQ(ierr); 450 ierr = PetscMalloc6(NsMax*NqMax*NcMax,&prob->f0,NsMax*NqMax*NcMax*dimEmbed,&prob->f1, 451 NsMax*NsMax*NqMax*NcMax*NcMax,&prob->g0,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g1, 452 NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed,&prob->g2,NsMax*NsMax*NqMax*NcMax*NcMax*dimEmbed*dimEmbed,&prob->g3);CHKERRQ(ierr); 453 if (prob->ops->setup) {ierr = (*prob->ops->setup)(prob);CHKERRQ(ierr);} 454 prob->setup = PETSC_TRUE; 455 PetscFunctionReturn(0); 456 } 457 458 static PetscErrorCode PetscDSDestroyStructs_Static(PetscDS prob) 459 { 460 PetscErrorCode ierr; 461 462 PetscFunctionBegin; 463 ierr = PetscFree2(prob->Nc,prob->Nb);CHKERRQ(ierr); 464 ierr = PetscFree2(prob->off,prob->offDer);CHKERRQ(ierr); 465 ierr = PetscFree2(prob->T,prob->Tf);CHKERRQ(ierr); 466 ierr = PetscFree3(prob->u,prob->u_t,prob->u_x);CHKERRQ(ierr); 467 ierr = PetscFree5(prob->x,prob->basisReal, prob->basisDerReal,prob->testReal,prob->testDerReal);CHKERRQ(ierr); 468 ierr = PetscFree6(prob->f0,prob->f1,prob->g0,prob->g1,prob->g2,prob->g3);CHKERRQ(ierr); 469 PetscFunctionReturn(0); 470 } 471 472 static PetscErrorCode PetscDSEnlarge_Static(PetscDS prob, PetscInt NfNew) 473 { 474 PetscObject *tmpd; 475 PetscBool *tmpi; 476 PetscInt *tmpk; 477 PetscBool *tmpc; 478 PetscPointFunc *tmpup; 479 PetscSimplePointFunc *tmpexactSol, *tmpexactSol_t; 480 void **tmpexactCtx, **tmpexactCtx_t; 481 void **tmpctx; 482 PetscInt Nf = prob->Nf, f; 483 PetscErrorCode ierr; 484 485 PetscFunctionBegin; 486 if (Nf >= NfNew) PetscFunctionReturn(0); 487 prob->setup = PETSC_FALSE; 488 ierr = PetscDSDestroyStructs_Static(prob);CHKERRQ(ierr); 489 ierr = PetscMalloc4(NfNew, &tmpd, NfNew, &tmpi, NfNew, &tmpc, NfNew, &tmpk);CHKERRQ(ierr); 490 for (f = 0; f < Nf; ++f) {tmpd[f] = prob->disc[f]; tmpi[f] = prob->implicit[f]; tmpc[f] = prob->cohesive[f]; tmpk[f] = prob->jetDegree[f];} 491 for (f = Nf; f < NfNew; ++f) {tmpd[f] = NULL; tmpi[f] = PETSC_TRUE, tmpc[f] = PETSC_FALSE; tmpk[f] = 1;} 492 ierr = PetscFree4(prob->disc, prob->implicit, prob->cohesive, prob->jetDegree);CHKERRQ(ierr); 493 ierr = PetscWeakFormSetNumFields(prob->wf, NfNew);CHKERRQ(ierr); 494 prob->Nf = NfNew; 495 prob->disc = tmpd; 496 prob->implicit = tmpi; 497 prob->cohesive = tmpc; 498 prob->jetDegree = tmpk; 499 ierr = PetscCalloc2(NfNew, &tmpup, NfNew, &tmpctx);CHKERRQ(ierr); 500 for (f = 0; f < Nf; ++f) tmpup[f] = prob->update[f]; 501 for (f = 0; f < Nf; ++f) tmpctx[f] = prob->ctx[f]; 502 for (f = Nf; f < NfNew; ++f) tmpup[f] = NULL; 503 for (f = Nf; f < NfNew; ++f) tmpctx[f] = NULL; 504 ierr = PetscFree2(prob->update, prob->ctx);CHKERRQ(ierr); 505 prob->update = tmpup; 506 prob->ctx = tmpctx; 507 ierr = PetscCalloc4(NfNew, &tmpexactSol, NfNew, &tmpexactCtx, NfNew, &tmpexactSol_t, NfNew, &tmpexactCtx_t);CHKERRQ(ierr); 508 for (f = 0; f < Nf; ++f) tmpexactSol[f] = prob->exactSol[f]; 509 for (f = 0; f < Nf; ++f) tmpexactCtx[f] = prob->exactCtx[f]; 510 for (f = 0; f < Nf; ++f) tmpexactSol_t[f] = prob->exactSol_t[f]; 511 for (f = 0; f < Nf; ++f) tmpexactCtx_t[f] = prob->exactCtx_t[f]; 512 for (f = Nf; f < NfNew; ++f) tmpexactSol[f] = NULL; 513 for (f = Nf; f < NfNew; ++f) tmpexactCtx[f] = NULL; 514 for (f = Nf; f < NfNew; ++f) tmpexactSol_t[f] = NULL; 515 for (f = Nf; f < NfNew; ++f) tmpexactCtx_t[f] = NULL; 516 ierr = PetscFree4(prob->exactSol, prob->exactCtx, prob->exactSol_t, prob->exactCtx_t);CHKERRQ(ierr); 517 prob->exactSol = tmpexactSol; 518 prob->exactCtx = tmpexactCtx; 519 prob->exactSol_t = tmpexactSol_t; 520 prob->exactCtx_t = tmpexactCtx_t; 521 PetscFunctionReturn(0); 522 } 523 524 /*@ 525 PetscDSDestroy - Destroys a PetscDS object 526 527 Collective on prob 528 529 Input Parameter: 530 . prob - the PetscDS object to destroy 531 532 Level: developer 533 534 .seealso PetscDSView() 535 @*/ 536 PetscErrorCode PetscDSDestroy(PetscDS *ds) 537 { 538 PetscInt f; 539 PetscErrorCode ierr; 540 541 PetscFunctionBegin; 542 if (!*ds) PetscFunctionReturn(0); 543 PetscValidHeaderSpecific((*ds), PETSCDS_CLASSID, 1); 544 545 if (--((PetscObject)(*ds))->refct > 0) {*ds = NULL; PetscFunctionReturn(0);} 546 ((PetscObject) (*ds))->refct = 0; 547 if ((*ds)->subprobs) { 548 PetscInt dim, d; 549 550 ierr = PetscDSGetSpatialDimension(*ds, &dim);CHKERRQ(ierr); 551 for (d = 0; d < dim; ++d) {ierr = PetscDSDestroy(&(*ds)->subprobs[d]);CHKERRQ(ierr);} 552 } 553 ierr = PetscFree((*ds)->subprobs);CHKERRQ(ierr); 554 ierr = PetscDSDestroyStructs_Static(*ds);CHKERRQ(ierr); 555 for (f = 0; f < (*ds)->Nf; ++f) { 556 ierr = PetscObjectDereference((*ds)->disc[f]);CHKERRQ(ierr); 557 } 558 ierr = PetscFree4((*ds)->disc, (*ds)->implicit, (*ds)->cohesive, (*ds)->jetDegree);CHKERRQ(ierr); 559 ierr = PetscWeakFormDestroy(&(*ds)->wf);CHKERRQ(ierr); 560 ierr = PetscFree2((*ds)->update,(*ds)->ctx);CHKERRQ(ierr); 561 ierr = PetscFree4((*ds)->exactSol,(*ds)->exactCtx,(*ds)->exactSol_t,(*ds)->exactCtx_t);CHKERRQ(ierr); 562 if ((*ds)->ops->destroy) {ierr = (*(*ds)->ops->destroy)(*ds);CHKERRQ(ierr);} 563 ierr = PetscDSDestroyBoundary(*ds);CHKERRQ(ierr); 564 ierr = PetscFree((*ds)->constants);CHKERRQ(ierr); 565 ierr = PetscHeaderDestroy(ds);CHKERRQ(ierr); 566 PetscFunctionReturn(0); 567 } 568 569 /*@ 570 PetscDSCreate - Creates an empty PetscDS object. The type can then be set with PetscDSSetType(). 571 572 Collective 573 574 Input Parameter: 575 . comm - The communicator for the PetscDS object 576 577 Output Parameter: 578 . ds - The PetscDS object 579 580 Level: beginner 581 582 .seealso: PetscDSSetType(), PETSCDSBASIC 583 @*/ 584 PetscErrorCode PetscDSCreate(MPI_Comm comm, PetscDS *ds) 585 { 586 PetscDS p; 587 PetscErrorCode ierr; 588 589 PetscFunctionBegin; 590 PetscValidPointer(ds, 2); 591 *ds = NULL; 592 ierr = PetscDSInitializePackage();CHKERRQ(ierr); 593 594 ierr = PetscHeaderCreate(p, PETSCDS_CLASSID, "PetscDS", "Discrete System", "PetscDS", comm, PetscDSDestroy, PetscDSView);CHKERRQ(ierr); 595 596 p->Nf = 0; 597 p->setup = PETSC_FALSE; 598 p->numConstants = 0; 599 p->constants = NULL; 600 p->dimEmbed = -1; 601 p->useJacPre = PETSC_TRUE; 602 ierr = PetscWeakFormCreate(comm, &p->wf);CHKERRQ(ierr); 603 604 *ds = p; 605 PetscFunctionReturn(0); 606 } 607 608 /*@ 609 PetscDSGetNumFields - Returns the number of fields in the DS 610 611 Not collective 612 613 Input Parameter: 614 . prob - The PetscDS object 615 616 Output Parameter: 617 . Nf - The number of fields 618 619 Level: beginner 620 621 .seealso: PetscDSGetSpatialDimension(), PetscDSCreate() 622 @*/ 623 PetscErrorCode PetscDSGetNumFields(PetscDS prob, PetscInt *Nf) 624 { 625 PetscFunctionBegin; 626 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 627 PetscValidPointer(Nf, 2); 628 *Nf = prob->Nf; 629 PetscFunctionReturn(0); 630 } 631 632 /*@ 633 PetscDSGetSpatialDimension - Returns the spatial dimension of the DS, meaning the topological dimension of the discretizations 634 635 Not collective 636 637 Input Parameter: 638 . prob - The PetscDS object 639 640 Output Parameter: 641 . dim - The spatial dimension 642 643 Level: beginner 644 645 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetNumFields(), PetscDSCreate() 646 @*/ 647 PetscErrorCode PetscDSGetSpatialDimension(PetscDS prob, PetscInt *dim) 648 { 649 PetscErrorCode ierr; 650 651 PetscFunctionBegin; 652 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 653 PetscValidPointer(dim, 2); 654 *dim = 0; 655 if (prob->Nf) { 656 PetscObject obj; 657 PetscClassId id; 658 659 ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr); 660 if (obj) { 661 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 662 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetSpatialDimension((PetscFE) obj, dim);CHKERRQ(ierr);} 663 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetSpatialDimension((PetscFV) obj, dim);CHKERRQ(ierr);} 664 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0); 665 } 666 } 667 PetscFunctionReturn(0); 668 } 669 670 /*@ 671 PetscDSGetCoordinateDimension - Returns the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded 672 673 Not collective 674 675 Input Parameter: 676 . prob - The PetscDS object 677 678 Output Parameter: 679 . dimEmbed - The coordinate dimension 680 681 Level: beginner 682 683 .seealso: PetscDSSetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate() 684 @*/ 685 PetscErrorCode PetscDSGetCoordinateDimension(PetscDS prob, PetscInt *dimEmbed) 686 { 687 PetscFunctionBegin; 688 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 689 PetscValidPointer(dimEmbed, 2); 690 if (prob->dimEmbed < 0) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONGSTATE, "No coordinate dimension set for this DS"); 691 *dimEmbed = prob->dimEmbed; 692 PetscFunctionReturn(0); 693 } 694 695 /*@ 696 PetscDSSetCoordinateDimension - Set the coordinate dimension of the DS, meaning the dimension of the space into which the discretiaztions are embedded 697 698 Logically collective on prob 699 700 Input Parameters: 701 + prob - The PetscDS object 702 - dimEmbed - The coordinate dimension 703 704 Level: beginner 705 706 .seealso: PetscDSGetCoordinateDimension(), PetscDSGetSpatialDimension(), PetscDSGetNumFields(), PetscDSCreate() 707 @*/ 708 PetscErrorCode PetscDSSetCoordinateDimension(PetscDS prob, PetscInt dimEmbed) 709 { 710 PetscFunctionBegin; 711 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 712 if (dimEmbed < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate dimension must be non-negative, not %D", dimEmbed); 713 prob->dimEmbed = dimEmbed; 714 PetscFunctionReturn(0); 715 } 716 717 /*@ 718 PetscDSIsCohesive - Returns the flag indicating that this DS is for a cohesive cell 719 720 Not collective 721 722 Input Parameter: 723 . ds - The PetscDS object 724 725 Output Parameter: 726 . isCohesive - The flag 727 728 Level: developer 729 730 .seealso: PetscDSGetNumCohesive(), PetscDSGetCohesive(), PetscDSSetCohesive(), PetscDSCreate() 731 @*/ 732 PetscErrorCode PetscDSIsCohesive(PetscDS ds, PetscBool *isCohesive) 733 { 734 PetscFunctionBegin; 735 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 736 PetscValidPointer(isCohesive, 2); 737 *isCohesive = ds->isCohesive; 738 PetscFunctionReturn(0); 739 } 740 741 /*@ 742 PetscDSGetNumCohesive - Returns the numer of cohesive fields, meaning those defined on the interior of a cohesive cell 743 744 Not collective 745 746 Input Parameter: 747 . ds - The PetscDS object 748 749 Output Parameter: 750 . numCohesive - The number of cohesive fields 751 752 Level: developer 753 754 .seealso: PetscDSSetCohesive(), PetscDSCreate() 755 @*/ 756 PetscErrorCode PetscDSGetNumCohesive(PetscDS ds, PetscInt *numCohesive) 757 { 758 PetscInt f; 759 760 PetscFunctionBegin; 761 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 762 PetscValidPointer(numCohesive, 2); 763 *numCohesive = 0; 764 for (f = 0; f < ds->Nf; ++f) *numCohesive += ds->cohesive[f] ? 1 : 0; 765 PetscFunctionReturn(0); 766 } 767 768 /*@ 769 PetscDSGetCohesive - Returns the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell 770 771 Not collective 772 773 Input Parameter: 774 + ds - The PetscDS object 775 - f - The field index 776 777 Output Parameter: 778 . isCohesive - The flag 779 780 Level: developer 781 782 .seealso: PetscDSSetCohesive(), PetscDSIsCohesive(), PetscDSCreate() 783 @*/ 784 PetscErrorCode PetscDSGetCohesive(PetscDS ds, PetscInt f, PetscBool *isCohesive) 785 { 786 PetscFunctionBegin; 787 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 788 PetscValidPointer(isCohesive, 3); 789 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 790 *isCohesive = ds->cohesive[f]; 791 PetscFunctionReturn(0); 792 } 793 794 /*@ 795 PetscDSSetCohesive - Set the flag indicating that a field is cohesive, meaning it is defined on the interior of a cohesive cell 796 797 Not collective 798 799 Input Parameters: 800 + ds - The PetscDS object 801 . f - The field index 802 - isCohesive - The flag for a cohesive field 803 804 Level: developer 805 806 .seealso: PetscDSGetCohesive(), PetscDSIsCohesive(), PetscDSCreate() 807 @*/ 808 PetscErrorCode PetscDSSetCohesive(PetscDS ds, PetscInt f, PetscBool isCohesive) 809 { 810 PetscInt i; 811 812 PetscFunctionBegin; 813 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 814 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 815 ds->cohesive[f] = isCohesive; 816 ds->isCohesive = PETSC_FALSE; 817 for (i = 0; i < ds->Nf; ++i) ds->isCohesive = ds->isCohesive || ds->cohesive[f] ? PETSC_TRUE : PETSC_FALSE; 818 PetscFunctionReturn(0); 819 } 820 821 /*@ 822 PetscDSGetTotalDimension - Returns the total size of the approximation space for this system 823 824 Not collective 825 826 Input Parameter: 827 . prob - The PetscDS object 828 829 Output Parameter: 830 . dim - The total problem dimension 831 832 Level: beginner 833 834 .seealso: PetscDSGetNumFields(), PetscDSCreate() 835 @*/ 836 PetscErrorCode PetscDSGetTotalDimension(PetscDS prob, PetscInt *dim) 837 { 838 PetscErrorCode ierr; 839 840 PetscFunctionBegin; 841 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 842 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 843 PetscValidPointer(dim, 2); 844 *dim = prob->totDim; 845 PetscFunctionReturn(0); 846 } 847 848 /*@ 849 PetscDSGetTotalComponents - Returns the total number of components in this system 850 851 Not collective 852 853 Input Parameter: 854 . prob - The PetscDS object 855 856 Output Parameter: 857 . dim - The total number of components 858 859 Level: beginner 860 861 .seealso: PetscDSGetNumFields(), PetscDSCreate() 862 @*/ 863 PetscErrorCode PetscDSGetTotalComponents(PetscDS prob, PetscInt *Nc) 864 { 865 PetscErrorCode ierr; 866 867 PetscFunctionBegin; 868 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 869 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 870 PetscValidPointer(Nc, 2); 871 *Nc = prob->totComp; 872 PetscFunctionReturn(0); 873 } 874 875 /*@ 876 PetscDSGetDiscretization - Returns the discretization object for the given field 877 878 Not collective 879 880 Input Parameters: 881 + prob - The PetscDS object 882 - f - The field number 883 884 Output Parameter: 885 . disc - The discretization object 886 887 Level: beginner 888 889 .seealso: PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 890 @*/ 891 PetscErrorCode PetscDSGetDiscretization(PetscDS prob, PetscInt f, PetscObject *disc) 892 { 893 PetscFunctionBeginHot; 894 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 895 PetscValidPointer(disc, 3); 896 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); 897 *disc = prob->disc[f]; 898 PetscFunctionReturn(0); 899 } 900 901 /*@ 902 PetscDSSetDiscretization - Sets the discretization object for the given field 903 904 Not collective 905 906 Input Parameters: 907 + prob - The PetscDS object 908 . f - The field number 909 - disc - The discretization object 910 911 Level: beginner 912 913 .seealso: PetscDSGetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 914 @*/ 915 PetscErrorCode PetscDSSetDiscretization(PetscDS prob, PetscInt f, PetscObject disc) 916 { 917 PetscErrorCode ierr; 918 919 PetscFunctionBegin; 920 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 921 if (disc) PetscValidPointer(disc, 3); 922 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 923 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 924 ierr = PetscObjectDereference(prob->disc[f]);CHKERRQ(ierr); 925 prob->disc[f] = disc; 926 ierr = PetscObjectReference(disc);CHKERRQ(ierr); 927 if (disc) { 928 PetscClassId id; 929 930 ierr = PetscObjectGetClassId(disc, &id);CHKERRQ(ierr); 931 if (id == PETSCFE_CLASSID) { 932 ierr = PetscDSSetImplicit(prob, f, PETSC_TRUE);CHKERRQ(ierr); 933 } else if (id == PETSCFV_CLASSID) { 934 ierr = PetscDSSetImplicit(prob, f, PETSC_FALSE);CHKERRQ(ierr); 935 } 936 ierr = PetscDSSetJetDegree(prob, f, 1);CHKERRQ(ierr); 937 } 938 PetscFunctionReturn(0); 939 } 940 941 /*@ 942 PetscDSGetWeakForm - Returns the weak form object 943 944 Not collective 945 946 Input Parameter: 947 . ds - The PetscDS object 948 949 Output Parameter: 950 . wf - The weak form object 951 952 Level: beginner 953 954 .seealso: PetscDSSetWeakForm(), PetscDSGetNumFields(), PetscDSCreate() 955 @*/ 956 PetscErrorCode PetscDSGetWeakForm(PetscDS ds, PetscWeakForm *wf) 957 { 958 PetscFunctionBegin; 959 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 960 PetscValidPointer(wf, 2); 961 *wf = ds->wf; 962 PetscFunctionReturn(0); 963 } 964 965 /*@ 966 PetscDSSetWeakForm - Sets the weak form object 967 968 Not collective 969 970 Input Parameters: 971 + ds - The PetscDS object 972 - wf - The weak form object 973 974 Level: beginner 975 976 .seealso: PetscDSGetWeakForm(), PetscDSGetNumFields(), PetscDSCreate() 977 @*/ 978 PetscErrorCode PetscDSSetWeakForm(PetscDS ds, PetscWeakForm wf) 979 { 980 PetscErrorCode ierr; 981 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 984 PetscValidHeaderSpecific(wf, PETSCWEAKFORM_CLASSID, 2); 985 ierr = PetscObjectDereference((PetscObject) ds->wf);CHKERRQ(ierr); 986 ds->wf = wf; 987 ierr = PetscObjectReference((PetscObject) wf);CHKERRQ(ierr); 988 ierr = PetscWeakFormSetNumFields(wf, ds->Nf);CHKERRQ(ierr); 989 PetscFunctionReturn(0); 990 } 991 992 /*@ 993 PetscDSAddDiscretization - Adds a discretization object 994 995 Not collective 996 997 Input Parameters: 998 + prob - The PetscDS object 999 - disc - The boundary discretization object 1000 1001 Level: beginner 1002 1003 .seealso: PetscDSGetDiscretization(), PetscDSSetDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1004 @*/ 1005 PetscErrorCode PetscDSAddDiscretization(PetscDS prob, PetscObject disc) 1006 { 1007 PetscErrorCode ierr; 1008 1009 PetscFunctionBegin; 1010 ierr = PetscDSSetDiscretization(prob, prob->Nf, disc);CHKERRQ(ierr); 1011 PetscFunctionReturn(0); 1012 } 1013 1014 /*@ 1015 PetscDSGetQuadrature - Returns the quadrature, which must agree for all fields in the DS 1016 1017 Not collective 1018 1019 Input Parameter: 1020 . prob - The PetscDS object 1021 1022 Output Parameter: 1023 . q - The quadrature object 1024 1025 Level: intermediate 1026 1027 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1028 @*/ 1029 PetscErrorCode PetscDSGetQuadrature(PetscDS prob, PetscQuadrature *q) 1030 { 1031 PetscObject obj; 1032 PetscClassId id; 1033 PetscErrorCode ierr; 1034 1035 PetscFunctionBegin; 1036 *q = NULL; 1037 if (!prob->Nf) PetscFunctionReturn(0); 1038 ierr = PetscDSGetDiscretization(prob, 0, &obj);CHKERRQ(ierr); 1039 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1040 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetQuadrature((PetscFE) obj, q);CHKERRQ(ierr);} 1041 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetQuadrature((PetscFV) obj, q);CHKERRQ(ierr);} 1042 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", 0); 1043 PetscFunctionReturn(0); 1044 } 1045 1046 /*@ 1047 PetscDSGetImplicit - Returns the flag for implicit solve for this field. This is just a guide for IMEX 1048 1049 Not collective 1050 1051 Input Parameters: 1052 + prob - The PetscDS object 1053 - f - The field number 1054 1055 Output Parameter: 1056 . implicit - The flag indicating what kind of solve to use for this field 1057 1058 Level: developer 1059 1060 .seealso: PetscDSSetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1061 @*/ 1062 PetscErrorCode PetscDSGetImplicit(PetscDS prob, PetscInt f, PetscBool *implicit) 1063 { 1064 PetscFunctionBegin; 1065 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1066 PetscValidPointer(implicit, 3); 1067 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); 1068 *implicit = prob->implicit[f]; 1069 PetscFunctionReturn(0); 1070 } 1071 1072 /*@ 1073 PetscDSSetImplicit - Set the flag for implicit solve for this field. This is just a guide for IMEX 1074 1075 Not collective 1076 1077 Input Parameters: 1078 + prob - The PetscDS object 1079 . f - The field number 1080 - implicit - The flag indicating what kind of solve to use for this field 1081 1082 Level: developer 1083 1084 .seealso: PetscDSGetImplicit(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1085 @*/ 1086 PetscErrorCode PetscDSSetImplicit(PetscDS prob, PetscInt f, PetscBool implicit) 1087 { 1088 PetscFunctionBegin; 1089 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1090 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); 1091 prob->implicit[f] = implicit; 1092 PetscFunctionReturn(0); 1093 } 1094 1095 /*@ 1096 PetscDSGetJetDegree - Returns the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate. 1097 1098 Not collective 1099 1100 Input Parameters: 1101 + ds - The PetscDS object 1102 - f - The field number 1103 1104 Output Parameter: 1105 . k - The highest derivative we need to tabulate 1106 1107 Level: developer 1108 1109 .seealso: PetscDSSetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1110 @*/ 1111 PetscErrorCode PetscDSGetJetDegree(PetscDS ds, PetscInt f, PetscInt *k) 1112 { 1113 PetscFunctionBegin; 1114 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1115 PetscValidPointer(k, 3); 1116 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1117 *k = ds->jetDegree[f]; 1118 PetscFunctionReturn(0); 1119 } 1120 1121 /*@ 1122 PetscDSSetJetDegree - Set the highest derivative for this field equation, or the k-jet that the discretization needs to tabulate. 1123 1124 Not collective 1125 1126 Input Parameters: 1127 + ds - The PetscDS object 1128 . f - The field number 1129 - k - The highest derivative we need to tabulate 1130 1131 Level: developer 1132 1133 .seealso: PetscDSGetJetDegree(), PetscDSSetDiscretization(), PetscDSAddDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 1134 @*/ 1135 PetscErrorCode PetscDSSetJetDegree(PetscDS ds, PetscInt f, PetscInt k) 1136 { 1137 PetscFunctionBegin; 1138 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1139 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1140 ds->jetDegree[f] = k; 1141 PetscFunctionReturn(0); 1142 } 1143 1144 PetscErrorCode PetscDSGetObjective(PetscDS ds, PetscInt f, 1145 void (**obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1146 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1147 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1148 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 1149 { 1150 PetscPointFunc *tmp; 1151 PetscInt n; 1152 PetscErrorCode ierr; 1153 1154 PetscFunctionBegin; 1155 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1156 PetscValidPointer(obj, 3); 1157 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1158 ierr = PetscWeakFormGetObjective(ds->wf, NULL, 0, f, 0, &n, &tmp);CHKERRQ(ierr); 1159 *obj = tmp ? tmp[0] : NULL; 1160 PetscFunctionReturn(0); 1161 } 1162 1163 PetscErrorCode PetscDSSetObjective(PetscDS ds, PetscInt f, 1164 void (*obj)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1165 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1166 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1167 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[])) 1168 { 1169 PetscErrorCode ierr; 1170 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1173 if (obj) PetscValidFunction(obj, 3); 1174 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1175 ierr = PetscWeakFormSetIndexObjective(ds->wf, NULL, 0, f, 0, 0, obj);CHKERRQ(ierr); 1176 PetscFunctionReturn(0); 1177 } 1178 1179 /*@C 1180 PetscDSGetResidual - Get the pointwise residual function for a given test field 1181 1182 Not collective 1183 1184 Input Parameters: 1185 + ds - The PetscDS 1186 - f - The test field number 1187 1188 Output Parameters: 1189 + f0 - integrand for the test function term 1190 - f1 - integrand for the test function gradient term 1191 1192 Note: We are using a first order FEM model for the weak form: 1193 1194 \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) 1195 1196 The calling sequence for the callbacks f0 and f1 is given by: 1197 1198 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1199 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1200 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1201 $ PetscReal t, const PetscReal x[], PetscScalar f0[]) 1202 1203 + dim - the spatial dimension 1204 . Nf - the number of fields 1205 . uOff - the offset into u[] and u_t[] for each field 1206 . uOff_x - the offset into u_x[] for each field 1207 . u - each field evaluated at the current point 1208 . u_t - the time derivative of each field evaluated at the current point 1209 . u_x - the gradient of each field evaluated at the current point 1210 . aOff - the offset into a[] and a_t[] for each auxiliary field 1211 . aOff_x - the offset into a_x[] for each auxiliary field 1212 . a - each auxiliary field evaluated at the current point 1213 . a_t - the time derivative of each auxiliary field evaluated at the current point 1214 . a_x - the gradient of auxiliary each field evaluated at the current point 1215 . t - current time 1216 . x - coordinates of the current point 1217 . numConstants - number of constant parameters 1218 . constants - constant parameters 1219 - f0 - output values at the current point 1220 1221 Level: intermediate 1222 1223 .seealso: PetscDSSetResidual() 1224 @*/ 1225 PetscErrorCode PetscDSGetResidual(PetscDS ds, PetscInt f, 1226 void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1227 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1228 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1229 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 1230 void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1231 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1232 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1233 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1234 { 1235 PetscPointFunc *tmp0, *tmp1; 1236 PetscInt n0, n1; 1237 PetscErrorCode ierr; 1238 1239 PetscFunctionBegin; 1240 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1241 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1242 ierr = PetscWeakFormGetResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);CHKERRQ(ierr); 1243 *f0 = tmp0 ? tmp0[0] : NULL; 1244 *f1 = tmp1 ? tmp1[0] : NULL; 1245 PetscFunctionReturn(0); 1246 } 1247 1248 /*@C 1249 PetscDSSetResidual - Set the pointwise residual function for a given test field 1250 1251 Not collective 1252 1253 Input Parameters: 1254 + ds - The PetscDS 1255 . f - The test field number 1256 . f0 - integrand for the test function term 1257 - f1 - integrand for the test function gradient term 1258 1259 Note: We are using a first order FEM model for the weak form: 1260 1261 \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) 1262 1263 The calling sequence for the callbacks f0 and f1 is given by: 1264 1265 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1266 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1267 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1268 $ PetscReal t, const PetscReal x[], PetscScalar f0[]) 1269 1270 + dim - the spatial dimension 1271 . Nf - the number of fields 1272 . uOff - the offset into u[] and u_t[] for each field 1273 . uOff_x - the offset into u_x[] for each field 1274 . u - each field evaluated at the current point 1275 . u_t - the time derivative of each field evaluated at the current point 1276 . u_x - the gradient of each field evaluated at the current point 1277 . aOff - the offset into a[] and a_t[] for each auxiliary field 1278 . aOff_x - the offset into a_x[] for each auxiliary field 1279 . a - each auxiliary field evaluated at the current point 1280 . a_t - the time derivative of each auxiliary field evaluated at the current point 1281 . a_x - the gradient of auxiliary each field evaluated at the current point 1282 . t - current time 1283 . x - coordinates of the current point 1284 . numConstants - number of constant parameters 1285 . constants - constant parameters 1286 - f0 - output values at the current point 1287 1288 Level: intermediate 1289 1290 .seealso: PetscDSGetResidual() 1291 @*/ 1292 PetscErrorCode PetscDSSetResidual(PetscDS ds, PetscInt f, 1293 void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1294 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1295 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1296 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 1297 void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1298 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1299 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1300 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 1301 { 1302 PetscErrorCode ierr; 1303 1304 PetscFunctionBegin; 1305 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1306 if (f0) PetscValidFunction(f0, 3); 1307 if (f1) PetscValidFunction(f1, 4); 1308 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1309 ierr = PetscWeakFormSetIndexResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);CHKERRQ(ierr); 1310 PetscFunctionReturn(0); 1311 } 1312 1313 /*@C 1314 PetscDSHasJacobian - Signals that Jacobian functions have been set 1315 1316 Not collective 1317 1318 Input Parameter: 1319 . prob - The PetscDS 1320 1321 Output Parameter: 1322 . hasJac - flag that pointwise function for the Jacobian has been set 1323 1324 Level: intermediate 1325 1326 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1327 @*/ 1328 PetscErrorCode PetscDSHasJacobian(PetscDS ds, PetscBool *hasJac) 1329 { 1330 PetscErrorCode ierr; 1331 1332 PetscFunctionBegin; 1333 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1334 ierr = PetscWeakFormHasJacobian(ds->wf, hasJac);CHKERRQ(ierr); 1335 PetscFunctionReturn(0); 1336 } 1337 1338 /*@C 1339 PetscDSGetJacobian - Get the pointwise Jacobian function for given test and basis field 1340 1341 Not collective 1342 1343 Input Parameters: 1344 + ds - The PetscDS 1345 . f - The test field number 1346 - g - The field number 1347 1348 Output Parameters: 1349 + g0 - integrand for the test and basis function term 1350 . g1 - integrand for the test function and basis function gradient term 1351 . g2 - integrand for the test function gradient and basis function term 1352 - g3 - integrand for the test function gradient and basis function gradient term 1353 1354 Note: We are using a first order FEM model for the weak form: 1355 1356 \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 1357 1358 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1359 1360 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1361 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1362 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1363 $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1364 1365 + dim - the spatial dimension 1366 . Nf - the number of fields 1367 . uOff - the offset into u[] and u_t[] for each field 1368 . uOff_x - the offset into u_x[] for each field 1369 . u - each field evaluated at the current point 1370 . u_t - the time derivative of each field evaluated at the current point 1371 . u_x - the gradient of each field evaluated at the current point 1372 . aOff - the offset into a[] and a_t[] for each auxiliary field 1373 . aOff_x - the offset into a_x[] for each auxiliary field 1374 . a - each auxiliary field evaluated at the current point 1375 . a_t - the time derivative of each auxiliary field evaluated at the current point 1376 . a_x - the gradient of auxiliary each field evaluated at the current point 1377 . t - current time 1378 . u_tShift - the multiplier a for dF/dU_t 1379 . x - coordinates of the current point 1380 . numConstants - number of constant parameters 1381 . constants - constant parameters 1382 - g0 - output values at the current point 1383 1384 Level: intermediate 1385 1386 .seealso: PetscDSSetJacobian() 1387 @*/ 1388 PetscErrorCode PetscDSGetJacobian(PetscDS ds, PetscInt f, PetscInt g, 1389 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1390 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1391 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1392 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1393 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1394 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1395 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1396 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1397 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1398 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1399 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1400 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1401 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1402 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1403 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1404 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1405 { 1406 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1407 PetscInt n0, n1, n2, n3; 1408 PetscErrorCode ierr; 1409 1410 PetscFunctionBegin; 1411 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1412 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1413 if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf); 1414 ierr = PetscWeakFormGetJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr); 1415 *g0 = tmp0 ? tmp0[0] : NULL; 1416 *g1 = tmp1 ? tmp1[0] : NULL; 1417 *g2 = tmp2 ? tmp2[0] : NULL; 1418 *g3 = tmp3 ? tmp3[0] : NULL; 1419 PetscFunctionReturn(0); 1420 } 1421 1422 /*@C 1423 PetscDSSetJacobian - Set the pointwise Jacobian function for given test and basis fields 1424 1425 Not collective 1426 1427 Input Parameters: 1428 + ds - The PetscDS 1429 . f - The test field number 1430 . g - The field number 1431 . g0 - integrand for the test and basis function term 1432 . g1 - integrand for the test function and basis function gradient term 1433 . g2 - integrand for the test function gradient and basis function term 1434 - g3 - integrand for the test function gradient and basis function gradient term 1435 1436 Note: We are using a first order FEM model for the weak form: 1437 1438 \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 1439 1440 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1441 1442 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1443 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1444 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1445 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1446 1447 + dim - the spatial dimension 1448 . Nf - the number of fields 1449 . uOff - the offset into u[] and u_t[] for each field 1450 . uOff_x - the offset into u_x[] for each field 1451 . u - each field evaluated at the current point 1452 . u_t - the time derivative of each field evaluated at the current point 1453 . u_x - the gradient of each field evaluated at the current point 1454 . aOff - the offset into a[] and a_t[] for each auxiliary field 1455 . aOff_x - the offset into a_x[] for each auxiliary field 1456 . a - each auxiliary field evaluated at the current point 1457 . a_t - the time derivative of each auxiliary field evaluated at the current point 1458 . a_x - the gradient of auxiliary each field evaluated at the current point 1459 . t - current time 1460 . u_tShift - the multiplier a for dF/dU_t 1461 . x - coordinates of the current point 1462 . numConstants - number of constant parameters 1463 . constants - constant parameters 1464 - g0 - output values at the current point 1465 1466 Level: intermediate 1467 1468 .seealso: PetscDSGetJacobian() 1469 @*/ 1470 PetscErrorCode PetscDSSetJacobian(PetscDS ds, PetscInt f, PetscInt g, 1471 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1472 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1473 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1474 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1475 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1476 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1477 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1478 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1479 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1480 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1481 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1482 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1483 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1484 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1485 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1486 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1487 { 1488 PetscErrorCode ierr; 1489 1490 PetscFunctionBegin; 1491 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1492 if (g0) PetscValidFunction(g0, 4); 1493 if (g1) PetscValidFunction(g1, 5); 1494 if (g2) PetscValidFunction(g2, 6); 1495 if (g3) PetscValidFunction(g3, 7); 1496 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1497 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1498 ierr = PetscWeakFormSetIndexJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr); 1499 PetscFunctionReturn(0); 1500 } 1501 1502 /*@C 1503 PetscDSUseJacobianPreconditioner - Whether to construct a Jacobian preconditioner 1504 1505 Not collective 1506 1507 Input Parameters: 1508 + prob - The PetscDS 1509 - useJacPre - flag that enables construction of a Jacobian preconditioner 1510 1511 Level: intermediate 1512 1513 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1514 @*/ 1515 PetscErrorCode PetscDSUseJacobianPreconditioner(PetscDS prob, PetscBool useJacPre) 1516 { 1517 PetscFunctionBegin; 1518 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 1519 prob->useJacPre = useJacPre; 1520 PetscFunctionReturn(0); 1521 } 1522 1523 /*@C 1524 PetscDSHasJacobianPreconditioner - Signals that a Jacobian preconditioner matrix has been set 1525 1526 Not collective 1527 1528 Input Parameter: 1529 . prob - The PetscDS 1530 1531 Output Parameter: 1532 . hasJacPre - flag that pointwise function for Jacobian preconditioner matrix has been set 1533 1534 Level: intermediate 1535 1536 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1537 @*/ 1538 PetscErrorCode PetscDSHasJacobianPreconditioner(PetscDS ds, PetscBool *hasJacPre) 1539 { 1540 PetscErrorCode ierr; 1541 1542 PetscFunctionBegin; 1543 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1544 *hasJacPre = PETSC_FALSE; 1545 if (!ds->useJacPre) PetscFunctionReturn(0); 1546 ierr = PetscWeakFormHasJacobianPreconditioner(ds->wf, hasJacPre);CHKERRQ(ierr); 1547 PetscFunctionReturn(0); 1548 } 1549 1550 /*@C 1551 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. 1552 1553 Not collective 1554 1555 Input Parameters: 1556 + ds - The PetscDS 1557 . f - The test field number 1558 - g - The field number 1559 1560 Output Parameters: 1561 + g0 - integrand for the test and basis function term 1562 . g1 - integrand for the test function and basis function gradient term 1563 . g2 - integrand for the test function gradient and basis function term 1564 - g3 - integrand for the test function gradient and basis function gradient term 1565 1566 Note: We are using a first order FEM model for the weak form: 1567 1568 \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 1569 1570 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1571 1572 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1573 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1574 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1575 $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1576 1577 + dim - the spatial dimension 1578 . Nf - the number of fields 1579 . uOff - the offset into u[] and u_t[] for each field 1580 . uOff_x - the offset into u_x[] for each field 1581 . u - each field evaluated at the current point 1582 . u_t - the time derivative of each field evaluated at the current point 1583 . u_x - the gradient of each field evaluated at the current point 1584 . aOff - the offset into a[] and a_t[] for each auxiliary field 1585 . aOff_x - the offset into a_x[] for each auxiliary field 1586 . a - each auxiliary field evaluated at the current point 1587 . a_t - the time derivative of each auxiliary field evaluated at the current point 1588 . a_x - the gradient of auxiliary each field evaluated at the current point 1589 . t - current time 1590 . u_tShift - the multiplier a for dF/dU_t 1591 . x - coordinates of the current point 1592 . numConstants - number of constant parameters 1593 . constants - constant parameters 1594 - g0 - output values at the current point 1595 1596 Level: intermediate 1597 1598 .seealso: PetscDSSetJacobianPreconditioner(), PetscDSGetJacobian() 1599 @*/ 1600 PetscErrorCode PetscDSGetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, 1601 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1602 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1603 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1604 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1605 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1606 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1607 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1608 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1609 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1610 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1611 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1612 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1613 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1614 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1615 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1616 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1617 { 1618 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1619 PetscInt n0, n1, n2, n3; 1620 PetscErrorCode ierr; 1621 1622 PetscFunctionBegin; 1623 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1624 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1625 if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf); 1626 ierr = PetscWeakFormGetJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr); 1627 *g0 = tmp0 ? tmp0[0] : NULL; 1628 *g1 = tmp1 ? tmp1[0] : NULL; 1629 *g2 = tmp2 ? tmp2[0] : NULL; 1630 *g3 = tmp3 ? tmp3[0] : NULL; 1631 PetscFunctionReturn(0); 1632 } 1633 1634 /*@C 1635 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. 1636 1637 Not collective 1638 1639 Input Parameters: 1640 + ds - The PetscDS 1641 . f - The test field number 1642 . g - The field number 1643 . g0 - integrand for the test and basis function term 1644 . g1 - integrand for the test function and basis function gradient term 1645 . g2 - integrand for the test function gradient and basis function term 1646 - g3 - integrand for the test function gradient and basis function gradient term 1647 1648 Note: We are using a first order FEM model for the weak form: 1649 1650 \int_\Omega \phi g_0(u, u_t, \nabla u, x, t) \psi + \phi {\vec g}_1(u, u_t, \nabla u, x, t) \nabla \psi + \nabla\phi \cdot {\vec g}_2(u, u_t, \nabla u, x, t) \psi + \nabla\phi \cdot {\overleftrightarrow g}_3(u, u_t, \nabla u, x, t) \cdot \nabla \psi 1651 1652 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1653 1654 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1655 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1656 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1657 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1658 1659 + dim - the spatial dimension 1660 . Nf - the number of fields 1661 . uOff - the offset into u[] and u_t[] for each field 1662 . uOff_x - the offset into u_x[] for each field 1663 . u - each field evaluated at the current point 1664 . u_t - the time derivative of each field evaluated at the current point 1665 . u_x - the gradient of each field evaluated at the current point 1666 . aOff - the offset into a[] and a_t[] for each auxiliary field 1667 . aOff_x - the offset into a_x[] for each auxiliary field 1668 . a - each auxiliary field evaluated at the current point 1669 . a_t - the time derivative of each auxiliary field evaluated at the current point 1670 . a_x - the gradient of auxiliary each field evaluated at the current point 1671 . t - current time 1672 . u_tShift - the multiplier a for dF/dU_t 1673 . x - coordinates of the current point 1674 . numConstants - number of constant parameters 1675 . constants - constant parameters 1676 - g0 - output values at the current point 1677 1678 Level: intermediate 1679 1680 .seealso: PetscDSGetJacobianPreconditioner(), PetscDSSetJacobian() 1681 @*/ 1682 PetscErrorCode PetscDSSetJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, 1683 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1684 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1685 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1686 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1687 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1688 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1689 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1690 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1691 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1692 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1693 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1694 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1695 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1696 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1697 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1698 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1699 { 1700 PetscErrorCode ierr; 1701 1702 PetscFunctionBegin; 1703 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1704 if (g0) PetscValidFunction(g0, 4); 1705 if (g1) PetscValidFunction(g1, 5); 1706 if (g2) PetscValidFunction(g2, 6); 1707 if (g3) PetscValidFunction(g3, 7); 1708 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1709 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1710 ierr = PetscWeakFormSetIndexJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr); 1711 PetscFunctionReturn(0); 1712 } 1713 1714 /*@C 1715 PetscDSHasDynamicJacobian - Signals that a dynamic Jacobian, dF/du_t, has been set 1716 1717 Not collective 1718 1719 Input Parameter: 1720 . ds - The PetscDS 1721 1722 Output Parameter: 1723 . hasDynJac - flag that pointwise function for dynamic Jacobian has been set 1724 1725 Level: intermediate 1726 1727 .seealso: PetscDSGetDynamicJacobian(), PetscDSSetDynamicJacobian(), PetscDSGetJacobian() 1728 @*/ 1729 PetscErrorCode PetscDSHasDynamicJacobian(PetscDS ds, PetscBool *hasDynJac) 1730 { 1731 PetscErrorCode ierr; 1732 1733 PetscFunctionBegin; 1734 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1735 ierr = PetscWeakFormHasDynamicJacobian(ds->wf, hasDynJac);CHKERRQ(ierr); 1736 PetscFunctionReturn(0); 1737 } 1738 1739 /*@C 1740 PetscDSGetDynamicJacobian - Get the pointwise dynamic Jacobian, dF/du_t, function for given test and basis field 1741 1742 Not collective 1743 1744 Input Parameters: 1745 + ds - The PetscDS 1746 . f - The test field number 1747 - g - The field number 1748 1749 Output Parameters: 1750 + g0 - integrand for the test and basis function term 1751 . g1 - integrand for the test function and basis function gradient term 1752 . g2 - integrand for the test function gradient and basis function term 1753 - g3 - integrand for the test function gradient and basis function gradient term 1754 1755 Note: We are using a first order FEM model for the weak form: 1756 1757 \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 1758 1759 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1760 1761 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1762 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1763 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1764 $ PetscReal t, const PetscReal u_tShift, const PetscReal x[], PetscScalar g0[]) 1765 1766 + dim - the spatial dimension 1767 . Nf - the number of fields 1768 . uOff - the offset into u[] and u_t[] for each field 1769 . uOff_x - the offset into u_x[] for each field 1770 . u - each field evaluated at the current point 1771 . u_t - the time derivative of each field evaluated at the current point 1772 . u_x - the gradient of each field evaluated at the current point 1773 . aOff - the offset into a[] and a_t[] for each auxiliary field 1774 . aOff_x - the offset into a_x[] for each auxiliary field 1775 . a - each auxiliary field evaluated at the current point 1776 . a_t - the time derivative of each auxiliary field evaluated at the current point 1777 . a_x - the gradient of auxiliary each field evaluated at the current point 1778 . t - current time 1779 . u_tShift - the multiplier a for dF/dU_t 1780 . x - coordinates of the current point 1781 . numConstants - number of constant parameters 1782 . constants - constant parameters 1783 - g0 - output values at the current point 1784 1785 Level: intermediate 1786 1787 .seealso: PetscDSSetJacobian() 1788 @*/ 1789 PetscErrorCode PetscDSGetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, 1790 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1791 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1792 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1793 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1794 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1795 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1796 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1797 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1798 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1799 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1800 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1801 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1802 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1803 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1804 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1805 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1806 { 1807 PetscPointJac *tmp0, *tmp1, *tmp2, *tmp3; 1808 PetscInt n0, n1, n2, n3; 1809 PetscErrorCode ierr; 1810 1811 PetscFunctionBegin; 1812 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1813 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1814 if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf); 1815 ierr = PetscWeakFormGetDynamicJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr); 1816 *g0 = tmp0 ? tmp0[0] : NULL; 1817 *g1 = tmp1 ? tmp1[0] : NULL; 1818 *g2 = tmp2 ? tmp2[0] : NULL; 1819 *g3 = tmp3 ? tmp3[0] : NULL; 1820 PetscFunctionReturn(0); 1821 } 1822 1823 /*@C 1824 PetscDSSetDynamicJacobian - Set the pointwise dynamic Jacobian, dF/du_t, function for given test and basis fields 1825 1826 Not collective 1827 1828 Input Parameters: 1829 + ds - The PetscDS 1830 . f - The test field number 1831 . g - The field number 1832 . g0 - integrand for the test and basis function term 1833 . g1 - integrand for the test function and basis function gradient term 1834 . g2 - integrand for the test function gradient and basis function term 1835 - g3 - integrand for the test function gradient and basis function gradient term 1836 1837 Note: We are using a first order FEM model for the weak form: 1838 1839 \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 1840 1841 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 1842 1843 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1844 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1845 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1846 $ PetscReal t, const PetscReal x[], PetscScalar g0[]) 1847 1848 + dim - the spatial dimension 1849 . Nf - the number of fields 1850 . uOff - the offset into u[] and u_t[] for each field 1851 . uOff_x - the offset into u_x[] for each field 1852 . u - each field evaluated at the current point 1853 . u_t - the time derivative of each field evaluated at the current point 1854 . u_x - the gradient of each field evaluated at the current point 1855 . aOff - the offset into a[] and a_t[] for each auxiliary field 1856 . aOff_x - the offset into a_x[] for each auxiliary field 1857 . a - each auxiliary field evaluated at the current point 1858 . a_t - the time derivative of each auxiliary field evaluated at the current point 1859 . a_x - the gradient of auxiliary each field evaluated at the current point 1860 . t - current time 1861 . u_tShift - the multiplier a for dF/dU_t 1862 . x - coordinates of the current point 1863 . numConstants - number of constant parameters 1864 . constants - constant parameters 1865 - g0 - output values at the current point 1866 1867 Level: intermediate 1868 1869 .seealso: PetscDSGetJacobian() 1870 @*/ 1871 PetscErrorCode PetscDSSetDynamicJacobian(PetscDS ds, PetscInt f, PetscInt g, 1872 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1873 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1874 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1875 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 1876 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1877 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1878 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1879 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 1880 void (*g2)(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, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 1884 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 1885 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 1886 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 1887 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 1888 { 1889 PetscErrorCode ierr; 1890 1891 PetscFunctionBegin; 1892 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1893 if (g0) PetscValidFunction(g0, 4); 1894 if (g1) PetscValidFunction(g1, 5); 1895 if (g2) PetscValidFunction(g2, 6); 1896 if (g3) PetscValidFunction(g3, 7); 1897 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1898 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 1899 ierr = PetscWeakFormSetIndexDynamicJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr); 1900 PetscFunctionReturn(0); 1901 } 1902 1903 /*@C 1904 PetscDSGetRiemannSolver - Returns the Riemann solver for the given field 1905 1906 Not collective 1907 1908 Input Parameters: 1909 + ds - The PetscDS object 1910 - f - The field number 1911 1912 Output Parameter: 1913 . r - Riemann solver 1914 1915 Calling sequence for r: 1916 1917 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 1918 1919 + dim - The spatial dimension 1920 . Nf - The number of fields 1921 . x - The coordinates at a point on the interface 1922 . n - The normal vector to the interface 1923 . uL - The state vector to the left of the interface 1924 . uR - The state vector to the right of the interface 1925 . flux - output array of flux through the interface 1926 . numConstants - number of constant parameters 1927 . constants - constant parameters 1928 - ctx - optional user context 1929 1930 Level: intermediate 1931 1932 .seealso: PetscDSSetRiemannSolver() 1933 @*/ 1934 PetscErrorCode PetscDSGetRiemannSolver(PetscDS ds, PetscInt f, 1935 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)) 1936 { 1937 PetscRiemannFunc *tmp; 1938 PetscInt n; 1939 PetscErrorCode ierr; 1940 1941 PetscFunctionBegin; 1942 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1943 PetscValidPointer(r, 3); 1944 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 1945 ierr = PetscWeakFormGetRiemannSolver(ds->wf, NULL, 0, f, 0, &n, &tmp);CHKERRQ(ierr); 1946 *r = tmp ? tmp[0] : NULL; 1947 PetscFunctionReturn(0); 1948 } 1949 1950 /*@C 1951 PetscDSSetRiemannSolver - Sets the Riemann solver for the given field 1952 1953 Not collective 1954 1955 Input Parameters: 1956 + ds - The PetscDS object 1957 . f - The field number 1958 - r - Riemann solver 1959 1960 Calling sequence for r: 1961 1962 $ r(PetscInt dim, PetscInt Nf, const PetscReal x[], const PetscReal n[], const PetscScalar uL[], const PetscScalar uR[], PetscScalar flux[], void *ctx) 1963 1964 + dim - The spatial dimension 1965 . Nf - The number of fields 1966 . x - The coordinates at a point on the interface 1967 . n - The normal vector to the interface 1968 . uL - The state vector to the left of the interface 1969 . uR - The state vector to the right of the interface 1970 . flux - output array of flux through the interface 1971 . numConstants - number of constant parameters 1972 . constants - constant parameters 1973 - ctx - optional user context 1974 1975 Level: intermediate 1976 1977 .seealso: PetscDSGetRiemannSolver() 1978 @*/ 1979 PetscErrorCode PetscDSSetRiemannSolver(PetscDS ds, PetscInt f, 1980 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)) 1981 { 1982 PetscErrorCode ierr; 1983 1984 PetscFunctionBegin; 1985 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 1986 if (r) PetscValidFunction(r, 3); 1987 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 1988 ierr = PetscWeakFormSetIndexRiemannSolver(ds->wf, NULL, 0, f, 0, 0, r);CHKERRQ(ierr); 1989 PetscFunctionReturn(0); 1990 } 1991 1992 /*@C 1993 PetscDSGetUpdate - Get the pointwise update function for a given field 1994 1995 Not collective 1996 1997 Input Parameters: 1998 + ds - The PetscDS 1999 - f - The field number 2000 2001 Output Parameter: 2002 . update - update function 2003 2004 Note: The calling sequence for the callback update is given by: 2005 2006 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2007 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2008 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2009 $ PetscReal t, const PetscReal x[], PetscScalar uNew[]) 2010 2011 + dim - the spatial dimension 2012 . Nf - the number of fields 2013 . uOff - the offset into u[] and u_t[] for each field 2014 . uOff_x - the offset into u_x[] for each field 2015 . u - each field evaluated at the current point 2016 . u_t - the time derivative of each field evaluated at the current point 2017 . u_x - the gradient of each field evaluated at the current point 2018 . aOff - the offset into a[] and a_t[] for each auxiliary field 2019 . aOff_x - the offset into a_x[] for each auxiliary field 2020 . a - each auxiliary field evaluated at the current point 2021 . a_t - the time derivative of each auxiliary field evaluated at the current point 2022 . a_x - the gradient of auxiliary each field evaluated at the current point 2023 . t - current time 2024 . x - coordinates of the current point 2025 - uNew - new value for field at the current point 2026 2027 Level: intermediate 2028 2029 .seealso: PetscDSSetUpdate(), PetscDSSetResidual() 2030 @*/ 2031 PetscErrorCode PetscDSGetUpdate(PetscDS ds, PetscInt f, 2032 void (**update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2033 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2034 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2035 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 2036 { 2037 PetscFunctionBegin; 2038 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2039 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2040 if (update) {PetscValidPointer(update, 3); *update = ds->update[f];} 2041 PetscFunctionReturn(0); 2042 } 2043 2044 /*@C 2045 PetscDSSetUpdate - Set the pointwise update function for a given field 2046 2047 Not collective 2048 2049 Input Parameters: 2050 + ds - The PetscDS 2051 . f - The field number 2052 - update - update function 2053 2054 Note: The calling sequence for the callback update is given by: 2055 2056 $ update(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2057 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2058 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2059 $ PetscReal t, const PetscReal x[], PetscScalar uNew[]) 2060 2061 + dim - the spatial dimension 2062 . Nf - the number of fields 2063 . uOff - the offset into u[] and u_t[] for each field 2064 . uOff_x - the offset into u_x[] for each field 2065 . u - each field evaluated at the current point 2066 . u_t - the time derivative of each field evaluated at the current point 2067 . u_x - the gradient of each field evaluated at the current point 2068 . aOff - the offset into a[] and a_t[] for each auxiliary field 2069 . aOff_x - the offset into a_x[] for each auxiliary field 2070 . a - each auxiliary field evaluated at the current point 2071 . a_t - the time derivative of each auxiliary field evaluated at the current point 2072 . a_x - the gradient of auxiliary each field evaluated at the current point 2073 . t - current time 2074 . x - coordinates of the current point 2075 - uNew - new field values at the current point 2076 2077 Level: intermediate 2078 2079 .seealso: PetscDSGetResidual() 2080 @*/ 2081 PetscErrorCode PetscDSSetUpdate(PetscDS ds, PetscInt f, 2082 void (*update)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2083 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2084 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2085 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar uNew[])) 2086 { 2087 PetscErrorCode ierr; 2088 2089 PetscFunctionBegin; 2090 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2091 if (update) PetscValidFunction(update, 3); 2092 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2093 ierr = PetscDSEnlarge_Static(ds, f+1);CHKERRQ(ierr); 2094 ds->update[f] = update; 2095 PetscFunctionReturn(0); 2096 } 2097 2098 PetscErrorCode PetscDSGetContext(PetscDS ds, PetscInt f, void *ctx) 2099 { 2100 PetscFunctionBegin; 2101 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2102 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2103 PetscValidPointer(ctx, 3); 2104 *(void**)ctx = ds->ctx[f]; 2105 PetscFunctionReturn(0); 2106 } 2107 2108 PetscErrorCode PetscDSSetContext(PetscDS ds, PetscInt f, void *ctx) 2109 { 2110 PetscErrorCode ierr; 2111 2112 PetscFunctionBegin; 2113 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2114 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2115 ierr = PetscDSEnlarge_Static(ds, f+1);CHKERRQ(ierr); 2116 ds->ctx[f] = ctx; 2117 PetscFunctionReturn(0); 2118 } 2119 2120 /*@C 2121 PetscDSGetBdResidual - Get the pointwise boundary residual function for a given test field 2122 2123 Not collective 2124 2125 Input Parameters: 2126 + ds - The PetscDS 2127 - f - The test field number 2128 2129 Output Parameters: 2130 + f0 - boundary integrand for the test function term 2131 - f1 - boundary integrand for the test function gradient term 2132 2133 Note: We are using a first order FEM model for the weak form: 2134 2135 \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 2136 2137 The calling sequence for the callbacks f0 and f1 is given by: 2138 2139 $ f0(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, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 2143 2144 + dim - the spatial dimension 2145 . Nf - the number of fields 2146 . uOff - the offset into u[] and u_t[] for each field 2147 . uOff_x - the offset into u_x[] for each field 2148 . u - each field evaluated at the current point 2149 . u_t - the time derivative of each field evaluated at the current point 2150 . u_x - the gradient of each field evaluated at the current point 2151 . aOff - the offset into a[] and a_t[] for each auxiliary field 2152 . aOff_x - the offset into a_x[] for each auxiliary field 2153 . a - each auxiliary field evaluated at the current point 2154 . a_t - the time derivative of each auxiliary field evaluated at the current point 2155 . a_x - the gradient of auxiliary each field evaluated at the current point 2156 . t - current time 2157 . x - coordinates of the current point 2158 . n - unit normal at the current point 2159 . numConstants - number of constant parameters 2160 . constants - constant parameters 2161 - f0 - output values at the current point 2162 2163 Level: intermediate 2164 2165 .seealso: PetscDSSetBdResidual() 2166 @*/ 2167 PetscErrorCode PetscDSGetBdResidual(PetscDS ds, PetscInt f, 2168 void (**f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2169 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2170 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2171 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 2172 void (**f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2173 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2174 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2175 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 2176 { 2177 PetscBdPointFunc *tmp0, *tmp1; 2178 PetscInt n0, n1; 2179 PetscErrorCode ierr; 2180 2181 PetscFunctionBegin; 2182 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2183 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2184 ierr = PetscWeakFormGetBdResidual(ds->wf, NULL, 0, f, 0, &n0, &tmp0, &n1, &tmp1);CHKERRQ(ierr); 2185 *f0 = tmp0 ? tmp0[0] : NULL; 2186 *f1 = tmp1 ? tmp1[0] : NULL; 2187 PetscFunctionReturn(0); 2188 } 2189 2190 /*@C 2191 PetscDSSetBdResidual - Get the pointwise boundary residual function for a given test field 2192 2193 Not collective 2194 2195 Input Parameters: 2196 + ds - The PetscDS 2197 . f - The test field number 2198 . f0 - boundary integrand for the test function term 2199 - f1 - boundary integrand for the test function gradient term 2200 2201 Note: We are using a first order FEM model for the weak form: 2202 2203 \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 2204 2205 The calling sequence for the callbacks f0 and f1 is given by: 2206 2207 $ f0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2208 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2209 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2210 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar f0[]) 2211 2212 + dim - the spatial dimension 2213 . Nf - the number of fields 2214 . uOff - the offset into u[] and u_t[] for each field 2215 . uOff_x - the offset into u_x[] for each field 2216 . u - each field evaluated at the current point 2217 . u_t - the time derivative of each field evaluated at the current point 2218 . u_x - the gradient of each field evaluated at the current point 2219 . aOff - the offset into a[] and a_t[] for each auxiliary field 2220 . aOff_x - the offset into a_x[] for each auxiliary field 2221 . a - each auxiliary field evaluated at the current point 2222 . a_t - the time derivative of each auxiliary field evaluated at the current point 2223 . a_x - the gradient of auxiliary each field evaluated at the current point 2224 . t - current time 2225 . x - coordinates of the current point 2226 . n - unit normal at the current point 2227 . numConstants - number of constant parameters 2228 . constants - constant parameters 2229 - f0 - output values at the current point 2230 2231 Level: intermediate 2232 2233 .seealso: PetscDSGetBdResidual() 2234 @*/ 2235 PetscErrorCode PetscDSSetBdResidual(PetscDS ds, PetscInt f, 2236 void (*f0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2237 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2238 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2239 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]), 2240 void (*f1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2241 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2242 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2243 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[])) 2244 { 2245 PetscErrorCode ierr; 2246 2247 PetscFunctionBegin; 2248 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2249 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2250 ierr = PetscWeakFormSetIndexBdResidual(ds->wf, NULL, 0, f, 0, 0, f0, 0, f1);CHKERRQ(ierr); 2251 PetscFunctionReturn(0); 2252 } 2253 2254 /*@ 2255 PetscDSHasBdJacobian - Signals that boundary Jacobian functions have been set 2256 2257 Not collective 2258 2259 Input Parameter: 2260 . ds - The PetscDS 2261 2262 Output Parameter: 2263 . hasBdJac - flag that pointwise function for the boundary Jacobian has been set 2264 2265 Level: intermediate 2266 2267 .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian() 2268 @*/ 2269 PetscErrorCode PetscDSHasBdJacobian(PetscDS ds, PetscBool *hasBdJac) 2270 { 2271 PetscErrorCode ierr; 2272 2273 PetscFunctionBegin; 2274 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2275 PetscValidBoolPointer(hasBdJac, 2); 2276 ierr = PetscWeakFormHasBdJacobian(ds->wf, hasBdJac);CHKERRQ(ierr); 2277 PetscFunctionReturn(0); 2278 } 2279 2280 /*@C 2281 PetscDSGetBdJacobian - Get the pointwise boundary Jacobian function for given test and basis field 2282 2283 Not collective 2284 2285 Input Parameters: 2286 + ds - The PetscDS 2287 . f - The test field number 2288 - g - The field number 2289 2290 Output Parameters: 2291 + g0 - integrand for the test and basis function term 2292 . g1 - integrand for the test function and basis function gradient term 2293 . g2 - integrand for the test function gradient and basis function term 2294 - g3 - integrand for the test function gradient and basis function gradient term 2295 2296 Note: We are using a first order FEM model for the weak form: 2297 2298 \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 2299 2300 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2301 2302 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2303 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2304 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2305 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2306 2307 + dim - the spatial dimension 2308 . Nf - the number of fields 2309 . uOff - the offset into u[] and u_t[] for each field 2310 . uOff_x - the offset into u_x[] for each field 2311 . u - each field evaluated at the current point 2312 . u_t - the time derivative of each field evaluated at the current point 2313 . u_x - the gradient of each field evaluated at the current point 2314 . aOff - the offset into a[] and a_t[] for each auxiliary field 2315 . aOff_x - the offset into a_x[] for each auxiliary field 2316 . a - each auxiliary field evaluated at the current point 2317 . a_t - the time derivative of each auxiliary field evaluated at the current point 2318 . a_x - the gradient of auxiliary each field evaluated at the current point 2319 . t - current time 2320 . u_tShift - the multiplier a for dF/dU_t 2321 . x - coordinates of the current point 2322 . n - normal at the current point 2323 . numConstants - number of constant parameters 2324 . constants - constant parameters 2325 - g0 - output values at the current point 2326 2327 Level: intermediate 2328 2329 .seealso: PetscDSSetBdJacobian() 2330 @*/ 2331 PetscErrorCode PetscDSGetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, 2332 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2333 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2334 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2335 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2336 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2337 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2338 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2339 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2340 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2341 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2342 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2343 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2344 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2345 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2346 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2347 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2348 { 2349 PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3; 2350 PetscInt n0, n1, n2, n3; 2351 PetscErrorCode ierr; 2352 2353 PetscFunctionBegin; 2354 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2355 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2356 if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf); 2357 ierr = PetscWeakFormGetBdJacobian(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr); 2358 *g0 = tmp0 ? tmp0[0] : NULL; 2359 *g1 = tmp1 ? tmp1[0] : NULL; 2360 *g2 = tmp2 ? tmp2[0] : NULL; 2361 *g3 = tmp3 ? tmp3[0] : NULL; 2362 PetscFunctionReturn(0); 2363 } 2364 2365 /*@C 2366 PetscDSSetBdJacobian - Set the pointwise boundary Jacobian function for given test and basis field 2367 2368 Not collective 2369 2370 Input Parameters: 2371 + ds - The PetscDS 2372 . f - The test field number 2373 . g - The field number 2374 . g0 - integrand for the test and basis function term 2375 . g1 - integrand for the test function and basis function gradient term 2376 . g2 - integrand for the test function gradient and basis function term 2377 - g3 - integrand for the test function gradient and basis function gradient term 2378 2379 Note: We are using a first order FEM model for the weak form: 2380 2381 \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 2382 2383 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2384 2385 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2386 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2387 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2388 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscScalar g0[]) 2389 2390 + dim - the spatial dimension 2391 . Nf - the number of fields 2392 . uOff - the offset into u[] and u_t[] for each field 2393 . uOff_x - the offset into u_x[] for each field 2394 . u - each field evaluated at the current point 2395 . u_t - the time derivative of each field evaluated at the current point 2396 . u_x - the gradient of each field evaluated at the current point 2397 . aOff - the offset into a[] and a_t[] for each auxiliary field 2398 . aOff_x - the offset into a_x[] for each auxiliary field 2399 . a - each auxiliary field evaluated at the current point 2400 . a_t - the time derivative of each auxiliary field evaluated at the current point 2401 . a_x - the gradient of auxiliary each field evaluated at the current point 2402 . t - current time 2403 . u_tShift - the multiplier a for dF/dU_t 2404 . x - coordinates of the current point 2405 . n - normal at the current point 2406 . numConstants - number of constant parameters 2407 . constants - constant parameters 2408 - g0 - output values at the current point 2409 2410 Level: intermediate 2411 2412 .seealso: PetscDSGetBdJacobian() 2413 @*/ 2414 PetscErrorCode PetscDSSetBdJacobian(PetscDS ds, PetscInt f, PetscInt g, 2415 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2416 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2417 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2418 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2419 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2420 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2421 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2422 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2423 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2424 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2425 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2426 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2427 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2428 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2429 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2430 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2431 { 2432 PetscErrorCode ierr; 2433 2434 PetscFunctionBegin; 2435 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2436 if (g0) PetscValidFunction(g0, 4); 2437 if (g1) PetscValidFunction(g1, 5); 2438 if (g2) PetscValidFunction(g2, 6); 2439 if (g3) PetscValidFunction(g3, 7); 2440 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2441 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 2442 ierr = PetscWeakFormSetIndexBdJacobian(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr); 2443 PetscFunctionReturn(0); 2444 } 2445 2446 /*@ 2447 PetscDSHasBdJacobianPreconditioner - Signals that boundary Jacobian preconditioner functions have been set 2448 2449 Not collective 2450 2451 Input Parameter: 2452 . ds - The PetscDS 2453 2454 Output Parameter: 2455 . hasBdJac - flag that pointwise function for the boundary Jacobian preconditioner has been set 2456 2457 Level: intermediate 2458 2459 .seealso: PetscDSHasJacobian(), PetscDSSetBdJacobian(), PetscDSGetBdJacobian() 2460 @*/ 2461 PetscErrorCode PetscDSHasBdJacobianPreconditioner(PetscDS ds, PetscBool *hasBdJacPre) 2462 { 2463 PetscErrorCode ierr; 2464 2465 PetscFunctionBegin; 2466 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2467 PetscValidBoolPointer(hasBdJacPre, 2); 2468 ierr = PetscWeakFormHasBdJacobianPreconditioner(ds->wf, hasBdJacPre);CHKERRQ(ierr); 2469 PetscFunctionReturn(0); 2470 } 2471 2472 /*@C 2473 PetscDSGetBdJacobianPreconditioner - Get the pointwise boundary Jacobian preconditioner function for given test and basis field 2474 2475 Not collective 2476 2477 Input Parameters: 2478 + ds - The PetscDS 2479 . f - The test field number 2480 - g - The field number 2481 2482 Output Parameters: 2483 + g0 - integrand for the test and basis function term 2484 . g1 - integrand for the test function and basis function gradient term 2485 . g2 - integrand for the test function gradient and basis function term 2486 - g3 - integrand for the test function gradient and basis function gradient term 2487 2488 Note: We are using a first order FEM model for the weak form: 2489 2490 \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 2491 2492 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2493 2494 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2495 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2496 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2497 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 2498 2499 + dim - the spatial dimension 2500 . Nf - the number of fields 2501 . NfAux - the number of auxiliary fields 2502 . uOff - the offset into u[] and u_t[] for each field 2503 . uOff_x - the offset into u_x[] for each field 2504 . u - each field evaluated at the current point 2505 . u_t - the time derivative of each field evaluated at the current point 2506 . u_x - the gradient of each field evaluated at the current point 2507 . aOff - the offset into a[] and a_t[] for each auxiliary field 2508 . aOff_x - the offset into a_x[] for each auxiliary field 2509 . a - each auxiliary field evaluated at the current point 2510 . a_t - the time derivative of each auxiliary field evaluated at the current point 2511 . a_x - the gradient of auxiliary each field evaluated at the current point 2512 . t - current time 2513 . u_tShift - the multiplier a for dF/dU_t 2514 . x - coordinates of the current point 2515 . n - normal at the current point 2516 . numConstants - number of constant parameters 2517 . constants - constant parameters 2518 - g0 - output values at the current point 2519 2520 This is not yet available in Fortran. 2521 2522 Level: intermediate 2523 2524 .seealso: PetscDSSetBdJacobianPreconditioner() 2525 @*/ 2526 PetscErrorCode PetscDSGetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, 2527 void (**g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2528 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2529 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2530 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2531 void (**g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2532 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2533 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2534 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2535 void (**g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2536 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2537 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2538 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2539 void (**g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2540 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2541 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2542 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2543 { 2544 PetscBdPointJac *tmp0, *tmp1, *tmp2, *tmp3; 2545 PetscInt n0, n1, n2, n3; 2546 PetscErrorCode ierr; 2547 2548 PetscFunctionBegin; 2549 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2550 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2551 if ((g < 0) || (g >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", g, ds->Nf); 2552 ierr = PetscWeakFormGetBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, &n0, &tmp0, &n1, &tmp1, &n2, &tmp2, &n3, &tmp3);CHKERRQ(ierr); 2553 *g0 = tmp0 ? tmp0[0] : NULL; 2554 *g1 = tmp1 ? tmp1[0] : NULL; 2555 *g2 = tmp2 ? tmp2[0] : NULL; 2556 *g3 = tmp3 ? tmp3[0] : NULL; 2557 PetscFunctionReturn(0); 2558 } 2559 2560 /*@C 2561 PetscDSSetBdJacobianPreconditioner - Set the pointwise boundary Jacobian preconditioner function for given test and basis field 2562 2563 Not collective 2564 2565 Input Parameters: 2566 + ds - The PetscDS 2567 . f - The test field number 2568 . g - The field number 2569 . g0 - integrand for the test and basis function term 2570 . g1 - integrand for the test function and basis function gradient term 2571 . g2 - integrand for the test function gradient and basis function term 2572 - g3 - integrand for the test function gradient and basis function gradient term 2573 2574 Note: We are using a first order FEM model for the weak form: 2575 2576 \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 2577 2578 The calling sequence for the callbacks g0, g1, g2 and g3 is given by: 2579 2580 $ g0(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2581 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2582 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2583 $ PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 2584 2585 + dim - the spatial dimension 2586 . Nf - the number of fields 2587 . NfAux - the number of auxiliary fields 2588 . uOff - the offset into u[] and u_t[] for each field 2589 . uOff_x - the offset into u_x[] for each field 2590 . u - each field evaluated at the current point 2591 . u_t - the time derivative of each field evaluated at the current point 2592 . u_x - the gradient of each field evaluated at the current point 2593 . aOff - the offset into a[] and a_t[] for each auxiliary field 2594 . aOff_x - the offset into a_x[] for each auxiliary field 2595 . a - each auxiliary field evaluated at the current point 2596 . a_t - the time derivative of each auxiliary field evaluated at the current point 2597 . a_x - the gradient of auxiliary each field evaluated at the current point 2598 . t - current time 2599 . u_tShift - the multiplier a for dF/dU_t 2600 . x - coordinates of the current point 2601 . n - normal at the current point 2602 . numConstants - number of constant parameters 2603 . constants - constant parameters 2604 - g0 - output values at the current point 2605 2606 This is not yet available in Fortran. 2607 2608 Level: intermediate 2609 2610 .seealso: PetscDSGetBdJacobianPreconditioner() 2611 @*/ 2612 PetscErrorCode PetscDSSetBdJacobianPreconditioner(PetscDS ds, PetscInt f, PetscInt g, 2613 void (*g0)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2614 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2615 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2616 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]), 2617 void (*g1)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2618 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2619 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2620 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g1[]), 2621 void (*g2)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2622 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2623 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2624 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g2[]), 2625 void (*g3)(PetscInt dim, PetscInt Nf, PetscInt NfAux, 2626 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 2627 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 2628 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[])) 2629 { 2630 PetscErrorCode ierr; 2631 2632 PetscFunctionBegin; 2633 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2634 if (g0) PetscValidFunction(g0, 4); 2635 if (g1) PetscValidFunction(g1, 5); 2636 if (g2) PetscValidFunction(g2, 6); 2637 if (g3) PetscValidFunction(g3, 7); 2638 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2639 if (g < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", g); 2640 ierr = PetscWeakFormSetIndexBdJacobianPreconditioner(ds->wf, NULL, 0, f, g, 0, 0, g0, 0, g1, 0, g2, 0, g3);CHKERRQ(ierr); 2641 PetscFunctionReturn(0); 2642 } 2643 2644 /*@C 2645 PetscDSGetExactSolution - Get the pointwise exact solution function for a given test field 2646 2647 Not collective 2648 2649 Input Parameters: 2650 + prob - The PetscDS 2651 - f - The test field number 2652 2653 Output Parameters: 2654 + exactSol - exact solution for the test field 2655 - exactCtx - exact solution context 2656 2657 Note: The calling sequence for the solution functions is given by: 2658 2659 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2660 2661 + dim - the spatial dimension 2662 . t - current time 2663 . x - coordinates of the current point 2664 . Nc - the number of field components 2665 . u - the solution field evaluated at the current point 2666 - ctx - a user context 2667 2668 Level: intermediate 2669 2670 .seealso: PetscDSSetExactSolution(), PetscDSGetExactSolutionTimeDerivative() 2671 @*/ 2672 PetscErrorCode PetscDSGetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2673 { 2674 PetscFunctionBegin; 2675 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2676 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); 2677 if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol[f];} 2678 if (ctx) {PetscValidPointer(ctx, 4); *ctx = prob->exactCtx[f];} 2679 PetscFunctionReturn(0); 2680 } 2681 2682 /*@C 2683 PetscDSSetExactSolution - Set the pointwise exact solution function for a given test field 2684 2685 Not collective 2686 2687 Input Parameters: 2688 + prob - The PetscDS 2689 . f - The test field number 2690 . sol - solution function for the test fields 2691 - ctx - solution context or NULL 2692 2693 Note: The calling sequence for solution functions is given by: 2694 2695 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2696 2697 + dim - the spatial dimension 2698 . t - current time 2699 . x - coordinates of the current point 2700 . Nc - the number of field components 2701 . u - the solution field evaluated at the current point 2702 - ctx - a user context 2703 2704 Level: intermediate 2705 2706 .seealso: PetscDSGetExactSolution() 2707 @*/ 2708 PetscErrorCode PetscDSSetExactSolution(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2709 { 2710 PetscErrorCode ierr; 2711 2712 PetscFunctionBegin; 2713 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2714 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2715 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 2716 if (sol) {PetscValidFunction(sol, 3); prob->exactSol[f] = sol;} 2717 if (ctx) {PetscValidFunction(ctx, 4); prob->exactCtx[f] = ctx;} 2718 PetscFunctionReturn(0); 2719 } 2720 2721 /*@C 2722 PetscDSGetExactSolutionTimeDerivative - Get the pointwise time derivative of the exact solution function for a given test field 2723 2724 Not collective 2725 2726 Input Parameters: 2727 + prob - The PetscDS 2728 - f - The test field number 2729 2730 Output Parameters: 2731 + exactSol - time derivative of the exact solution for the test field 2732 - exactCtx - time derivative of the exact solution context 2733 2734 Note: The calling sequence for the solution functions is given by: 2735 2736 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2737 2738 + dim - the spatial dimension 2739 . t - current time 2740 . x - coordinates of the current point 2741 . Nc - the number of field components 2742 . u - the solution field evaluated at the current point 2743 - ctx - a user context 2744 2745 Level: intermediate 2746 2747 .seealso: PetscDSSetExactSolutionTimeDerivative(), PetscDSGetExactSolution() 2748 @*/ 2749 PetscErrorCode PetscDSGetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (**sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void **ctx) 2750 { 2751 PetscFunctionBegin; 2752 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2753 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); 2754 if (sol) {PetscValidPointer(sol, 3); *sol = prob->exactSol_t[f];} 2755 if (ctx) {PetscValidPointer(ctx, 4); *ctx = prob->exactCtx_t[f];} 2756 PetscFunctionReturn(0); 2757 } 2758 2759 /*@C 2760 PetscDSSetExactSolutionTimeDerivative - Set the pointwise time derivative of the exact solution function for a given test field 2761 2762 Not collective 2763 2764 Input Parameters: 2765 + prob - The PetscDS 2766 . f - The test field number 2767 . sol - time derivative of the solution function for the test fields 2768 - ctx - time derivative of the solution context or NULL 2769 2770 Note: The calling sequence for solution functions is given by: 2771 2772 $ sol(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx) 2773 2774 + dim - the spatial dimension 2775 . t - current time 2776 . x - coordinates of the current point 2777 . Nc - the number of field components 2778 . u - the solution field evaluated at the current point 2779 - ctx - a user context 2780 2781 Level: intermediate 2782 2783 .seealso: PetscDSGetExactSolutionTimeDerivative(), PetscDSSetExactSolution() 2784 @*/ 2785 PetscErrorCode PetscDSSetExactSolutionTimeDerivative(PetscDS prob, PetscInt f, PetscErrorCode (*sol)(PetscInt dim, PetscReal t, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx), void *ctx) 2786 { 2787 PetscErrorCode ierr; 2788 2789 PetscFunctionBegin; 2790 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2791 if (f < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be non-negative", f); 2792 ierr = PetscDSEnlarge_Static(prob, f+1);CHKERRQ(ierr); 2793 if (sol) {PetscValidFunction(sol, 3); prob->exactSol_t[f] = sol;} 2794 if (ctx) {PetscValidFunction(ctx, 4); prob->exactCtx_t[f] = ctx;} 2795 PetscFunctionReturn(0); 2796 } 2797 2798 /*@C 2799 PetscDSGetConstants - Returns the array of constants passed to point functions 2800 2801 Not collective 2802 2803 Input Parameter: 2804 . prob - The PetscDS object 2805 2806 Output Parameters: 2807 + numConstants - The number of constants 2808 - constants - The array of constants, NULL if there are none 2809 2810 Level: intermediate 2811 2812 .seealso: PetscDSSetConstants(), PetscDSCreate() 2813 @*/ 2814 PetscErrorCode PetscDSGetConstants(PetscDS prob, PetscInt *numConstants, const PetscScalar *constants[]) 2815 { 2816 PetscFunctionBegin; 2817 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2818 if (numConstants) {PetscValidPointer(numConstants, 2); *numConstants = prob->numConstants;} 2819 if (constants) {PetscValidPointer(constants, 3); *constants = prob->constants;} 2820 PetscFunctionReturn(0); 2821 } 2822 2823 /*@C 2824 PetscDSSetConstants - Set the array of constants passed to point functions 2825 2826 Not collective 2827 2828 Input Parameters: 2829 + prob - The PetscDS object 2830 . numConstants - The number of constants 2831 - constants - The array of constants, NULL if there are none 2832 2833 Level: intermediate 2834 2835 .seealso: PetscDSGetConstants(), PetscDSCreate() 2836 @*/ 2837 PetscErrorCode PetscDSSetConstants(PetscDS prob, PetscInt numConstants, PetscScalar constants[]) 2838 { 2839 PetscErrorCode ierr; 2840 2841 PetscFunctionBegin; 2842 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2843 if (numConstants != prob->numConstants) { 2844 ierr = PetscFree(prob->constants);CHKERRQ(ierr); 2845 prob->numConstants = numConstants; 2846 if (prob->numConstants) { 2847 ierr = PetscMalloc1(prob->numConstants, &prob->constants);CHKERRQ(ierr); 2848 } else { 2849 prob->constants = NULL; 2850 } 2851 } 2852 if (prob->numConstants) { 2853 PetscValidPointer(constants, 3); 2854 ierr = PetscArraycpy(prob->constants, constants, prob->numConstants);CHKERRQ(ierr); 2855 } 2856 PetscFunctionReturn(0); 2857 } 2858 2859 /*@ 2860 PetscDSGetFieldIndex - Returns the index of the given field 2861 2862 Not collective 2863 2864 Input Parameters: 2865 + prob - The PetscDS object 2866 - disc - The discretization object 2867 2868 Output Parameter: 2869 . f - The field number 2870 2871 Level: beginner 2872 2873 .seealso: PetscGetDiscretization(), PetscDSGetNumFields(), PetscDSCreate() 2874 @*/ 2875 PetscErrorCode PetscDSGetFieldIndex(PetscDS prob, PetscObject disc, PetscInt *f) 2876 { 2877 PetscInt g; 2878 2879 PetscFunctionBegin; 2880 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2881 PetscValidPointer(f, 3); 2882 *f = -1; 2883 for (g = 0; g < prob->Nf; ++g) {if (disc == prob->disc[g]) break;} 2884 if (g == prob->Nf) SETERRQ(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Field not found in PetscDS."); 2885 *f = g; 2886 PetscFunctionReturn(0); 2887 } 2888 2889 /*@ 2890 PetscDSGetFieldSize - Returns the size of the given field in the full space basis 2891 2892 Not collective 2893 2894 Input Parameters: 2895 + prob - The PetscDS object 2896 - f - The field number 2897 2898 Output Parameter: 2899 . size - The size 2900 2901 Level: beginner 2902 2903 .seealso: PetscDSGetFieldOffset(), PetscDSGetNumFields(), PetscDSCreate() 2904 @*/ 2905 PetscErrorCode PetscDSGetFieldSize(PetscDS prob, PetscInt f, PetscInt *size) 2906 { 2907 PetscErrorCode ierr; 2908 2909 PetscFunctionBegin; 2910 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2911 PetscValidPointer(size, 3); 2912 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); 2913 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 2914 *size = prob->Nb[f]; 2915 PetscFunctionReturn(0); 2916 } 2917 2918 /*@ 2919 PetscDSGetFieldOffset - Returns the offset of the given field in the full space basis 2920 2921 Not collective 2922 2923 Input Parameters: 2924 + prob - The PetscDS object 2925 - f - The field number 2926 2927 Output Parameter: 2928 . off - The offset 2929 2930 Level: beginner 2931 2932 .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate() 2933 @*/ 2934 PetscErrorCode PetscDSGetFieldOffset(PetscDS prob, PetscInt f, PetscInt *off) 2935 { 2936 PetscInt size, g; 2937 PetscErrorCode ierr; 2938 2939 PetscFunctionBegin; 2940 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 2941 PetscValidPointer(off, 3); 2942 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); 2943 *off = 0; 2944 for (g = 0; g < f; ++g) { 2945 ierr = PetscDSGetFieldSize(prob, g, &size);CHKERRQ(ierr); 2946 *off += size; 2947 } 2948 PetscFunctionReturn(0); 2949 } 2950 2951 /*@ 2952 PetscDSGetFieldOffsetCohesive - Returns the offset of the given field in the full space basis on a cohesive cell 2953 2954 Not collective 2955 2956 Input Parameters: 2957 + prob - The PetscDS object 2958 - f - The field number 2959 2960 Output Parameter: 2961 . off - The offset 2962 2963 Level: beginner 2964 2965 .seealso: PetscDSGetFieldSize(), PetscDSGetNumFields(), PetscDSCreate() 2966 @*/ 2967 PetscErrorCode PetscDSGetFieldOffsetCohesive(PetscDS ds, PetscInt f, PetscInt *off) 2968 { 2969 PetscInt size, g; 2970 PetscErrorCode ierr; 2971 2972 PetscFunctionBegin; 2973 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 2974 PetscValidPointer(off, 3); 2975 if ((f < 0) || (f >= ds->Nf)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Field number %d must be in [0, %d)", f, ds->Nf); 2976 *off = 0; 2977 for (g = 0; g < f; ++g) { 2978 PetscBool cohesive; 2979 2980 ierr = PetscDSGetCohesive(ds, g, &cohesive);CHKERRQ(ierr); 2981 ierr = PetscDSGetFieldSize(ds, g, &size);CHKERRQ(ierr); 2982 *off += cohesive ? size : size*2; 2983 } 2984 PetscFunctionReturn(0); 2985 } 2986 2987 /*@ 2988 PetscDSGetDimensions - Returns the size of the approximation space for each field on an evaluation point 2989 2990 Not collective 2991 2992 Input Parameter: 2993 . prob - The PetscDS object 2994 2995 Output Parameter: 2996 . dimensions - The number of dimensions 2997 2998 Level: beginner 2999 3000 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate() 3001 @*/ 3002 PetscErrorCode PetscDSGetDimensions(PetscDS prob, PetscInt *dimensions[]) 3003 { 3004 PetscErrorCode ierr; 3005 3006 PetscFunctionBegin; 3007 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3008 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3009 PetscValidPointer(dimensions, 2); 3010 *dimensions = prob->Nb; 3011 PetscFunctionReturn(0); 3012 } 3013 3014 /*@ 3015 PetscDSGetComponents - Returns the number of components for each field on an evaluation point 3016 3017 Not collective 3018 3019 Input Parameter: 3020 . prob - The PetscDS object 3021 3022 Output Parameter: 3023 . components - The number of components 3024 3025 Level: beginner 3026 3027 .seealso: PetscDSGetComponentOffsets(), PetscDSGetNumFields(), PetscDSCreate() 3028 @*/ 3029 PetscErrorCode PetscDSGetComponents(PetscDS prob, PetscInt *components[]) 3030 { 3031 PetscErrorCode ierr; 3032 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3035 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3036 PetscValidPointer(components, 2); 3037 *components = prob->Nc; 3038 PetscFunctionReturn(0); 3039 } 3040 3041 /*@ 3042 PetscDSGetComponentOffset - Returns the offset of the given field on an evaluation point 3043 3044 Not collective 3045 3046 Input Parameters: 3047 + prob - The PetscDS object 3048 - f - The field number 3049 3050 Output Parameter: 3051 . off - The offset 3052 3053 Level: beginner 3054 3055 .seealso: PetscDSGetNumFields(), PetscDSCreate() 3056 @*/ 3057 PetscErrorCode PetscDSGetComponentOffset(PetscDS prob, PetscInt f, PetscInt *off) 3058 { 3059 PetscErrorCode ierr; 3060 3061 PetscFunctionBegin; 3062 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3063 PetscValidPointer(off, 3); 3064 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); 3065 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3066 *off = prob->off[f]; 3067 PetscFunctionReturn(0); 3068 } 3069 3070 /*@ 3071 PetscDSGetComponentOffsets - Returns the offset of each field on an evaluation point 3072 3073 Not collective 3074 3075 Input Parameter: 3076 . prob - The PetscDS object 3077 3078 Output Parameter: 3079 . offsets - The offsets 3080 3081 Level: beginner 3082 3083 .seealso: PetscDSGetNumFields(), PetscDSCreate() 3084 @*/ 3085 PetscErrorCode PetscDSGetComponentOffsets(PetscDS prob, PetscInt *offsets[]) 3086 { 3087 PetscErrorCode ierr; 3088 3089 PetscFunctionBegin; 3090 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3091 PetscValidPointer(offsets, 2); 3092 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3093 *offsets = prob->off; 3094 PetscFunctionReturn(0); 3095 } 3096 3097 /*@ 3098 PetscDSGetComponentDerivativeOffsets - Returns the offset of each field derivative on an evaluation point 3099 3100 Not collective 3101 3102 Input Parameter: 3103 . prob - The PetscDS object 3104 3105 Output Parameter: 3106 . offsets - The offsets 3107 3108 Level: beginner 3109 3110 .seealso: PetscDSGetNumFields(), PetscDSCreate() 3111 @*/ 3112 PetscErrorCode PetscDSGetComponentDerivativeOffsets(PetscDS prob, PetscInt *offsets[]) 3113 { 3114 PetscErrorCode ierr; 3115 3116 PetscFunctionBegin; 3117 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3118 PetscValidPointer(offsets, 2); 3119 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3120 *offsets = prob->offDer; 3121 PetscFunctionReturn(0); 3122 } 3123 3124 /*@C 3125 PetscDSGetTabulation - Return the basis tabulation at quadrature points for the volume discretization 3126 3127 Not collective 3128 3129 Input Parameter: 3130 . prob - The PetscDS object 3131 3132 Output Parameter: 3133 . T - The basis function and derivatives tabulation at quadrature points for each field 3134 3135 Level: intermediate 3136 3137 .seealso: PetscDSCreate() 3138 @*/ 3139 PetscErrorCode PetscDSGetTabulation(PetscDS prob, PetscTabulation *T[]) 3140 { 3141 PetscErrorCode ierr; 3142 3143 PetscFunctionBegin; 3144 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3145 PetscValidPointer(T, 2); 3146 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3147 *T = prob->T; 3148 PetscFunctionReturn(0); 3149 } 3150 3151 /*@C 3152 PetscDSGetFaceTabulation - Return the basis tabulation at quadrature points on the faces 3153 3154 Not collective 3155 3156 Input Parameter: 3157 . prob - The PetscDS object 3158 3159 Output Parameter: 3160 . Tf - The basis function and derivative tabulation on each local face at quadrature points for each and field 3161 3162 Level: intermediate 3163 3164 .seealso: PetscDSGetTabulation(), PetscDSCreate() 3165 @*/ 3166 PetscErrorCode PetscDSGetFaceTabulation(PetscDS prob, PetscTabulation *Tf[]) 3167 { 3168 PetscErrorCode ierr; 3169 3170 PetscFunctionBegin; 3171 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3172 PetscValidPointer(Tf, 2); 3173 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3174 *Tf = prob->Tf; 3175 PetscFunctionReturn(0); 3176 } 3177 3178 PetscErrorCode PetscDSGetEvaluationArrays(PetscDS prob, PetscScalar **u, PetscScalar **u_t, PetscScalar **u_x) 3179 { 3180 PetscErrorCode ierr; 3181 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3184 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3185 if (u) {PetscValidPointer(u, 2); *u = prob->u;} 3186 if (u_t) {PetscValidPointer(u_t, 3); *u_t = prob->u_t;} 3187 if (u_x) {PetscValidPointer(u_x, 4); *u_x = prob->u_x;} 3188 PetscFunctionReturn(0); 3189 } 3190 3191 PetscErrorCode PetscDSGetWeakFormArrays(PetscDS prob, PetscScalar **f0, PetscScalar **f1, PetscScalar **g0, PetscScalar **g1, PetscScalar **g2, PetscScalar **g3) 3192 { 3193 PetscErrorCode ierr; 3194 3195 PetscFunctionBegin; 3196 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3197 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3198 if (f0) {PetscValidPointer(f0, 2); *f0 = prob->f0;} 3199 if (f1) {PetscValidPointer(f1, 3); *f1 = prob->f1;} 3200 if (g0) {PetscValidPointer(g0, 4); *g0 = prob->g0;} 3201 if (g1) {PetscValidPointer(g1, 5); *g1 = prob->g1;} 3202 if (g2) {PetscValidPointer(g2, 6); *g2 = prob->g2;} 3203 if (g3) {PetscValidPointer(g3, 7); *g3 = prob->g3;} 3204 PetscFunctionReturn(0); 3205 } 3206 3207 PetscErrorCode PetscDSGetWorkspace(PetscDS prob, PetscReal **x, PetscScalar **basisReal, PetscScalar **basisDerReal, PetscScalar **testReal, PetscScalar **testDerReal) 3208 { 3209 PetscErrorCode ierr; 3210 3211 PetscFunctionBegin; 3212 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3213 ierr = PetscDSSetUp(prob);CHKERRQ(ierr); 3214 if (x) {PetscValidPointer(x, 2); *x = prob->x;} 3215 if (basisReal) {PetscValidPointer(basisReal, 3); *basisReal = prob->basisReal;} 3216 if (basisDerReal) {PetscValidPointer(basisDerReal, 4); *basisDerReal = prob->basisDerReal;} 3217 if (testReal) {PetscValidPointer(testReal, 5); *testReal = prob->testReal;} 3218 if (testDerReal) {PetscValidPointer(testDerReal, 6); *testDerReal = prob->testDerReal;} 3219 PetscFunctionReturn(0); 3220 } 3221 3222 /*@C 3223 PetscDSAddBoundary - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual(). 3224 3225 Collective on ds 3226 3227 Input Parameters: 3228 + ds - The PetscDS object 3229 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 3230 . name - The BC name 3231 . label - The label defining constrained points 3232 . Nv - The number of DMLabel values for constrained points 3233 . values - An array of label values for constrained points 3234 . field - The field to constrain 3235 . Nc - The number of constrained field components (0 will constrain all fields) 3236 . comps - An array of constrained component numbers 3237 . bcFunc - A pointwise function giving boundary values 3238 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3239 - ctx - An optional user context for bcFunc 3240 3241 Output Parameters: 3242 - bd - The boundary number 3243 3244 Options Database Keys: 3245 + -bc_<boundary name> <num> - Overrides the boundary ids 3246 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3247 3248 Note: 3249 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 3250 3251 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3252 3253 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 3254 3255 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3256 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3257 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3258 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3259 3260 + dim - the spatial dimension 3261 . Nf - the number of fields 3262 . uOff - the offset into u[] and u_t[] for each field 3263 . uOff_x - the offset into u_x[] for each field 3264 . u - each field evaluated at the current point 3265 . u_t - the time derivative of each field evaluated at the current point 3266 . u_x - the gradient of each field evaluated at the current point 3267 . aOff - the offset into a[] and a_t[] for each auxiliary field 3268 . aOff_x - the offset into a_x[] for each auxiliary field 3269 . a - each auxiliary field evaluated at the current point 3270 . a_t - the time derivative of each auxiliary field evaluated at the current point 3271 . a_x - the gradient of auxiliary each field evaluated at the current point 3272 . t - current time 3273 . x - coordinates of the current point 3274 . numConstants - number of constant parameters 3275 . constants - constant parameters 3276 - bcval - output values at the current point 3277 3278 Level: developer 3279 3280 .seealso: PetscDSAddBoundaryByName(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual() 3281 @*/ 3282 PetscErrorCode PetscDSAddBoundary(PetscDS ds, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 3283 { 3284 DSBoundary head = ds->boundary, b; 3285 PetscInt n = 0; 3286 const char *lname; 3287 PetscErrorCode ierr; 3288 3289 PetscFunctionBegin; 3290 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3291 PetscValidLogicalCollectiveEnum(ds, type, 2); 3292 PetscValidCharPointer(name, 3); 3293 PetscValidHeaderSpecific(label, DMLABEL_CLASSID, 4); 3294 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3295 PetscValidLogicalCollectiveInt(ds, field, 7); 3296 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3297 if (Nc > 0) { 3298 PetscInt *fcomps; 3299 PetscInt c; 3300 3301 ierr = PetscDSGetComponents(ds, &fcomps);CHKERRQ(ierr); 3302 if (Nc > fcomps[field]) SETERRQ3(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_OUTOFRANGE, "Number of constrained components %D > %D components for field %D", Nc, fcomps[field], field); 3303 for (c = 0; c < Nc; ++c) { 3304 if (comps[c] < 0 || comps[c] >= fcomps[field]) SETERRQ4(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_OUTOFRANGE, "Constrained component[%D] %D not in [0, %D) components for field %D", c, comps[c], fcomps[field], field); 3305 } 3306 } 3307 ierr = PetscNew(&b);CHKERRQ(ierr); 3308 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 3309 ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);CHKERRQ(ierr); 3310 ierr = PetscWeakFormSetNumFields(b->wf, ds->Nf);CHKERRQ(ierr); 3311 ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr); 3312 if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);} 3313 ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr); 3314 if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);} 3315 ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr); 3316 ierr = PetscStrallocpy(lname, (char **) &b->lname);CHKERRQ(ierr); 3317 b->type = type; 3318 b->label = label; 3319 b->Nv = Nv; 3320 b->field = field; 3321 b->Nc = Nc; 3322 b->func = bcFunc; 3323 b->func_t = bcFunc_t; 3324 b->ctx = ctx; 3325 b->next = NULL; 3326 /* Append to linked list so that we can preserve the order */ 3327 if (!head) ds->boundary = b; 3328 while (head) { 3329 if (!head->next) { 3330 head->next = b; 3331 head = b; 3332 } 3333 head = head->next; 3334 ++n; 3335 } 3336 if (bd) {PetscValidIntPointer(bd, 13); *bd = n;} 3337 PetscFunctionReturn(0); 3338 } 3339 3340 /*@C 3341 PetscDSAddBoundaryByName - Add a boundary condition to the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual(). 3342 3343 Collective on ds 3344 3345 Input Parameters: 3346 + ds - The PetscDS object 3347 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 3348 . name - The BC name 3349 . lname - The naem of the label defining constrained points 3350 . Nv - The number of DMLabel values for constrained points 3351 . values - An array of label values for constrained points 3352 . field - The field to constrain 3353 . Nc - The number of constrained field components (0 will constrain all fields) 3354 . comps - An array of constrained component numbers 3355 . bcFunc - A pointwise function giving boundary values 3356 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3357 - ctx - An optional user context for bcFunc 3358 3359 Output Parameters: 3360 - bd - The boundary number 3361 3362 Options Database Keys: 3363 + -bc_<boundary name> <num> - Overrides the boundary ids 3364 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3365 3366 Note: 3367 This function should only be used with DMForest currently, since labels cannot be defined before the underlygin Plex is built. 3368 3369 Both bcFunc abd bcFunc_t will depend on the boundary condition type. If the type if DM_BC_ESSENTIAL, Then the calling sequence is: 3370 3371 $ bcFunc(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar bcval[]) 3372 3373 If the type is DM_BC_ESSENTIAL_FIELD or other _FIELD value, then the calling sequence is: 3374 3375 $ bcFunc(PetscInt dim, PetscInt Nf, PetscInt NfAux, 3376 $ const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 3377 $ const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 3378 $ PetscReal time, const PetscReal x[], PetscScalar bcval[]) 3379 3380 + dim - the spatial dimension 3381 . Nf - the number of fields 3382 . uOff - the offset into u[] and u_t[] for each field 3383 . uOff_x - the offset into u_x[] for each field 3384 . u - each field evaluated at the current point 3385 . u_t - the time derivative of each field evaluated at the current point 3386 . u_x - the gradient of each field evaluated at the current point 3387 . aOff - the offset into a[] and a_t[] for each auxiliary field 3388 . aOff_x - the offset into a_x[] for each auxiliary field 3389 . a - each auxiliary field evaluated at the current point 3390 . a_t - the time derivative of each auxiliary field evaluated at the current point 3391 . a_x - the gradient of auxiliary each field evaluated at the current point 3392 . t - current time 3393 . x - coordinates of the current point 3394 . numConstants - number of constant parameters 3395 . constants - constant parameters 3396 - bcval - output values at the current point 3397 3398 Level: developer 3399 3400 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSSetResidual(), PetscDSSetBdResidual() 3401 @*/ 3402 PetscErrorCode PetscDSAddBoundaryByName(PetscDS ds, DMBoundaryConditionType type, const char name[], const char lname[], PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx, PetscInt *bd) 3403 { 3404 DSBoundary head = ds->boundary, b; 3405 PetscInt n = 0; 3406 PetscErrorCode ierr; 3407 3408 PetscFunctionBegin; 3409 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3410 PetscValidLogicalCollectiveEnum(ds, type, 2); 3411 PetscValidCharPointer(name, 3); 3412 PetscValidCharPointer(lname, 4); 3413 PetscValidLogicalCollectiveInt(ds, Nv, 5); 3414 PetscValidLogicalCollectiveInt(ds, field, 7); 3415 PetscValidLogicalCollectiveInt(ds, Nc, 8); 3416 ierr = PetscNew(&b);CHKERRQ(ierr); 3417 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 3418 ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &b->wf);CHKERRQ(ierr); 3419 ierr = PetscWeakFormSetNumFields(b->wf, ds->Nf);CHKERRQ(ierr); 3420 ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr); 3421 if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);} 3422 ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr); 3423 if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);} 3424 ierr = PetscStrallocpy(lname, (char **) &b->lname);CHKERRQ(ierr); 3425 b->type = type; 3426 b->label = NULL; 3427 b->Nv = Nv; 3428 b->field = field; 3429 b->Nc = Nc; 3430 b->func = bcFunc; 3431 b->func_t = bcFunc_t; 3432 b->ctx = ctx; 3433 b->next = NULL; 3434 /* Append to linked list so that we can preserve the order */ 3435 if (!head) ds->boundary = b; 3436 while (head) { 3437 if (!head->next) { 3438 head->next = b; 3439 head = b; 3440 } 3441 head = head->next; 3442 ++n; 3443 } 3444 if (bd) {PetscValidIntPointer(bd, 13); *bd = n;} 3445 PetscFunctionReturn(0); 3446 } 3447 3448 /*@C 3449 PetscDSUpdateBoundary - Change a boundary condition for the model. The pointwise functions are used to provide boundary values for essential boundary conditions. In FEM, they are acting upon by dual basis functionals to generate FEM coefficients which are fixed. Natural boundary conditions signal to PETSc that boundary integrals should be performaed, using the kernels from PetscDSSetBdResidual(). 3450 3451 Input Parameters: 3452 + ds - The PetscDS object 3453 . bd - The boundary condition number 3454 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 3455 . name - The BC name 3456 . label - The label defining constrained points 3457 . Nv - The number of DMLabel ids for constrained points 3458 . values - An array of ids for constrained points 3459 . field - The field to constrain 3460 . Nc - The number of constrained field components 3461 . comps - An array of constrained component numbers 3462 . bcFunc - A pointwise function giving boundary values 3463 . bcFunc_t - A pointwise function giving the time derivative of the boundary values, or NULL 3464 - ctx - An optional user context for bcFunc 3465 3466 Note: 3467 The boundary condition number is the order in which it was registered. The user can get the number of boundary conditions from PetscDSGetNumBoundary(). See PetscDSAddBoundary() for a description of the calling sequences for the callbacks. 3468 3469 Level: developer 3470 3471 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary(), PetscDSGetNumBoundary() 3472 @*/ 3473 PetscErrorCode PetscDSUpdateBoundary(PetscDS ds, PetscInt bd, DMBoundaryConditionType type, const char name[], DMLabel label, PetscInt Nv, const PetscInt values[], PetscInt field, PetscInt Nc, const PetscInt comps[], void (*bcFunc)(void), void (*bcFunc_t)(void), void *ctx) 3474 { 3475 DSBoundary b = ds->boundary; 3476 PetscInt n = 0; 3477 PetscErrorCode ierr; 3478 3479 PetscFunctionBegin; 3480 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3481 while (b) { 3482 if (n == bd) break; 3483 b = b->next; 3484 ++n; 3485 } 3486 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 3487 if (name) { 3488 ierr = PetscFree(b->name);CHKERRQ(ierr); 3489 ierr = PetscStrallocpy(name, (char **) &b->name);CHKERRQ(ierr); 3490 } 3491 b->type = type; 3492 if (label) { 3493 const char *name; 3494 3495 b->label = label; 3496 ierr = PetscFree(b->lname);CHKERRQ(ierr); 3497 ierr = PetscObjectGetName((PetscObject) label, &name);CHKERRQ(ierr); 3498 ierr = PetscStrallocpy(name, (char **) &b->lname);CHKERRQ(ierr); 3499 } 3500 if (Nv >= 0) { 3501 b->Nv = Nv; 3502 ierr = PetscFree(b->values);CHKERRQ(ierr); 3503 ierr = PetscMalloc1(Nv, &b->values);CHKERRQ(ierr); 3504 if (Nv) {ierr = PetscArraycpy(b->values, values, Nv);CHKERRQ(ierr);} 3505 } 3506 if (field >= 0) b->field = field; 3507 if (Nc >= 0) { 3508 b->Nc = Nc; 3509 ierr = PetscFree(b->comps);CHKERRQ(ierr); 3510 ierr = PetscMalloc1(Nc, &b->comps);CHKERRQ(ierr); 3511 if (Nc) {ierr = PetscArraycpy(b->comps, comps, Nc);CHKERRQ(ierr);} 3512 } 3513 if (bcFunc) b->func = bcFunc; 3514 if (bcFunc_t) b->func_t = bcFunc_t; 3515 if (ctx) b->ctx = ctx; 3516 PetscFunctionReturn(0); 3517 } 3518 3519 /*@ 3520 PetscDSGetNumBoundary - Get the number of registered BC 3521 3522 Input Parameters: 3523 . ds - The PetscDS object 3524 3525 Output Parameters: 3526 . numBd - The number of BC 3527 3528 Level: intermediate 3529 3530 .seealso: PetscDSAddBoundary(), PetscDSGetBoundary() 3531 @*/ 3532 PetscErrorCode PetscDSGetNumBoundary(PetscDS ds, PetscInt *numBd) 3533 { 3534 DSBoundary b = ds->boundary; 3535 3536 PetscFunctionBegin; 3537 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3538 PetscValidPointer(numBd, 2); 3539 *numBd = 0; 3540 while (b) {++(*numBd); b = b->next;} 3541 PetscFunctionReturn(0); 3542 } 3543 3544 /*@C 3545 PetscDSGetBoundary - Gets a boundary condition to the model 3546 3547 Input Parameters: 3548 + ds - The PetscDS object 3549 - bd - The BC number 3550 3551 Output Parameters: 3552 + wf - The PetscWeakForm holding the pointwise functions 3553 . type - The type of condition, e.g. DM_BC_ESSENTIAL/DM_BC_ESSENTIAL_FIELD (Dirichlet), or DM_BC_NATURAL (Neumann) 3554 . name - The BC name 3555 . label - The label defining constrained points 3556 . Nv - The number of DMLabel ids for constrained points 3557 . values - An array of ids for constrained points 3558 . field - The field to constrain 3559 . Nc - The number of constrained field components 3560 . comps - An array of constrained component numbers 3561 . bcFunc - A pointwise function giving boundary values 3562 . bcFunc_t - A pointwise function giving the time derivative of the boundary values 3563 - ctx - An optional user context for bcFunc 3564 3565 Options Database Keys: 3566 + -bc_<boundary name> <num> - Overrides the boundary ids 3567 - -bc_<boundary name>_comp <num> - Overrides the boundary components 3568 3569 Level: developer 3570 3571 .seealso: PetscDSAddBoundary() 3572 @*/ 3573 PetscErrorCode PetscDSGetBoundary(PetscDS ds, PetscInt bd, PetscWeakForm *wf, DMBoundaryConditionType *type, const char *name[], DMLabel *label, PetscInt *Nv, const PetscInt *values[], PetscInt *field, PetscInt *Nc, const PetscInt *comps[], void (**func)(void), void (**func_t)(void), void **ctx) 3574 { 3575 DSBoundary b = ds->boundary; 3576 PetscInt n = 0; 3577 3578 PetscFunctionBegin; 3579 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3580 while (b) { 3581 if (n == bd) break; 3582 b = b->next; 3583 ++n; 3584 } 3585 if (!b) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boundary %d is not in [0, %d)", bd, n); 3586 if (wf) { 3587 PetscValidPointer(wf, 3); 3588 *wf = b->wf; 3589 } 3590 if (type) { 3591 PetscValidPointer(type, 4); 3592 *type = b->type; 3593 } 3594 if (name) { 3595 PetscValidPointer(name, 5); 3596 *name = b->name; 3597 } 3598 if (label) { 3599 PetscValidPointer(label, 6); 3600 *label = b->label; 3601 } 3602 if (Nv) { 3603 PetscValidIntPointer(Nv, 7); 3604 *Nv = b->Nv; 3605 } 3606 if (values) { 3607 PetscValidPointer(values, 8); 3608 *values = b->values; 3609 } 3610 if (field) { 3611 PetscValidIntPointer(field, 9); 3612 *field = b->field; 3613 } 3614 if (Nc) { 3615 PetscValidIntPointer(Nc, 10); 3616 *Nc = b->Nc; 3617 } 3618 if (comps) { 3619 PetscValidPointer(comps, 11); 3620 *comps = b->comps; 3621 } 3622 if (func) { 3623 PetscValidPointer(func, 12); 3624 *func = b->func; 3625 } 3626 if (func_t) { 3627 PetscValidPointer(func_t, 13); 3628 *func_t = b->func_t; 3629 } 3630 if (ctx) { 3631 PetscValidPointer(ctx, 14); 3632 *ctx = b->ctx; 3633 } 3634 PetscFunctionReturn(0); 3635 } 3636 3637 static PetscErrorCode DSBoundaryDuplicate_Internal(DSBoundary b, DSBoundary *bNew) 3638 { 3639 PetscErrorCode ierr; 3640 3641 PetscFunctionBegin; 3642 ierr = PetscNew(bNew);CHKERRQ(ierr); 3643 ierr = PetscWeakFormCreate(PETSC_COMM_SELF, &(*bNew)->wf);CHKERRQ(ierr); 3644 ierr = PetscWeakFormCopy(b->wf, (*bNew)->wf);CHKERRQ(ierr); 3645 ierr = PetscStrallocpy(b->name,(char **) &((*bNew)->name));CHKERRQ(ierr); 3646 ierr = PetscStrallocpy(b->lname,(char **) &((*bNew)->lname));CHKERRQ(ierr); 3647 (*bNew)->type = b->type; 3648 (*bNew)->label = b->label; 3649 (*bNew)->Nv = b->Nv; 3650 ierr = PetscMalloc1(b->Nv, &(*bNew)->values);CHKERRQ(ierr); 3651 ierr = PetscArraycpy((*bNew)->values, b->values, b->Nv);CHKERRQ(ierr); 3652 (*bNew)->field = b->field; 3653 (*bNew)->Nc = b->Nc; 3654 ierr = PetscMalloc1(b->Nc, &(*bNew)->comps);CHKERRQ(ierr); 3655 ierr = PetscArraycpy((*bNew)->comps, b->comps, b->Nc);CHKERRQ(ierr); 3656 (*bNew)->func = b->func; 3657 (*bNew)->func_t = b->func_t; 3658 (*bNew)->ctx = b->ctx; 3659 PetscFunctionReturn(0); 3660 } 3661 3662 /*@ 3663 PetscDSCopyBoundary - Copy all boundary condition objects to the new problem 3664 3665 Not collective 3666 3667 Input Parameters: 3668 + ds - The source PetscDS object 3669 . numFields - The number of selected fields, or PETSC_DEFAULT for all fields 3670 - fields - The selected fields, or NULL for all fields 3671 3672 Output Parameter: 3673 . newds - The target PetscDS, now with a copy of the boundary conditions 3674 3675 Level: intermediate 3676 3677 .seealso: PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3678 @*/ 3679 PetscErrorCode PetscDSCopyBoundary(PetscDS ds, PetscInt numFields, const PetscInt fields[], PetscDS newds) 3680 { 3681 DSBoundary b, *lastnext; 3682 PetscErrorCode ierr; 3683 3684 PetscFunctionBegin; 3685 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3686 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 4); 3687 if (ds == newds) PetscFunctionReturn(0); 3688 ierr = PetscDSDestroyBoundary(newds);CHKERRQ(ierr); 3689 lastnext = &(newds->boundary); 3690 for (b = ds->boundary; b; b = b->next) { 3691 DSBoundary bNew; 3692 PetscInt fieldNew = -1; 3693 3694 if (numFields > 0 && fields) { 3695 PetscInt f; 3696 3697 for (f = 0; f < numFields; ++f) if (b->field == fields[f]) break; 3698 if (f == numFields) continue; 3699 fieldNew = f; 3700 } 3701 ierr = DSBoundaryDuplicate_Internal(b, &bNew);CHKERRQ(ierr); 3702 bNew->field = fieldNew < 0 ? b->field : fieldNew; 3703 *lastnext = bNew; 3704 lastnext = &(bNew->next); 3705 } 3706 PetscFunctionReturn(0); 3707 } 3708 3709 /*@ 3710 PetscDSDestroyBoundary - Remove all DMBoundary objects from the PetscDS 3711 3712 Not collective 3713 3714 Input Parameter: 3715 . ds - The PetscDS object 3716 3717 Level: intermediate 3718 3719 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations() 3720 @*/ 3721 PetscErrorCode PetscDSDestroyBoundary(PetscDS ds) 3722 { 3723 DSBoundary next = ds->boundary; 3724 PetscErrorCode ierr; 3725 3726 PetscFunctionBegin; 3727 while (next) { 3728 DSBoundary b = next; 3729 3730 next = b->next; 3731 ierr = PetscWeakFormDestroy(&b->wf);CHKERRQ(ierr); 3732 ierr = PetscFree(b->name);CHKERRQ(ierr); 3733 ierr = PetscFree(b->lname);CHKERRQ(ierr); 3734 ierr = PetscFree(b->values);CHKERRQ(ierr); 3735 ierr = PetscFree(b->comps);CHKERRQ(ierr); 3736 ierr = PetscFree(b);CHKERRQ(ierr); 3737 } 3738 PetscFunctionReturn(0); 3739 } 3740 3741 /*@ 3742 PetscDSSelectDiscretizations - Copy discretizations to the new problem with different field layout 3743 3744 Not collective 3745 3746 Input Parameters: 3747 + prob - The PetscDS object 3748 . numFields - Number of new fields 3749 - fields - Old field number for each new field 3750 3751 Output Parameter: 3752 . newprob - The PetscDS copy 3753 3754 Level: intermediate 3755 3756 .seealso: PetscDSSelectEquations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3757 @*/ 3758 PetscErrorCode PetscDSSelectDiscretizations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3759 { 3760 PetscInt Nf, Nfn, fn; 3761 PetscErrorCode ierr; 3762 3763 PetscFunctionBegin; 3764 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3765 if (fields) PetscValidPointer(fields, 3); 3766 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3767 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3768 ierr = PetscDSGetNumFields(newprob, &Nfn);CHKERRQ(ierr); 3769 numFields = numFields < 0 ? Nf : numFields; 3770 for (fn = 0; fn < numFields; ++fn) { 3771 const PetscInt f = fields ? fields[fn] : fn; 3772 PetscObject disc; 3773 3774 if (f >= Nf) continue; 3775 ierr = PetscDSGetDiscretization(prob, f, &disc);CHKERRQ(ierr); 3776 ierr = PetscDSSetDiscretization(newprob, fn, disc);CHKERRQ(ierr); 3777 } 3778 PetscFunctionReturn(0); 3779 } 3780 3781 /*@ 3782 PetscDSSelectEquations - Copy pointwise function pointers to the new problem with different field layout 3783 3784 Not collective 3785 3786 Input Parameters: 3787 + prob - The PetscDS object 3788 . numFields - Number of new fields 3789 - fields - Old field number for each new field 3790 3791 Output Parameter: 3792 . newprob - The PetscDS copy 3793 3794 Level: intermediate 3795 3796 .seealso: PetscDSSelectDiscretizations(), PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3797 @*/ 3798 PetscErrorCode PetscDSSelectEquations(PetscDS prob, PetscInt numFields, const PetscInt fields[], PetscDS newprob) 3799 { 3800 PetscInt Nf, Nfn, fn, gn; 3801 PetscErrorCode ierr; 3802 3803 PetscFunctionBegin; 3804 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3805 if (fields) PetscValidPointer(fields, 3); 3806 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 4); 3807 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3808 ierr = PetscDSGetNumFields(newprob, &Nfn);CHKERRQ(ierr); 3809 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); 3810 for (fn = 0; fn < numFields; ++fn) { 3811 const PetscInt f = fields ? fields[fn] : fn; 3812 PetscPointFunc obj; 3813 PetscPointFunc f0, f1; 3814 PetscBdPointFunc f0Bd, f1Bd; 3815 PetscRiemannFunc r; 3816 3817 if (f >= Nf) continue; 3818 ierr = PetscDSGetObjective(prob, f, &obj);CHKERRQ(ierr); 3819 ierr = PetscDSGetResidual(prob, f, &f0, &f1);CHKERRQ(ierr); 3820 ierr = PetscDSGetBdResidual(prob, f, &f0Bd, &f1Bd);CHKERRQ(ierr); 3821 ierr = PetscDSGetRiemannSolver(prob, f, &r);CHKERRQ(ierr); 3822 ierr = PetscDSSetObjective(newprob, fn, obj);CHKERRQ(ierr); 3823 ierr = PetscDSSetResidual(newprob, fn, f0, f1);CHKERRQ(ierr); 3824 ierr = PetscDSSetBdResidual(newprob, fn, f0Bd, f1Bd);CHKERRQ(ierr); 3825 ierr = PetscDSSetRiemannSolver(newprob, fn, r);CHKERRQ(ierr); 3826 for (gn = 0; gn < numFields; ++gn) { 3827 const PetscInt g = fields ? fields[gn] : gn; 3828 PetscPointJac g0, g1, g2, g3; 3829 PetscPointJac g0p, g1p, g2p, g3p; 3830 PetscBdPointJac g0Bd, g1Bd, g2Bd, g3Bd; 3831 3832 if (g >= Nf) continue; 3833 ierr = PetscDSGetJacobian(prob, f, g, &g0, &g1, &g2, &g3);CHKERRQ(ierr); 3834 ierr = PetscDSGetJacobianPreconditioner(prob, f, g, &g0p, &g1p, &g2p, &g3p);CHKERRQ(ierr); 3835 ierr = PetscDSGetBdJacobian(prob, f, g, &g0Bd, &g1Bd, &g2Bd, &g3Bd);CHKERRQ(ierr); 3836 ierr = PetscDSSetJacobian(newprob, fn, gn, g0, g1, g2, g3);CHKERRQ(ierr); 3837 ierr = PetscDSSetJacobianPreconditioner(newprob, fn, gn, g0p, g1p, g2p, g3p);CHKERRQ(ierr); 3838 ierr = PetscDSSetBdJacobian(newprob, fn, gn, g0Bd, g1Bd, g2Bd, g3Bd);CHKERRQ(ierr); 3839 } 3840 } 3841 PetscFunctionReturn(0); 3842 } 3843 3844 /*@ 3845 PetscDSCopyEquations - Copy all pointwise function pointers to the new problem 3846 3847 Not collective 3848 3849 Input Parameter: 3850 . prob - The PetscDS object 3851 3852 Output Parameter: 3853 . newprob - The PetscDS copy 3854 3855 Level: intermediate 3856 3857 .seealso: PetscDSCopyBoundary(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3858 @*/ 3859 PetscErrorCode PetscDSCopyEquations(PetscDS prob, PetscDS newprob) 3860 { 3861 PetscWeakForm wf, newwf; 3862 PetscInt Nf, Ng; 3863 PetscErrorCode ierr; 3864 3865 PetscFunctionBegin; 3866 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3867 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3868 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3869 ierr = PetscDSGetNumFields(newprob, &Ng);CHKERRQ(ierr); 3870 if (Nf != Ng) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_SIZ, "Number of fields must match %D != %D", Nf, Ng); 3871 ierr = PetscDSGetWeakForm(prob, &wf);CHKERRQ(ierr); 3872 ierr = PetscDSGetWeakForm(newprob, &newwf);CHKERRQ(ierr); 3873 ierr = PetscWeakFormCopy(wf, newwf);CHKERRQ(ierr); 3874 PetscFunctionReturn(0); 3875 } 3876 3877 /*@ 3878 PetscDSCopyConstants - Copy all constants to the new problem 3879 3880 Not collective 3881 3882 Input Parameter: 3883 . prob - The PetscDS object 3884 3885 Output Parameter: 3886 . newprob - The PetscDS copy 3887 3888 Level: intermediate 3889 3890 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3891 @*/ 3892 PetscErrorCode PetscDSCopyConstants(PetscDS prob, PetscDS newprob) 3893 { 3894 PetscInt Nc; 3895 const PetscScalar *constants; 3896 PetscErrorCode ierr; 3897 3898 PetscFunctionBegin; 3899 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3900 PetscValidHeaderSpecific(newprob, PETSCDS_CLASSID, 2); 3901 ierr = PetscDSGetConstants(prob, &Nc, &constants);CHKERRQ(ierr); 3902 ierr = PetscDSSetConstants(newprob, Nc, (PetscScalar *) constants);CHKERRQ(ierr); 3903 PetscFunctionReturn(0); 3904 } 3905 3906 /*@ 3907 PetscDSCopyExactSolutions - Copy all exact solutions to the new problem 3908 3909 Not collective 3910 3911 Input Parameter: 3912 . ds - The PetscDS object 3913 3914 Output Parameter: 3915 . newds - The PetscDS copy 3916 3917 Level: intermediate 3918 3919 .seealso: PetscDSCopyBoundary(), PetscDSCopyEquations(), PetscDSSetResidual(), PetscDSSetJacobian(), PetscDSSetRiemannSolver(), PetscDSSetBdResidual(), PetscDSSetBdJacobian(), PetscDSCreate() 3920 @*/ 3921 PetscErrorCode PetscDSCopyExactSolutions(PetscDS ds, PetscDS newds) 3922 { 3923 PetscSimplePointFunc sol; 3924 void *ctx; 3925 PetscInt Nf, f; 3926 PetscErrorCode ierr; 3927 3928 PetscFunctionBegin; 3929 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3930 PetscValidHeaderSpecific(newds, PETSCDS_CLASSID, 2); 3931 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 3932 for (f = 0; f < Nf; ++f) { 3933 ierr = PetscDSGetExactSolution(ds, f, &sol, &ctx);CHKERRQ(ierr); 3934 ierr = PetscDSSetExactSolution(newds, f, sol, ctx);CHKERRQ(ierr); 3935 ierr = PetscDSGetExactSolutionTimeDerivative(ds, f, &sol, &ctx);CHKERRQ(ierr); 3936 ierr = PetscDSSetExactSolutionTimeDerivative(newds, f, sol, ctx);CHKERRQ(ierr); 3937 } 3938 PetscFunctionReturn(0); 3939 } 3940 3941 PetscErrorCode PetscDSGetHeightSubspace(PetscDS prob, PetscInt height, PetscDS *subprob) 3942 { 3943 PetscInt dim, Nf, f; 3944 PetscErrorCode ierr; 3945 3946 PetscFunctionBegin; 3947 PetscValidHeaderSpecific(prob, PETSCDS_CLASSID, 1); 3948 PetscValidPointer(subprob, 3); 3949 if (height == 0) {*subprob = prob; PetscFunctionReturn(0);} 3950 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 3951 ierr = PetscDSGetSpatialDimension(prob, &dim);CHKERRQ(ierr); 3952 if (height > dim) SETERRQ2(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_OUTOFRANGE, "DS can only handle height in [0, %D], not %D", dim, height); 3953 if (!prob->subprobs) {ierr = PetscCalloc1(dim, &prob->subprobs);CHKERRQ(ierr);} 3954 if (!prob->subprobs[height-1]) { 3955 PetscInt cdim; 3956 3957 ierr = PetscDSCreate(PetscObjectComm((PetscObject) prob), &prob->subprobs[height-1]);CHKERRQ(ierr); 3958 ierr = PetscDSGetCoordinateDimension(prob, &cdim);CHKERRQ(ierr); 3959 ierr = PetscDSSetCoordinateDimension(prob->subprobs[height-1], cdim);CHKERRQ(ierr); 3960 for (f = 0; f < Nf; ++f) { 3961 PetscFE subfe; 3962 PetscObject obj; 3963 PetscClassId id; 3964 3965 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 3966 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3967 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetHeightSubspace((PetscFE) obj, height, &subfe);CHKERRQ(ierr);} 3968 else SETERRQ1(PetscObjectComm((PetscObject) prob), PETSC_ERR_ARG_WRONG, "Unsupported discretization type for field %d", f); 3969 ierr = PetscDSSetDiscretization(prob->subprobs[height-1], f, (PetscObject) subfe);CHKERRQ(ierr); 3970 } 3971 } 3972 *subprob = prob->subprobs[height-1]; 3973 PetscFunctionReturn(0); 3974 } 3975 3976 PetscErrorCode PetscDSGetDiscType_Internal(PetscDS ds, PetscInt f, PetscDiscType *disctype) 3977 { 3978 PetscObject obj; 3979 PetscClassId id; 3980 PetscInt Nf; 3981 PetscErrorCode ierr; 3982 3983 PetscFunctionBegin; 3984 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 3985 PetscValidPointer(disctype, 3); 3986 *disctype = PETSC_DISC_NONE; 3987 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 3988 if (f >= Nf) SETERRQ2(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_SIZ, "Field %D must be in [0, %D)", f, Nf); 3989 ierr = PetscDSGetDiscretization(ds, f, &obj);CHKERRQ(ierr); 3990 if (obj) { 3991 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 3992 if (id == PETSCFE_CLASSID) *disctype = PETSC_DISC_FE; 3993 else *disctype = PETSC_DISC_FV; 3994 } 3995 PetscFunctionReturn(0); 3996 } 3997 3998 static PetscErrorCode PetscDSDestroy_Basic(PetscDS ds) 3999 { 4000 PetscErrorCode ierr; 4001 4002 PetscFunctionBegin; 4003 ierr = PetscFree(ds->data);CHKERRQ(ierr); 4004 PetscFunctionReturn(0); 4005 } 4006 4007 static PetscErrorCode PetscDSInitialize_Basic(PetscDS ds) 4008 { 4009 PetscFunctionBegin; 4010 ds->ops->setfromoptions = NULL; 4011 ds->ops->setup = NULL; 4012 ds->ops->view = NULL; 4013 ds->ops->destroy = PetscDSDestroy_Basic; 4014 PetscFunctionReturn(0); 4015 } 4016 4017 /*MC 4018 PETSCDSBASIC = "basic" - A discrete system with pointwise residual and boundary residual functions 4019 4020 Level: intermediate 4021 4022 .seealso: PetscDSType, PetscDSCreate(), PetscDSSetType() 4023 M*/ 4024 4025 PETSC_EXTERN PetscErrorCode PetscDSCreate_Basic(PetscDS ds) 4026 { 4027 PetscDS_Basic *b; 4028 PetscErrorCode ierr; 4029 4030 PetscFunctionBegin; 4031 PetscValidHeaderSpecific(ds, PETSCDS_CLASSID, 1); 4032 ierr = PetscNewLog(ds, &b);CHKERRQ(ierr); 4033 ds->data = b; 4034 4035 ierr = PetscDSInitialize_Basic(ds);CHKERRQ(ierr); 4036 PetscFunctionReturn(0); 4037 } 4038