diff --git a/dune/stuff/functions.hh b/dune/stuff/functions.hh index 2a75266c433f88c34746e0fa7a09fab1ce656ddc..528477d8e5417d71799d2fe9de3cc7faa49dbb74 100644 --- a/dune/stuff/functions.hh +++ b/dune/stuff/functions.hh @@ -16,165 +16,202 @@ #include "functions/interfaces.hh" #include "functions/checkerboard.hh" #include "functions/constant.hh" -#include "functions/ESV2007.hh" #include "functions/expression.hh" +#include "functions/flattop.hh" +#include "functions/ESV2007.hh" +#include "playground/functions/indicator.hh" #include "functions/spe10.hh" namespace Dune { namespace Stuff { -namespace internal { /** - * \brief Base class containing functions that are available for all dimension. + * \note If you want to add a new function FooBar, do the following: provide a definition that is available for all + * template arguments, like: +\code +template< class E, class D, int d, class R, int r, int rC = 1 > +class FooBar + : public LocalizableFunctionInterface< E, D, d, R, r, rC > +{ + FooBar() { static_assert(AlwaysFalse< E >::value, "Not available for these dimensions!"); } +}; +\endcode + * Every specialization that can be provided by the provider then has to define: +\code +static const bool available = true; +\endcode + * This is all you have to do when implementing the function. In addition you have to add the appropriate include + * in this file (of course) and the appropriate type below (just like the rest, should be obvious). */ template <class E, class D, int d, class R, int r, int rC = 1> -class FunctionsProviderBase +class FunctionsProvider { public: typedef LocalizableFunctionInterface<E, D, d, R, r, rC> InterfaceType; -protected: - template <class FunctionType> - static std::unique_ptr<InterfaceType> call_create(const Common::Configuration& config) +private: + template <class FunctionType, bool available = false> + struct Call { - if (config.empty()) - return FunctionType::create(); - else - return FunctionType::create(config); - } // ... call_create(...) + static std::vector<std::string> append(std::vector<std::string> in) + { + return in; + } + + static bool compare(const std::string& /*type*/) + { + return false; + } + + static Common::Configuration default_config(const std::string /*sub_name*/) + { + DUNE_THROW(Stuff::Exceptions::internal_error, "This should not happen!"); + return Common::Configuration(0); + } + + static std::unique_ptr<FunctionType> create(const Common::Configuration& /*cfg*/) + { + DUNE_THROW(Stuff::Exceptions::internal_error, "This should not happen!"); + return std::unique_ptr<FunctionType>(nullptr); + } + }; // struct Call -public: - static std::vector<std::string> available() + template <class FunctionType> + struct Call<FunctionType, true> { - return {Functions::Constant<E, D, d, R, r, rC>::static_id()}; - } // ... available(...) - - static Common::Configuration default_config(const std::string type = available()[0], const std::string sub_name = "") + static std::vector<std::string> append(std::vector<std::string> in) + { + in.push_back(FunctionType::static_id()); + return in; + } + + static bool compare(const std::string& type) + { + return type == FunctionType::static_id(); + } + + static Common::Configuration default_config(const std::string sub_name) + { + return FunctionType::default_config(sub_name); + } + + static std::unique_ptr<FunctionType> create(const Common::Configuration& cfg) + { + if (cfg.empty()) + return FunctionType::create(); + else + return FunctionType::create(cfg); + } + }; // struct Call< ..., true > + + template <class F> + static std::vector<std::string> call_append(std::vector<std::string> in) { - if (type == Functions::Constant<E, D, d, R, r, rC>::static_id()) - return Functions::Constant<E, D, d, R, r, rC>::default_config(sub_name); - else - DUNE_THROW(Exceptions::wrong_input_given, - "Requested type '" << type << "' is not a valid " << InterfaceType::static_id() << "!"); - } // ... default_config(...) + return Call<F, F::available>::append(in); + } - static std::unique_ptr<InterfaceType> create(const std::string type = available()[0], - const Common::Configuration config = Common::Configuration()) + template <class F> + static bool call_compare(const std::string& type) { - if (type == Functions::Constant<E, D, d, R, r, rC>::static_id()) - return call_create<Functions::Constant<E, D, d, R, r, rC>>(config); - else - DUNE_THROW(Exceptions::wrong_input_given, - "Requested type '" << type << "' is not a valid " << InterfaceType::static_id() << "!"); - } // ... create(...) -}; // class FunctionsProviderBase - - -} // namespace internal + return Call<F, F::available>::compare(type); + } - -template <class E, class D, int d, class R, int r, int rC = 1> -class FunctionsProvider : public internal::FunctionsProviderBase<E, D, d, R, r, rC> -{ -}; - - -template <class E, class D, int d, class R, int r> -class FunctionsProvider<E, D, d, R, r, 1> : public internal::FunctionsProviderBase<E, D, d, R, r, 1> -{ - static const unsigned int rC = 1; - typedef internal::FunctionsProviderBase<E, D, d, R, r, rC> BaseType; - -public: - using typename BaseType::InterfaceType; - - static std::vector<std::string> available() + template <class F> + static Common::Configuration call_default_config(const std::string sub_name) { - auto base = BaseType::available(); - base.push_back(Functions::Expression<E, D, d, R, r, rC>::static_id()); - base.push_back(Functions::Checkerboard<E, D, d, R, r, rC>::static_id()); - return base; - } // ... available(...) + return Call<F, F::available>::default_config(sub_name); + } - static Common::Configuration default_config(const std::string type = available()[0], const std::string sub_name = "") + template <class F> + static std::unique_ptr<F> call_create(const Common::Configuration& cfg) { - if (type == Functions::Expression<E, D, d, R, r, rC>::static_id()) - return Functions::Expression<E, D, d, R, r, rC>::default_config(sub_name); - else if (type == Functions::Checkerboard<E, D, d, R, r, rC>::static_id()) - return Functions::Checkerboard<E, D, d, R, r, rC>::default_config(sub_name); - else - return BaseType::default_config(type, sub_name); - } // ... default_config(...) + return Call<F, F::available>::create(cfg); + } - static std::unique_ptr<InterfaceType> create(const std::string type = available()[0], - const Common::Configuration config = Common::Configuration()) + static std::string available_as_str() { - if (type == Functions::Expression<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::Expression<E, D, d, R, r, rC>>(config); - else if (type == Functions::Checkerboard<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::Checkerboard<E, D, d, R, r, rC>>(config); - else - return BaseType::create(type, config); - } // ... create(...) -}; // class FunctionsProvider< ..., 1 > - - -template <class E, class D, class R> -class FunctionsProvider<E, D, 2, R, 1, 1> : public internal::FunctionsProviderBase<E, D, 2, R, 1, 1> -{ - static const unsigned int d = 2; - static const unsigned int r = 1; - static const unsigned int rC = 1; - typedef internal::FunctionsProviderBase<E, D, d, R, r, rC> BaseType; + std::string ret = ""; + const auto vals = available(); + if (vals.size() > 0) { + ret += vals[0]; + for (size_t ii = 1; ii < vals.size(); ++ii) + ret += ", " + vals[ii]; + } + return ret; + } // ... available_as_str(...) + + typedef Functions::Checkerboard<E, D, d, R, r, rC> CheckerboardType; + typedef Functions::Constant<E, D, d, R, r, rC> ConstantType; + typedef Functions::Expression<E, D, d, R, r, rC> ExpressionType; + typedef Functions::FlatTop<E, D, d, R, r, rC> FlattopType; + typedef Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC> ESV2007Testcase1ForceType; + typedef Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC> ESV2007Testcase1ExactSolutionType; + typedef Functions::Indicator<E, D, d, R, r, rC> IndicatorType; + typedef Functions::Spe10::Model1<E, D, d, R, r, rC> Spe10Model1Type; public: - using typename BaseType::InterfaceType; - static std::vector<std::string> available() { - auto base = BaseType::available(); - base.push_back(Functions::Expression<E, D, d, R, r, rC>::static_id()); - base.push_back(Functions::Checkerboard<E, D, d, R, r, rC>::static_id()); - base.push_back(Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC>::static_id()); - base.push_back(Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC>::static_id()); - base.push_back(Functions::Spe10::Model1<E, D, d, R, r, rC>::static_id()); - return base; + std::vector<std::string> ret; + ret = call_append<CheckerboardType>(ret); + ret = call_append<ConstantType>(ret); + ret = call_append<ExpressionType>(ret); + ret = call_append<FlattopType>(ret); + ret = call_append<ESV2007Testcase1ForceType>(ret); + ret = call_append<ESV2007Testcase1ExactSolutionType>(ret); + ret = call_append<IndicatorType>(ret); + ret = call_append<Spe10Model1Type>(ret); + return ret; } // ... available(...) - static Common::Configuration default_config(const std::string type = available()[0], const std::string sub_name = "") + static Common::Configuration default_config(const std::string type, const std::string sub_name = "") { - if (type == Functions::Expression<E, D, d, R, r, rC>::static_id()) - return Functions::Expression<E, D, d, R, r, rC>::default_config(sub_name); - else if (type == Functions::Checkerboard<E, D, d, R, r, rC>::static_id()) - return Functions::Checkerboard<E, D, d, R, r, rC>::default_config(sub_name); - else if (type == Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC>::static_id()) - return Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC>::default_config(sub_name); - else if (type == Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC>::static_id()) - return Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC>::default_config(sub_name); - else if (type == Functions::Spe10::Model1<E, D, d, R, r, rC>::static_id()) - return Functions::Spe10::Model1<E, D, d, R, r, rC>::default_config(sub_name); + if (call_compare<CheckerboardType>(type)) + return call_default_config<CheckerboardType>(sub_name); + else if (call_compare<ConstantType>(type)) + return call_default_config<ConstantType>(sub_name); + else if (call_compare<ExpressionType>(type)) + return call_default_config<ExpressionType>(sub_name); + else if (call_compare<FlattopType>(type)) + return call_default_config<FlattopType>(sub_name); + else if (call_compare<ESV2007Testcase1ForceType>(type)) + return call_default_config<ESV2007Testcase1ForceType>(sub_name); + else if (call_compare<ESV2007Testcase1ExactSolutionType>(type)) + return call_default_config<ESV2007Testcase1ExactSolutionType>(sub_name); + else if (call_compare<IndicatorType>(type)) + return call_default_config<IndicatorType>(sub_name); + else if (call_compare<Spe10Model1Type>(type)) + return call_default_config<Spe10Model1Type>(sub_name); else - return BaseType::default_config(type, sub_name); + DUNE_THROW(Exceptions::wrong_input_given, + "Requested type '" << type << "' is not one of:\n " << available_as_str()); } // ... default_config(...) static std::unique_ptr<InterfaceType> create(const std::string type = available()[0], - const Common::Configuration config = Common::Configuration()) + const Common::Configuration cfg = Common::Configuration()) { - if (type == Functions::Expression<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::Expression<E, D, d, R, r, rC>>(config); - else if (type == Functions::Checkerboard<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::Checkerboard<E, D, d, R, r, rC>>(config); - else if (type == Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::ESV2007::Testcase1Force<E, D, d, R, r, rC>>(config); - else if (type == Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::ESV2007::Testcase1ExactSolution<E, D, d, R, r, rC>>(config); - else if (type == Functions::Spe10::Model1<E, D, d, R, r, rC>::static_id()) - return BaseType::template call_create<Functions::Spe10::Model1<E, D, d, R, r, rC>>(config); + if (call_compare<CheckerboardType>(type)) + return call_create<CheckerboardType>(cfg); + else if (call_compare<ConstantType>(type)) + return call_create<ConstantType>(cfg); + else if (call_compare<ExpressionType>(type)) + return call_create<ExpressionType>(cfg); + else if (call_compare<FlattopType>(type)) + return call_create<FlattopType>(cfg); + else if (call_compare<ESV2007Testcase1ForceType>(type)) + return call_create<ESV2007Testcase1ForceType>(cfg); + else if (call_compare<ESV2007Testcase1ExactSolutionType>(type)) + return call_create<ESV2007Testcase1ExactSolutionType>(cfg); + else if (call_compare<IndicatorType>(type)) + return call_create<IndicatorType>(cfg); + else if (call_compare<Spe10Model1Type>(type)) + return call_create<Spe10Model1Type>(cfg); else - return BaseType::create(type, config); + DUNE_THROW(Exceptions::wrong_input_given, + "Requested type '" << type << "' is not one of:\n " << available_as_str()); } // ... create(...) -}; // class FunctionsProvider< ..., 2, 1, 1 > +}; // class FunctionsProvider } // namespace Stuff diff --git a/dune/stuff/functions/ESV2007.hh b/dune/stuff/functions/ESV2007.hh index a6ab2caf26442dacfb1124e95d5fe3c1ebe98738..d9c3ccaf266d1398be6a9f4e53909824d8bb74bc 100644 --- a/dune/stuff/functions/ESV2007.hh +++ b/dune/stuff/functions/ESV2007.hh @@ -187,10 +187,13 @@ private: namespace ESV2007 { -template <class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1> -class Testcase1Force +template <class E, class D, int d, class R, int r, int rC = 1> +class Testcase1Force : public LocalizableFunctionInterface<E, D, d, R, r, rC> { - static_assert(AlwaysFalse<EntityImp>::value, "Not available for these dimensions!"); + Testcase1Force() + { + static_assert(AlwaysFalse<E>::value, "Not available for these dimensions!"); + } }; @@ -207,6 +210,8 @@ public: using typename BaseType::RangeType; using typename BaseType::JacobianRangeType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".ESV2007.testcase1.force"; @@ -295,10 +300,13 @@ private: }; // class Testcase1Force -template <class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1> -class Testcase1ExactSolution +template <class E, class D, int d, class R, int r, int rC = 1> +class Testcase1ExactSolution : public LocalizableFunctionInterface<E, D, d, R, r, rC> { - static_assert(AlwaysFalse<EntityImp>::value, "Not available for these dimensions!"); + Testcase1ExactSolution() + { + static_assert(AlwaysFalse<E>::value, "Not available for these dimensions!"); + } }; @@ -315,6 +323,8 @@ public: using typename BaseType::RangeType; using typename BaseType::JacobianRangeType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".ESV2007.testcase1.exactsolution"; diff --git a/dune/stuff/functions/checkerboard.hh b/dune/stuff/functions/checkerboard.hh index f23a2621bdcea1ce3ea0a8f1049df12d99df1bda..b3bbe4f9ccb16e682468a612ef2fe1508a14b952 100644 --- a/dune/stuff/functions/checkerboard.hh +++ b/dune/stuff/functions/checkerboard.hh @@ -97,6 +97,8 @@ public: typedef typename BaseType::JacobianRangeType JacobianRangeType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".checkerboard"; diff --git a/dune/stuff/functions/constant.hh b/dune/stuff/functions/constant.hh index 22233dfeca9c3db3de388d9b26bdc11187e28e79..ef95c3c99af4f26a1085650e327457f88506f4d5 100644 --- a/dune/stuff/functions/constant.hh +++ b/dune/stuff/functions/constant.hh @@ -91,6 +91,8 @@ public: using typename BaseType::LocalfunctionType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".constant"; diff --git a/dune/stuff/functions/expression.hh b/dune/stuff/functions/expression.hh index 57907bd1008b644b4825f85639f13548a4dd9f55..1b608488da1a8ff990d9d41d52d6a19bfe445d3a 100644 --- a/dune/stuff/functions/expression.hh +++ b/dune/stuff/functions/expression.hh @@ -201,6 +201,8 @@ public: typedef typename BaseType::JacobianRangeType JacobianRangeType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".expression"; diff --git a/dune/stuff/functions/flattop.hh b/dune/stuff/functions/flattop.hh index aded8d7dfa3c6b229f167c4f68e4849d1f1a889c..22688d91ba32010d8bf3ed4d7efe7e1a7c1879f7 100644 --- a/dune/stuff/functions/flattop.hh +++ b/dune/stuff/functions/flattop.hh @@ -25,9 +25,12 @@ namespace Functions { * Subsection 2.1.1 */ template <class E, class D, int d, class R, int r, int rC = 1> -class FlatTop +class FlatTop : public LocalizableFunctionInterface<E, D, d, R, r, rC> { - static_assert(AlwaysFalse<E>::value, "Not available for these dimensions!"); + FlatTop() + { + static_assert(AlwaysFalse<E>::value, "Not available for these dimensions!"); + } }; @@ -45,6 +48,8 @@ public: typedef typename BaseType::RangeType RangeType; typedef typename BaseType::RangeFieldType RangeFieldType; + static const bool available = true; + static std::string static_id() { return BaseType::static_id() + ".flattop"; diff --git a/dune/stuff/functions/interfaces.hh b/dune/stuff/functions/interfaces.hh index e9560777a670d086830a00793d58b0765c988994..8e97ff10f674bbf5db7e3c65be46cff08e833216 100644 --- a/dune/stuff/functions/interfaces.hh +++ b/dune/stuff/functions/interfaces.hh @@ -323,6 +323,8 @@ public: typedef typename LocalfunctionType::RangeType RangeType; typedef typename LocalfunctionType::JacobianRangeType JacobianRangeType; + static const bool available = false; + typedef Functions::Difference<ThisType, ThisType> DifferenceType; typedef Functions::Sum<ThisType, ThisType> SumType; diff --git a/dune/stuff/functions/spe10.hh b/dune/stuff/functions/spe10.hh index e0b25609a9fda1e38ddaff02ccf1965fe07dc673..a39819bee8d2d8d2614fb91713ebfaf1f62b9c44 100644 --- a/dune/stuff/functions/spe10.hh +++ b/dune/stuff/functions/spe10.hh @@ -63,6 +63,8 @@ public: static const int dimRange = BaseType::dimRange; typedef typename BaseType::RangeType RangeType; + static const bool available = true; + static std::string static_id() { return LocalizableFunctionInterface<EntityImp, DomainFieldImp, 2, RangeFieldImp, 1, 1>::static_id() @@ -151,10 +153,13 @@ public: // default, to allow for specialization -template <class EntityImp, class DomainFieldImp, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1> -class Model1 +template <class E, class D, int d, class R, int r, int rC = 1> +class Model1 : public LocalizableFunctionInterface<E, D, d, R, r, rC> { - static_assert(AlwaysFalse<EntityImp>::value, "Not available for these dimensions!"); + Model1() + { + static_assert(AlwaysFalse<E>::value, "Not available for these dimensions!"); + } };