diff --git a/src/nicefunction.hh b/src/nicefunction.hh index 2c86abcdd257e81e0a296c72984eec34c47040e1..449e2f63c95c24c29e7e594a74df3d8b5385e950 100644 --- a/src/nicefunction.hh +++ b/src/nicefunction.hh @@ -35,5 +35,60 @@ class TrivialFunction : public NiceFunction { double virtual rightDifferential(const double) const { return 0; } }; + +// slope in [n-1,n] is n +class HorribleFunction : public NiceFunction { +public: + void virtual evaluate(const double& x, double& y) const { + double const fl = floor(x); + double const sum = fl * (fl + 1) / 2; + y = sum + (fl + 1) * (x - fl); + } + + double virtual leftDifferential(const double x) const { + double const fl = floor(x); + if (x - fl < 1e-14) + return fl; + else + return fl + 1; + } + + double virtual rightDifferential(const double x) const { + double const c = ceil(x); + if (c - x < 1e-14) + return c + 1; + else + return c; + } +}; + +// slope in [n-1,n] is log(n+1) +class HorribleFunctionLogarithmic : public NiceFunction { +public: + void virtual evaluate(const double& x, double& y) const { + y = 0; + size_t const fl = floor(x); + for (size_t i = 1; i <= fl;) + y += log(++i); // factorials grow to fast so we compute this incrementally + + y += log(fl + 2) * (x - fl); + } + + double virtual leftDifferential(const double x) const { + double const fl = floor(x); + if (x - fl < 1e-14) + return log(fl + 1); + else + return log(fl + 2); + } + + double virtual rightDifferential(const double x) const { + double const c = ceil(x); + if (c - x < 1e-14) + return log(c + 2); + else + return log(c + 1); + } +}; } #endif diff --git a/src/test-gradient-method.cc b/src/test-gradient-method.cc index 4443b527e6f087eb42772d99491d7e1375c10aa9..eb7b5e5c28d7d210be7b41f6cc22de84168f484a 100644 --- a/src/test-gradient-method.cc +++ b/src/test-gradient-method.cc @@ -182,6 +182,76 @@ void testTrivialFunction() { assert(std::abs(ret1 - ret2) < 1e-5); } +void testHorribleFunction() { + int const dim = 2; + typedef Dune::SampleFunctional<dim> SampleFunctional; + + SampleFunctional::SmallMatrix A; + A[0][0] = 3; + A[0][1] = 1.5; + A[1][0] = 1.5; + A[1][1] = 4; + SampleFunctional::SmallVector b; + b[0] = 1; + b[1] = 2; + + Dune::HorribleFunction f; + SampleFunctional J(A, b, Dune::MyNonlinearity<dim>(f)); + + SampleFunctional::SmallVector start = b; + start *= 17; + + double const ret1 = functionTester(J, start, 7); + + // Something random + start[0] = 279; + start[1] = -96; + + double const ret2 = functionTester(J, start, 8); + assert(std::abs(ret1 - ret2) < 1e-5); + + start[0] = 0; + start[1] = 0; + + double const ret3 = functionTester(J, start, 4); + assert(std::abs(ret1 - ret3) < 1e-5); +} + +void testHorribleFunctionLogarithmic() { + int const dim = 2; + typedef Dune::SampleFunctional<dim> SampleFunctional; + + SampleFunctional::SmallMatrix A; + A[0][0] = 3; + A[0][1] = 1.5; + A[1][0] = 1.5; + A[1][1] = 4; + SampleFunctional::SmallVector b; + b[0] = 1; + b[1] = 2; + + Dune::HorribleFunctionLogarithmic f; + SampleFunctional J(A, b, Dune::MyNonlinearity<dim>(f)); + + SampleFunctional::SmallVector start = b; + start *= 17; + + double const ret1 = functionTester(J, start, 6); + + // Something random + start[0] = 279; + start[1] = -96; + + double const ret2 = functionTester(J, start, 12); + assert(std::abs(ret1 - ret2) < 1e-5); + + start[0] = 0; + start[1] = 0; + + double const ret3 = functionTester(J, start, 4); + assert(std::abs(ret1 - ret3) < 1e-5); +} + int main() { try { testSampleFunction(); @@ -189,6 +259,10 @@ int main() { testSampleFunctionNonsmooth(); std::cout << std::endl << std::endl << std::endl; testTrivialFunction(); + std::cout << std::endl << std::endl << std::endl; + testHorribleFunction(); + std::cout << std::endl << std::endl << std::endl; + testHorribleFunctionLogarithmic(); return 0; } catch (Dune::Exception &e) {