diff --git a/src/multi-body-problem-2D.cfg b/src/multi-body-problem-2D.cfg index a308c80b63b9cb2b48f0cc096ade7d9cdf464e57..676d1a408726cc0c1a71d3c87010a35182156147 100644 --- a/src/multi-body-problem-2D.cfg +++ b/src/multi-body-problem-2D.cfg @@ -1,6 +1,6 @@ # -*- mode:conf -*- [boundary.friction] -smallestDiameter = 0.01 # 2e-3 [m] +smallestDiameter = 0.5 # 2e-3 [m] [timeSteps] refinementTolerance = 1e-5 # 1e-5 diff --git a/src/multi-body-problem.cfg b/src/multi-body-problem.cfg index d58f80cfbe067c712e6d8396d2a37faf5eba7317..77de9404eafc006ed026f47ebfd43b58a4db1fe1 100644 --- a/src/multi-body-problem.cfg +++ b/src/multi-body-problem.cfg @@ -11,7 +11,7 @@ vtk.write = true [problem] finalTime = 100 # [s] #1000 -bodyCount = 4 +bodyCount = 2 [body] bulkModulus = 0.5e5 # [Pa] diff --git a/src/spatial-solving/tnnmg/functional.hh b/src/spatial-solving/tnnmg/functional.hh index 5a1d3b3736dcb65621342dfdeefeec21f0dfe12c..97dab68876812aefab43d4fe30549bdecf20429e 100644 --- a/src/spatial-solving/tnnmg/functional.hh +++ b/src/spatial-solving/tnnmg/functional.hh @@ -16,10 +16,12 @@ #include <dune/tnnmg/functionals/boxconstrainedquadraticfunctional.hh> +#include "../../utils/debugutils.hh" + template<class M, class V, class N, class L, class U, class R> class DirectionalRestriction; -template<class M, class V, class N, class R> +template<class M, class E, class V, class N, class R> class ShiftedFunctional; template <class M, class V, class N, class L, class U, class R> @@ -33,21 +35,23 @@ class Functional; * \tparam V nonlinearity type * \tparam R Range type */ -template<class M, class V, class N, class R> +template<class M, class E, class V, class N, class R> class ShiftedFunctional : public Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunctional<M,V,R> { using Base = Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunctional<M,V,R>; public: using Matrix = M; + using Eigenvalues = E; using Vector = V; using Nonlinearity = N; using LowerObstacle = Vector; using UpperObstacle = Vector; using Range = R; - ShiftedFunctional(const Matrix& quadraticPart, const Vector& linearPart, const Nonlinearity& phi, const LowerObstacle& lowerObstacle, const UpperObstacle& upperObstacle, const Vector& origin) : + ShiftedFunctional(const Matrix& quadraticPart, const Eigenvalues& maxEigenvalues, const Vector& linearPart, const Nonlinearity& phi, const LowerObstacle& lowerObstacle, const UpperObstacle& upperObstacle, const Vector& origin) : Base(quadraticPart, linearPart, lowerObstacle, upperObstacle, origin), - phi_(phi) + phi_(phi), + maxEigenvalues_(maxEigenvalues) {} Range operator()(const Vector& v) const @@ -63,14 +67,13 @@ class ShiftedFunctional : public Dune::TNNMG::ShiftedBoxConstrainedQuadraticFunc return phi_; } - friend auto directionalRestriction(const ShiftedFunctional& f, const Vector& origin, const Vector& direction) - -> DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range> - { - return DirectionalRestriction<Matrix, Vector, Nonlinearity, LowerObstacle, UpperObstacle, Range>(f.quadraticPart(), f.originalLinearPart(), f.phi(), f.originalLowerObstacle(), f.originalUpperObstacle(), origin, direction); + const auto& maxEigenvalues() const { + return maxEigenvalues_; } protected: const Nonlinearity& phi_; + const Eigenvalues& maxEigenvalues_; }; @@ -167,80 +170,56 @@ class DirectionalRestriction : * \tparam U Upper obstacle type * \tparam R Range type */ -/*template<class V, class N, class L, class U, class O, class D, class R> -class FirstOrderModelFunctional { +template<class N, class V, class R> +class FirstOrderFunctional { using Interval = typename Dune::Solvers::Interval<R>; public: - using Vector = std::decay_t<V>; using Nonlinearity = std::decay_t<N>; - using LowerObstacle = std::decay_t<L>; - using UpperObstacle = std::decay_t<U>; + using Vector = V; + using LowerObstacle = V; + using UpperObstacle = V; using Range = R; - using field_type = typename Vector::field_type; - + using field_type = typename V::field_type; public: - template <class VV1, class NN, class LL, class UU, class VV2> - FirstOrderModelFunctional( + template <class NN, class LL, class UU, class OO, class DD> + FirstOrderFunctional( const Range& maxEigenvalue, - VV1&& linearTerm, + const Range& linearPart, NN&& phi, LL&& lower, UU&& upper, - VV2&& origin) : - maxEigenvalue_(maxEigenvalue), - linearTerm_(std::forward<VV1>(linearTerm)), + OO&& origin, + DD&& direction) : + quadraticPart_(maxEigenvalue), + linearPart_(linearPart), lower_(std::forward<LL>(lower)), upper_(std::forward<UU>(upper)), - origin_(std::forward<VV2>(origin)), - //direction_(linearTerm_), + origin_(std::forward<OO>(origin)), + direction_(std::forward<DD>(direction)), phi_(std::forward<NN>(phi)) { - auto& origin = origin_.get(); - auto& direction = direction_.get(); - - auto v = ri; - double const vnorm = v.two_norm(); - if (vnorm > 1.0) - v /= vnorm; - // set defect obstacles defectLower_ = -std::numeric_limits<field_type>::max(); defectUpper_ = std::numeric_limits<field_type>::max(); - Dune::TNNMG::directionalObstacles(origin, direction, lower_.get(), upper_.get(), defectLower_, defectUpper_); + Dune::TNNMG::directionalObstacles(origin_.get(), direction_.get(), lower_.get(), upper_.get(), defectLower_, defectUpper_); // set domain - phi_.get().directionalDomain(origin, direction, domain_); + phi_.get().directionalDomain(origin_.get(), direction_.get(), domain_); - if (domain_[0] < defectLower_) { + /*if (domain_[0] < defectLower_) { domain_[0] = defectLower_; } if (domain_[1] > defectUpper_) { domain_[1] = defectUpper_; - } + }*/ } - template <class BitVector> - auto setIgnore(const BitVector& ignore) const { - Vector direction = direction_.get(); - Vector origin = origin_.get(); - // Dune::Solvers::resizeInitializeZero(direction, linearPart()); - for (size_t j = 0; j < ignore.size(); ++j) - if (ignore[j]) - direction[j] = 0; // makes sure result remains in subspace after correction - else - origin[j] = 0; // shift affine offset - - // set quadratic and linear parts of functional - quadraticPart_ = maxEigenvalue_ * direction.two_norm2(); - linearPart_ = linearTerm_.get() * direction; - } - Range operator()(const Vector& v) const { - DUNE_THROW(Dune::NotImplemented, "Evaluation of FirstOrderModelFunctional not implemented"); + DUNE_THROW(Dune::NotImplemented, "Evaluation of FirstOrderFunctional not implemented"); } auto subDifferential(double x) const { @@ -261,49 +240,53 @@ class FirstOrderModelFunctional { return domain_; } - const Vector& origin() const { + const auto& origin() const { return origin_.get(); } - const Vector& direction() const { + const auto& direction() const { return direction_.get(); } - const field_type& defectLower() const { + const auto& lowerObstacle() const { return defectLower_; } - const field_type& defectUpper() const { + const auto& upperObstacle() const { return defectUpper_; } + const auto& quadraticPart() const { + return quadraticPart_; + } + + const auto& linearPart() const { + return linearPart_; + } private: - Dune::Solvers::ConstCopyOrReference<V> linearTerm_; - Dune::Solvers::ConstCopyOrReference<L> lower_; - Dune::Solvers::ConstCopyOrReference<U> upper_; + const Range quadraticPart_; + const Range linearPart_; + + Dune::Solvers::ConstCopyOrReference<LowerObstacle> lower_; + Dune::Solvers::ConstCopyOrReference<UpperObstacle> upper_; - Dune::Solvers::ConstCopyOrReference<O> origin_; - Dune::Solvers::ConstCopyOrReference<D> direction_; + Dune::Solvers::ConstCopyOrReference<Vector> origin_; + Dune::Solvers::ConstCopyOrReference<Vector> direction_; Dune::Solvers::ConstCopyOrReference<N> phi_; Interval domain_; - Range maxEigenvalue_; - - field_type quadraticPart_; - field_type linearPart_; - field_type defectLower_; field_type defectUpper_; -};*/ +}; // \ToDo This should be an inline friend of ShiftedBoxConstrainedQuadraticFunctional // but gcc-4.9.2 shipped with debian jessie does not accept // inline friends with auto return type due to bug-59766. // Notice, that this is fixed in gcc-4.9.3. -template<class Index, class M, class V, class Nonlinearity, class R> -auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, const Index& i) +template<class Index, class M, class E, class V, class Nonlinearity, class R> +auto coordinateRestriction(const ShiftedFunctional<M, E, V, Nonlinearity, R>& f, const Index& i) { using Range = R; using LocalMatrix = std::decay_t<decltype(f.quadraticPart()[i][i])>; @@ -316,6 +299,8 @@ auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, co const LocalMatrix* Aii_p = nullptr; + //print(f.origin(), "f.origin: "); + LocalVector ri = f.originalLinearPart()[i]; const auto& Ai = f.quadraticPart()[i]; sparseRangeFor(Ai, [&](auto&& Aij, auto&& j) { @@ -326,35 +311,9 @@ auto coordinateRestriction(const ShiftedFunctional<M, V, Nonlinearity, R>& f, co Dune::TNNMG::Imp::mmv(Aij, f.origin()[j], ri, Dune::PriorityTag<1>()); }); - // set maxEigenvalue from matrix - LocalVector eigenvalues; - Dune::FMatrixHelp::eigenValues(*Aii_p, eigenvalues); - auto maxEigenvalue = *std::max_element(std::begin(eigenvalues), std::end(eigenvalues)); - - Dune::MatrixVector::addProduct(ri, maxEigenvalue, f.origin()[i]); - - LocalMatrix Aii = 0; - for (size_t d=0; d<Aii.N(); d++) { - Aii[d][d] = maxEigenvalue; - } - - LocalLowerObstacle dli = f.originalLowerObstacle()[i]; - LocalUpperObstacle dui = f.originalUpperObstacle()[i]; - dli -= f.origin()[i]; - dui -= f.origin()[i]; - auto&& phii = f.phi().restriction(i); - /*std::cout << "maxEigenvalue matrix: " << std::endl; - for (size_t i=0; i<Aii.N(); i++) { - for (size_t j=0; j<Aii.M(); j++) { - std::cout << Aii[i][j] << " "; - } - std::cout << std::endl; - }*/ - - //return FirstOrderModelFunctional<LocalVector, decltype(phii), LocalLowerObstacle, LocalUpperObstacle, LocalVector, LocalVector, Range>(maxEigenvalue, std::move(ri), std::move(phii), std::move(dli), std::move(dui), std::move(f.origin()[i])); - return ShiftedFunctional<LocalMatrix, LocalVector, decltype(phii), Range>(std::move(Aii), std::move(ri), std::move(phii), std::move(dli), std::move(dui), f.origin()[i]); + return ShiftedFunctional<LocalMatrix, Range, LocalVector, decltype(phii), Range>(*Aii_p, f.maxEigenvalues()[i], std::move(ri), std::move(phii), f.originalLowerObstacle()[i], f.originalUpperObstacle()[i], f.origin()[i]); } @@ -382,8 +341,11 @@ class Functional : public Dune::TNNMG::BoxConstrainedQuadraticFunctional<M, V, L using LowerObstacle = typename Base::LowerObstacle; using UpperObstacle = typename Base::UpperObstacle; + using Eigenvalues = std::vector<Range>; + private: Dune::Solvers::ConstCopyOrReference<N> phi_; + Eigenvalues maxEigenvalues_; public: @@ -395,13 +357,25 @@ class Functional : public Dune::TNNMG::BoxConstrainedQuadraticFunctional<M, V, L LL&& lower, UU&& upper) : Base(std::forward<MM>(matrix), std::forward<VV>(linearPart), std::forward<LL>(lower), std::forward<UU>(upper)), - phi_(std::forward<NN>(phi)) - {} + phi_(std::forward<NN>(phi)), + maxEigenvalues_(this->linearPart().size()) + { + for (size_t i=0; i<this->quadraticPart().N(); ++i) { + typename Vector::block_type eigenvalues; + Dune::FMatrixHelp::eigenValues(this->quadraticPart()[i][i], eigenvalues); + maxEigenvalues_[i] = + *std::max_element(std::begin(eigenvalues), std::end(eigenvalues)); + } + } const Nonlinearity& phi() const { return phi_.get(); } + const auto& maxEigenvalues() const { + return maxEigenvalues_; + } + Range operator()(const Vector& v) const { if (Dune::TNNMG::checkInsideBox(v, this->lower_.get(), this->upper_.get())) @@ -416,9 +390,9 @@ class Functional : public Dune::TNNMG::BoxConstrainedQuadraticFunctional<M, V, L } friend auto shift(const Functional& f, const Vector& origin) - -> ShiftedFunctional<Matrix, Vector, Nonlinearity, Range> + -> ShiftedFunctional<Matrix, Eigenvalues, Vector, Nonlinearity, Range> { - return ShiftedFunctional<Matrix, Vector, Nonlinearity, Range>(f.quadraticPart(), f.linearPart(), f.phi(), f.lowerObstacle(), f.upperObstacle(), origin); + return ShiftedFunctional<Matrix, Eigenvalues, Vector, Nonlinearity, Range>(f.quadraticPart(), f.maxEigenvalues(), f.linearPart(), f.phi(), f.lowerObstacle(), f.upperObstacle(), origin); } }; diff --git a/src/spatial-solving/tnnmg/localbisectionsolver.hh b/src/spatial-solving/tnnmg/localbisectionsolver.hh index 33f69e956c5c0e6b9102164932d4a440b08c611b..b24eb8ee6f84da9652d11924ea1a44056a1836c8 100644 --- a/src/spatial-solving/tnnmg/localbisectionsolver.hh +++ b/src/spatial-solving/tnnmg/localbisectionsolver.hh @@ -3,8 +3,13 @@ #ifndef DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH #define DUNE_TECTONIC_LOCALBISECTIONSOLVER_HH +#include <dune/matrix-vector/axpy.hh> + #include <dune/tnnmg/localsolvers/scalarobstaclesolver.hh> #include <dune/tnnmg/problem-classes/bisection.hh> + +#include "functional.hh" + #include "../../utils/debugutils.hh" /** @@ -21,26 +26,33 @@ class LocalBisectionSolver return; } - Vector origin = f.origin(); - Vector direction = f.originalLinearPart(); + auto maxEigenvalue = f.maxEigenvalues(); + + auto origin = f.origin(); + auto linearPart = f.originalLinearPart(); + Dune::MatrixVector::addProduct(linearPart, maxEigenvalue, origin); for (size_t j = 0; j < ignore.size(); ++j) if (ignore[j]) - direction[j] = 0; // makes sure result remains in subspace after correction + linearPart[j] = 0; // makes sure result remains in subspace after correction else origin[j] = 0; // shift affine offset - double const directionNorm = direction.two_norm(); - if (directionNorm <= 0.0) + double const linearPartNorm = linearPart.two_norm(); + if (linearPartNorm <= 0.0) return; - direction /= directionNorm; + linearPart /= linearPartNorm; - auto&& directionalF = directionalRestriction(f, origin, direction); + using Nonlinearity = std::decay_t<decltype(f.phi())>; + using Range = std::decay_t<decltype(f.maxEigenvalues())>; + using FirstOrderFunctional = FirstOrderFunctional<Nonlinearity, Vector, Range>; + + FirstOrderFunctional firstOrderFunctional(maxEigenvalue, linearPartNorm, f.phi(), f.originalLowerObstacle(), f.originalUpperObstacle(), origin, linearPart); // scalar obstacle solver without nonlinearity typename Functional::Range alpha; - Dune::TNNMG::ScalarObstacleSolver obstacleSolver; - obstacleSolver(alpha, directionalF, false); + /*Dune::TNNMG::ScalarObstacleSolver obstacleSolver; + obstacleSolver(alpha, firstOrderFunctional, false);*/ //direction *= alpha; @@ -59,23 +71,31 @@ class LocalBisectionSolver auto D = directionalF.subDifferential(0); std::cout << "subDiff at x: " << D[0] << " " << D[1] << std::endl;*/ - const auto& domain = directionalF.domain(); + const auto& domain = firstOrderFunctional.domain(); if (std::abs(domain[0]-domain[1])>safety) { int bisectionsteps = 0; - const Bisection globalBisection; + const Bisection globalBisection(0.0, 1.0, 0.0, 0.0); + + alpha = globalBisection.minimize(firstOrderFunctional, 0.0, 0.0, bisectionsteps); + + if (alpha < firstOrderFunctional.lowerObstacle() ) { + alpha = firstOrderFunctional.lowerObstacle(); + } - alpha = globalBisection.minimize(directionalF, alpha, 0.0, bisectionsteps); + if (alpha > firstOrderFunctional.upperObstacle() ) { + alpha = firstOrderFunctional.upperObstacle(); + } } - direction *= alpha; + linearPart *= alpha; #ifdef NEW_TNNMG_COMPUTE_ITERATES_DIRECTLY x = origin; - x += direction; + x += linearPart; #else //x = origin; - x -= f.origin(); - x += direction; + //x -= f.origin(); + x = linearPart; #endif } };