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