Go to the documentation of this file.
28#ifndef EWOMS_VCFV_STENCIL_HH
29#define EWOMS_VCFV_STENCIL_HH
31#include <dune/common/version.hh>
32#include <dune/geometry/referenceelements.hh>
34#include <dune/grid/common/intersectioniterator.hh>
35#include <dune/grid/common/mcmgmapper.hh>
39#if HAVE_DUNE_LOCALFUNCTIONS
40#include <dune/localfunctions/lagrange/pqkfactory.hh>
65template < class Scalar, unsigned dim, ElementType basicGeomType>
66class VcfvScvGeometries;
71template < class Scalar>
72class VcfvScvGeometries<Scalar, 1, ElementType::cube>
78 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
83 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] = {
94 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
95 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
99 static const ScvLocalGeometry& get( unsigned scvIdx)
100 { return scvGeoms_[scvIdx]; }
103 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
106template < class Scalar>
113 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
115 static const ScvLocalGeometry& get( unsigned)
117 throw std::logic_error( "Not implemented: VcfvScvGeometries<Scalar, 1, ElementType::simplex>");
124template < class Scalar>
131 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
133 static const ScvLocalGeometry& get( unsigned scvIdx)
134 { return scvGeoms_[scvIdx]; }
139 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
163 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
164 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
169 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
172template < class Scalar>
179 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
181 static const ScvLocalGeometry& get( unsigned scvIdx)
182 { return scvGeoms_[scvIdx]; }
187 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
218 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
219 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
223 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
229template < class Scalar>
236 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
238 static const ScvLocalGeometry& get( unsigned scvIdx)
239 { return scvGeoms_[scvIdx]; }
244 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
250 { 1.0/3, 1.0/3, 0.0 },
253 { 1.0/3, 0.0, 1.0/3 },
254 { 0.0, 1.0/3, 1.0/3 },
255 { 1.0/4, 1.0/4, 1.0/4 },
261 { 1.0/3, 1.0/3, 0.0 },
262 { 1.0/2, 1.0/2, 0.0 },
264 { 1.0/3, 0.0, 1.0/3 },
265 { 1.0/2, 0.0, 1.0/2 },
266 { 1.0/4, 1.0/4, 1.0/4 },
267 { 1.0/3, 1.0/3, 1.0/3 },
272 { 1.0/3, 1.0/3, 0.0 },
274 { 1.0/2, 1.0/2, 0.0 },
276 { 0.0, 1.0/3, 1.0/3 },
277 { 1.0/4, 1.0/4, 1.0/4 },
278 { 0.0, 1.0/2, 1.0/2 },
279 { 1.0/3, 1.0/3, 1.0/3 },
284 { 1.0/3, 0.0, 1.0/3 },
285 { 0.0, 1.0/3, 1.0/3 },
286 { 1.0/4, 1.0/4, 1.0/4 },
289 { 1.0/2, 0.0, 1.0/2 },
290 { 0.0, 1.0/2, 1.0/2 },
291 { 1.0/3, 1.0/3, 1.0/3 },
295 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
296 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
301 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
304template < class Scalar>
311 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
313 static const ScvLocalGeometry& get( unsigned scvIdx)
314 { return scvGeoms_[scvIdx]; }
319 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
325 { 1.0/2, 1.0/2, 0.0 },
328 { 1.0/2, 0.0, 1.0/2 },
329 { 0.0, 1.0/2, 1.0/2 },
330 { 1.0/2, 1.0/2, 1.0/2 },
336 { 1.0/2, 1.0/2, 0.0 },
339 { 1.0/2, 0.0, 1.0/2 },
341 { 1.0/2, 1.0/2, 1.0/2 },
342 { 1.0, 1.0/2, 1.0/2 },
347 { 1.0/2, 1.0/2, 0.0 },
351 { 0.0, 1.0/2, 1.0/2 },
352 { 1.0/2, 1.0/2, 1.0/2 },
354 { 1.0/2, 1.0, 1.0/2 },
358 { 1.0/2, 1.0/2, 0.0 },
363 { 1.0/2, 1.0/2, 1.0/2 },
364 { 1.0, 1.0/2, 1.0/2 },
365 { 1.0/2, 1.0, 1.0/2 },
371 { 1.0/2, 0.0, 1.0/2 },
372 { 0.0, 1.0/2, 1.0/2 },
373 { 1.0/2, 1.0/2, 1.0/2 },
378 { 1.0/2, 1.0/2, 1.0 },
382 { 1.0/2, 0.0, 1.0/2 },
384 { 1.0/2, 1.0/2, 1.0/2 },
385 { 1.0, 1.0/2, 1.0/2 },
389 { 1.0/2, 1.0/2, 1.0 },
394 { 0.0, 1.0/2, 1.0/2 },
395 { 1.0/2, 1.0/2, 1.0/2 },
397 { 1.0/2, 1.0, 1.0/2 },
400 { 1.0/2, 1.0/2, 1.0 },
406 { 1.0/2, 1.0/2, 1.0/2 },
407 { 1.0, 1.0/2, 1.0/2 },
408 { 1.0/2, 1.0, 1.0/2 },
411 { 1.0/2, 1.0/2, 1.0 },
418 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
419 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
423 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
449template < class Scalar, class Gr idView>
452 enum { dim = GridView::dimension };
453 enum { dimWorld = GridView::dimensionworld };
454 enum { maxNC = dim < 3 ? 4 : 8 };
455 enum { maxNE = dim < 3 ? 4 : 12 };
456 enum { maxNF = dim < 3 ? 1 : 6 };
457 enum { maxBF = dim < 3 ? 8 : 24 };
458 using CoordScalar = typename GridView::ctype;
459 using Element = typename GridView::Traits::template Codim<0>::Entity;
462 using Entity = typename GridView::Traits::template Codim<dim>::Entity;
465 using Geometry = typename Element::Geometry;
466 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
467 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
468 using LocalPosition = Dune::FieldVector<CoordScalar, dim>;
469 using IntersectionIterator = typename GridView::IntersectionIterator;
473#if HAVE_DUNE_LOCALFUNCTIONS
474 using LocalFiniteElementCache = Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
475 using LocalFiniteElement = typename LocalFiniteElementCache::FiniteElementType;
476 using LocalBasisTraits = typename LocalFiniteElement::Traits::LocalBasisType::Traits;
477 using ShapeJacobian = typename LocalBasisTraits::JacobianType;
480 Scalar quadrilateralArea( const GlobalPosition& p0,
481 const GlobalPosition& p1,
482 const GlobalPosition& p2,
483 const GlobalPosition& p3)
485 return 0.5 * std::abs((p3[0] - p1[0]) * (p2[1] - p0[1]) -
486 (p3[1] - p1[1]) * (p2[0] - p0[0]));
489 void crossProduct(DimVector& c, const DimVector& a, const DimVector& b)
491 c[0] = a[1] * b[2] - a[2] * b[1];
492 c[1] = a[2] * b[0] - a[0] * b[2];
493 c[2] = a[0] * b[1] - a[1] * b[0];
496 Scalar pyramidVolume( const GlobalPosition& p0,
497 const GlobalPosition& p1,
498 const GlobalPosition& p2,
499 const GlobalPosition& p3,
500 const GlobalPosition& p4)
502 DimVector a(p2); a -= p0;
503 DimVector b(p3); b -= p1;
506 crossProduct(n, a, b);
510 return 1.0 / 6.0 * (n * a);
513 Scalar prismVolume( const GlobalPosition& p0,
514 const GlobalPosition& p1,
515 const GlobalPosition& p2,
516 const GlobalPosition& p3,
517 const GlobalPosition& p4,
518 const GlobalPosition& p5)
521 for ( unsigned k = 0; k < dimWorld; ++k) {
525 for ( unsigned k = 0; k < dimWorld; ++k) {
529 crossProduct(m, a, b);
531 for ( unsigned k = 0; k < dimWorld; ++k) {
532 a[k] = p1[k] - p0[k];
534 for ( unsigned k = 0; k < dimWorld; ++k) {
535 b[k] = p2[k] - p0[k];
538 crossProduct(n, a, b);
541 for ( unsigned k = 0; k < dimWorld; ++k) {
542 a[k] = p5[k] - p0[k];
545 return std::abs(1.0 / 6.0 * (n * a));
548 Scalar hexahedronVolume( const GlobalPosition& p0,
549 const GlobalPosition& p1,
550 const GlobalPosition& p2,
551 const GlobalPosition& p3,
552 const GlobalPosition& p4,
553 const GlobalPosition& p5,
554 const GlobalPosition& p6,
555 const GlobalPosition& p7)
557 return prismVolume(p0, p1, p2, p4, p5, p6) +
558 prismVolume(p0, p2, p3, p4, p6, p7);
561 void normalOfQuadrilateral3D(DimVector& normal,
562 const GlobalPosition& p0,
563 const GlobalPosition& p1,
564 const GlobalPosition& p2,
565 const GlobalPosition& p3)
568 for ( unsigned k = 0; k < dimWorld; ++k) {
572 for ( unsigned k = 0; k < dimWorld; ++k) {
576 crossProduct(normal, a, b);
580 Scalar quadrilateralArea3D( const GlobalPosition& p0,
581 const GlobalPosition& p1,
582 const GlobalPosition& p2,
583 const GlobalPosition& p3)
586 normalOfQuadrilateral3D(normal, p0, p1, p2, p3);
587 return normal.two_norm();
590 void getFaceIndices( unsigned numElemVertices, unsigned k, unsigned& leftFace, unsigned& rightFace)
592 static const unsigned edgeToFaceTet[2][6] = {
596 static const unsigned edgeToFacePyramid[2][8] = {
597 {1, 2, 3, 4, 1, 3, 4, 2},
598 {0, 0, 0, 0, 3, 2, 1, 4}
600 static const unsigned edgeToFacePrism[2][9] = {
601 {1, 0, 2, 0, 1, 2, 4, 4, 4},
602 {0, 2, 1, 3, 3, 3, 0, 1, 2}
604 static const unsigned edgeToFaceHex[2][12] = {
605 {0, 2, 3, 1, 4, 1, 2, 4, 0, 5, 5, 3},
606 {2, 1, 0, 3, 0, 4, 4, 3, 5, 1, 2, 5}
609 switch (numElemVertices) {
611 leftFace = edgeToFaceTet[0][k];
612 rightFace = edgeToFaceTet[1][k];
615 leftFace = edgeToFacePyramid[0][k];
616 rightFace = edgeToFacePyramid[1][k];
619 leftFace = edgeToFacePrism[0][k];
620 rightFace = edgeToFacePrism[1][k];
623 leftFace = edgeToFaceHex[0][k];
624 rightFace = edgeToFaceHex[1][k];
627 throw std::logic_error( "Not implemented: VcfvStencil::getFaceIndices for "
633 void getEdgeIndices( unsigned numElemVertices, unsigned face, unsigned vert,
634 unsigned& leftEdge, unsigned& rightEdge)
636 static const int faceAndVertexToLeftEdgeTet[4][4] = {
642 static const int faceAndVertexToRightEdgeTet[4][4] = {
648 static const int faceAndVertexToLeftEdgePyramid[5][5] = {
655 static const int faceAndVertexToRightEdgePyramid[5][5] = {
662 static const int faceAndVertexToLeftEdgePrism[5][6] = {
663 { 3, 3, -1, 0, 1, -1},
664 { 4, -1, 4, 0, -1, 2},
665 {-1, 5, 5, -1, 1, 2},
666 { 3, 3, 5, -1, -1, -1},
667 {-1, -1, -1, 6, 6, 8}
669 static const int faceAndVertexToRightEdgePrism[5][6] = {
670 { 0, 1, -1, 6, 6, -1},
671 { 0, -1, 2, 7, -1, 7},
672 {-1, 1, 2, -1, 8, 8},
673 { 4, 5, 4, -1, -1, -1},
674 {-1, -1, -1, 7, 8, 7}
676 static const int faceAndVertexToLeftEdgeHex[6][8] = {
677 { 0, -1, 4, -1, 8, -1, 2, -1},
678 {-1, 5, -1, 3, -1, 1, -1, 9},
679 { 6, 1, -1, -1, 0, 10, -1, -1},
680 {-1, -1, 2, 7, -1, -1, 11, 3},
681 { 4, 6, 7, 5, -1, -1, -1, -1},
682 {-1, -1, -1, -1, 10, 9, 8, 11}
684 static const int faceAndVertexToRightEdgeHex[6][8] = {
685 { 4, -1, 2, -1, 0, -1, 8, -1},
686 {-1, 1, -1, 5, -1, 9, -1, 3},
687 { 0, 6, -1, -1, 10, 1, -1, -1},
688 {-1, -1, 7, 3, -1, -1, 2, 11},
689 { 6, 5, 4, 7, -1, -1, -1, -1},
690 {-1, -1, -1, -1, 8, 10, 11, 9}
693 switch (numElemVertices) {
695 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgeTet[face][vert]);
696 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgeTet[face][vert]);
699 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgePyramid[face][vert]);
700 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgePyramid[face][vert]);
703 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgePrism[face][vert]);
704 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgePrism[face][vert]);
707 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgeHex[face][vert]);
708 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgeHex[face][vert]);
711 throw std::logic_error( "Not implemented: VcfvStencil::getFaceIndices for "
719 using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
727 const GlobalPosition corner( unsigned cornerIdx) const
730 const GlobalPosition global( const LocalPosition& localPos) const
731 { return element_->geometry().global(localPos); }
813 : gridView_(gridView)
814 , vertexMapper_(mapper )
815 , element_(*gridView.template begin<0>())
818 assert( static_cast<int>(gridView.size(dimWorld)) == static_cast<int>(mapper.size()));
820 static bool localGeometriesInitialized = false;
821 if (!localGeometriesInitialized) {
822 localGeometriesInitialized = true;
841 numVertices = e.subEntities(dim);
842 numEdges = e.subEntities(dim-1);
843 if constexpr (dim == 3) {
844 numFaces = e.subEntities(1);
850 numBoundarySegments_ = 0;
853 const Geometry& geometry = e.geometry();
854 geometryType_ = geometry.type();
855 const auto& referenceElement = Dune::ReferenceElements<CoordScalar,dim>::general(geometryType_);
856 for ( unsigned vertexIdx = 0; vertexIdx < numVertices; ++vertexIdx) {
857 subContVol[vertexIdx].local = referenceElement.position( static_cast<int>(vertexIdx), dim);
858 subContVol[vertexIdx].global = geometry.corner( static_cast<int>(vertexIdx));
874 const Geometry& geometry = e.geometry();
875 geometryType_ = geometry.type();
877 const auto& referenceElement = Dune::ReferenceElements<CoordScalar,dim>::general(geometryType_);
879 elementVolume = geometry.volume();
880 elementLocal = referenceElement.position(0, 0);
881 elementGlobal = geometry.global(elementLocal);
884 for ( unsigned vert = 0; vert < numVertices; ++vert) {
885 subContVol[vert].local = referenceElement.position( static_cast<int>(vert), dim);
886 subContVol[vert].global = geometry.global(subContVol[vert].local);
890 for ( unsigned edge = 0; edge < numEdges; ++edge) {
891 edgeCoord[edge] = geometry.global(referenceElement.position( static_cast<int>(edge), dim - 1));
895 for ( unsigned face = 0; face < numFaces; ++face) {
896 faceCoord[face] = geometry.global(referenceElement.position( static_cast<int>(face), 1));
904 fillSubContVolData_();
907 for ( unsigned k = 0; k < numEdges; ++k) {
909 static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(k), dim - 1, 0, dim));
911 static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(k), dim - 1, 1, dim));
912 if (numEdges == 4 && (i == 2 || j == 2)) {
915 subContVolFace[k].i = i;
916 subContVolFace[k].j = j;
923 LocalPosition ipLocal;
925 if constexpr (dim == 1) {
926 subContVolFace[k].ipLocal_ = 0.5;
927 subContVolFace[k].normal_ = 1.0;
928 subContVolFace[k].area_ = 1.0;
929 ipLocal = subContVolFace[k].ipLocal_;
931 else if constexpr (dim == 2) {
932 ipLocal = referenceElement.position( static_cast<int>(k), dim - 1) + elementLocal;
934 subContVolFace[k].ipLocal_ = ipLocal;
935 for ( unsigned m = 0; m < dimWorld; ++m) {
936 diffVec[m] = elementGlobal[m] - edgeCoord[k][m];
938 subContVolFace[k].normal_[0] = diffVec[1];
939 subContVolFace[k].normal_[1] = -diffVec[0];
941 for ( unsigned m = 0; m < dimWorld; ++m) {
942 diffVec[m] = subContVol[j].global[m] - subContVol[i].global[m];
945 if (subContVolFace[k].normal_ * diffVec < 0) {
946 subContVolFace[k].normal_ *= -1;
949 subContVolFace[k].area_ = subContVolFace[k].normal_.two_norm();
950 subContVolFace[k].normal_ /= subContVolFace[k].area_;
952 else if constexpr (dim == 3) {
955 getFaceIndices(numVertices, k, leftFace, rightFace);
956 ipLocal = referenceElement.position( static_cast<int>(k), dim - 1) +
958 referenceElement.position( static_cast<int>(leftFace), 1) +
959 referenceElement.position( static_cast<int>(rightFace), 1);
961 subContVolFace[k].ipLocal_ = ipLocal;
962 normalOfQuadrilateral3D(subContVolFace[k].normal_,
963 edgeCoord[k], faceCoord[rightFace],
964 elementGlobal, faceCoord[leftFace]);
965 subContVolFace[k].area_ = subContVolFace[k].normal_.two_norm();
966 subContVolFace[k].normal_ /= subContVolFace[k].area_;
970 subContVolFace[k].ipGlobal_ = geometry.global(ipLocal);
974 for ( const auto& intersection : intersections(gridView_, e)) {
975 if (!intersection.boundary()) {
979 const unsigned face = static_cast<unsigned>(intersection.indexInInside());
980 const unsigned numVerticesOfFace = static_cast<unsigned>(referenceElement.size( static_cast<int>(face), 1, dim));
981 for ( unsigned vertInFace = 0; vertInFace < numVerticesOfFace; ++vertInFace) {
982 const unsigned short vertInElement = static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(face), 1, static_cast<int>(vertInFace), dim));
983 const unsigned bfIdx = numBoundarySegments_;
984 ++numBoundarySegments_;
986 if constexpr (dim == 1) {
987 boundaryFace_[bfIdx].ipLocal_ = referenceElement.position( static_cast<int>(vertInElement), dim);
988 boundaryFace_[bfIdx].area_ = 1.0;
990 else if constexpr (dim == 2) {
991 boundaryFace_[bfIdx].ipLocal_ =
992 referenceElement.position( static_cast<int>(vertInElement), dim) +
993 referenceElement.position( static_cast<int>(face), 1);
994 boundaryFace_[bfIdx].ipLocal_ *= 0.5;
995 boundaryFace_[bfIdx].area_ = 0.5 * intersection.geometry().volume();
997 else if constexpr (dim == 3) {
1000 getEdgeIndices(numVertices, face, vertInElement, leftEdge, rightEdge);
1001 boundaryFace_[bfIdx].ipLocal_ =
1002 referenceElement.position( static_cast<int>(vertInElement), dim) +
1003 referenceElement.position( static_cast<int>(face), 1) +
1004 referenceElement.position( static_cast<int>(leftEdge), dim - 1) +
1005 referenceElement.position( static_cast<int>(rightEdge), dim - 1);
1006 boundaryFace_[bfIdx].ipLocal_ *= 0.25;
1007 boundaryFace_[bfIdx].area_ =
1008 quadrilateralArea3D(subContVol[vertInElement].global,
1009 edgeCoord[rightEdge],
1011 edgeCoord[leftEdge]);
1014 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim));
1017 boundaryFace_[bfIdx].ipGlobal_ = geometry.global(boundaryFace_[bfIdx].ipLocal_);
1018 boundaryFace_[bfIdx].i = vertInElement;
1019 boundaryFace_[bfIdx].j = vertInElement;
1022 boundaryFace_[bfIdx].normal_ = intersection.centerUnitOuterNormal();
1031 auto geomType = element.geometry().type();
1034 if (geomType.isTriangle() || geomType.isTetrahedron()) {
1035 for ( unsigned vertIdx = 0; vertIdx < numVertices; ++vertIdx) {
1036 subContVol[vertIdx].geometry_.element_ = &element;
1037 subContVol[vertIdx].geometry_.localGeometry_ =
1038 &VcfvScvGeometries<Scalar, dim, ElementType::simplex>::get(vertIdx);
1041 else if (geomType.isLine() || geomType.isQuadrilateral() || geomType.isHexahedron()) {
1042 for ( unsigned vertIdx = 0; vertIdx < numVertices; ++vertIdx) {
1043 subContVol[vertIdx].geometry_.element_ = &element;
1044 subContVol[vertIdx].geometry_.localGeometry_ =
1045 &VcfvScvGeometries<Scalar, dim, ElementType::cube>::get(vertIdx);
1049 throw std::logic_error( "Not implemented: SCV geometries for non hexahedron elements");
1053#if HAVE_DUNE_LOCALFUNCTIONS
1054 void updateCenterGradients()
1056 const auto& localFiniteElement = feCache_.get(element_.type());
1057 const auto& geom = element_.geometry();
1059 std::vector<ShapeJacobian> localJac;
1061 for ( unsigned scvIdx = 0; scvIdx < numVertices; ++scvIdx) {
1062 const auto& localCenter = subContVol[scvIdx].localGeometry().center();
1063 localFiniteElement.localBasis().evaluateJacobian(localCenter, localJac);
1064 const auto& globalPos = subContVol[scvIdx].geometry().center();
1066 const auto jacInvT = geom.jacobianInverseTransposed(globalPos);
1067 for ( unsigned vert = 0; vert < numVertices; ++vert) {
1068 jacInvT.mv(localJac[vert][0], subContVol[scvIdx].gradCenter[vert]);
1075 { return numVertices; }
1081 { return element_.template subEntity<dim>(scvIdx)-> partitionType(); }
1085 assert(scvIdx < numDof());
1086 return subContVol[scvIdx];
1090 { return numEdges; }
1093 { return numBoundarySegments_; }
1096 { return subContVolFace[faceIdx]; }
1099 { return boundaryFace_[bfIdx]; }
1107 assert(dofIdx < numDof());
1109 return static_cast<unsigned>(vertexMapper_.subIndex(element_, static_cast<int>(dofIdx), dim));
1118 assert(dofIdx < numDof());
1119 return element_.template subEntity<dim>( static_cast<int>(dofIdx));
1123#if __GNUC__ || __clang__
1124#pragma GCC diagnostic push
1125#pragma GCC diagnostic ignored "-Wpragmas"
1126#pragma GCC diagnostic ignored "-Warray-bounds"
1128 void fillSubContVolData_()
1130 if constexpr (dim == 1) {
1132 subContVol[0].volume_ = 0.5 * elementVolume;
1133 subContVol[1].volume_ = 0.5 * elementVolume;
1135 else if constexpr (dim == 2) {
1136 switch (numVertices) {
1138 subContVol[0].volume_ = elementVolume / 3;
1139 subContVol[1].volume_ = elementVolume / 3;
1140 subContVol[2].volume_ = elementVolume / 3;
1143 subContVol[0].volume_ =
1144 quadrilateralArea(subContVol[0].global,
1148 subContVol[1].volume_ =
1149 quadrilateralArea(subContVol[1].global,
1153 subContVol[2].volume_ =
1154 quadrilateralArea(subContVol[2].global,
1158 subContVol[3].volume_ =
1159 quadrilateralArea(subContVol[3].global,
1165 throw std::logic_error( "Not implemented:VcfvStencil dim = " + std::to_string(dim) +
1169 else if constexpr (dim == 3) {
1170 switch (numVertices) {
1172 for ( unsigned k = 0; k < numVertices; k++) {
1173 subContVol[k].volume_ = elementVolume / 4.0;
1177 subContVol[0].volume_ =
1178 hexahedronVolume(subContVol[0].global,
1186 subContVol[1].volume_ =
1187 hexahedronVolume(subContVol[1].global,
1195 subContVol[2].volume_ =
1196 hexahedronVolume(subContVol[2].global,
1204 subContVol[3].volume_ =
1205 hexahedronVolume(subContVol[3].global,
1213 subContVol[4].volume_ = elementVolume -
1214 subContVol[0].volume_ -
1215 subContVol[1].volume_ -
1216 subContVol[2].volume_ -
1217 subContVol[3].volume_;
1220 subContVol[0].volume_ =
1221 hexahedronVolume(subContVol[0].global,
1229 subContVol[1].volume_ =
1230 hexahedronVolume(subContVol[1].global,
1238 subContVol[2].volume_ =
1239 hexahedronVolume(subContVol[2].global,
1247 subContVol[3].volume_ =
1248 hexahedronVolume(edgeCoord[0],
1252 subContVol[3].global,
1256 subContVol[4].volume_ =
1257 hexahedronVolume(edgeCoord[1],
1261 subContVol[4].global,
1265 subContVol[5].volume_ =
1266 hexahedronVolume(edgeCoord[2],
1270 subContVol[5].global,
1276 subContVol[0].volume_ =
1277 hexahedronVolume(subContVol[0].global,
1285 subContVol[1].volume_ =
1286 hexahedronVolume(subContVol[1].global,
1294 subContVol[2].volume_ =
1295 hexahedronVolume(subContVol[2].global,
1303 subContVol[3].volume_ =
1304 hexahedronVolume(subContVol[3].global,
1312 subContVol[4].volume_ =
1313 hexahedronVolume(edgeCoord[0],
1317 subContVol[4].global,
1321 subContVol[5].volume_ =
1322 hexahedronVolume(edgeCoord[1],
1326 subContVol[5].global,
1330 subContVol[6].volume_ =
1331 hexahedronVolume(edgeCoord[2],
1335 subContVol[6].global,
1339 subContVol[7].volume_ =
1340 hexahedronVolume(edgeCoord[3],
1344 subContVol[7].global,
1350 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim) +
1355 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim));
1358#if __GNUC__ || __clang__
1359#pragma GCC diagnostic pop
1362 const GridView& gridView_;
1363 const Mapper& vertexMapper_;
1367#if HAVE_DUNE_LOCALFUNCTIONS
1368 static LocalFiniteElementCache feCache_;
1372 LocalPosition elementLocal;
1375 GlobalPosition elementGlobal;
1378 Scalar elementVolume;
1381 std::array<SubControlVolume, maxNC> subContVol{};
1384 std::array<SubControlVolumeFace, maxNE> subContVolFace{};
1387 std::array<BoundaryFace, maxBF> boundaryFace_{};
1389 unsigned numBoundarySegments_{};
1392 std::array<GlobalPosition, maxNE> edgeCoord{};
1395 std::array<GlobalPosition, maxNF> faceCoord{};
1398 unsigned numVertices{};
1401 unsigned numEdges{};
1404 unsigned numFaces{};
1406 Dune::GeometryType geometryType_;
1409#if HAVE_DUNE_LOCALFUNCTIONS
1410template< class Scalar, class Gr idView>
1411typename VcfvStencil<Scalar, GridView>::LocalFiniteElementCache
1412VcfvStencil<Scalar, GridView>::feCache_;
1415template < class Scalar>
1416std::array< typename VcfvScvGeometries<Scalar, 1, ElementType::cube>::ScvLocalGeometry,
1420template < class Scalar>
1425template < class Scalar>
1426std::array< typename VcfvScvGeometries<Scalar, 2, ElementType::cube>::ScvLocalGeometry,
1430template < class Scalar>
1435template < class Scalar>
1436std::array< typename VcfvScvGeometries<Scalar, 3, ElementType::cube>::ScvLocalGeometry,
Quadrature geometry for quadrilaterals. Definition: quadraturegeometries.hh:44
const GlobalPosition & corner(unsigned cornerIdx) const Return the position of the corner with a given index. Definition: quadraturegeometries.hh:133
const GlobalPosition & center() const Returns the center of weight of the polyhedron. Definition: quadraturegeometries.hh:73
Definition: vcfvstencil.hh:722
const GlobalPosition center() const Definition: vcfvstencil.hh:724
const ScvLocalGeometry * localGeometry_ Definition: vcfvstencil.hh:736
const Element * element_ Definition: vcfvstencil.hh:737
const GlobalPosition corner(unsigned cornerIdx) const Definition: vcfvstencil.hh:727
const GlobalPosition global(const LocalPosition &localPos) const Definition: vcfvstencil.hh:730
const ScvLocalGeometry & localGeometry() const Definition: vcfvstencil.hh:733
Represents the finite volume geometry of a single element in the VCFV discretization. Definition: vcfvstencil.hh:451
unsigned numPrimaryDof() const Definition: vcfvstencil.hh:1077
const SubControlVolume & subControlVolume(unsigned scvIdx) const Definition: vcfvstencil.hh:1083
VcfvStencil(const GridView &gridView, const Mapper &mapper) Definition: vcfvstencil.hh:812
unsigned numBoundaryFaces() const Definition: vcfvstencil.hh:1092
unsigned globalSpaceIndex(unsigned dofIdx) const Return the global space index given the index of a degree of freedom. Definition: vcfvstencil.hh:1105
unsigned numDof() const Definition: vcfvstencil.hh:1074
Dune::MultipleCodimMultipleGeomTypeMapper< GridView > Mapper exported Mapper type Definition: vcfvstencil.hh:719
void update(const Element &e) Definition: vcfvstencil.hh:870
unsigned numInteriorFaces() const Definition: vcfvstencil.hh:1089
Entity entity(unsigned dofIdx) const Return the global space index given the index of a degree of freedom. Definition: vcfvstencil.hh:1116
void updatePrimaryTopology(const Element &element) Definition: vcfvstencil.hh:862
typename GridView::Traits::template Codim< dim >::Entity Entity Definition: vcfvstencil.hh:462
const SubControlVolumeFace & interiorFace(unsigned faceIdx) const Definition: vcfvstencil.hh:1095
const BoundaryFace & boundaryFace(unsigned bfIdx) const Definition: vcfvstencil.hh:1098
Dune::PartitionType partitionType(unsigned scvIdx) const Definition: vcfvstencil.hh:1080
void updateTopology(const Element &e) Update the non-geometric part of the stencil. Definition: vcfvstencil.hh:837
void updateScvGeometry(const Element &element) Definition: vcfvstencil.hh:1029
static constexpr int dim Definition: structuredgridvanguard.hh:68
Definition: blackoilboundaryratevector.hh:39
ElementType The types of reference elements available. Definition: vcfvstencil.hh:56
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
interior face of a sub control volume Definition: vcfvstencil.hh:774
Scalar area() const Definition: vcfvstencil.hh:784
Scalar area_ area of face Definition: vcfvstencil.hh:806
unsigned short j Definition: vcfvstencil.hh:794
unsigned short exteriorIndex() const Definition: vcfvstencil.hh:781
GlobalPosition ipGlobal_ integration point in global coords Definition: vcfvstencil.hh:800
const GlobalPosition & integrationPos() const Definition: vcfvstencil.hh:790
unsigned short interiorIndex() const Definition: vcfvstencil.hh:778
DimVector normal_ normal on face pointing to CV j or outward of the domain with length equal to |scvf| Definition: vcfvstencil.hh:803
unsigned short i scvf seperates corner i and j of elem Definition: vcfvstencil.hh:794
const DimVector & normal() const Definition: vcfvstencil.hh:775
const LocalPosition & localPos() const Definition: vcfvstencil.hh:787
LocalPosition ipLocal_ integration point in local coords Definition: vcfvstencil.hh:797
finite volume intersected with element Definition: vcfvstencil.hh:741
ScvGeometry geometry_ The geometry of the sub-control volume in local coordinates. Definition: vcfvstencil.hh:767
const ScvGeometry & geometry() const Definition: vcfvstencil.hh:754
LocalPosition local local vertex position Definition: vcfvstencil.hh:758
GlobalPosition global global vertex position Definition: vcfvstencil.hh:761
Scalar volume() const Definition: vcfvstencil.hh:748
const GlobalPosition center() const Definition: vcfvstencil.hh:745
Scalar volume_ space occupied by the sub-control volume Definition: vcfvstencil.hh:764
const GlobalPosition & globalPos() const Definition: vcfvstencil.hh:742
const ScvLocalGeometry & localGeometry() const Definition: vcfvstencil.hh:751
Dune::FieldVector< DimVector, maxNC > gradCenter derivative of shape function at the center of the sub control volume Definition: vcfvstencil.hh:770
|