From bcf73446fdcd39a9205a371ad4cc25ce0d3c35b4 Mon Sep 17 00:00:00 2001 From: Elias Pipping <elias.pipping@fu-berlin.de> Date: Sun, 10 Feb 2013 19:49:23 +0100 Subject: [PATCH] Implement eulerPair scheme (implicitEuler for u,v) --- src/enum_scheme.cc | 3 ++ src/enums.hh | 3 +- src/one-body-sample.cc | 5 ++ src/timestepping.cc | 106 +++++++++++++++++++++++++++++++++++++++ src/timestepping.hh | 37 ++++++++++++++ src/timestepping_tmpl.cc | 1 + 6 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/enum_scheme.cc b/src/enum_scheme.cc index 9866d4d5..615d8933 100644 --- a/src/enum_scheme.cc +++ b/src/enum_scheme.cc @@ -11,6 +11,9 @@ template <> struct StringToEnum<Config::scheme> { if (s == "newmark") return Config::Newmark; + if (s == "eulerPair") + return Config::EulerPair; + DUNE_THROW(Dune::Exception, "failed to parse enum"); } }; diff --git a/src/enums.hh b/src/enums.hh index f8d05d21..b6ffb733 100644 --- a/src/enums.hh +++ b/src/enums.hh @@ -9,7 +9,8 @@ struct Config { enum scheme { ImplicitTwoStep, ImplicitEuler, - Newmark + Newmark, + EulerPair }; }; #endif diff --git a/src/one-body-sample.cc b/src/one-body-sample.cc index c978a555..4525e6bb 100644 --- a/src/one-body-sample.cc +++ b/src/one-body-sample.cc @@ -108,6 +108,11 @@ initTimeStepper(Config::scheme scheme, FunctionType const &dirichletFunction, Newmark<VectorType, MatrixType, FunctionType, dims>>( stiffnessMatrix, massMatrix, u_initial, ud_initial, udd_initial, ignoreNodes, dirichletFunction); + case Config::EulerPair: + return Dune::make_shared< + EulerPair<VectorType, MatrixType, FunctionType, dims>>( + stiffnessMatrix, massMatrix, u_initial, ud_initial, udd_initial, + ignoreNodes, dirichletFunction); } } template <class SingletonVectorType, class VectorType> diff --git a/src/timestepping.cc b/src/timestepping.cc index 07d1bf41..614ed718 100644 --- a/src/timestepping.cc +++ b/src/timestepping.cc @@ -337,5 +337,111 @@ TimeSteppingScheme<VectorType, MatrixType, FunctionType, dim> * Newmark<VectorType, MatrixType, FunctionType, dim>::clone() { return new Newmark<VectorType, MatrixType, FunctionType, dim>(*this); } +template <class VectorType, class MatrixType, class FunctionType, int dim> +EulerPair<VectorType, MatrixType, FunctionType, dim>::EulerPair( + MatrixType const &_A, MatrixType const &_B, VectorType const &_u_initial, + VectorType const &_ud_initial, VectorType const &_udd_initial, + Dune::BitSetVector<dim> const &_dirichletNodes, + FunctionType const &_dirichletFunction) + : A(_A), + B(_B), + u(_u_initial), + ud(_ud_initial), + udd(_udd_initial), + dirichletNodes(_dirichletNodes), + dirichletFunction(_dirichletFunction) {} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +void EulerPair<VectorType, MatrixType, FunctionType, dim>::nextTimeStep() { + udd_old = udd; + ud_old = ud; + u_old = u; +} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +void EulerPair<VectorType, MatrixType, FunctionType, dim>::setup( + VectorType const &ell, double _tau, double time, VectorType &problem_rhs, + VectorType &problem_iterate, MatrixType &problem_A) { + postProcessCalled = false; + + tau = _tau; + + problem_rhs = ell; + B.usmv(1.0 / tau, ud_old, problem_rhs); + A.usmv(-1.0, u_old, problem_rhs); + + // For fixed tau, we'd only really have to do this once + Dune::MatrixIndexSet indices(A.N(), A.M()); + indices.import(A); + indices.import(B); + indices.exportIdx(problem_A); + problem_A = 0.0; + Arithmetic::addProduct(problem_A, tau, A); + Arithmetic::addProduct(problem_A, 1.0 / tau, B); + + // ud_old makes a good initial iterate; we could use anything, though + problem_iterate = ud_old; + + for (size_t i = 0; i < dirichletNodes.size(); ++i) + switch (dirichletNodes[i].count()) { + case 0: + continue; + case dim: + problem_iterate[i] = 0; + dirichletFunction.evaluate(time, problem_iterate[i][0]); + break; + case 1: + if (dirichletNodes[i][0]) { + dirichletFunction.evaluate(time, problem_iterate[i][0]); + break; + } + if (dirichletNodes[i][1]) { + problem_iterate[i][1] = 0; + break; + } + assert(false); + default: + assert(false); + } +} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +void EulerPair<VectorType, MatrixType, FunctionType, dim>::postProcess( + VectorType const &problem_iterate) { + postProcessCalled = true; + + ud = problem_iterate; + + u = u_old; + Arithmetic::addProduct(u, tau, ud); + + udd = 0; + Arithmetic::addProduct(udd, 1.0 / tau, ud); + Arithmetic::addProduct(udd, -1.0 / tau, ud_old); +} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +void EulerPair<VectorType, MatrixType, FunctionType, dim>::extractDisplacement( + VectorType &displacement) const { + if (!postProcessCalled) + DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!"); + + displacement = u; +} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +void EulerPair<VectorType, MatrixType, FunctionType, dim>::extractVelocity( + VectorType &velocity) const { + if (!postProcessCalled) + DUNE_THROW(Dune::Exception, "It seems you forgot to call postProcess!"); + + velocity = ud; +} + +template <class VectorType, class MatrixType, class FunctionType, int dim> +TimeSteppingScheme<VectorType, MatrixType, FunctionType, dim> * +EulerPair<VectorType, MatrixType, FunctionType, dim>::clone() { + return new EulerPair<VectorType, MatrixType, FunctionType, dim>(*this); +} #include "timestepping_tmpl.cc" diff --git a/src/timestepping.hh b/src/timestepping.hh index 84da56b7..f57d67ff 100644 --- a/src/timestepping.hh +++ b/src/timestepping.hh @@ -112,6 +112,43 @@ class Newmark virtual TimeSteppingScheme<VectorType, MatrixType, FunctionType, dim> * clone(); +private: + MatrixType const &A; + MatrixType const &B; + VectorType u; + VectorType ud; + VectorType udd; + Dune::BitSetVector<dim> const &dirichletNodes; + FunctionType const &dirichletFunction; + + VectorType u_old; + VectorType ud_old; + VectorType udd_old; + + double tau; + + bool postProcessCalled = false; +}; +template <class VectorType, class MatrixType, class FunctionType, int dim> +class EulerPair + : public TimeSteppingScheme<VectorType, MatrixType, FunctionType, dim> { +public: + EulerPair(MatrixType const &_A, MatrixType const &_B, + VectorType const &_u_initial, VectorType const &_ud_initial, + VectorType const &_udd_initial, + Dune::BitSetVector<dim> const &_dirichletNodes, + FunctionType const &_dirichletFunction); + + void virtual nextTimeStep(); + void virtual setup(VectorType const &, double, double, VectorType &, + VectorType &, MatrixType &); + void virtual postProcess(VectorType const &); + void virtual extractDisplacement(VectorType &) const; + void virtual extractVelocity(VectorType &) const; + + virtual TimeSteppingScheme<VectorType, MatrixType, FunctionType, dim> * + clone(); + private: MatrixType const &A; MatrixType const &B; diff --git a/src/timestepping_tmpl.cc b/src/timestepping_tmpl.cc index 3db2ba60..5feceaf6 100644 --- a/src/timestepping_tmpl.cc +++ b/src/timestepping_tmpl.cc @@ -17,3 +17,4 @@ typedef Dune::VirtualFunction<double, double> FunctionType; template class ImplicitEuler<VectorType, MatrixType, FunctionType, DIM>; template class ImplicitTwoStep<VectorType, MatrixType, FunctionType, DIM>; template class Newmark<VectorType, MatrixType, FunctionType, DIM>; +template class EulerPair<VectorType, MatrixType, FunctionType, DIM>; -- GitLab