FirstOrderTestDivTrialvec.hpp 3.71 KB
Newer Older
1
2
3
4
#pragma once

#include <type_traits>

5
#include <amdis/GridFunctionOperator.hpp>
6
#include <amdis/utility/LocalBasisCache.hpp>
7
#include <amdis/Output.hpp>
8
#include <amdis/common/StaticSize.hpp>
9
10
11

namespace AMDiS
{
12
13
14
15
16
  /**
   * \addtogroup operators
   * @{
   **/

17
18
19
20
21
22
  namespace tag
  {
    struct test_divtrialvec {};
  }


23
  /// first-order operator \f$ \langle\psi, c\,\nabla\cdot\Phi\rangle \f$
24
25
26
  template <class LC, class GridFct>
  class GridFunctionOperator<tag::test_divtrialvec, LC, GridFct>
      : public GridFunctionOperatorBase<GridFunctionOperator<tag::test_divtrialvec, LC, GridFct>, LC, GridFct>
27
  {
28
    using Self = GridFunctionOperator;
29
    using Super = GridFunctionOperatorBase<Self, LC, GridFct>;
30

31
    static_assert( static_size_v<typename GridFct::Range> == 1, "Expression must be of scalar type." );
32
33

  public:
34
35
    GridFunctionOperator(tag::test_divtrialvec, GridFct const& expr)
      : Super(expr, 1)
36
37
    {}

38
39
    template <class CG, class RN, class CN, class Mat>
    void getElementMatrix(CG const& contextGeo, RN const& rowNode, CN const& colNode, Mat& elementMatrix)
40
    {
41
42
      static_assert(RN::isLeaf && CN::isPower,
        "row-node must be Leaf-Node and col-node must be a Power-Node.");
43

44
45
      static const std::size_t CHILDREN = CN::CHILDREN;
      static_assert( CHILDREN == CG::dow, "" );
46

47
      auto const& quad = this->getQuadratureRule(contextGeo.type(), rowNode, colNode);
48
49
      auto const& rowLocalFE = rowNode.finiteElement();
      auto const& colLocalFE = colNode.child(0).finiteElement();
50
51
      std::size_t rowSize = rowLocalFE.size();
      std::size_t colSize = colLocalFE.size();
52

53
      using RangeFieldType = typename NodeQuadCache<typename CN::ChildType>::Traits::RangeFieldType;
54

55
56
      NodeQuadCache<RN> rowCache(rowLocalFE.localBasis());
      NodeQuadCache<typename CN::ChildType> colCache(colLocalFE.localBasis());
57

58
59
      auto const& shapeValuesCache = rowCache.evaluateFunctionAtQP(contextGeo, quad);
      auto const& shapeGradientsCache = colCache.evaluateJacobianAtQP(contextGeo, quad);
60
      for (std::size_t iq = 0; iq < quad.size(); ++iq) {
61
        // Position of the current quadrature point in the reference element
62
        decltype(auto) local = contextGeo.local(quad[iq].position());
63
64

        // The transposed inverse Jacobian of the map from the reference element to the element
65
        const auto jacobian = contextGeo.geometry().jacobianInverseTransposed(local);
66
67

        // The multiplicative factor in the integral transformation formula
68
        const auto factor = Super::coefficient(local) * contextGeo.integrationElement(quad[iq].position()) * quad[iq].weight();
69

70
71
        // the values of the shape functions on the reference element at the quadrature point
        auto const& shapeValues = shapeValuesCache[iq];
72
73

        // The gradients of the shape functions on the reference element
74
        auto const& shapeGradients = shapeGradientsCache[iq];
75
76

        // Compute the shape function gradients on the real element
77
        using WorldVector = FieldVector<RangeFieldType,CG::dow>;
78
        thread_local std::vector<WorldVector> colGradients;
79
        colGradients.resize(shapeGradients.size());
80
81

        for (std::size_t i = 0; i < colGradients.size(); ++i)
82
          jacobian.mv(shapeGradients[i][0], colGradients[i]);
83

84
        for (std::size_t i = 0; i < rowSize; ++i) {
85
86
          const auto local_i = rowNode.localIndex(i);
          const auto value = factor * shapeValues[i];
87
          for (std::size_t j = 0; j < colSize; ++j) {
88
            for (std::size_t k = 0; k < CHILDREN; ++k) {
89
              const auto local_kj = colNode.child(k).localIndex(j);
90
91
92
93
94
95
96
97
98
              elementMatrix[local_i][local_kj] += value * colGradients[j][k];
            }
          }
        }
      }

    }
  };

99
100
  /** @} **/

101
} // end namespace AMDiS