File: facenormalgridfunction.hh

package info (click to toggle)
dune-functions 2.10.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,544 kB
  • sloc: cpp: 14,241; python: 661; makefile: 3
file content (198 lines) | stat: -rw-r--r-- 5,438 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:

// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later

#ifndef DUNE_FUNCTIONS_GRIDFUNCTIONS_FACENORMALGRIDFUNCTION_HH
#define DUNE_FUNCTIONS_GRIDFUNCTIONS_FACENORMALGRIDFUNCTION_HH

#include <type_traits>
#include <optional>

#include <dune/common/exceptions.hh>
#include <dune/common/typeutilities.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/geometry/referenceelements.hh>

#include <dune/functions/gridfunctions/gridfunction.hh>
#include <dune/functions/gridfunctions/gridviewentityset.hh>


namespace Dune::Functions {

namespace Impl {

// Compute closest face to point
template<class ReferenceElement, class Coordinate>
auto closestFaceIndex(const ReferenceElement& re, const Coordinate& x)
{
  auto closestFaceIndex = decltype(re.subEntity(0,1,0,1)){};
  double closestFaceDistance = std::numeric_limits<double>::max();
  for(auto&& faceIndex : Dune::range(re.size(1)))
  {
    // For a face unit outer normal consider the orthogonal projection
    // Px = x + <c-x,n>*n into the face. Then the distance to the face
    // is given by |x-Px| = |<c-x,n>||n| = <c-x,n>.
    auto normal = re.integrationOuterNormal(faceIndex);
    normal /= normal.two_norm();
    auto c = re.position(faceIndex,1);
    c -= x;
    auto faceDistance = (c*normal);
    if (faceDistance<closestFaceDistance)
    {
      closestFaceDistance = faceDistance;
      closestFaceIndex = faceIndex;
    }
  }
  return closestFaceIndex;
}

} // end namespace Impl




/**
 * \brief Grid function implementing the piecewise element face normal.
 *
 * \ingroup FunctionImplementations
 *
 * This function implements the grid interface.
 * When evaluated at a point x inside of an element, it computes
 * the unit outward normal vector of the face closest to this
 * point.
 *
 * \tparam GV  The GridView associated to the grid-function
 */
template<class GV>
class FaceNormalGridFunction
{
public:
  using GridView = GV;
  using EntitySet = GridViewEntitySet<GridView, 0>;
  using Element = typename EntitySet::Element;

  using LocalDomain = typename EntitySet::LocalCoordinate;
  using Domain = typename EntitySet::GlobalCoordinate;
  using Range = typename EntitySet::GlobalCoordinate;

private:

  using Traits = Imp::GridFunctionTraits<Range(Domain), EntitySet, DefaultDerivativeTraits, 16>;

  class LocalFunction
  {
    using Geometry = typename Element::Geometry;
    static const int dimension = GV::dimension;
  public:

    /**
     * \brief Bind the local-function to the passed element.
     *
     * This function stores a copy of `element` and its geometry.
     *
     * \b Expects:
     * - The `element` is in the entitySet of the grid-fuction.
     *
     * \b Ensures:
     * - The local-function is bound the the `element`.
     **/
    void bind(const Element& element)
    {
      element_ = element;
      geometry_.emplace(element_.geometry());
    }

    void unbind()
    {
      geometry_.reset();
    }

    /** \brief Return if the local function is bound to a grid element
     */
    bool bound() const
    {
      return static_cast<bool>(geometry_);
    }

    /**
     * \brief Evaluate the local-function in local coordinates `x`.
     *
     * This function computes the unit outward normal vector of the
     * face closest to the point `x` in the bound element.
     *
     * \b Expects:
     * - The local-function is bound to an element.
     **/
    Range operator()(const LocalDomain& x) const
    {
      auto&& re = Dune::referenceElement(*geometry_);
      // Compute reference normal of closest face to given point
      auto face = Impl::closestFaceIndex(re, x);
      auto localNormal = re.integrationOuterNormal(face);

      // Transform reference normal into global unit outer normal using
      // covariant Piola transformation
      auto normal = Range{};
      geometry_->jacobianInverseTransposed(x).mv(localNormal, normal);
      normal /= normal.two_norm();
      return normal;
    }

    //! Return the bound element stored as copy in the \ref bind function.
    const Element& localContext() const
    {
      return element_;
    }

    //! Not implemented.
    friend typename Traits::LocalFunctionTraits::DerivativeInterface derivative(const LocalFunction& t)
    {
      DUNE_THROW(NotImplemented,"not implemented");
    }

  private:
    std::optional<Geometry> geometry_;
    Element element_;
  };

public:
  //! Construct the FaceNormalGridFunction.
  FaceNormalGridFunction(const GridView& gridView) :
    entitySet_(gridView)
  {}

  //! Not implemented.
  Range operator()(const Domain& x) const
  {
    DUNE_THROW(NotImplemented,"not implemented");
  }

  //! Not implemented.
  friend typename Traits::DerivativeInterface derivative(const FaceNormalGridFunction& t)
  {
    DUNE_THROW(NotImplemented,"not implemented");
  }

  //! Return a local-function associated to FaceNormalGridFunction.
  friend LocalFunction localFunction(const FaceNormalGridFunction& t)
  {
    return LocalFunction{};
  }

  //! Return the stored GridViewEntitySet.
  const EntitySet& entitySet() const
  {
    return entitySet_;
  }

private:
  EntitySet entitySet_;
};



} // namespace Dune::Functions

#endif // DUNE_FUNCTIONS_GRIDFUNCTIONS_FACENORMALGRIDFUNCTION_HH