From 800506cc5bdb61b9681092cfc81060a74e085399 Mon Sep 17 00:00:00 2001 From: bangerth Date: Wed, 16 Nov 2011 14:33:54 +0000 Subject: [PATCH] Provide ScalarFunctionFromFunctionObject. git-svn-id: https://svn.dealii.org/trunk@24750 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/doc/news/changes.h | 6 ++ deal.II/include/deal.II/base/function.h | 108 ++++++++++++++++++++++++ deal.II/source/base/function.cc | 28 ++++++ tests/base/functions_05.cc | 83 ++++++++++++++++++ tests/base/functions_05/cmp/generic | 7 ++ 5 files changed, 232 insertions(+) create mode 100644 tests/base/functions_05.cc create mode 100644 tests/base/functions_05/cmp/generic diff --git a/deal.II/doc/news/changes.h b/deal.II/doc/news/changes.h index 8747872fc0..09a6e01a97 100644 --- a/deal.II/doc/news/changes.h +++ b/deal.II/doc/news/changes.h @@ -78,6 +78,12 @@ enabled due to a missing include file in file

Specific improvements

    +
  1. New: The class ScalarFunctionFromFunctionObject provides a quick way to +convert an arbitrary function into a function object that can be passed +to part of the library that require the Function@ interface. +
    +(Wolfgang Bangerth, 2011/10/30) +
  2. New: FETools::get_fe_from_name() can now return objects of type FE_Nothing.
    (Scott Miller, Jonathan Pitt, 2011/11/10) diff --git a/deal.II/include/deal.II/base/function.h b/deal.II/include/deal.II/base/function.h index c9daa892be..5073ee55ce 100644 --- a/deal.II/include/deal.II/base/function.h +++ b/deal.II/include/deal.II/base/function.h @@ -19,6 +19,8 @@ #include #include #include +#include + #include DEAL_II_NAMESPACE_OPEN @@ -705,6 +707,112 @@ class ComponentSelectFunction : public ConstantFunction }; +/** + * This class provides a way to convert a scalar function of the kind + * @code + * double foo (const Point &); + * @endcode + * into an object of type Function@. + * Since the argument returns a scalar, the result is clearly a + * Function object for which function.n_components==1. + * The class works by storing a pointer to the given function and + * every time function.value(p,component) is called, + * calls foo(p) and returns the corresponding value. It + * also makes sure that component is in fact zero, as needs + * be for scalar functions. + * + * The class provides an easy way to turn a simple global function into + * something that has the required Function@ interface for operations + * like VectorTools::interpolate_boundary_values() etc., and thereby + * allows for simpler experimenting without having to write all the + * boiler plate code of declaring a class that is derived from Function + * and implementing the Function::value() function. + * + * The class gains additional expressvive power because the argument it + * takes does not have to be a pointer to an actual function. Rather, it is + * a function object, i.e., it can also be the result of call to + * std::bind (or boost::bind) or some other object that can be called with + * a single argument. For example, if you need a Function object that + * returns the norm of a point, you could write it like so: + * @code + * template + * class Norm : public Function { + * public: + * virtual double value (const Point &p, + * const unsigned int component) const { + * Assert (component == 0, ExcMessage ("This object is scalar!")); + * return p.norm(); + * } + * }; + * + * Norm<2> my_norm_object; + * @endcode + * and then pass the my_norm_object around, or you could write it + * like so: + * @code + * ScalarFunctionFromFunctionObject my_norm_object (&Point::norm); + * @endcode + * + * Similarly, to generate an object that computes the distance to a point + * q, we could do this: + * @code + * template + * class DistanceTo : public Function { + * public: + * DistanceTo (const Point &q) : q(q) {} + * virtual double value (const Point &p, + * const unsigned int component) const { + * Assert (component == 0, ExcMessage ("This object is scalar!")); + * return q.distance(p); + * } + * private: + * const Point q; + * }; + * + * Point<2> q (2,3); + * DistanceTo<2> my_distance_object; + * @endcode + * or we could write it like so: + * @code + * ScalarFunctionFromFunctionObject + * my_distance_object (std_cxx1x::bind (&Point::distance, + * q, + * std_cxx1x::_1)); + * @endcode + * The savings in work to write this are apparent. + * + * @author Wolfgang Bangerth, 2011 + */ +template +class ScalarFunctionFromFunctionObject : public Function +{ +public: + /** + * Given a function object that takes a Point and returns a double + * value, convert this into an object that matches the Function + * interface. + */ + ScalarFunctionFromFunctionObject (const std_cxx1x::function &)> &function_object); + + /** + * Return the value of the + * function at the given + * point. Returns the value the + * function given to the constructor + * produces for this point. + */ + virtual double value (const Point &p, + const unsigned int component = 0) const; + +private: + /** + * The function object which we call when this class's value() or + * value_list() functions are called. + **/ + const std_cxx1x::function &)> function_object; +}; + + DEAL_II_NAMESPACE_CLOSE #endif diff --git a/deal.II/source/base/function.cc b/deal.II/source/base/function.cc index 2ac7405647..f558d533e6 100644 --- a/deal.II/source/base/function.cc +++ b/deal.II/source/base/function.cc @@ -516,19 +516,47 @@ ComponentSelectFunction::memory_consumption () const } +template +ScalarFunctionFromFunctionObject:: +ScalarFunctionFromFunctionObject (const std_cxx1x::function &)> &function_object) +: +Function(1), +function_object (function_object) +{} + + + +template +double +ScalarFunctionFromFunctionObject::value (const Point &p, + const unsigned int component) const +{ + Assert (component == 0, + ExcMessage ("This object represents only scalar functions")); + return function_object (p); +} + + + // explicit instantiations template class Function<1>; template class ZeroFunction<1>; template class ConstantFunction<1>; template class ComponentSelectFunction<1>; +template class ScalarFunctionFromFunctionObject<1>; + template class Function<2>; template class ZeroFunction<2>; template class ConstantFunction<2>; template class ComponentSelectFunction<2>; +template class ScalarFunctionFromFunctionObject<2>; + template class Function<3>; template class ZeroFunction<3>; template class ConstantFunction<3>; template class ComponentSelectFunction<3>; +template class ScalarFunctionFromFunctionObject<3>; + DEAL_II_NAMESPACE_CLOSE diff --git a/tests/base/functions_05.cc b/tests/base/functions_05.cc new file mode 100644 index 0000000000..43a8673d94 --- /dev/null +++ b/tests/base/functions_05.cc @@ -0,0 +1,83 @@ +//----------------------------------------------------------------------------- +// $Id$ +// Version: $Name$ +// +// Copyright (C) 2007, 2008, 2010, 2011 by the deal.II authors +// +// This file is subject to QPL and may not be distributed +// without copyright and license information. Please refer +// to the file deal.II/doc/license.html for the text and +// further information on this license. +// +//----------------------------------------------------------------------------- + +// Test ScalarFunctionFromFunctionObject + +#include "../tests.h" +#include + + +template +void check1 () +{ + ScalarFunctionFromFunctionObject + object (&Point::norm); + + for (unsigned int i=0; i<10; ++i) + { + Point p; + for (unsigned int d=0; d +void check2 () +{ + Point q; + for (unsigned int d=0; d + object (std_cxx1x::bind (&Point::distance, + q, + std_cxx1x::_1)); + + for (unsigned int i=0; i<10; ++i) + { + Point p; + for (unsigned int d=0; d (); + check1<2> (); + check1<3> (); + + check2<1> (); + check2<2> (); + check2<3> (); +} + + diff --git a/tests/base/functions_05/cmp/generic b/tests/base/functions_05/cmp/generic new file mode 100644 index 0000000000..0aa61ff573 --- /dev/null +++ b/tests/base/functions_05/cmp/generic @@ -0,0 +1,7 @@ + +DEAL::OK +DEAL::OK +DEAL::OK +DEAL::OK +DEAL::OK +DEAL::OK -- 2.39.5