Loading [MathJax]/extensions/tex2jax.js

dune-mmesh (1.4)

pyskeletontrace.hh
1#ifndef DUNE_MMESH_PYSKELETONTRACE
2#define DUNE_MMESH_PYSKELETONTRACE
3
4#if HAVE_DUNE_FEM
5
6#include <dune/common/exceptions.hh>
7#include <dune/python/common/typeregistry.hh>
8#include <dune/fem/common/intersectionside.hh>
9#include <dune/fem/function/localfunction/const.hh>
10#include <dune/fem/function/localfunction/bindable.hh>
11#include <dune/fempy/py/grid/gridpart.hh>
12#include <dune/fempy/py/grid/function.hh>
13
14namespace Dune
15{
16
17 namespace Fem
18 {
19
21 // Skeleton function //
23
24 template <class BulkGV, class InterfaceGridFunction>
25 struct SkeletonGF
26 : public BindableGridFunctionWithSpace<FemPy::GridPart<BulkGV>,
27 typename InterfaceGridFunction::RangeType>
28 {
29 using GridView = BulkGV;
30 using GridPart = FemPy::GridPart<BulkGV>;
31 using Base = BindableGridFunctionWithSpace<GridPart, typename InterfaceGridFunction::RangeType>;
32 using ILocalFunction = ConstLocalFunction<InterfaceGridFunction>;
33 using SideGeometry = typename GridPart::GridType::Intersection::LocalGeometry::Implementation;
34 static constexpr bool scalar = (InterfaceGridFunction::RangeType::dimension == 1);
35
36 SkeletonGF(const BulkGV &bulkGV, const InterfaceGridFunction &igf)
37 : Base(FemPy::gridPart<BulkGV>(bulkGV), "skeleton_"+igf.name(), igf.order()),
38 ilf_(igf), onInterface_(false)
39 {}
40
41 void bind(const typename Base::EntityType &entity)
42 {
43 Base::bind(entity);
44 }
45
46 void bind(const typename BulkGV::Intersection &intersection,
47 IntersectionSide side)
48 {
49 if( Base::gridPart().grid().isInterface( intersection ) )
50 {
51 onInterface_ = true;
52 ilf_.bind( Base::gridPart().grid().asInterfaceEntity( intersection ) );
53 sideGeometry_ = (side == IntersectionSide::in)
54 ? intersection.geometryInInside().impl() : intersection.geometryInOutside().impl();
55 }
56 else onInterface_ = false;
57 }
58
59 public:
60 template <class Point>
61 void evaluate(const Point &x, typename Base::RangeType &ret) const
62 {
63 if (onInterface_)
64 {
65 auto xLocal = Dune::Fem::coordinate(x);
66 auto ix = sideGeometry_.local( xLocal );
67 ilf_.evaluate(ix,ret);
68 } else ret = typename Base::RangeType(0);
69 }
70
71 template <class Point>
72 void jacobian(const Point &x, typename Base::JacobianRangeType &ret) const
73 {
74 if (onInterface_)
75 {
76 auto xLocal = Dune::Fem::coordinate(x);
77 auto ix = sideGeometry_.local( xLocal );
78 ilf_.jacobian(ix,ret);
79 } else ret = typename Base::JacobianRangeType(0);
80 }
81
82 template <class Point>
83 void hessian(const Point &x, typename Base::HessianRangeType &ret) const
84 {
85 if (onInterface_)
86 {
87 auto xLocal = Dune::Fem::coordinate(x);
88 auto ix = sideGeometry_.local( xLocal );
89 ilf_.hessian(ix,ret);
90 } else ret = typename Base::HessianRangeType(0);
91 }
92
93 private:
94 ILocalFunction ilf_;
95 bool onInterface_;
96 SideGeometry sideGeometry_;
97 };
98
99 template< class BulkGV, class InterfaceGridFunction >
100 inline static void registerSkeletonGF(pybind11::module module, pybind11::class_< SkeletonGF<BulkGV, InterfaceGridFunction> > cls)
101 {
102 using pybind11::operator""_a;
103
104 cls.def( pybind11::init( [] ( const BulkGV &bulkGV, const InterfaceGridFunction &bgf ) {
105 return SkeletonGF<BulkGV, InterfaceGridFunction> ( bulkGV, bgf );
106 } ), "bulkGV"_a, "igf"_a, pybind11::keep_alive< 1, 2 >(), pybind11::keep_alive< 1, 3 >() );
107
108 cls.def_property_readonly( "scalar", [] ( SkeletonGF<BulkGV, InterfaceGridFunction> &self ) { return self.scalar; } );
109
110 Dune::FemPy::registerGridFunction( module, cls );
111 }
112
113
115 // Trace function //
117
118 template <class IGV, class BulkGridFunction, Dune::Fem::IntersectionSide side>
119 struct TraceGF
120 : public Dune::Fem::BindableGridFunctionWithSpace<Dune::FemPy::GridPart<IGV>,
121 typename BulkGridFunction::RangeType>
122 {
123 using GridView = IGV;
124 using GridPart = Dune::FemPy::GridPart<IGV>;
125 using Base = Dune::Fem::BindableGridFunctionWithSpace<GridPart,typename BulkGridFunction::RangeType>;
126 using BLocalFunction = Dune::Fem::ConstLocalFunction<BulkGridFunction>;
127 using BulkGridPart = typename BulkGridFunction::GridPartType;
128 using SideGeometry = typename GridPart::GridType::MMeshType::Intersection::LocalGeometry::Implementation;
129 static constexpr bool scalar = (BulkGridFunction::RangeType::dimension == 1);
130
131 TraceGF(const IGV &iGV, const BulkGridFunction &bgf)
132 : Base(Dune::FemPy::gridPart<IGV>(iGV), "trace_"+bgf.name(), bgf.order() ),
133 bulkGridPart_(bgf.gridPart()),
134 blf_(bgf)
135 {}
136
137 void bind(const typename Base::EntityType &entity)
138 {
139 Base::bind(entity);
140 const auto intersection = Base::gridPart().grid().getMMesh().asIntersection( entity );
141
142 if constexpr (side == Dune::Fem::IntersectionSide::in)
143 blf_.bind(bulkGridPart_.convert(intersection.inside()));
144 else if (intersection.neighbor())
145 blf_.bind(bulkGridPart_.convert(intersection.outside()));
146 else // is this the best we can do?
147 DUNE_THROW( Dune::NotImplemented, "TraceFunction on boundary can no be used with outside entity" );
148 sideGeometry_ = (side == IntersectionSide::in)
149 ? intersection.geometryInInside().impl() : intersection.geometryInOutside().impl();
150 }
151
152 template <class Point>
153 void evaluate(const Point &x, typename Base::RangeType &ret) const
154 {
155 // again need to transfer the x (in this case on the interface) to an x in bulk
156 auto xLocal = Dune::Fem::coordinate(x);
157 auto bx = sideGeometry_.global( xLocal );
158 blf_.evaluate(bx,ret);
159 }
160
161 // need to implement jacobian and hessian as their tangential components
162 template <class Point>
163 void jacobian(const Point &x, typename Base::JacobianRangeType &ret) const
164 {
165 // again need to transfer the x (in this case on the interface) to an x in bulk
166 auto xLocal = Dune::Fem::coordinate(x);
167 auto bx = sideGeometry_.global( xLocal );
168 typename BulkGridFunction::JacobianRangeType bulkJac;
169 blf_.jacobian(bx,bulkJac);
170 ret = bulkJac; // could decide to remove normal component - but perhaps don't have to?
171 }
172
173 template <class Point>
174 void hessian(const Point &x, typename Base::HessianRangeType &ret) const
175 {
176 // again need to transfer the x (in this case on the interface) to an x in bulk
177 auto xLocal = Dune::Fem::coordinate(x);
178 auto bx = sideGeometry_.global( xLocal );
179 typename BulkGridFunction::HessianRangeType bulkHessian;
180 blf_.hessian(bx,bulkHessian);
181 ret = bulkHessian;
182 }
183
184 private:
185 BLocalFunction blf_;
186 const BulkGridPart& bulkGridPart_;
187 SideGeometry sideGeometry_;
188 };
189
190 template< class IGV, class BulkGridFunction, Dune::Fem::IntersectionSide side >
191 inline static void registerTraceGF(pybind11::module module, pybind11::class_< TraceGF<IGV, BulkGridFunction, side> > cls)
192 {
193 using pybind11::operator""_a;
194
195 cls.def( pybind11::init( [] ( const IGV &iGV, const BulkGridFunction &bgf ) {
196 return TraceGF<IGV, BulkGridFunction, side> ( iGV, bgf );
197 } ), "iGV"_a, "bgf"_a, pybind11::keep_alive< 1, 2 >(), pybind11::keep_alive< 1, 3 >() );
198
199 cls.def_property_readonly( "scalar", [] ( TraceGF<IGV, BulkGridFunction, side> &self ) { return self.scalar; } );
200
201 Dune::FemPy::registerGridFunction( module, cls );
202 }
203
204
205 } // namespace Fem
206
207} // namespace Dune
208
209#endif // HAVE_DUNE_FEM
210
211#endif // DUNE_MMESH_PYSKELETONTRACE
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 6, 22:49, 2025)