diff --git a/.gitignore b/.gitignore index 7b551f5eb63e26bcd64d480adb982ce6099cbede..3bf554cabd3688d698583b602cc7f5ae25056def 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ src/dune_fem_functionals-dune_fem_functionals.o tests/functional/.deps tests/functional/l2functional_test tests/functional/l2functional_test-l2functional_test.o +tests/functional/discretelinearfunctional_test +tests/functional/discretelinearfunctional_test-discretelinearfunctional_test.o diff --git a/CMakeLists.txt b/CMakeLists.txt index 70fcc37c2d4db6f562941b3ab93f6b0278849a16..79f4076f691bcf43b84a7edb304fb89277bacfd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -123,4 +123,7 @@ set( COMMON_LIBS "fem" "grid" "common" ${BLAS_LIB} "alugrid" "GL" ) ADD_EXECUTABLE( l2functional_test "tests/functional/l2functional_test.cc" ${header} ${common} ${grid} ${istl} ${fem} ${femhowto} ${fem-functionals} ) TARGET_LINK_LIBRARIES( l2functional_test ${COMMON_LIBS} ) +ADD_EXECUTABLE( discretelinearfunctional_test "tests/functional/discretelinearfunctional_test.cc" ${header} ${common} ${grid} ${istl} ${fem} ${femhowto} ${fem-functionals} ) +TARGET_LINK_LIBRARIES( discretelinearfunctional_test ${COMMON_LIBS} ) + #HEADERCHECK( ${header} ) diff --git a/dune/fem/functional/discretelinearfunctional.hh b/dune/fem/functional/discretelinearfunctional.hh new file mode 100644 index 0000000000000000000000000000000000000000..77ed1646a3ea0c0f18f5d2cd555153ba1709d2f1 --- /dev/null +++ b/dune/fem/functional/discretelinearfunctional.hh @@ -0,0 +1,169 @@ +#ifndef DUNE_FEM_FUNCTIONALS_DISCRETELINEARFUNCTIONAL_HH +#define DUNE_FEM_FUNCTIONALS_DISCRETELINEARFUNCTIONAL_HH + +// dune fem-functionals includes +#include <dune/fem/dofvector/dofvector.hh> + +// include this file after all other includes because some of them might undef the macros we want to use +#include <dune/common/bartonnackmanifcheck.hh> + +namespace Dune { + +namespace Functionals { + +/** + * \brief This class is the interfac for all discrete linear functionals. + * + * \todo Doc me, please! + **/ +template <class DiscreteLinearFunctionalTraitsImp> +class DiscreteLinearFunctionalInterface +{ +public: + //! Traits. + typedef DiscreteLinearFunctionalTraitsImp Traits; + +private: + //! For crtp trick. + typedef typename Traits::DiscreteLinearFunctionalType DiscreteLinearFunctionalType; + +public: + //! Type of the function, which induces the functional. + typedef typename Traits::InducingFunctionType InducingFunctionType; + + //! Type of the inducing functions range field. + typedef typename InducingFunctionType::RangeFieldType RangeFieldType; + + //! Constructor (empty). + DiscreteLinearFunctionalInterface() + { + std::cout << "DiscreteLinearFunctionalInterface::DiscreteLinearFunctionalInterface()" << std::endl; + } + + //! Destructor (empty). + ~DiscreteLinearFunctionalInterface() + { + std::cout << "DiscreteLinearFunctionalInterface::~DiscreteLinearFunctionalInterface()" << std::endl; + } + + /** + * \brief This operator represents the application of the functional to a discrete function. + * + * This operator calls the operator of the derived class. + * + * \todo Doc me, please! + **/ + template <class DiscreteFunctionType> + RangeFieldType operator()(const DiscreteFunctionType& discreteFunction) const + { + std::cout << "DiscreteLinearFunctionalInterface::operator()" << std::endl; + CHECK_AND_CALL_INTERFACE_IMPLEMENTATION(asImp().operator()(discreteFunction)); + } + +protected: + //! For crtp trick. + DiscreteLinearFunctionalType& asImp() + { + return static_cast<DiscreteLinearFunctionalType&>(*this); + } + + //! For crtp trick. + const DiscreteLinearFunctionalType& asImp() const + { + return static_cast<const DiscreteLinearFunctionalType&>(*this); + } + +}; // end DiscreteLinearFunctionalInterface + +// forward declaration +template <class DiscreteLinearFunctionalDefaultTraitsImp> +class DiscreteLinearFunctionalDefault; + +/** + * \brief This class is the traits class for the class DiscreteLinearFunctionalDefault. + * + * \todo Doc me, please! + **/ +template <class InducingFunctionImp> +class DiscreteLinearFunctionalDefaultTraits +{ +public: + //! For crtp trick. + typedef DiscreteLinearFunctionalDefault<DiscreteLinearFunctionalDefaultTraits> DiscreteLinearFunctionalType; + + //! Type of the function, which induces the functional. + typedef InducingFunctionImp InducingFunctionType; + +}; // end DiscreteLinearFunctionalDefaultTraits + + +/** + * \brief This class is the default implementation of a discrete linear functional. + * + * This class implements the operator() as a gridwalk and calls applyLocal() of the derived class on + * each entity. + * + * \todo Doc me, please! + **/ +template <class DiscreteLinearFunctionalDefaultTraitsImp> +class DiscreteLinearFunctionalDefault + : public DiscreteLinearFunctionalInterface<DiscreteLinearFunctionalDefaultTraitsImp> +{ +public: + typedef DiscreteLinearFunctionalDefaultTraitsImp Traits; + +private: + typedef DiscreteLinearFunctionalDefault<Traits> ThisType; + + typedef DiscreteLinearFunctionalInterface<Traits> BaseType; + +public: + //! Type of the function, which induces the functional. + typedef typename Traits::InducingFunctionType InducingFunctionType; + + //! Type of the inducing functions range field. + typedef typename InducingFunctionType::RangeFieldType RangeFieldType; + + /** + * \brief Constructor. + * + * Calls the constructor of the base class. + **/ + DiscreteLinearFunctionalDefault() + : BaseType() + { + std::cout << "DiscreteLinearFunctionalDefault::DiscreteLinearFunctionalDefault()" << std::endl; + } + + /** + * \brief Destructor (empty). + **/ + ~DiscreteLinearFunctionalDefault() + { + std::cout << "DiscreteLinearFunctionalDefault::~DiscreteLinearFunctionalDefault()" << std::endl; + } + + /** + * \brief This operator represents the application of the functional to a discrete function. + * + * This operator does a grid walk and calls applyLocal() of the derived class on each entity. + * + * \todo Doc me, please! + **/ + template <class DiscreteFunctionType> + RangeFieldType operator()(const DiscreteFunctionType& discreteFunction) const + { + RangeFieldType ret = 0.0; + + std::cout << "DiscreteLinearFunctionalDefault::operator()" << std::endl; + + return ret; + } + +}; // end class DiscreteLinearFunctionalDefault + +} // end namespace Functionals + +} // end namespace Dune + +#endif // end DUNE_FEM_FUNCTIONALS_DISCRETELINEARFUNCTIONAL_HH diff --git a/dune/fem/functional/l2functional.hh b/dune/fem/functional/l2functional.hh index ba1d323455f4206a2b71291ba93c6bd6e8e770d5..8611b3d241a7f64cd33a430eaba649bd57b00f9c 100644 --- a/dune/fem/functional/l2functional.hh +++ b/dune/fem/functional/l2functional.hh @@ -9,6 +9,7 @@ #include <dune/fem/quadrature/cachingquadrature.hh> // dune fem-functionals includes +#include <dune/fem/functional/discretelinearfunctional.hh> #include <dune/fem/dofvector/dofvector.hh> // dune fem-tools includes @@ -41,8 +42,7 @@ public: } /** - * \brief This function represents the application of the functional to a - * discrete function. + * \brief This operator represents the application of the functional to a discrete function. * * \todo Doc me, please! **/ diff --git a/tests/functional/Makefile.am b/tests/functional/Makefile.am index 5d26e8553b0909f986df5260c7ceb8dad3997382..4b40dd8f3727fffd20a8a5bc1d81aacfcd3a383c 100644 --- a/tests/functional/Makefile.am +++ b/tests/functional/Makefile.am @@ -1,7 +1,9 @@ -SUBDIRS = +GRIDDIM=2 +GRIDTYPE=YASPGRID +POLORDER=1 -noinst_PROGRAMS = l2functional_test +noinst_PROGRAMS = l2functional_test discretelinearfunctional_test l2functional_test_SOURCES = l2functional_test.cc @@ -10,7 +12,7 @@ l2functional_test_CPPFLAGS = $(AM_CPPFLAGS) \ $(UG_CPPFLAGS) \ $(AMIRAMESH_CPPFLAGS) \ $(ALBERTA_CPPFLAGS) \ - $(ALUGRID_CPPFLAGS) + $(ALUGRID_CPPFLAGS) -DGRIDDIM=$(GRIDDIM) -D$(GRIDTYPE) -DPOLORDER=$(POLORDER) -Wall -O0 -DDEBUG -funroll-loops -g -ggdb -fno-strict-aliasing -std=c++0x # The libraries have to be given in reverse order (most basic libraries # last). Also, due to some misunderstanding, a lot of libraries include the # -L option in LDFLAGS instead of LIBS -- so we have to include the LDFLAGS @@ -31,6 +33,34 @@ l2functional_test_LDFLAGS = $(AM_LDFLAGS) \ $(ALUGRID_LDFLAGS) \ $(DUNE_LDFLAGS) +discretelinearfunctional_test_SOURCES = discretelinearfunctional_test.cc + +discretelinearfunctional_test_CPPFLAGS = $(AM_CPPFLAGS) \ + $(DUNEMPICPPFLAGS) \ + $(UG_CPPFLAGS) \ + $(AMIRAMESH_CPPFLAGS) \ + $(ALBERTA_CPPFLAGS) \ + $(ALUGRID_CPPFLAGS) -DGRIDDIM=$(GRIDDIM) -D$(GRIDTYPE) -DPOLORDER=$(POLORDER) -Wall -O0 -DDEBUG -funroll-loops -g -ggdb -fno-strict-aliasing -std=c++0x +# The libraries have to be given in reverse order (most basic libraries +# last). Also, due to some misunderstanding, a lot of libraries include the +# -L option in LDFLAGS instead of LIBS -- so we have to include the LDFLAGS +# here as well. +discretelinearfunctional_test_LDADD = \ + $(DUNE_LDFLAGS) $(DUNE_LIBS) \ + $(ALUGRID_LDFLAGS) $(ALUGRID_LIBS) \ + $(ALBERTA_LDFLAGS) $(ALBERTA_LIBS) \ + $(AMIRAMESH_LDFLAGS) $(AMIRAMESH_LIBS) \ + $(UG_LDFLAGS) $(UG_LIBS) \ + $(DUNEMPILIBS) \ + $(LDADD) +discretelinearfunctional_test_LDFLAGS = $(AM_LDFLAGS) \ + $(DUNEMPILDFLAGS) \ + $(UG_LDFLAGS) \ + $(AMIRAMESH_LDFLAGS) \ + $(ALBERTA_LDFLAGS) \ + $(ALUGRID_LDFLAGS) \ + $(DUNE_LDFLAGS) + # don't follow the full GNU-standard # we need automake 1.5 AUTOMAKE_OPTIONS = foreign 1.5 diff --git a/tests/functional/discretelinearfunctional_test.cc b/tests/functional/discretelinearfunctional_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..70d54bcda93d12ac074476c5cacfc47794dfe452 --- /dev/null +++ b/tests/functional/discretelinearfunctional_test.cc @@ -0,0 +1,124 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// system includes +#include <iostream> + +// dune common includes +#include <dune/common/exceptions.hh> + +// dune grid includes +#include <dune/grid/yaspgrid.hh> +#include <dune/grid/io/file/dgfparser/dgfparser.hh> + +// dune fem includes +//#include <dune/fem/io/parameter.hh> +#include <dune/fem/misc/mpimanager.hh> +#include <dune/fem/gridpart/adaptiveleafgridpart.hh> +#include <dune/fem/space/common/functionspace.hh> +#include <dune/fem/function/common/function.hh> +#include <dune/fem/space/lagrangespace.hh> +#include <dune/fem/function/adaptivefunction.hh> + +// dune fem-functionals includes +#include <dune/fem/functional/discretelinearfunctional.hh> + +// dune fem-tools includes +#include "../../tools/function/functiontools.hh" + +/** + * \brief Analytical function which induces the functional. + **/ +template <class FunctionSpaceImp> +class AnalyticalFunction : public Dune::Function<FunctionSpaceImp, AnalyticalFunction<FunctionSpaceImp>> +{ +public: + typedef FunctionSpaceImp FunctionSpaceType; + typedef AnalyticalFunction<FunctionSpaceType> ThisType; + typedef Dune::Function<FunctionSpaceType, ThisType> BaseType; + typedef typename FunctionSpaceType::DomainType DomainType; + typedef typename FunctionSpaceType::RangeType RangeType; + typedef typename FunctionSpaceType::RangeFieldType RangeFieldType; + + AnalyticalFunction() + { + } + + ~AnalyticalFunction() + { + } + + inline void evaluate(const DomainType& arg, RangeType& ret) const + { + ret = 0.5; + } +}; + +// main +int main(int argc, char** argv) +{ + try { + + // print welcome + std::cout << "Discrete linear functional test:" << std::endl; + + // mpi + Dune::MPIManager::initialize(argc, argv); + + // dimension and grid + const int dim = 2; + + typedef Dune::YaspGrid<dim> GridType; + + Dune::GridPtr<GridType> gridPtr("unitcube_2d.dgf"); + + typedef Dune::AdaptiveLeafGridPart<GridType> GridPartType; + + GridPartType gridPart(*gridPtr); + + // analytical function space and function + typedef Dune::FunctionSpace<double, double, dim, 1> AnalyticalFunctionSpaceType; + typedef AnalyticalFunction<AnalyticalFunctionSpaceType> AnalyticalFunctionType; + + const AnalyticalFunctionType analyticalFunction; + + // discrete function space and function + const int polOrder = 1; + + typedef Dune::LagrangeDiscreteFunctionSpace<AnalyticalFunctionSpaceType, GridPartType, polOrder> + DiscreteFunctionSpaceType; + + const DiscreteFunctionSpaceType discreteFunctionSpace(gridPart); + + typedef Dune::AdaptiveDiscreteFunction<DiscreteFunctionSpaceType> DiscreteFunctionType; + + DiscreteFunctionType discreteFunction("discrete_function", discreteFunctionSpace); + Dune::FemTools::setDiscreteFunctionToScalarValue(discreteFunction, 2.0); + + // test functional + typedef Dune::Functionals::DiscreteLinearFunctionalDefaultTraits<AnalyticalFunctionType> + DiscreteLinearFunctionalDefaultTraitsType; + typedef Dune::Functionals::DiscreteLinearFunctionalDefault<DiscreteLinearFunctionalDefaultTraitsType> + DiscreteLinearFunctionalDefaultType; + typedef Dune::Functionals::DiscreteLinearFunctionalInterface<DiscreteLinearFunctionalDefaultTraitsType> + DiscreteLinearFunctionalInterfaceType; + + DiscreteLinearFunctionalDefaultType discreteLinearFunctionalDefault; + + // DiscreteLinearFunctionalInterfaceType discreteLinearFunctionalInterface; + discreteLinearFunctionalDefault(discreteFunction); + + // if ( volume == 1.0 ) + // std::cout << "passed!" << std::endl; + // else + // std::cout << "failed (result should equal 1, is " << volume << ")!" << std::endl; + + // we don't make no errors^^ + return 0; + } catch (Dune::Exception& e) { + std::cerr << "Dune reported error: " << e << std::endl; + } catch (...) { + std::cerr << "Unknown exception thrown!" << std::endl; + } +} diff --git a/tests/functional/l2functional_test.cc b/tests/functional/l2functional_test.cc index 44763eb7680393d04b6f8b27d0e653a3c4780f2c..b8dd624db4feb2989b9cfd38c9c3db8f45efc735 100644 --- a/tests/functional/l2functional_test.cc +++ b/tests/functional/l2functional_test.cc @@ -66,9 +66,6 @@ int main(int argc, char** argv) // mpi Dune::MPIManager::initialize(argc, argv); - // // command line arguments - // Dune::Parameter::append( argc, argv ); - // dimension and grid const int dim = 2; @@ -103,6 +100,8 @@ int main(int argc, char** argv) typedef Dune::Functionals::L2Functional<AnalyticalFunctionType> L2FunctionalType; const L2FunctionalType l2Functional(analyticalFunction); + // functions are chosen to equal 1 when multiplied, thus the application of the functional should yield the volume + // of the area, which in turn should be 1 in case of the two-dimensional unitcube const double volume = l2Functional(discreteFunction); if (volume == 1.0)