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