KASKADE 7 development version
limexWithoutJens.hh
Go to the documentation of this file.
1#ifndef LIMEX_HH
2#define LIMEX_HH
3
4#include <complex>
5#include <fstream>
6#include <iostream>
7#include <iomanip>
8#include <cstdlib>
9
10#include <boost/timer/timer.hpp>
11
12#include "dune/istl/solvers.hh"
13#include "dune/istl/preconditioners.hh"
14
16#include "fem/iterate_grid.hh"
19
20#include "fem/assemble.hh"
21#include "fem/istlinterface.hh"
22#include "fem/functional_aux.hh"
24#include "fem/lagrangespace.hh"
25
28#include "linalg/mumps_solve.hh"
29// #include "linalg/superlu_solve.hh"
30
32#include "linalg/direct.hh"
33#include "linalg/triplet.hh"
34#include "linalg/iluprecond.hh"
35#include "linalg/hyprecond.hh"
37
38#include "utilities/enums.hh"
39
41
42namespace Kaskade
43{
54 template <class Eq>
55 class Limex
56 {
57 public:
59 typedef typename EvolutionEquation::AnsatzVars::VariableSet State;
60
61 private:
64
65 public:
72 typename EvolutionEquation::AnsatzVars const& ansatzVars_,
74 int verbosity_ = 1)
75 : gridManager(gridManager_), ansatzVars(ansatzVars_), eq(&eq_,0)
76 , assembler(ansatzVars.spaces), extrap(0),
78 initSolutionTime(0.0), estimateTime(0), directType(st), precondType(precondType_), verbosity(verbosity_)
79 {}
80
81
98 State const& step(State const& x, double dt, int order,
99 std::vector<std::pair<double,double>> const& tolX)
100 {
101 boost::timer::cpu_timer timer;
102
103 std::vector<double> stepFractions(order+1);
104 for (int i=0; i<=order; ++i)
105 stepFractions[i] = 1.0/(i+1); // harmonic sequence for extrapolation
106 extrap.clear();
107
108 int const nvars = EvolutionEquation::AnsatzVars::noOfVariables;
109 int const neq = EvolutionEquation::TestVars::noOfVariables;
110 size_t nnz = assembler.nnz(0,neq,0,nvars,false);
111
112 MatrixAsTriplet<double> triplet(nnz);
113
114 typedef typename EvolutionEquation::AnsatzVars::template CoefficientVectorRepresentation<0,neq>::type CoefficientVectors;
115
117 State dx(x), dxsum(x), tmp(x);
118 double const t = eq.parabolicEquation().time();
119
121
122 bool const iterative = false; // false: use a direct solver, true: use an iterative solver
123
124
125 // Loop over extrapolation orders. For each order, an Euler solution is computed
126 // on an equidistant time grid with shorter and shorter time sub-steps. At the
127 // joint final time, the value is extrapolated.
128 for (int i=0; i<=order; ++i)
129 {
130 double const tau = stepFractions[i]*dt;
131 eq.setTau(tau);
133
134 // mesh adaptation loop. Just once if i>0.
135 gridManager.setVerbosity(verbosity);
136 bool accurate = true;
137 do {
138 int dimension = gridManager.grid().dimension;
139
140 // Evaluate and factorize matrix B(t)-tau*J
141 dx *= 0;
142 timer.start();
143 assembler.assemble(Linearization(eq,x,x,dx));
144 matrixAssemblyTime += (double)(timer.elapsed().user)/1e9;
145 Op A(assembler);
146
147 timer.start();
148 CoefficientVectors rhs(assembler.rhs());
149 CoefficientVectors solution = ansatzVars.zeroCoefficientVector();
150
151 if (iterative)
152 {
153 typedef typename EvolutionEquation::AnsatzVars::template CoefficientVectorRepresentation<0,neq>::type LinearSpaceX;
154
155 if ( verbosity>0 )
156 {
157 std::cout << " eq 0: dof = " << boost::fusion::at_c<0>(dx.data).space().degreesOfFreedom()
158 << " pts in mesh = " << gridManager.grid().size(dimension) << std::endl;
159 if ( verbosity>1 )
160 std::cout << " dimension of grid = " << dimension << std::endl;
161 };
162
163 initSolutionTime += (double)(timer.elapsed().user)/1e9;
164 elapsedTimeSinceReset = (double)(timer.elapsed().user)/1e9;
165
166 // in der Folge finden sich vesrschiedene iterative L�ser
167 // und Vorkonditionierer zur Auswahl per Ein-/Auskommentieren.
168 // Der Mechanismus muss noch umgestaltet werden mittels
169 // passender Parameter aus dem Main()-Programm via itegrate.hh !!!!
170
171 int iteSteps = 5000;
172 double iteEps = 1.0e-10;
173 Dune::InverseOperatorResult res;
174
175 switch (precondType)
176 {
178 {
180 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
181 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,trivial,iteEps,iteSteps,verbosity-1);
182 cg.apply(solution,rhs,res);
183 }
184 break;
186 {
187 int steps = iteSteps;
188 int coarsentype = 21;
189 int interpoltype = 0;
190 int cycleType = 1;
191 int relaxType = 3;
192 int variant = 0;
193 int overlap = 1;
194 int syseqn = 1;
195 double tol = iteEps;
196 double strongThreshold = (dimension==2)?0.25:0.6;
197 BoomerAMG<Op> BoomerAMGPrecon(A,steps,coarsentype,interpoltype,tol,cycleType,relaxType,
198 strongThreshold,variant,overlap,syseqn,verbosity);
199 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
200 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,BoomerAMGPrecon,iteEps,iteSteps,verbosity-1); // 1e-10
201 cg.apply(solution,rhs,res);
202 }
203 break;
205 {
206 int fill_lev = 1;
207 ILUKPreconditioner<Op> iluk(A,fill_lev,verbosity);
208 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
209 //Dune::CGSolver<LinearSpace> cg(A,iluk,iteEps,iteSteps,verbosity-1);
210 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,iluk,iteEps,iteSteps,verbosity-1);
211 cg.apply(solution,rhs,res);
212 }
213 break;
215 default:
216 {
217 JacobiPreconditioner<Op> jacobi(A,1.0);
218 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
219 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,jacobi,iteEps,iteSteps,verbosity-1);
220 // alternative: Dune::LoopSolver<LinearSpaceX> cg(A,jacobi,iteEps,iteSteps,verbosity-1);
221 cg.apply(solution,rhs,res);
222 }
223 break;
224 }
225
226 if ( !(res.converged) || (res.iterations == 2001) ) {
227 std::cout << " no of iterations in cg = " << res.iterations << std::endl;
228 std::cout << " convergence status of cg = " << res.converged << std::endl;
229 //std::cout << "A: " << std::endl;
230 //for (size_t ii=0; ii<nnz; ii++)
231 // std::cout << A.getmat().ridx[ii] << ", "
232 // << A.getmat().cidx[ii] << ", "
233 // << A.getmat().data[ii] << std::endl;
234 //std::cout << "A, end: " << std::endl;
235 assert(0);
236 }
237 }
238 else
239 {
240 directInverseOperator(A,directType).applyscaleadd(1.0,rhs,solution);
241 factorizationTime += (double)(timer.elapsed().user)/1e9;
242 }
243 dx.data = solution.data;
244 solutionTime += (double)(timer.elapsed().user)/1e9;
245
246
247 timer.start();
248 // Mesh adaptation only if requested and only for the full
249 // implicit Euler step (first stage).
250 if (!tolX.empty() && i==0)
251 {
252 // Compute spatial error estimate
253 tmp = dx;
255 tmp -= dx;
256
257 // perform mesh adaptation
258 accurate = embeddedErrorEstimator(ansatzVars,tmp,x,eq.parabolicEquation().scaling(),tolX,gridManager,verbosity);
259 if (!accurate)
260 nnz = assembler.nnz(0,neq,0,nvars,false);
261 estimateTime += (double)(timer.elapsed().user)/1e9;
262 }
263 } while (!accurate);
264
265 dxsum = dx;
266
267 // propagate by linearly implicit Euler
268 if (order==0)
269 {
270 // insert into extrapolation tableau
271 extrap.push_back(dxsum,stepFractions[i]);
272
273 // restore initial time
275 if (verbosity>1)
276 std::cout << " end of limex step" << std::endl;
277 return extrap.back();
278 }
279 else
280 for (int j=1; j<=i; ++j)
281 {
282 // Assemble new right hand side tau*f(x_j)
284 tmp = x; tmp += dxsum;
285 State zero(x); zero *= 0;
286 timer.start();
287 assembler.assemble(Linearization(eq,tmp,x,zero),Assembler::RHS|Assembler::MATRIX);
288 rhsAssemblyTime += (double)(timer.elapsed().user)/1e9;
289
290 Op A(assembler);
291
292 timer.start();
293 CoefficientVectors rhs(assembler.rhs());
294 CoefficientVectors solution(EvolutionEquation::AnsatzVars::template CoefficientVectorRepresentation<0,neq>::init(ansatzVars.spaces));
295 solution = 0;
296
297 if (iterative)
298 {
299 typedef typename EvolutionEquation::AnsatzVars::template CoefficientVectorRepresentation<0,neq>::type LinearSpaceX;
300
301 initSolutionTime += (double)(timer.elapsed().user)/1e9;
302 elapsedTimeSinceReset = (double)(timer.elapsed().user)/1e9;
303
304
305 int iteSteps = 5000;
306 double iteEps = 1.0e-10;
307 Dune::InverseOperatorResult res;
308
309 switch (precondType)
310 {
312 {
314 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
315 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,trivial,iteEps,iteSteps,verbosity-1);
316 cg.apply(solution,rhs,res);
317 }
318 break;
320 {
321 int steps = iteSteps;
322 int coarsentype = 21;
323 int interpoltype = 0;
324 int cycleType = 1;
325 int relaxType = 3;
326 int variant = 0;
327 int overlap = 1;
328 int syseqn = 1;
329 double tol = iteEps;
330 int dimension = gridManager.grid().dimension;
331 double strongThreshold = (dimension==2)?0.25:0.6;
332 BoomerAMG<Op> BoomerAMGPrecon(A,steps,coarsentype,interpoltype,tol,cycleType,relaxType,
333 strongThreshold,variant,overlap,syseqn,verbosity);
334 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
335 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,BoomerAMGPrecon,iteEps,iteSteps,verbosity-1); // 1e-10
336 cg.apply(solution,rhs,res);
337 }
338 break;
340 {
341 int fill_lev = 1;
342 ILUKPreconditioner<Op> iluk(A,fill_lev,verbosity);
343 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
344 //Dune::CGSolver<LinearSpace> cg(A,iluk,iteEps,iteSteps,verbosity-1);
345 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,iluk,iteEps,iteSteps,verbosity-1);
346 cg.apply(solution,rhs,res);
347 }
348 break;
350 default:
351 {
352 JacobiPreconditioner<Op> jacobi(A,1.0);
353 precAssemblyTime += (double)(timer.elapsed().user)/1e9-elapsedTimeSinceReset;
354 Dune::BiCGSTABSolver<LinearSpaceX> cg(A,jacobi,iteEps,iteSteps,verbosity-1);
355 cg.apply(solution,rhs,res);
356 }
357 break;
358 }
359
360 if ( !(res.converged) || (res.iterations == 2001) )
361 {
362 typedef typename Op::field_type field_type;
363 MatrixAsTriplet<field_type> triplet = A.template get<MatrixAsTriplet<field_type> >();
364
365 std::cout << " no of iterations in cg = " << res.iterations << std::endl;
366 std::cout << " convergence status of cg = " << res.converged << std::endl;
367 std::cout << "A: " << std::endl;
368 for (size_t ii=0; ii<nnz; ii++)
369 std::cout << triplet.ridx[ii] << ", " << triplet.cidx[ii] << ", " << triplet.data[ii] << std::endl;
370 std::cout << "A, end: " << std::endl;
371 assert(0);
372 }
373 }
374 else
375 {
376 directInverseOperator(A,directType).applyscaleadd(1.0,rhs,solution);
377 }
378 dx.data = solution.data;
379
380 dxsum += dx;
381 solutionTime += (double)(timer.elapsed().user)/1e9;
382 }
383 // insert into extrapolation tableau
384 extrap.push_back(dxsum,stepFractions[i]);
385
386 // restore initial time
388 }
389
390 return extrap.back();
391 }
392
399 std::vector<std::pair<double,double> > estimateError(State const& x,int i, int j) const
400 {
401 assert(extrap.size()>1);
402
403 std::vector<std::pair<double,double> > e(ansatzVars.noOfVariables);
404
405 relativeError(typename EvolutionEquation::AnsatzVars::Variables(),extrap[i].data,
406 extrap[j].data,x.data,
407 ansatzVars.spaces,eq.parabolicEquation().scaling(),e.begin());
408
409 return e;
410 }
411
412 template <class OutStream>
413 void reportTime(OutStream& out) const {
414 out << "Limex time: " << matrixAssemblyTime << "s matrix assembly\n"
415 << " " << rhsAssemblyTime << "s rhs assembly\n"
416 << " " << precAssemblyTime << "s preconditioner assembly\n"
417 << " " << factorizationTime << "s factorization\n"
418 << " " << initSolutionTime << "s init solution\n"
419 << " " << solutionTime << "s solution\n"
420 << " " << estimateTime << "s estimate\n"
421 << std::flush;
422 }
423
424 void advanceTime(double dt)
425 {
426 eq.parabolicEquation().setTime(eq.time()+dt);
427 }
428
429
430 private:
432 typename EvolutionEquation::AnsatzVars const& ansatzVars;
434 Assembler assembler;
435
436 public:
443 };
444} // namespace Kaskade
445#endif
An adaptor presenting a Dune::LinearOperator <domain_type,range_type> interface to a contiguous sub-b...
void push_back(T t, double hnew)
Grid const & grid() const
Returns a const reference on the owned grid.
Definition: gridmanager.hh:292
Self & setVerbosity(const bool verbosity)
sets the verbosity level of the grid manager
Definition: gridmanager.hh:499
EvolutionEquation::AnsatzVars::VariableSet State
double rhsAssemblyTime
Definition: limex.hh:172
double elapsedTimeSinceReset
double matrixAssemblyTime
Definition: limex.hh:172
void advanceTime(double dt)
State const & step(State const &x, double dt, int order, std::vector< std::pair< double, double > > const &tolX)
Computes a state increment that advances the given state in time. The time in the given evolution equ...
PrecondType precondType
double solutionTime
Definition: limex.hh:172
std::vector< std::pair< double, double > > estimateError(State const &x, int i, int j) const
ExtrapolationTableau< State > extrap
Definition: limex.hh:171
Limex(GridManager< typename EvolutionEquation::AnsatzVars::Grid > &gridManager_, EvolutionEquation &eq_, typename EvolutionEquation::AnsatzVars const &ansatzVars_, DirectType st=DirectType::MUMPS, PrecondType precondType_=PrecondType::ILUK, int verbosity_=1)
void reportTime(OutStream &out) const
double factorizationTime
Definition: limex.hh:172
DirectType directType
std::vector< SparseIndexInt > ridx
row indices
Definition: triplet.hh:669
std::vector< SparseIndexInt > cidx
column indices
Definition: triplet.hh:671
std::vector< Scalar > data
data
Definition: triplet.hh:673
Self & setTau(Scalar dt)
Sets the time step size.
Definition: semieuler.hh:428
ParabolicEquation & parabolicEquation()
Definition: semieuler.hh:442
Proxy class for the linearization of semi-linear time stepping schemes.
The trivial preconditioner: this is simply the identity that does exactly nothing.
TestVariableSetDescription::template CoefficientVectorRepresentation< first, last >::type rhs() const
Returns a contiguous subrange of the rhs coefficient vectors.
size_t nnz(size_t rbegin=0, size_t rend=TestVariableSetDescription::noOfVariables, size_t cbegin=0, size_t cend=AnsatzVariableSetDescription::noOfVariables, bool extractOnlyLowerTriangle=false) const
Returns the number of structurally nonzero entries in the submatrix defined by the half-open block ra...
void assemble(F const &f, unsigned int flags=Assembler::EVERYTHING, int nThreads=0, bool verbose=false)
Assembly without block filter or cell filter.
void temporalEvaluationRange(double t0, double t1)
Notifies the PDE in which time interval evaluations will be done.
double time() const
Reports the current simulated time for which the evaluations are done.
ParabolicEquation & setTime(double t)
Sets a new time for evaluating PDE coefficients.
PrecondType
Definition: enums.hh:18
Utility classes for the definition and use of variational functionals.
void projectHierarchically(VariableSet< VariableSetDescription > &f)
Projects the given FE function onto the the polynomial ansatz subspace of one order lower....
bool embeddedErrorEstimator(VariableSetDescription const &varDesc, typename VariableSetDescription::VariableSet const &err, typename VariableSetDescription::VariableSet const &sol, Scaling const &scaling, std::vector< std::pair< double, double > > const &tol, GridManager< typename VariableSetDescription::Grid > &gridManager, int verbosity=1)
Embedded error estimation and mesh refinement.
DirectType
Available direct solvers for linear equation systems.
Definition: enums.hh:35
@ MUMPS
MUMPS sparse solver.
@ UMFPACK
UMFPack from SuiteSparse, using 32 bit integer indices.
Hierarchic Finite Elements.
Lagrange Finite Elements.
DirectType xyz
InverseLinearOperator< DirectSolver< typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Domain, typename AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol >::Range > > directInverseOperator(AssembledGalerkinOperator< GOP, firstRow, lastRow, firstCol, lastCol > const &A, DirectType directType, MatrixProperties properties)
Definition: direct.hh:618
void relativeError(Variables const &varDesc, Functions const &f1, Functions const &f2, Functions const &f3, Spaces const &spaces, Scaling const &scaling, OutIter out)