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>
66template < class Scalar, unsigned dim, ElementType basicGeomType>
67class VcfvScvGeometries;
72template < class Scalar>
73class VcfvScvGeometries<Scalar, 1, ElementType::cube>
79 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
84 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] = {
95 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
96 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
100 static const ScvLocalGeometry& get( unsigned scvIdx)
101 { return scvGeoms_[scvIdx]; }
104 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
107template < class Scalar>
114 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
116 static const ScvLocalGeometry& get( unsigned)
118 throw std::logic_error( "Not implemented: VcfvScvGeometries<Scalar, 1, ElementType::simplex>");
125template < class Scalar>
132 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
134 static const ScvLocalGeometry& get( unsigned scvIdx)
135 { return scvGeoms_[scvIdx]; }
140 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
164 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
165 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
170 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
173template < class Scalar>
180 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
182 static const ScvLocalGeometry& get( unsigned scvIdx)
183 { return scvGeoms_[scvIdx]; }
188 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
219 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
220 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
224 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
230template < class Scalar>
237 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
239 static const ScvLocalGeometry& get( unsigned scvIdx)
240 { return scvGeoms_[scvIdx]; }
245 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
251 { 1.0/3, 1.0/3, 0.0 },
254 { 1.0/3, 0.0, 1.0/3 },
255 { 0.0, 1.0/3, 1.0/3 },
256 { 1.0/4, 1.0/4, 1.0/4 },
262 { 1.0/3, 1.0/3, 0.0 },
263 { 1.0/2, 1.0/2, 0.0 },
265 { 1.0/3, 0.0, 1.0/3 },
266 { 1.0/2, 0.0, 1.0/2 },
267 { 1.0/4, 1.0/4, 1.0/4 },
268 { 1.0/3, 1.0/3, 1.0/3 },
273 { 1.0/3, 1.0/3, 0.0 },
275 { 1.0/2, 1.0/2, 0.0 },
277 { 0.0, 1.0/3, 1.0/3 },
278 { 1.0/4, 1.0/4, 1.0/4 },
279 { 0.0, 1.0/2, 1.0/2 },
280 { 1.0/3, 1.0/3, 1.0/3 },
285 { 1.0/3, 0.0, 1.0/3 },
286 { 0.0, 1.0/3, 1.0/3 },
287 { 1.0/4, 1.0/4, 1.0/4 },
290 { 1.0/2, 0.0, 1.0/2 },
291 { 0.0, 1.0/2, 1.0/2 },
292 { 1.0/3, 1.0/3, 1.0/3 },
296 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
297 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
302 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
305template < class Scalar>
312 using ScvLocalGeometry = QuadrialteralQuadratureGeometry<Scalar, dim>;
314 static const ScvLocalGeometry& get( unsigned scvIdx)
315 { return scvGeoms_[scvIdx]; }
320 const Scalar scvCorners[numScv][ScvLocalGeometry::numCorners][ dim] =
326 { 1.0/2, 1.0/2, 0.0 },
329 { 1.0/2, 0.0, 1.0/2 },
330 { 0.0, 1.0/2, 1.0/2 },
331 { 1.0/2, 1.0/2, 1.0/2 },
337 { 1.0/2, 1.0/2, 0.0 },
340 { 1.0/2, 0.0, 1.0/2 },
342 { 1.0/2, 1.0/2, 1.0/2 },
343 { 1.0, 1.0/2, 1.0/2 },
348 { 1.0/2, 1.0/2, 0.0 },
352 { 0.0, 1.0/2, 1.0/2 },
353 { 1.0/2, 1.0/2, 1.0/2 },
355 { 1.0/2, 1.0, 1.0/2 },
359 { 1.0/2, 1.0/2, 0.0 },
364 { 1.0/2, 1.0/2, 1.0/2 },
365 { 1.0, 1.0/2, 1.0/2 },
366 { 1.0/2, 1.0, 1.0/2 },
372 { 1.0/2, 0.0, 1.0/2 },
373 { 0.0, 1.0/2, 1.0/2 },
374 { 1.0/2, 1.0/2, 1.0/2 },
379 { 1.0/2, 1.0/2, 1.0 },
383 { 1.0/2, 0.0, 1.0/2 },
385 { 1.0/2, 1.0/2, 1.0/2 },
386 { 1.0, 1.0/2, 1.0/2 },
390 { 1.0/2, 1.0/2, 1.0 },
395 { 0.0, 1.0/2, 1.0/2 },
396 { 1.0/2, 1.0/2, 1.0/2 },
398 { 1.0/2, 1.0, 1.0/2 },
401 { 1.0/2, 1.0/2, 1.0 },
407 { 1.0/2, 1.0/2, 1.0/2 },
408 { 1.0, 1.0/2, 1.0/2 },
409 { 1.0/2, 1.0, 1.0/2 },
412 { 1.0/2, 1.0/2, 1.0 },
419 for ( unsigned scvIdx = 0; scvIdx < numScv; ++scvIdx) {
420 scvGeoms_[scvIdx].setCorners(scvCorners[scvIdx], ScvLocalGeometry::numCorners);
424 static std::array<ScvLocalGeometry, numScv> scvGeoms_;
450template < class Scalar, class Gr idView>
453 enum { dim = GridView::dimension };
454 enum { dimWorld = GridView::dimensionworld };
455 enum { maxNC = dim < 3 ? 4 : 8 };
456 enum { maxNE = dim < 3 ? 4 : 12 };
457 enum { maxNF = dim < 3 ? 1 : 6 };
458 enum { maxBF = dim < 3 ? 8 : 24 };
459 using CoordScalar = typename GridView::ctype;
460 using Element = typename GridView::Traits::template Codim<0>::Entity;
463 using Entity = typename GridView::Traits::template Codim<dim>::Entity;
466 using Geometry = typename Element::Geometry;
467 using DimVector = Dune::FieldVector<Scalar, dimWorld>;
468 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
469 using LocalPosition = Dune::FieldVector<CoordScalar, dim>;
470 using IntersectionIterator = typename GridView::IntersectionIterator;
474#if HAVE_DUNE_LOCALFUNCTIONS
475 using LocalFiniteElementCache = Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
476 using LocalFiniteElement = typename LocalFiniteElementCache::FiniteElementType;
477 using LocalBasisTraits = typename LocalFiniteElement::Traits::LocalBasisType::Traits;
478 using ShapeJacobian = typename LocalBasisTraits::JacobianType;
481 Scalar quadrilateralArea( const GlobalPosition& p0,
482 const GlobalPosition& p1,
483 const GlobalPosition& p2,
484 const GlobalPosition& p3)
486 return 0.5 * std::abs((p3[0] - p1[0]) * (p2[1] - p0[1]) -
487 (p3[1] - p1[1]) * (p2[0] - p0[0]));
490 void crossProduct(DimVector& c, const DimVector& a, const DimVector& b)
492 c[0] = a[1] * b[2] - a[2] * b[1];
493 c[1] = a[2] * b[0] - a[0] * b[2];
494 c[2] = a[0] * b[1] - a[1] * b[0];
497 Scalar pyramidVolume( const GlobalPosition& p0,
498 const GlobalPosition& p1,
499 const GlobalPosition& p2,
500 const GlobalPosition& p3,
501 const GlobalPosition& p4)
503 DimVector a(p2); a -= p0;
504 DimVector b(p3); b -= p1;
507 crossProduct(n, a, b);
511 return 1.0 / 6.0 * (n * a);
514 Scalar prismVolume( const GlobalPosition& p0,
515 const GlobalPosition& p1,
516 const GlobalPosition& p2,
517 const GlobalPosition& p3,
518 const GlobalPosition& p4,
519 const GlobalPosition& p5)
522 for ( unsigned k = 0; k < dimWorld; ++k) {
526 for ( unsigned k = 0; k < dimWorld; ++k) {
530 crossProduct(m, a, b);
532 for ( unsigned k = 0; k < dimWorld; ++k) {
533 a[k] = p1[k] - p0[k];
535 for ( unsigned k = 0; k < dimWorld; ++k) {
536 b[k] = p2[k] - p0[k];
539 crossProduct(n, a, b);
542 for ( unsigned k = 0; k < dimWorld; ++k) {
543 a[k] = p5[k] - p0[k];
546 return std::abs(1.0 / 6.0 * (n * a));
549 Scalar hexahedronVolume( const GlobalPosition& p0,
550 const GlobalPosition& p1,
551 const GlobalPosition& p2,
552 const GlobalPosition& p3,
553 const GlobalPosition& p4,
554 const GlobalPosition& p5,
555 const GlobalPosition& p6,
556 const GlobalPosition& p7)
558 return prismVolume(p0, p1, p2, p4, p5, p6) +
559 prismVolume(p0, p2, p3, p4, p6, p7);
562 void normalOfQuadrilateral3D(DimVector& normal,
563 const GlobalPosition& p0,
564 const GlobalPosition& p1,
565 const GlobalPosition& p2,
566 const GlobalPosition& p3)
569 for ( unsigned k = 0; k < dimWorld; ++k) {
573 for ( unsigned k = 0; k < dimWorld; ++k) {
577 crossProduct(normal, a, b);
581 Scalar quadrilateralArea3D( const GlobalPosition& p0,
582 const GlobalPosition& p1,
583 const GlobalPosition& p2,
584 const GlobalPosition& p3)
587 normalOfQuadrilateral3D(normal, p0, p1, p2, p3);
588 return normal.two_norm();
591 void getFaceIndices( unsigned numElemVertices, unsigned k, unsigned& leftFace, unsigned& rightFace)
593 static const unsigned edgeToFaceTet[2][6] = {
597 static const unsigned edgeToFacePyramid[2][8] = {
598 {1, 2, 3, 4, 1, 3, 4, 2},
599 {0, 0, 0, 0, 3, 2, 1, 4}
601 static const unsigned edgeToFacePrism[2][9] = {
602 {1, 0, 2, 0, 1, 2, 4, 4, 4},
603 {0, 2, 1, 3, 3, 3, 0, 1, 2}
605 static const unsigned edgeToFaceHex[2][12] = {
606 {0, 2, 3, 1, 4, 1, 2, 4, 0, 5, 5, 3},
607 {2, 1, 0, 3, 0, 4, 4, 3, 5, 1, 2, 5}
610 switch (numElemVertices) {
612 leftFace = edgeToFaceTet[0][k];
613 rightFace = edgeToFaceTet[1][k];
616 leftFace = edgeToFacePyramid[0][k];
617 rightFace = edgeToFacePyramid[1][k];
620 leftFace = edgeToFacePrism[0][k];
621 rightFace = edgeToFacePrism[1][k];
624 leftFace = edgeToFaceHex[0][k];
625 rightFace = edgeToFaceHex[1][k];
628 throw std::logic_error( "Not implemented: VcfvStencil::getFaceIndices for "
634 void getEdgeIndices( unsigned numElemVertices, unsigned face, unsigned vert,
635 unsigned& leftEdge, unsigned& rightEdge)
637 static const int faceAndVertexToLeftEdgeTet[4][4] = {
643 static const int faceAndVertexToRightEdgeTet[4][4] = {
649 static const int faceAndVertexToLeftEdgePyramid[5][5] = {
656 static const int faceAndVertexToRightEdgePyramid[5][5] = {
663 static const int faceAndVertexToLeftEdgePrism[5][6] = {
664 { 3, 3, -1, 0, 1, -1},
665 { 4, -1, 4, 0, -1, 2},
666 {-1, 5, 5, -1, 1, 2},
667 { 3, 3, 5, -1, -1, -1},
668 {-1, -1, -1, 6, 6, 8}
670 static const int faceAndVertexToRightEdgePrism[5][6] = {
671 { 0, 1, -1, 6, 6, -1},
672 { 0, -1, 2, 7, -1, 7},
673 {-1, 1, 2, -1, 8, 8},
674 { 4, 5, 4, -1, -1, -1},
675 {-1, -1, -1, 7, 8, 7}
677 static const int faceAndVertexToLeftEdgeHex[6][8] = {
678 { 0, -1, 4, -1, 8, -1, 2, -1},
679 {-1, 5, -1, 3, -1, 1, -1, 9},
680 { 6, 1, -1, -1, 0, 10, -1, -1},
681 {-1, -1, 2, 7, -1, -1, 11, 3},
682 { 4, 6, 7, 5, -1, -1, -1, -1},
683 {-1, -1, -1, -1, 10, 9, 8, 11}
685 static const int faceAndVertexToRightEdgeHex[6][8] = {
686 { 4, -1, 2, -1, 0, -1, 8, -1},
687 {-1, 1, -1, 5, -1, 9, -1, 3},
688 { 0, 6, -1, -1, 10, 1, -1, -1},
689 {-1, -1, 7, 3, -1, -1, 2, 11},
690 { 6, 5, 4, 7, -1, -1, -1, -1},
691 {-1, -1, -1, -1, 8, 10, 11, 9}
694 switch (numElemVertices) {
696 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgeTet[face][vert]);
697 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgeTet[face][vert]);
700 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgePyramid[face][vert]);
701 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgePyramid[face][vert]);
704 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgePrism[face][vert]);
705 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgePrism[face][vert]);
708 leftEdge = static_cast<unsigned>(faceAndVertexToLeftEdgeHex[face][vert]);
709 rightEdge = static_cast<unsigned>(faceAndVertexToRightEdgeHex[face][vert]);
712 throw std::logic_error( "Not implemented: VcfvStencil::getFaceIndices for "
720 using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
728 const GlobalPosition corner( unsigned cornerIdx) const
731 const GlobalPosition global( const LocalPosition& localPos) const
732 { return element_->geometry().global(localPos); }
814 : gridView_(gridView)
815 , vertexMapper_(mapper )
816 , element_(*gridView.template begin<0>())
819 assert( static_cast<int>(gridView.size(dimWorld)) == static_cast<int>(mapper.size()));
821 static bool localGeometriesInitialized = false;
822 if (!localGeometriesInitialized) {
823 localGeometriesInitialized = true;
842 numVertices = e.subEntities(dim);
843 numEdges = e.subEntities(dim-1);
844 if constexpr (dim == 3) {
845 numFaces = e.subEntities(1);
851 numBoundarySegments_ = 0;
854 const Geometry& geometry = e.geometry();
855 geometryType_ = geometry.type();
856 const auto& referenceElement = Dune::ReferenceElements<CoordScalar,dim>::general(geometryType_);
858 assert(numVertices == static_cast<unsigned>(referenceElement.size(dim)));
859 numVertices = std::min(numVertices, static_cast<unsigned>(referenceElement.size(dim)));
860 for ( unsigned vertexIdx = 0; vertexIdx < numVertices; ++vertexIdx) {
861 subContVol[vertexIdx].local = referenceElement.position( static_cast<int>(vertexIdx), dim);
862 subContVol[vertexIdx].global = geometry.corner( static_cast<int>(vertexIdx));
878 const Geometry& geometry = e.geometry();
879 geometryType_ = geometry.type();
881 const auto& referenceElement = Dune::ReferenceElements<CoordScalar,dim>::general(geometryType_);
883 elementVolume = geometry.volume();
884 elementLocal = referenceElement.position(0, 0);
885 elementGlobal = geometry.global(elementLocal);
888 for ( unsigned vert = 0; vert < numVertices; ++vert) {
889 subContVol[vert].local = referenceElement.position( static_cast<int>(vert), dim);
890 subContVol[vert].global = geometry.global(subContVol[vert].local);
894 for ( unsigned edge = 0; edge < numEdges; ++edge) {
895 edgeCoord[edge] = geometry.global(referenceElement.position( static_cast<int>(edge), dim - 1));
899 for ( unsigned face = 0; face < numFaces; ++face) {
900 faceCoord[face] = geometry.global(referenceElement.position( static_cast<int>(face), 1));
908 fillSubContVolData_();
911 for ( unsigned k = 0; k < numEdges; ++k) {
913 static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(k), dim - 1, 0, dim));
915 static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(k), dim - 1, 1, dim));
916 if (numEdges == 4 && (i == 2 || j == 2)) {
919 subContVolFace[k].i = i;
920 subContVolFace[k].j = j;
927 LocalPosition ipLocal;
929 if constexpr (dim == 1) {
930 subContVolFace[k].ipLocal_ = 0.5;
931 subContVolFace[k].normal_ = 1.0;
932 subContVolFace[k].area_ = 1.0;
933 ipLocal = subContVolFace[k].ipLocal_;
935 else if constexpr (dim == 2) {
936 ipLocal = referenceElement.position( static_cast<int>(k), dim - 1) + elementLocal;
938 subContVolFace[k].ipLocal_ = ipLocal;
939 for ( unsigned m = 0; m < dimWorld; ++m) {
940 diffVec[m] = elementGlobal[m] - edgeCoord[k][m];
942 subContVolFace[k].normal_[0] = diffVec[1];
943 subContVolFace[k].normal_[1] = -diffVec[0];
945 for ( unsigned m = 0; m < dimWorld; ++m) {
946 diffVec[m] = subContVol[j].global[m] - subContVol[i].global[m];
949 if (subContVolFace[k].normal_ * diffVec < 0) {
950 subContVolFace[k].normal_ *= -1;
953 subContVolFace[k].area_ = subContVolFace[k].normal_.two_norm();
954 subContVolFace[k].normal_ /= subContVolFace[k].area_;
956 else if constexpr (dim == 3) {
959 getFaceIndices(numVertices, k, leftFace, rightFace);
960 ipLocal = referenceElement.position( static_cast<int>(k), dim - 1) +
962 referenceElement.position( static_cast<int>(leftFace), 1) +
963 referenceElement.position( static_cast<int>(rightFace), 1);
965 subContVolFace[k].ipLocal_ = ipLocal;
966 normalOfQuadrilateral3D(subContVolFace[k].normal_,
967 edgeCoord[k], faceCoord[rightFace],
968 elementGlobal, faceCoord[leftFace]);
969 subContVolFace[k].area_ = subContVolFace[k].normal_.two_norm();
970 subContVolFace[k].normal_ /= subContVolFace[k].area_;
974 subContVolFace[k].ipGlobal_ = geometry.global(ipLocal);
978 for ( const auto& intersection : intersections(gridView_, e)) {
979 if (!intersection.boundary()) {
983 const unsigned face = static_cast<unsigned>(intersection.indexInInside());
984 const unsigned numVerticesOfFace = static_cast<unsigned>(referenceElement.size( static_cast<int>(face), 1, dim));
985 for ( unsigned vertInFace = 0; vertInFace < numVerticesOfFace; ++vertInFace) {
986 const unsigned short vertInElement = static_cast<unsigned short>(referenceElement.subEntity( static_cast<int>(face), 1, static_cast<int>(vertInFace), dim));
987 const unsigned bfIdx = numBoundarySegments_;
988 ++numBoundarySegments_;
990 if constexpr (dim == 1) {
991 boundaryFace_[bfIdx].ipLocal_ = referenceElement.position( static_cast<int>(vertInElement), dim);
992 boundaryFace_[bfIdx].area_ = 1.0;
994 else if constexpr (dim == 2) {
995 boundaryFace_[bfIdx].ipLocal_ =
996 referenceElement.position( static_cast<int>(vertInElement), dim) +
997 referenceElement.position( static_cast<int>(face), 1);
998 boundaryFace_[bfIdx].ipLocal_ *= 0.5;
999 boundaryFace_[bfIdx].area_ = 0.5 * intersection.geometry().volume();
1001 else if constexpr (dim == 3) {
1004 getEdgeIndices(numVertices, face, vertInElement, leftEdge, rightEdge);
1005 boundaryFace_[bfIdx].ipLocal_ =
1006 referenceElement.position( static_cast<int>(vertInElement), dim) +
1007 referenceElement.position( static_cast<int>(face), 1) +
1008 referenceElement.position( static_cast<int>(leftEdge), dim - 1) +
1009 referenceElement.position( static_cast<int>(rightEdge), dim - 1);
1010 boundaryFace_[bfIdx].ipLocal_ *= 0.25;
1011 boundaryFace_[bfIdx].area_ =
1012 quadrilateralArea3D(subContVol[vertInElement].global,
1013 edgeCoord[rightEdge],
1015 edgeCoord[leftEdge]);
1018 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim));
1021 boundaryFace_[bfIdx].ipGlobal_ = geometry.global(boundaryFace_[bfIdx].ipLocal_);
1022 boundaryFace_[bfIdx].i = vertInElement;
1023 boundaryFace_[bfIdx].j = vertInElement;
1026 boundaryFace_[bfIdx].normal_ = intersection.centerUnitOuterNormal();
1035 auto geomType = element.geometry().type();
1038 if (geomType.isTriangle() || geomType.isTetrahedron()) {
1039 for ( unsigned vertIdx = 0; vertIdx < numVertices; ++vertIdx) {
1040 subContVol[vertIdx].geometry_.element_ = &element;
1041 subContVol[vertIdx].geometry_.localGeometry_ =
1042 &VcfvScvGeometries<Scalar, dim, ElementType::simplex>::get(vertIdx);
1045 else if (geomType.isLine() || geomType.isQuadrilateral() || geomType.isHexahedron()) {
1046 for ( unsigned vertIdx = 0; vertIdx < numVertices; ++vertIdx) {
1047 subContVol[vertIdx].geometry_.element_ = &element;
1048 subContVol[vertIdx].geometry_.localGeometry_ =
1049 &VcfvScvGeometries<Scalar, dim, ElementType::cube>::get(vertIdx);
1053 throw std::logic_error( "Not implemented: SCV geometries for non hexahedron elements");
1057#if HAVE_DUNE_LOCALFUNCTIONS
1058 void updateCenterGradients()
1060 const auto& localFiniteElement = feCache_.get(element_.type());
1061 const auto& geom = element_.geometry();
1063 std::vector<ShapeJacobian> localJac;
1065 for ( unsigned scvIdx = 0; scvIdx < numVertices; ++scvIdx) {
1066 const auto& localCenter = subContVol[scvIdx].localGeometry().center();
1067 localFiniteElement.localBasis().evaluateJacobian(localCenter, localJac);
1068 const auto& globalPos = subContVol[scvIdx].geometry().center();
1070 const auto jacInvT = geom.jacobianInverseTransposed(globalPos);
1071 for ( unsigned vert = 0; vert < numVertices; ++vert) {
1072 jacInvT.mv(localJac[vert][0], subContVol[scvIdx].gradCenter[vert]);
1079 { return numVertices; }
1085 { return element_.template subEntity<dim>(scvIdx)-> partitionType(); }
1089 assert(scvIdx < numDof());
1090 return subContVol[scvIdx];
1094 { return numEdges; }
1097 { return numBoundarySegments_; }
1100 { return subContVolFace[faceIdx]; }
1103 { return boundaryFace_[bfIdx]; }
1111 assert(dofIdx < numDof());
1113 return static_cast<unsigned>(vertexMapper_.subIndex(element_, static_cast<int>(dofIdx), dim));
1122 assert(dofIdx < numDof());
1123 return element_.template subEntity<dim>( static_cast<int>(dofIdx));
1127#if __GNUC__ || __clang__
1128#pragma GCC diagnostic push
1129#pragma GCC diagnostic ignored "-Wpragmas"
1130#pragma GCC diagnostic ignored "-Warray-bounds"
1132 void fillSubContVolData_()
1134 if constexpr (dim == 1) {
1136 subContVol[0].volume_ = 0.5 * elementVolume;
1137 subContVol[1].volume_ = 0.5 * elementVolume;
1139 else if constexpr (dim == 2) {
1140 switch (numVertices) {
1142 subContVol[0].volume_ = elementVolume / 3;
1143 subContVol[1].volume_ = elementVolume / 3;
1144 subContVol[2].volume_ = elementVolume / 3;
1147 subContVol[0].volume_ =
1148 quadrilateralArea(subContVol[0].global,
1152 subContVol[1].volume_ =
1153 quadrilateralArea(subContVol[1].global,
1157 subContVol[2].volume_ =
1158 quadrilateralArea(subContVol[2].global,
1162 subContVol[3].volume_ =
1163 quadrilateralArea(subContVol[3].global,
1169 throw std::logic_error( "Not implemented:VcfvStencil dim = " + std::to_string(dim) +
1173 else if constexpr (dim == 3) {
1174 switch (numVertices) {
1176 for ( unsigned k = 0; k < numVertices; k++) {
1177 subContVol[k].volume_ = elementVolume / 4.0;
1181 subContVol[0].volume_ =
1182 hexahedronVolume(subContVol[0].global,
1190 subContVol[1].volume_ =
1191 hexahedronVolume(subContVol[1].global,
1199 subContVol[2].volume_ =
1200 hexahedronVolume(subContVol[2].global,
1208 subContVol[3].volume_ =
1209 hexahedronVolume(subContVol[3].global,
1217 subContVol[4].volume_ = elementVolume -
1218 subContVol[0].volume_ -
1219 subContVol[1].volume_ -
1220 subContVol[2].volume_ -
1221 subContVol[3].volume_;
1224 subContVol[0].volume_ =
1225 hexahedronVolume(subContVol[0].global,
1233 subContVol[1].volume_ =
1234 hexahedronVolume(subContVol[1].global,
1242 subContVol[2].volume_ =
1243 hexahedronVolume(subContVol[2].global,
1251 subContVol[3].volume_ =
1252 hexahedronVolume(edgeCoord[0],
1256 subContVol[3].global,
1260 subContVol[4].volume_ =
1261 hexahedronVolume(edgeCoord[1],
1265 subContVol[4].global,
1269 subContVol[5].volume_ =
1270 hexahedronVolume(edgeCoord[2],
1274 subContVol[5].global,
1280 subContVol[0].volume_ =
1281 hexahedronVolume(subContVol[0].global,
1289 subContVol[1].volume_ =
1290 hexahedronVolume(subContVol[1].global,
1298 subContVol[2].volume_ =
1299 hexahedronVolume(subContVol[2].global,
1307 subContVol[3].volume_ =
1308 hexahedronVolume(subContVol[3].global,
1316 subContVol[4].volume_ =
1317 hexahedronVolume(edgeCoord[0],
1321 subContVol[4].global,
1325 subContVol[5].volume_ =
1326 hexahedronVolume(edgeCoord[1],
1330 subContVol[5].global,
1334 subContVol[6].volume_ =
1335 hexahedronVolume(edgeCoord[2],
1339 subContVol[6].global,
1343 subContVol[7].volume_ =
1344 hexahedronVolume(edgeCoord[3],
1348 subContVol[7].global,
1354 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim) +
1359 throw std::logic_error( "Not implemented:VcfvStencil for dim = " + std::to_string(dim));
1362#if __GNUC__ || __clang__
1363#pragma GCC diagnostic pop
1366 const GridView& gridView_;
1367 const Mapper& vertexMapper_;
1371#if HAVE_DUNE_LOCALFUNCTIONS
1372 static LocalFiniteElementCache feCache_;
1376 LocalPosition elementLocal;
1379 GlobalPosition elementGlobal;
1382 Scalar elementVolume;
1385 std::array<SubControlVolume, maxNC> subContVol{};
1388 std::array<SubControlVolumeFace, maxNE> subContVolFace{};
1391 std::array<BoundaryFace, maxBF> boundaryFace_{};
1393 unsigned numBoundarySegments_{};
1396 std::array<GlobalPosition, maxNE> edgeCoord{};
1399 std::array<GlobalPosition, maxNF> faceCoord{};
1402 unsigned numVertices{};
1405 unsigned numEdges{};
1408 unsigned numFaces{};
1410 Dune::GeometryType geometryType_;
1413#if HAVE_DUNE_LOCALFUNCTIONS
1414template< class Scalar, class Gr idView>
1415typename VcfvStencil<Scalar, GridView>::LocalFiniteElementCache
1416VcfvStencil<Scalar, GridView>::feCache_;
1419template < class Scalar>
1420std::array< typename VcfvScvGeometries<Scalar, 1, ElementType::cube>::ScvLocalGeometry,
1424template < class Scalar>
1429template < class Scalar>
1430std::array< typename VcfvScvGeometries<Scalar, 2, ElementType::cube>::ScvLocalGeometry,
1434template < class Scalar>
1439template < class Scalar>
1440std::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:723
const GlobalPosition center() const Definition: vcfvstencil.hh:725
const ScvLocalGeometry * localGeometry_ Definition: vcfvstencil.hh:737
const Element * element_ Definition: vcfvstencil.hh:738
const GlobalPosition corner(unsigned cornerIdx) const Definition: vcfvstencil.hh:728
const GlobalPosition global(const LocalPosition &localPos) const Definition: vcfvstencil.hh:731
const ScvLocalGeometry & localGeometry() const Definition: vcfvstencil.hh:734
Represents the finite volume geometry of a single element in the VCFV discretization. Definition: vcfvstencil.hh:452
unsigned numPrimaryDof() const Definition: vcfvstencil.hh:1081
const SubControlVolume & subControlVolume(unsigned scvIdx) const Definition: vcfvstencil.hh:1087
VcfvStencil(const GridView &gridView, const Mapper &mapper) Definition: vcfvstencil.hh:813
unsigned numBoundaryFaces() const Definition: vcfvstencil.hh:1096
unsigned globalSpaceIndex(unsigned dofIdx) const Return the global space index given the index of a degree of freedom. Definition: vcfvstencil.hh:1109
unsigned numDof() const Definition: vcfvstencil.hh:1078
Dune::MultipleCodimMultipleGeomTypeMapper< GridView > Mapper exported Mapper type Definition: vcfvstencil.hh:720
void update(const Element &e) Definition: vcfvstencil.hh:874
unsigned numInteriorFaces() const Definition: vcfvstencil.hh:1093
Entity entity(unsigned dofIdx) const Return the global space index given the index of a degree of freedom. Definition: vcfvstencil.hh:1120
void updatePrimaryTopology(const Element &element) Definition: vcfvstencil.hh:866
typename GridView::Traits::template Codim< dim >::Entity Entity Definition: vcfvstencil.hh:463
const SubControlVolumeFace & interiorFace(unsigned faceIdx) const Definition: vcfvstencil.hh:1099
const BoundaryFace & boundaryFace(unsigned bfIdx) const Definition: vcfvstencil.hh:1102
Dune::PartitionType partitionType(unsigned scvIdx) const Definition: vcfvstencil.hh:1084
void updateTopology(const Element &e) Update the non-geometric part of the stencil. Definition: vcfvstencil.hh:838
void updateScvGeometry(const Element &element) Definition: vcfvstencil.hh:1033
static constexpr int dim Definition: structuredgridvanguard.hh:68
Definition: blackoilbioeffectsmodules.hh:45
ElementType The types of reference elements available. Definition: vcfvstencil.hh:57
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
interior face of a sub control volume Definition: vcfvstencil.hh:775
Scalar area() const Definition: vcfvstencil.hh:785
Scalar area_ area of face Definition: vcfvstencil.hh:807
unsigned short j Definition: vcfvstencil.hh:795
unsigned short exteriorIndex() const Definition: vcfvstencil.hh:782
GlobalPosition ipGlobal_ integration point in global coords Definition: vcfvstencil.hh:801
const GlobalPosition & integrationPos() const Definition: vcfvstencil.hh:791
unsigned short interiorIndex() const Definition: vcfvstencil.hh:779
DimVector normal_ normal on face pointing to CV j or outward of the domain with length equal to |scvf| Definition: vcfvstencil.hh:804
unsigned short i scvf seperates corner i and j of elem Definition: vcfvstencil.hh:795
const DimVector & normal() const Definition: vcfvstencil.hh:776
const LocalPosition & localPos() const Definition: vcfvstencil.hh:788
LocalPosition ipLocal_ integration point in local coords Definition: vcfvstencil.hh:798
finite volume intersected with element Definition: vcfvstencil.hh:742
ScvGeometry geometry_ The geometry of the sub-control volume in local coordinates. Definition: vcfvstencil.hh:768
const ScvGeometry & geometry() const Definition: vcfvstencil.hh:755
LocalPosition local local vertex position Definition: vcfvstencil.hh:759
GlobalPosition global global vertex position Definition: vcfvstencil.hh:762
Scalar volume() const Definition: vcfvstencil.hh:749
const GlobalPosition center() const Definition: vcfvstencil.hh:746
Scalar volume_ space occupied by the sub-control volume Definition: vcfvstencil.hh:765
const GlobalPosition & globalPos() const Definition: vcfvstencil.hh:743
const ScvLocalGeometry & localGeometry() const Definition: vcfvstencil.hh:752
Dune::FieldVector< DimVector, maxNC > gradCenter derivative of shape function at the center of the sub control volume Definition: vcfvstencil.hh:771
|