DUNE-FEM (unstable)

basicimplicit.hh
1#ifndef DUNE_FEM_SOLVER_RUNGEKUTTA_BASICIMPLICIT_HH
2#define DUNE_FEM_SOLVER_RUNGEKUTTA_BASICIMPLICIT_HH
3
4//- system includes
5#include <cassert>
6#include <cmath>
7#include <limits>
8#include <sstream>
9#include <vector>
10
11//- dune-common includes
14
15//- dune-fem includes
16#include <dune/fem/solver/odesolverinterface.hh>
17
18namespace DuneODE
19{
20
21 // NoImplicitRungeKuttaSourceTerm
22 // ------------------------------
23
24 struct NoImplicitRungeKuttaSourceTerm
25 {
26 template< class T >
27 bool operator() ( double time, double timeStepSize, int stage, const T &u, const std::vector< T * > &update, T &source )
28 {
29 return false;
30 }
31
32 template< class T >
33 void limit( T& update, const double time ) {}
34
35 template< class T >
36 double initialTimeStepEstimate ( double time, const T &u ) const
37 {
38 // return negative value to indicate that implicit time step should be used
39 return -1.0;
40 }
41
42 double timeStepEstimate () const
43 {
45 }
46 };
47
48
49
51 template< class HelmholtzOperator, class NonlinearSolver, class TimeStepControl, class SourceTerm = NoImplicitRungeKuttaSourceTerm >
53 : public OdeSolverInterface< typename HelmholtzOperator::DomainFunctionType >
54 {
57
58 public:
59 typedef typename BaseType::MonitorType MonitorType;
60 typedef typename BaseType::DestinationType DestinationType;
61
62 typedef HelmholtzOperator HelmholtzOperatorType;
63 typedef NonlinearSolver NonlinearSolverType;
64 typedef TimeStepControl TimeStepControlType;
65 typedef SourceTerm SourceTermType;
66
68
69 typedef typename TimeStepControlType::ParameterType ParameterType;
70 typedef typename NonlinearSolver::ParameterType NonlinearSolverParameterType;
71
79 template< class ButcherTable >
80 BasicImplicitRungeKuttaSolver ( HelmholtzOperatorType &helmholtzOp,
81 const ButcherTable &butcherTable,
82 const TimeStepControlType &timeStepControl,
83 const SourceTermType &sourceTerm,
84 const NonlinearSolverParameterType& parameters )
85 : helmholtzOp_( helmholtzOp ),
86 nonlinearSolver_( parameters ),
87 timeStepControl_( timeStepControl ),
88 sourceTerm_( sourceTerm ),
89 stages_( butcherTable.stages() ),
90 ord_( butcherTable.order() ),
91 alpha_( butcherTable.A() ),
92 gamma_( stages() ),
93 beta_( stages() ),
94 c_( butcherTable.c() ),
95 rhs_( "RK rhs", helmholtzOp_.space() ),
96 updateStorage_(),
97 update_( stages(), nullptr )
98 {
99 setup( butcherTable );
100 }
101
108 template< class ButcherTable >
109 BasicImplicitRungeKuttaSolver ( HelmholtzOperatorType &helmholtzOp,
110 const ButcherTable &butcherTable,
111 const TimeStepControlType &timeStepControl,
112 const NonlinearSolverParameterType& parameters )
113 : helmholtzOp_( helmholtzOp ),
114 nonlinearSolver_( parameters ),
115 timeStepControl_( timeStepControl ),
116 stages_( butcherTable.stages() ),
117 ord_( butcherTable.order() ),
118 alpha_( butcherTable.A() ),
119 gamma_( stages() ),
120 beta_( stages() ),
121 c_( butcherTable.c() ),
122 rhs_( "RK rhs", helmholtzOp_.space() ),
123 updateStorage_(),
124 update_( stages(), nullptr )
125 {
126 setup( butcherTable );
127 }
128
129 template< class ButcherTable >
130 BasicImplicitRungeKuttaSolver ( HelmholtzOperatorType &helmholtzOp,
131 const ButcherTable &butcherTable,
132 const TimeStepControlType &timeStepControl,
133 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
134 : BasicImplicitRungeKuttaSolver( helmholtzOp, butcherTable, timeStepControl,
135 NonlinearSolverParameterType( parameter ) )
136 {
137 }
138
139 template< class ButcherTable >
140 BasicImplicitRungeKuttaSolver ( HelmholtzOperatorType &helmholtzOp,
141 const ButcherTable &butcherTable,
142 const Dune::Fem::ParameterReader &parameter = Dune::Fem::Parameter::container() )
143 : BasicImplicitRungeKuttaSolver( helmholtzOp, butcherTable,
144 TimeStepControlType( parameter ), NonlinearSolverParameterType( parameter ) )
145 {
146 }
147
148 template< class ButcherTable >
149 void setup( const ButcherTable& butcherTable )
150 {
151 update_.clear();
152 update_.resize( stages(), nullptr );
153 updateStorage_.resize( stages() );
154
155 // create intermediate functions
156 for( int i = 0; i < stages(); ++i )
157 {
158 std::ostringstream name;
159 name << "RK stage " << i;
160 updateStorage_[ i ].reset( new DestinationType( name.str(), helmholtzOp_.space() ) );
161 update_[ i ] = updateStorage_[ i ].operator ->();
162 }
163
164 // compute coefficients
166 for( int i = 0; i < stages(); ++i )
167 {
168 gamma_[ i ] = AL[ i ][ i ];
169 AL[ i ][ i ] = 0.0;
170 }
171
172 alpha_.invert();
173 alpha_.mtv( butcherTable.b(), beta_ );
174
175 alpha_.leftmultiply( AL );
176 for( int i = 0; i < stages(); ++i )
177 alpha_[ i ][ i ] = gamma_[ i ];
178
179 for( int i = 0; i < stages(); ++i )
180 {
181 gamma_[ i ] = 1.0;
182 for( int j = 0; j < i; ++j )
183 gamma_[ i ] -= alpha_[ i ][ j ];
184 }
185
186 delta_ = 1.0;
187 for( int i = 0; i < stages(); ++i )
188 delta_ -= beta_[ i ];
189
190 }
191
193 void initialize ( const DestinationType &U0 )
194 {
195 const double time = timeStepControl_.time();
196
197 helmholtzOp_.setTime( time );
198 helmholtzOp_.initializeTimeStepSize( U0 );
199 const double helmholtzEstimate = helmholtzOp_.timeStepEstimate();
200
201 double sourceTermEstimate = sourceTerm_.initialTimeStepEstimate( time, U0 );
202 // negative time step is given by the empty source term
203 if( sourceTermEstimate < 0.0 ) sourceTermEstimate = helmholtzEstimate ;
204
205 timeStepControl_.initialTimeStepSize( helmholtzEstimate, sourceTermEstimate );
206 }
207
208 using BaseType::solve;
209
211 void solve ( DestinationType &U, MonitorType &monitor )
212 {
213 monitor.reset();
214
215 const double time = timeStepControl_.time();
216 const double timeStepSize = timeStepControl_.timeStepSize();
217 assert( timeStepSize > 0.0 );
218 for( int s = 0; s < stages(); ++s )
219 {
220 assert( update_[ s ] );
221 // update for stage s
222 DestinationType& updateStage = *update_[ s ];
223
224 // assemble rhs of nonlinear equation
225 updateStage.assign( U );
226 updateStage *= gamma_[ s ];
227 for( int k = 0; k < s; ++k )
228 updateStage.axpy( alpha_[ s ][ k ], *update_[ k ] );
229
230 const double stageTime = time + c_[ s ]*timeStepSize;
231 if( sourceTerm_( time, timeStepSize, s, U, update_, rhs_ ) )
232 {
233 updateStage.axpy( alpha_[ s ][ s ]*timeStepSize, rhs_ );
234 sourceTerm_.limit( updateStage, stageTime );
235 }
236
237 // apply Helmholtz operator to right hand side
238 helmholtzOp_.setTime( stageTime );
239 helmholtzOp_.setLambda( 0 );
240 helmholtzOp_( updateStage, rhs_ );
241
242 // solve the system
243 helmholtzOp_.setLambda( alpha_[ s ][ s ]*timeStepSize );
244 nonlinearSolver_.bind( helmholtzOp_ );
245 nonlinearSolver_( rhs_, updateStage );
246 nonlinearSolver_.unbind();
247
248 // update monitor
249 monitor.newtonIterations_ += nonlinearSolver_.iterations();
250 monitor.linearSolverIterations_ += nonlinearSolver_.linearIterations();
251
252 // on failure break solving
253 if( !nonlinearSolver_.converged() )
254 return timeStepControl_.reduceTimeStep( helmholtzOp_.timeStepEstimate(), sourceTerm_.timeStepEstimate(), monitor );
255 }
256
257 double error = 0.0;
258 if( timeStepControl_.computeError() )
259 {
260 // store U (to be revised)
261 DestinationType Uerr( U );
262
263 // update solution
264 U *= delta_;
265 for( int s = 0; s < stages(); ++s )
266 U.axpy( beta_[ s ], *update_[ s ] );
267
268 //error = infNorm( U, Uerr );
269 Uerr.axpy( -1.0, U );
270 const double errorU = Uerr.scalarProductDofs( Uerr );
271 const double normU = U.scalarProductDofs( U );
272
273 if( normU > 0 && errorU > 0 )
274 {
275 error = std::sqrt( errorU / normU );
276 }
277 std::cout << std::scientific << "Error in RK = " << error << " norm " << errorU << " " << normU << std::endl;
278 //std::cout << std::scientific << "Error in RK = " << error << std::endl;
279 }
280 else
281 {
282 // update solution
283 U *= delta_;
284 for( int s = 0; s < stages(); ++s )
285 U.axpy( beta_[ s ], *update_[ s ] );
286 }
287 // set error to monitor
288 monitor.error_ = error;
289
290 // update time step size
291 timeStepControl_.timeStepEstimate( helmholtzOp_.timeStepEstimate(), sourceTerm_.timeStepEstimate(), monitor );
292 }
293
294 int stages () const { return stages_; }
295
296 int order () const { return ord_; }
297
298 void description ( std::ostream &out ) const
299 {
300 out << "Generic " << stages() << "-stage implicit Runge-Kutta solver.\\\\" << std::endl;
301 }
302
303 protected:
304 double infNorm(const DestinationType& U, const DestinationType& Uerr ) const
305 {
306 typedef typename DestinationType :: ConstDofIteratorType ConstDofIteratorType ;
307 const ConstDofIteratorType uend = U.dend();
308 double res = 0;
309 for( ConstDofIteratorType u = U.dbegin(), uerr = Uerr.dbegin(); u != uend; ++u, ++uerr )
310 {
311 double uval = *u;
312 double uerrval = *uerr ;
313 double div = std::abs( std::max( uval, uerrval ) );
314
315 double norm = std::abs( uval - uerrval );
316 if( std::abs(div) > 1e-12 )
317 norm /= div;
318 res = std::max( res, norm );
319 }
320 return res;
321 }
322
323 HelmholtzOperatorType& helmholtzOp_;
324 NonlinearSolverType nonlinearSolver_;
325 TimeStepControl timeStepControl_;
326 SourceTerm sourceTerm_;
327
328 int stages_;
329 int ord_;
330
331 double delta_;
333 Dune::DynamicVector< double > gamma_, beta_, c_;
334
335 DestinationType rhs_;
336 std::vector< std::unique_ptr< DestinationType > > updateStorage_;
337 std::vector< DestinationType* > update_;
338 };
339
340} // namespace DuneODE
341
342#endif // #ifndef DUNE_FEM_SOLVER_RUNGEKUTTA_BASICIMPLICIT_HH
Implicit RungeKutta ODE solver.
Definition: basicimplicit.hh:54
void description(std::ostream &out) const
print description of ODE solver to out stream
Definition: basicimplicit.hh:298
int stages() const
return stages of RK solver (-1 if not implemented)
Definition: basicimplicit.hh:294
BasicImplicitRungeKuttaSolver(HelmholtzOperatorType &helmholtzOp, const ButcherTable &butcherTable, const TimeStepControlType &timeStepControl, const SourceTermType &sourceTerm, const NonlinearSolverParameterType &parameters)
constructor
Definition: basicimplicit.hh:80
void initialize(const DestinationType &U0)
apply operator once to get dt estimate
Definition: basicimplicit.hh:193
int order() const
return order of RK solver (-1 if not implemented)
Definition: basicimplicit.hh:296
BasicImplicitRungeKuttaSolver(HelmholtzOperatorType &helmholtzOp, const ButcherTable &butcherTable, const TimeStepControlType &timeStepControl, const NonlinearSolverParameterType &parameters)
constructor
Definition: basicimplicit.hh:109
void solve(DestinationType &U, MonitorType &monitor)
solve the system
Definition: basicimplicit.hh:211
Interface class for ODE Solver.
Definition: odesolverinterface.hh:21
Monitor MonitorType
monitor type
Definition: odesolverinterface.hh:59
virtual void solve(DestinationType &u)
solve where is the internal operator.
Definition: odesolverinterface.hh:75
DestinationImp DestinationType
type of destination
Definition: odesolverinterface.hh:62
void invert(bool doPivoting=true)
Compute inverse.
MAT & leftmultiply(const DenseMatrix< M2 > &M)
Multiplies M from the left to this matrix.
Definition: densematrix.hh:632
constexpr void mtv(const X &x, Y &y) const
y = A^T x
Definition: densematrix.hh:392
constexpr derived_type & axpy(const field_type &a, const DenseVector< Other > &x)
vector space axpy operation ( *this += a x )
Definition: densevector.hh:590
general base for time providers
Definition: timeprovider.hh:36
This file implements a dense matrix with dynamic numbers of rows and columns.
This file implements a dense vector with a dynamic size.
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:489
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jan 10, 23:35, 2026)