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