1 #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/ 2 #include <petsc/private/petscfeimpl.h> /*I "petscdmfield.h" I*/ 3 #include <petscdmplex.h> 4 5 const char *const DMFieldContinuities[] = { 6 "VERTEX", 7 "EDGE", 8 "FACET", 9 "CELL", 10 0 11 }; 12 13 PETSC_INTERN PetscErrorCode DMFieldCreate(DM dm,PetscInt numComponents,DMFieldContinuity continuity,DMField *field) 14 { 15 PetscErrorCode ierr; 16 DMField b; 17 18 PetscFunctionBegin; 19 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 20 PetscValidPointer(field,2); 21 ierr = DMFieldInitializePackage();CHKERRQ(ierr); 22 23 ierr = PetscHeaderCreate(b,DMFIELD_CLASSID,"DMField","Field over DM","DM",PetscObjectComm((PetscObject)dm),DMFieldDestroy,DMFieldView);CHKERRQ(ierr); 24 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 25 b->dm = dm; 26 b->continuity = continuity; 27 b->numComponents = numComponents; 28 *field = b; 29 PetscFunctionReturn(0); 30 } 31 32 /*@ 33 DMFieldDestroy - destroy a DMField 34 35 Collective 36 37 Input Arguments: 38 . field - address of DMField 39 40 Level: advanced 41 42 .seealso: DMFieldCreate() 43 @*/ 44 PetscErrorCode DMFieldDestroy(DMField *field) 45 { 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 if (!*field) PetscFunctionReturn(0); 50 PetscValidHeaderSpecific((*field),DMFIELD_CLASSID,1); 51 if (--((PetscObject)(*field))->refct > 0) {*field = 0; PetscFunctionReturn(0);} 52 if ((*field)->ops->destroy) {ierr = (*(*field)->ops->destroy)(*field);CHKERRQ(ierr);} 53 ierr = DMDestroy(&((*field)->dm));CHKERRQ(ierr); 54 ierr = PetscHeaderDestroy(field);CHKERRQ(ierr); 55 PetscFunctionReturn(0); 56 } 57 58 /*@C 59 DMFieldView - view a DMField 60 61 Collective 62 63 Input Arguments: 64 + field - DMField 65 - viewer - viewer to display field, for example PETSC_VIEWER_STDOUT_WORLD 66 67 Level: advanced 68 69 .seealso: DMFieldCreate() 70 @*/ 71 PetscErrorCode DMFieldView(DMField field,PetscViewer viewer) 72 { 73 PetscErrorCode ierr; 74 PetscBool iascii; 75 76 PetscFunctionBegin; 77 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 78 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)field),&viewer);CHKERRQ(ierr);} 79 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 80 PetscCheckSameComm(field,1,viewer,2); 81 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 82 if (iascii) { 83 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)field,viewer);CHKERRQ(ierr); 84 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 85 ierr = PetscViewerASCIIPrintf(viewer,"%D components\n",field->numComponents);CHKERRQ(ierr); 86 ierr = PetscViewerASCIIPrintf(viewer,"%s continuity\n",DMFieldContinuities[field->continuity]);CHKERRQ(ierr); 87 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_DEFAULT);CHKERRQ(ierr); 88 ierr = DMView(field->dm,viewer);CHKERRQ(ierr); 89 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 90 } 91 if (field->ops->view) {ierr = (*field->ops->view)(field,viewer);CHKERRQ(ierr);} 92 if (iascii) { 93 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 94 } 95 PetscFunctionReturn(0); 96 } 97 98 /*@C 99 DMFieldSetType - set the DMField implementation 100 101 Collective on DMField 102 103 Input Parameters: 104 + field - the DMField context 105 - type - a known method 106 107 Notes: 108 See "include/petscvec.h" for available methods (for instance) 109 + DMFIELDDA - a field defined only by its values at the corners of a DMDA 110 . DMFIELDDS - a field defined by a discretization over a mesh set with DMSetField() 111 - DMFIELDSHELL - a field defined by arbitrary callbacks 112 113 Level: advanced 114 115 .keywords: DMField, set, type 116 117 .seealso: DMFieldType, 118 @*/ 119 PetscErrorCode DMFieldSetType(DMField field,DMFieldType type) 120 { 121 PetscErrorCode ierr,(*r)(DMField); 122 PetscBool match; 123 124 PetscFunctionBegin; 125 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 126 PetscValidCharPointer(type,2); 127 128 ierr = PetscObjectTypeCompare((PetscObject)field,type,&match);CHKERRQ(ierr); 129 if (match) PetscFunctionReturn(0); 130 131 ierr = PetscFunctionListFind(DMFieldList,type,&r);CHKERRQ(ierr); 132 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested DMField type %s",type); 133 /* Destroy the previous private DMField context */ 134 if (field->ops->destroy) { 135 ierr = (*(field)->ops->destroy)(field);CHKERRQ(ierr); 136 } 137 ierr = PetscMemzero(field->ops,sizeof(*field->ops));CHKERRQ(ierr); 138 ierr = PetscObjectChangeTypeName((PetscObject)field,type);CHKERRQ(ierr); 139 field->ops->create = r; 140 ierr = (*r)(field);CHKERRQ(ierr); 141 PetscFunctionReturn(0); 142 } 143 144 /*@C 145 DMFieldGetType - Gets the DMField type name (as a string) from the DMField. 146 147 Not Collective 148 149 Input Parameter: 150 . field - The DMField context 151 152 Output Parameter: 153 . type - The DMField type name 154 155 Level: advanced 156 157 .keywords: DMField, get, type, name 158 .seealso: DMFieldSetType() 159 @*/ 160 PetscErrorCode DMFieldGetType(DMField field, DMFieldType *type) 161 { 162 PetscErrorCode ierr; 163 164 PetscFunctionBegin; 165 PetscValidHeaderSpecific(field, VEC_TAGGER_CLASSID,1); 166 PetscValidPointer(type,2); 167 ierr = DMFieldRegisterAll();CHKERRQ(ierr); 168 *type = ((PetscObject)field)->type_name; 169 PetscFunctionReturn(0); 170 } 171 172 /*@ 173 DMFieldGetNumComponents - Returns the number of components in the field 174 175 Not collective 176 177 Input Parameter: 178 . field - The DMField object 179 180 Output Parameter: 181 . nc - The number of field components 182 183 Level: intermediate 184 185 .seealso: DMFieldEvaluate() 186 @*/ 187 PetscErrorCode DMFieldGetNumComponents(DMField field, PetscInt *nc) 188 { 189 PetscFunctionBegin; 190 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 191 PetscValidIntPointer(nc,2); 192 *nc = field->numComponents; 193 PetscFunctionReturn(0); 194 } 195 196 /*@ 197 DMFieldGetDM - Returns the DM for the manifold over which the field is defined. 198 199 Not collective 200 201 Input Parameter: 202 . field - The DMField object 203 204 Output Parameter: 205 . dm - The DM object 206 207 Level: intermediate 208 209 .seealso: DMFieldEvaluate() 210 @*/ 211 PetscErrorCode DMFieldGetDM(DMField field, DM *dm) 212 { 213 PetscFunctionBegin; 214 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 215 PetscValidPointer(dm,2); 216 *dm = field->dm; 217 PetscFunctionReturn(0); 218 } 219 220 /*@ 221 DMFieldEvaluate - Evaluate the field and its derivatives on a set of points 222 223 Collective on Vec 224 225 Input Parameter: 226 + field - The DMField object 227 . points - The points at which to evaluate the field. Should have size d x n, 228 where d is the coordinate dimension of the manifold and n is the number 229 of points 230 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR. 231 If the field is complex and datatype is PETSC_REAL, the real part of the 232 field is returned. 233 234 235 Output Parameter: 236 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field. 237 If B is not NULL, the values of the field are written in this array, varying first by component, 238 then by point. 239 . D - pointer to data of size d * c * n * sizeof(datatype). 240 If D is not NULL, the values of the field's spatial derivatives are written in this array, 241 varying first by the partial derivative component, then by field component, then by point. 242 - H - pointer to data of size d * d * c * n * sizeof(datatype). 243 If H is not NULL, the values of the field's second spatial derivatives are written in this array, 244 varying first by the second partial derivative component, then by field component, then by point. 245 246 Level: intermediate 247 248 .seealso: DMFieldGetDM(), DMFieldGetNumComponents(), DMFieldEvaluateFE(), DMFieldEvaluateFV() 249 @*/ 250 PetscErrorCode DMFieldEvaluate(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H) 251 { 252 PetscErrorCode ierr; 253 254 PetscFunctionBegin; 255 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 256 PetscValidHeaderSpecific(points,VEC_CLASSID,2); 257 if (B) PetscValidPointer(B,3); 258 if (D) PetscValidPointer(D,4); 259 if (H) PetscValidPointer(H,5); 260 if (field->ops->evaluate) { 261 ierr = (*field->ops->evaluate) (field, points, datatype, B, D, H);CHKERRQ(ierr); 262 } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type"); 263 PetscFunctionReturn(0); 264 } 265 266 /*@ 267 DMFieldEvaluateFE - Evaluate the field and its derivatives on a set of points mapped from 268 quadrature points on a reference point. The derivatives are taken with respect to the 269 reference coordinates. 270 271 Not collective 272 273 Input Parameter: 274 + field - The DMField object 275 . cellIS - Index set for cells on which to evaluate the field 276 . points - The quadature containing the points in the reference cell at which to evaluate the field. 277 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR. 278 If the field is complex and datatype is PETSC_REAL, the real part of the 279 field is returned. 280 281 282 Output Parameter: 283 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field. 284 If B is not NULL, the values of the field are written in this array, varying first by component, 285 then by point. 286 . D - pointer to data of size d * c * n * sizeof(datatype). 287 If D is not NULL, the values of the field's spatial derivatives are written in this array, 288 varying first by the partial derivative component, then by field component, then by point. 289 - H - pointer to data of size d * d * c * n * sizeof(datatype). 290 If H is not NULL, the values of the field's second spatial derivatives are written in this array, 291 varying first by the second partial derivative component, then by field component, then by point. 292 293 Level: intermediate 294 295 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFV() 296 @*/ 297 PetscErrorCode DMFieldEvaluateFE(DMField field, IS cellIS, PetscQuadrature points, PetscDataType datatype, void *B, void *D, void *H) 298 { 299 PetscErrorCode ierr; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 303 PetscValidHeaderSpecific(cellIS,IS_CLASSID,2); 304 PetscValidHeader(points,3); 305 if (B) PetscValidPointer(B,4); 306 if (D) PetscValidPointer(D,5); 307 if (H) PetscValidPointer(H,6); 308 if (field->ops->evaluateFE) { 309 ierr = (*field->ops->evaluateFE) (field, cellIS, points, datatype, B, D, H);CHKERRQ(ierr); 310 } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type"); 311 PetscFunctionReturn(0); 312 } 313 314 /*@ 315 DMFieldEvaluateFV - Evaluate the mean of a field and its finite volume derivatives on a set of points. 316 317 Not collective 318 319 Input Parameter: 320 + field - The DMField object 321 . cellIS - Index set for cells on which to evaluate the field 322 - datatype - The PetscDataType of the output arrays: either PETSC_REAL or PETSC_SCALAR. 323 If the field is complex and datatype is PETSC_REAL, the real part of the 324 field is returned. 325 326 327 Output Parameter: 328 + B - pointer to data of size c * n * sizeof(datatype), where c is the number of components in the field. 329 If B is not NULL, the values of the field are written in this array, varying first by component, 330 then by point. 331 . D - pointer to data of size d * c * n * sizeof(datatype). 332 If D is not NULL, the values of the field's spatial derivatives are written in this array, 333 varying first by the partial derivative component, then by field component, then by point. 334 - H - pointer to data of size d * d * c * n * sizeof(datatype). 335 If H is not NULL, the values of the field's second spatial derivatives are written in this array, 336 varying first by the second partial derivative component, then by field component, then by point. 337 338 Level: intermediate 339 340 .seealso: DMFieldGetNumComponents(), DMFieldEvaluate(), DMFieldEvaluateFE() 341 @*/ 342 PetscErrorCode DMFieldEvaluateFV(DMField field, IS cellIS, PetscDataType datatype, void *B, void *D, void *H) 343 { 344 PetscErrorCode ierr; 345 346 PetscFunctionBegin; 347 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 348 PetscValidHeaderSpecific(cellIS,IS_CLASSID,2); 349 if (B) PetscValidPointer(B,3); 350 if (D) PetscValidPointer(D,4); 351 if (H) PetscValidPointer(H,5); 352 if (field->ops->evaluateFV) { 353 ierr = (*field->ops->evaluateFV) (field, cellIS, datatype, B, D, H);CHKERRQ(ierr); 354 } else SETERRQ (PetscObjectComm((PetscObject)field),PETSC_ERR_SUP,"Not implemented for this type"); 355 PetscFunctionReturn(0); 356 } 357 358 /*@ 359 DMFieldGetDegree - Get the polynomial degree of a field when pulled back onto the 360 reference element 361 362 Not collective 363 364 Input Arguments: 365 + field - the DMField object 366 - cellIS - the index set of points over which we want know the invariance 367 368 Output Arguments: 369 + minDegree - the degree of the largest polynomial space contained in the field on each element 370 - maxDegree - the largest degree of the smallest polynomial space containing the field on any element 371 372 Level: intermediate 373 374 .seealso: DMFieldEvaluateFE() 375 @*/ 376 PetscErrorCode DMFieldGetDegree(DMField field, IS cellIS, PetscInt *minDegree, PetscInt *maxDegree) 377 { 378 PetscErrorCode ierr; 379 380 PetscFunctionBegin; 381 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 382 PetscValidHeaderSpecific(cellIS,IS_CLASSID,2); 383 if (minDegree) PetscValidPointer(minDegree,3); 384 if (maxDegree) PetscValidPointer(maxDegree,4); 385 386 if (minDegree) *minDegree = -1; 387 if (maxDegree) *maxDegree = PETSC_MAX_INT; 388 389 if (field->ops->getDegree) { 390 ierr = (*field->ops->getDegree) (field,cellIS,minDegree,maxDegree);CHKERRQ(ierr); 391 } 392 PetscFunctionReturn(0); 393 } 394 395 /*@ 396 DMFieldCreateDefaultQuadrature - Creates a quadrature sufficient to integrate the field on the selected 397 points via pullback onto the reference element 398 399 Not collective 400 401 Input Arguments: 402 + field - the DMField object 403 - pointIS - the index set of points over which we wish to integrate the field 404 405 Output Arguments: 406 . quad - a PetscQuadrature object 407 408 Level: developer 409 410 .seealso: DMFieldEvaluteFE(), DMFieldGetDegree() 411 @*/ 412 PetscErrorCode DMFieldCreateDefaultQuadrature(DMField field, IS pointIS, PetscQuadrature *quad) 413 { 414 PetscErrorCode ierr; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 418 PetscValidHeaderSpecific(pointIS,IS_CLASSID,2); 419 PetscValidPointer(quad,3); 420 421 *quad = NULL; 422 if (field->ops->createDefaultQuadrature) { 423 ierr = (*field->ops->createDefaultQuadrature)(field, pointIS, quad);CHKERRQ(ierr); 424 } 425 PetscFunctionReturn(0); 426 } 427 428 /*@C 429 DMFieldCreateFEGeom - Compute and create the geometric factors of a coordinate field 430 431 Not collective 432 433 Input Arguments: 434 + field - the DMField object 435 . pointIS - the index set of points over which we wish to integrate the field 436 . quad - the quadrature points at which to evaluate the geometric factors 437 - faceData - whether additional data for facets (the normal vectors and adjacent cells) should 438 be calculated 439 440 Output Arguments: 441 . geom - the geometric factors 442 443 Level: developer 444 445 .seealso: DMFieldEvaluateFE(), DMFieldCreateDefaulteQuadrature(), DMFieldGetDegree() 446 @*/ 447 PetscErrorCode DMFieldCreateFEGeom(DMField field, IS pointIS, PetscQuadrature quad, PetscBool faceData, PetscFEGeom **geom) 448 { 449 PetscInt dim, dE; 450 PetscInt nPoints; 451 PetscInt maxDegree; 452 PetscFEGeom *g; 453 PetscErrorCode ierr; 454 455 PetscFunctionBegin; 456 PetscValidHeaderSpecific(field,DMFIELD_CLASSID,1); 457 PetscValidHeaderSpecific(pointIS,IS_CLASSID,2); 458 PetscValidHeader(quad,3); 459 ierr = ISGetLocalSize(pointIS,&nPoints);CHKERRQ(ierr); 460 dE = field->numComponents; 461 ierr = PetscFEGeomCreate(quad,nPoints,dE,faceData,&g);CHKERRQ(ierr); 462 ierr = DMFieldEvaluateFE(field,pointIS,quad,PETSC_REAL,g->v,g->J,NULL);CHKERRQ(ierr); 463 dim = g->dim; 464 if (dE > dim) { 465 /* space out J and make square Jacobians */ 466 PetscInt i, j, k, N = g->numPoints * g->numCells; 467 468 for (i = N-1; i >= 0; i--) { 469 PetscReal J[9]; 470 471 for (j = 0; j < dE; j++) { 472 for (k = 0; k < dim; k++) { 473 J[j*dE + k] = g->J[i*dE*dim + j*dim + k]; 474 } 475 } 476 switch (dim) { 477 case 0: 478 for (j = 0; j < dE; j++) { 479 for (k = 0; k < dE; k++) { 480 J[j * dE + k] = (j == k) ? 1. : 0.; 481 } 482 } 483 break; 484 case 1: 485 if (dE == 2) { 486 PetscReal norm = PetscSqrtReal(J[0] * J[0] + J[2] * J[2]); 487 488 J[1] = -J[2] / norm; 489 J[3] = J[0] / norm; 490 } else { 491 PetscReal inorm = 1./PetscSqrtReal(J[0] * J[0] + J[3] * J[3] + J[6] * J[6]); 492 PetscReal x = J[0] * inorm; 493 PetscReal y = J[3] * inorm; 494 PetscReal z = J[6] * inorm; 495 496 if (x > 0.) { 497 PetscReal inv1pX = 1./ (1. + x); 498 499 J[1] = -y; J[2] = -z; 500 J[4] = 1. - y*y*inv1pX; J[5] = -y*z*inv1pX; 501 J[7] = -y*z*inv1pX; J[8] = 1. - z*z*inv1pX; 502 } else { 503 PetscReal inv1mX = 1./ (1. - x); 504 505 J[1] = z; J[2] = y; 506 J[4] = -y*z*inv1mX; J[5] = 1. - y*y*inv1mX; 507 J[7] = 1. - z*z*inv1mX; J[8] = -y*z*inv1mX; 508 } 509 } 510 break; 511 case 2: 512 { 513 PetscReal inorm; 514 515 J[2] = J[3] * J[7] - J[6] * J[4]; 516 J[5] = J[6] * J[1] - J[0] * J[7]; 517 J[8] = J[0] * J[4] - J[3] * J[1]; 518 519 inorm = 1./ PetscSqrtReal(J[2]*J[2] + J[5]*J[5] + J[8]*J[8]); 520 521 J[2] *= inorm; 522 J[5] *= inorm; 523 J[8] *= inorm; 524 } 525 break; 526 } 527 for (j = 0; j < dE*dE; j++) { 528 g->J[i*dE*dE + j] = J[j]; 529 } 530 } 531 } 532 ierr = PetscFEGeomComplete(g);CHKERRQ(ierr); 533 ierr = DMFieldGetDegree(field,pointIS,NULL,&maxDegree);CHKERRQ(ierr); 534 g->isAffine = (maxDegree <= 1) ? PETSC_TRUE : PETSC_FALSE; 535 if (faceData) { 536 if (!field->ops->computeFaceData) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMField implementation does not compute face data\n"); 537 ierr = (*field->ops->computeFaceData) (field, pointIS, quad, g);CHKERRQ(ierr); 538 } 539 *geom = g; 540 PetscFunctionReturn(0); 541 } 542