DUNE-FEM (unstable)

linearized.hh
1#ifndef DUNE_FEM_SCHEMES_LINEARIZED_HH
2#define DUNE_FEM_SCHEMES_LINEARIZED_HH
3
4#include <cstddef>
5
6#include <tuple>
7#include <type_traits>
8#include <utility>
9#include <vector>
10
11#include <dune/fem/operator/common/operator.hh>
12#include <dune/fem/space/common/interpolate.hh>
13#include <dune/fem/io/parameter.hh>
14#include <dune/fem/schemes/femscheme.hh>
15
16
17namespace Dune
18{
19
20 namespace Fem
21 {
22 /*
23 Idea is to setup the first two terms in the Taylor expansion:
24 L[w] = S[u] + DS[u](w-u)
25 = S[u] - DS[u]u + DS[u]w
26 = DS[u]w + b
27
28 So b = S[u] - DS[u]u
29 and L[w] = DS[u]w + b
30
31 The solve method with rhs=f computs the solution w to
32 L[w] = f <=> DS[u]w = f-b
33
34 With Dirichlet BCs:
35 From construction of the underlying scheme we have
36 S[u] = u - g and DS[u]w = w on the boundary.
37
38 Therefore on the boundary we have
39 b = S[u] - DS[u]u = u - g - u = -g
40 and L[w] = DS[u]w + b = w - g
41 and solving L[w] = f is the same as DS[u]w = f-b or w = f-b = f+g on the boundary
42
43 Note: we store -b in the LinearizedScheme, the LinearScheme
44 represents the above but with b=0
45 */
46
48
49 // This class implements the Jacobian part of a scheme, i.e., L[w] = DS[u]w
50 // without the rhs 'b'.
51 template< class Scheme >
52 struct LinearScheme : public Scheme::LinearOperatorType,
53 public FemScheme< Scheme, typename Scheme::LinearInverseOperatorType, typename Scheme::LinearInverseOperatorType >
54 {
55 typedef Scheme SchemeType;
56 typedef typename SchemeType::LinearInverseOperatorType LinearInverseOperatorType;
57
58 // base types
59 typedef typename SchemeType::LinearOperatorType BaseType;
60 typedef FemScheme< SchemeType, LinearInverseOperatorType, LinearInverseOperatorType > FSBaseType;
61
62 typedef typename SchemeType::DiscreteFunctionType DiscreteFunctionType;
63 typedef typename SchemeType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
64 typedef typename SchemeType::GridPartType GridPartType;
65 typedef typename LinearInverseOperatorType::SolverParameterType ParameterType;
66 typedef typename SchemeType::ModelType ModelType;
67
68 typedef typename SchemeType::JacobianOperatorType JacobianOperatorType;
69 typedef typename SchemeType::DomainFunctionType DomainFunctionType;
70 typedef typename SchemeType::RangeFunctionType RangeFunctionType;
71
72 typedef typename SchemeType::DirichletBlockVector DirichletBlockVector;
73
75 // std::function to represents the Python function passed as potential preconditioner
76 typedef typename PreconditionerFunctionWrapperType::PreconditionerFunctionType PreconditionerFunctionType;
77
78 using FSBaseType :: fullOperator;
79 using FSBaseType :: setConstraints;
80 using FSBaseType :: space;
81
82 // from femscheme.hh
83 typedef typename LinearInverseOperatorType::SolverInfoType SolverInfoType ;
84
86 LinearScheme ( SchemeType &scheme,
87 Dune::Fem::ParameterReader parameter = Dune::Fem::Parameter::container() )
88 : BaseType( "linearized Op", scheme.space(), scheme.space() ),
89 FSBaseType( scheme, parameter ),
90 isBound_(false),
91 parameter_( std::move( parameter ) ),
92 tmp_( "LS::tmp", scheme.space() )
93 {
94 }
95
97 LinearScheme ( SchemeType &scheme, const DiscreteFunctionType &ubar,
98 Dune::Fem::ParameterReader parameter = Dune::Fem::Parameter::container() )
99 : BaseType( "linearized Op", scheme.space(), scheme.space() ),
100 FSBaseType( scheme, parameter ),
101 isBound_(false),
102 parameter_( std::move( parameter ) ),
103 tmp_( "LS::tmp", scheme.space() )
104 {
105 fullOperator().jacobian(ubar,*this);
106 }
107
112 void setErrorMeasure() const {}
113
114 using BaseType::clear;
115 virtual void clear() override
116 {
117 BaseType::clear();
118 invOp_.unbind();
119 isBound_ = false;
120 }
121
122 void operator() ( const DiscreteFunctionType &u, DiscreteFunctionType &w ) const override
123 {
124 // use linear op (instead of fullOperator)
125 BaseType::operator()(u,w);
126 }
127
128 template <class GridFunction>
129 void operator() ( const GridFunction &arg, DiscreteFunctionType &dest ) const
130 {
131 Fem::interpolate(arg, tmp_);
132 // apply operator (i.e. matvec)
133 (*this)(tmp_, dest);
134 }
135
136 SolverInfoType solve ( const DiscreteFunctionType &rhs, DiscreteFunctionType &solution) const
137 {
138 if (!isBound_)
139 {
140 invOp_.bind(*this);
141 isBound_ = true;
142 }
143
144 // copy Dirichlet constraints from rhs to solution
145 setConstraints(rhs, solution);
146 invOp_(rhs, solution );
147 return invOp_.info();
148 }
149
150 SolverInfoType solve ( const DiscreteFunctionType &rhs, DiscreteFunctionType &solution, const PreconditionerFunctionType& p) const
151 {
152 if (isBound_)
153 invOp_.unbind();
154
155 PreconditionerFunctionWrapperType pre( p );
156 invOp_.bind(*this, pre);
157 isBound_ = true;
158 auto info = solve( rhs, solution );
159 invOp_.unbind();
160 isBound_ = false;
161 return info;
162 }
163
171 SolverInfoType solve ( DiscreteFunctionType &solution ) const
172 {
173 if (!isBound_)
174 {
175 invOp_.bind(*this);
176 isBound_ = true;
177 }
178 DiscreteFunctionType& zero = tmp_;
179 zero.clear();
180 setConstraints(typename DiscreteFunctionType::RangeType(0), solution);
181 invOp_( zero, solution );
182 return invOp_.info();
183 }
184
185 const SchemeType &scheme() const { return fullOperator(); }
186 const ParameterReader& parameter () const { return parameter_; }
187
188 DiscreteFunctionType& temporaryData() const { return tmp_; }
189 protected:
190 using FSBaseType :: invOp_;
191 mutable bool isBound_;
192 Dune::Fem::ParameterReader parameter_;
193 mutable DiscreteFunctionType tmp_;
194 };
195
196 // This class stores a 'LinearScheme' and defines 'setup' methods that
197 // compute the rhs 'b'. All methods are then
198 template< class Scheme >
199 struct LinearizedScheme
200 : public Dune::Fem::Operator<typename Scheme::DomainFunctionType, typename Scheme::RangeFunctionType>
201 {
202 typedef Scheme SchemeType;
203 typedef typename SchemeType::DiscreteFunctionType DiscreteFunctionType;
204 typedef typename SchemeType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
205 typedef typename SchemeType::GridPartType GridPartType;
206 typedef typename SchemeType::LinearInverseOperatorType LinearInverseOperatorType;
207 typedef typename SchemeType::ModelType ModelType;
208
209 typedef typename SchemeType::JacobianOperatorType JacobianOperatorType;
210 typedef typename SchemeType::DomainFunctionType DomainFunctionType;
211 typedef typename SchemeType::RangeFunctionType RangeFunctionType;
212
213 typedef typename SchemeType::DirichletBlockVector DirichletBlockVector;
214 typedef LinearScheme<SchemeType> LinearOperatorType;
215 typedef typename LinearOperatorType::SolverInfoType SolverInfoType;
216
219 typename LinearOperatorType::DomainFunctionType > PreconditionerFunctionWrapperType;
220 // std::function to represents the Python function passed as potential preconditioner
221 typedef typename PreconditionerFunctionWrapperType::PreconditionerFunctionType PreconditionerFunctionType;
222
223 LinearizedScheme ( SchemeType &scheme,
224 const Dune::Fem::ParameterReader& parameter = Dune::Fem::Parameter::container() )
225 : linOp_( scheme, parameter ),
226 rhs_( "affine shift", scheme.space() ),
227 ubar_( "ubar", scheme.space() )
228 {
229 setup();
230 }
231 LinearizedScheme ( SchemeType &scheme, const DiscreteFunctionType &ubar,
232 const Dune::Fem::ParameterReader& parameter = Dune::Fem::Parameter::container() )
233 : linOp_( scheme, ubar, parameter ),
234 rhs_( "affine shift", scheme.space() ),
235 ubar_( "ubar", scheme.space() )
236 {
237 setup(ubar);
238 }
239
240 void setup(const DiscreteFunctionType &ubar)
241 {
242 ubar_.assign(ubar);
243 setup_();
244 }
245
246 template <class GridFunction>
247 void setup(const GridFunction &ubar)
248 {
249 Fem::interpolate(ubar, ubar_);
250 setup_();
251 }
252 void setup()
253 {
254 ubar_.clear();
255 setup_(true); // provide info that `ubar=0`
256 }
257
262 void setErrorMeasure() const {}
263 void setConstraints( DomainFunctionType &u ) const
264 {
265 linOp_.setConstraints(u);
266 }
267 void setConstraints( const typename DiscreteFunctionType::RangeType &value, DiscreteFunctionType &u ) const
268 {
269 linOp_.setConstraints(value, u);
270 }
271 void setConstraints( const DiscreteFunctionType &u, DiscreteFunctionType &v ) const
272 {
273 linOp_.setConstraints(u, v);
274 }
275 template < class GridFunctionType,
276 typename = std::enable_if_t< std::is_base_of<Dune::Fem::HasLocalFunction, GridFunctionType>::value > >
277 void setConstraints( const GridFunctionType &u, DiscreteFunctionType &v ) const
278 {
279 linOp_.setConstraints(u, v);
280 }
281 void subConstraints( const DiscreteFunctionType &u, DiscreteFunctionType &v ) const
282 {
283 linOp_.subConstraints(u, v);
284 }
285 void subConstraints( DiscreteFunctionType &v ) const
286 {
287 linOp_.subConstraints(v);
288 }
289 void addConstraints( const DiscreteFunctionType &u, DiscreteFunctionType &v ) const
290 {
291 linOp_.addConstraints(u, v);
292 }
293 void addConstraints( DiscreteFunctionType &v ) const
294 {
295 linOp_.addConstraints(v);
296 }
297 const auto& dirichletBlocks() const
298 {
299 return linOp_.dirichletBlocks();
300 }
301
302 void operator() ( const DiscreteFunctionType &u, DiscreteFunctionType &w ) const override
303 {
304 linOp_(u,w);
305 w -= rhs_;
306 }
307 template <class GridFunction>
308 void operator() ( const GridFunction &arg, DiscreteFunctionType &w ) const
309 {
310 linOp_(arg, w);
311 w -= rhs_;
312 }
313
314 SolverInfoType solve ( const DiscreteFunctionType &rhs, DiscreteFunctionType &solution) const
315 {
316 return _solve(rhs, solution, nullptr );
317 }
318
319 SolverInfoType solve ( const DiscreteFunctionType &rhs, DiscreteFunctionType &solution, const PreconditionerFunctionType& p) const
320 {
321 // TODO: Pass preconditioning to solver !
322 return _solve( rhs, solution, &p );
323 }
324
332 SolverInfoType solve ( DiscreteFunctionType &solution ) const
333 {
334 // rhs_ = DS[u]u-S[u] and = u-(u-g) = g on boundary so
335 // solution = u - DS[u]^{-1}S[u] and = g on the boundary
336 return linOp_.solve( rhs_, solution );
337 }
338
339 const GridPartType &gridPart () const { return linOp_.gridPart(); }
340 const DiscreteFunctionSpaceType &space() const { return linOp_.space(); }
341 const SchemeType &scheme() { return linOp_.scheme(); }
342 const ParameterReader& parameter () const { return linOp_.parameter(); }
343
344 protected:
345 SolverInfoType _solve ( const DiscreteFunctionType &rhs, DiscreteFunctionType &solution, const PreconditionerFunctionType* p) const
346 {
347 DiscreteFunctionType& sumRhs = linOp_.temporaryData();
348 sumRhs.assign(rhs);
349 sumRhs += rhs_;
350
351 // rhs_ = DS[u]u-S[u] and = u-(u-g) = g on boundary so
352 // solution = u - DS[u]^{-1}(rhs+S[u]) and = rhs+g on the boundary
353 if( p )
354 return linOp_.solve( sumRhs, solution, *p); // don't add constraints again
355 else
356 return linOp_.solve( sumRhs, solution); // don't add constraints again
357 }
358
359 void setup_(bool isZero=false)
360 {
361 scheme().jacobian(ubar_, linOp_);
362
363 // compute rhs
364 DiscreteFunctionType& tmp = linOp_.temporaryData();
365
366 // compute tmp = S[u] (tmp = u-g on boundary)
367 tmp.clear();
368 scheme()( ubar_, tmp );
369
370 // compute rhs_ = DS[u]u (rhs_ = u on boundary)
371 rhs_.clear();
372 if (!isZero)
373 linOp_( ubar_, rhs_ );
374
375 // compute rhs_ - tmp = DS[u]u-S[u] and u-(u-g)=g on boundary
376 rhs_ -= tmp;
377 }
378
379 LinearOperatorType linOp_;
382 };
383
384 } // namespace Fem
385
386} // namespace Dune
387
388#endif // #ifndef DUNE_FEM_SCHEMES_LINEARIZED_HH
void clear()
set all degrees of freedom to zero
Definition: discretefunction.hh:731
DiscreteFunctionSpaceType::RangeType RangeType
type of range vector
Definition: discretefunction.hh:614
void assign(const DiscreteFunctionInterface< DFType > &g)
Definition: discretefunction_inline.hh:132
void jacobian(const DomainType &x, JacobianRangeType &jacobian) const
evaluate the Jacobian of the function
Definition: discretefunction.hh:845
Wrapper for functions passed from Python side that implements a preconditioner.
Definition: preconditionfunctionwrapper.hh:23
forward declaration
Definition: discretefunction.hh:51
static void interpolate(const GridFunction &u, DiscreteFunction &v)
perform native interpolation of a discrete function space
Definition: interpolate.hh:54
Dune namespace.
Definition: alignedallocator.hh:13
STL namespace.
abstract operator
Definition: operator.hh:34
DomainFunction DomainFunctionType
type of discrete function in the operator's domain
Definition: operator.hh:36
RangeFunction RangeFunctionType
type of discrete function in the operator's range
Definition: operator.hh:38
SparseRowLinearOperator.
Definition: spoperator.hh:25
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 27, 22:29, 2024)