ldomain.cc 21.57 KiB
// -*- tab-width: 2; indent-tabs-mode: nil -*-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <dune/pdelab/boilerplate/pdelab.hh>
#include <dune/pdelab/localoperator/convectiondiffusionfem.hh>
//***********************************************************************
//***********************************************************************
// define the reentrant corner in the L-domain with known exact solution
//***********************************************************************
//***********************************************************************
template<typename GV, typename RF>
class ReentrantCornerProblem
  typedef Dune::PDELab::ConvectionDiffusionBoundaryConditions::Type BCType;
public:
  typedef Dune::PDELab::ConvectionDiffusionParameterTraits<GV,RF> Traits;
  //! tensor diffusion coefficient
  typename Traits::PermTensorType
  A (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
    typename Traits::PermTensorType I;
    for (std::size_t i=0; i<Traits::dimDomain; i++)
      for (std::size_t j=0; j<Traits::dimDomain; j++)
        I[i][j] = (i==j) ? 1.0 : 0.0;
    return I;
  //! velocity field
  typename Traits::RangeType
  b (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
    typename Traits::RangeType v(0.0);
    return v;
  //! sink term
  typename Traits::RangeFieldType
  c (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
    return 0.0;
  //! source term
  typename Traits::RangeFieldType
  f (const typename Traits::ElementType& e, const typename Traits::DomainType& x) const
    return 0.0;
  //! boundary condition type function
  BCType
  bctype (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const
    //typename Traits::DomainType xglobal = is.geometry().global(x);
    return Dune::PDELab::ConvectionDiffusionBoundaryConditions::Dirichlet;
  //! Dirichlet boundary condition value
  typename Traits::RangeFieldType
  g (const typename Traits::ElementType& e, const typename Traits::DomainType& xlocal) const
    typename Traits::DomainType x = e.geometry().global(xlocal);
    typename Traits::DomainFieldType theta = std::atan2(x[1], x[0]);
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
if(theta < 0.0) theta += 2*M_PI; typename Traits::DomainFieldType r = x.two_norm(); return pow(r,2.0/3.0)*std::sin(theta*2.0/3.0); } //! Neumann boundary condition typename Traits::RangeFieldType j (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const { return 0.0; } //! Neumann boundary condition typename Traits::RangeFieldType o (const typename Traits::IntersectionType& is, const typename Traits::IntersectionDomainType& x) const { return 0.0; } }; //*********************************************************************** //*********************************************************************** // a grid function giving the gradient of the exact solution // needed for computing H^1 errors //*********************************************************************** //*********************************************************************** //! exact gradient of solution template<typename GV, typename RF> class ExactGradient : public Dune::PDELab::GridFunctionBase< Dune::PDELab::GridFunctionTraits<GV,RF, GV::dimension,Dune::FieldVector<RF,GV::dimension> >, ExactGradient<GV,RF> > { GV gv; public: typedef Dune::PDELab::GridFunctionTraits<GV,RF, GV::dimension,Dune::FieldVector<RF,GV::dimension> > Traits; typedef Dune::PDELab::GridFunctionBase<Traits,ExactGradient<GV,RF> > BaseT; ExactGradient (const GV& gv_) : gv(gv_) {} inline void evaluate (const typename Traits::ElementType& e, const typename Traits::DomainType& xlocal, typename Traits::RangeType& y) const { typename Traits::DomainType x = e.geometry().global(xlocal); typename Traits::DomainFieldType theta = std::atan2(x[1], x[0]); if(theta < 0.0) theta += 2*M_PI; typename Traits::DomainFieldType r = x.two_norm(); y[0] = (2.0/3.0)*pow(r,-1.0/3.0)*(cos(theta)*sin(2.0*theta/3.0) - sin(theta)*cos(2.0*theta/3.0)); y[1] = (2.0/3.0)*pow(r,-1.0/3.0)*(sin(theta)*sin(2.0*theta/3.0) + cos(theta)*cos(2.0*theta/3.0)); } inline const typename Traits::GridViewType& getGridView () const { return gv; } }; //*********************************************************************** //*********************************************************************** // some function adapters //*********************************************************************** //***********************************************************************
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
/*! \brief Adapter returning f1(x)-f2(x) for two given grid functions \tparam T1 a grid function type \tparam T2 a grid function type */ template<typename T1, typename T2> class DifferenceAdapter : public Dune::PDELab::GridFunctionBase< Dune::PDELab::GridFunctionTraits<typename T1::Traits::GridViewType, typename T1::Traits::RangeFieldType, 1,Dune::FieldVector<typename T1::Traits::RangeFieldType,1> > ,DifferenceAdapter<T1,T2> > { public: typedef Dune::PDELab::GridFunctionTraits<typename T1::Traits::GridViewType, typename T1::Traits::RangeFieldType, 1,Dune::FieldVector<typename T1::Traits::RangeFieldType,1> > Traits; //! constructor DifferenceAdapter (const T1& t1_, const T2& t2_) : t1(t1_), t2(t2_) {} //! \copydoc GridFunctionBase::evaluate() inline void evaluate (const typename Traits::ElementType& e, const typename Traits::DomainType& x, typename Traits::RangeType& y) const { typename Traits::RangeType y1; t1.evaluate(e,x,y1); typename Traits::RangeType y2; t2.evaluate(e,x,y2); y1 -= y2; y = y1; } inline const typename Traits::GridViewType& getGridView () const { return t1.getGridView(); } private: const T1& t1; const T2& t2; }; /*! \brief Adapter returning ||f1(x)-f2(x)||^2 for two given grid functions \tparam T1 a grid function type \tparam T2 a grid function type */ template<typename T1, typename T2> class DifferenceSquaredAdapter : public Dune::PDELab::GridFunctionBase< Dune::PDELab::GridFunctionTraits<typename T1::Traits::GridViewType, typename T1::Traits::RangeFieldType, 1,Dune::FieldVector<typename T1::Traits::RangeFieldType,1> > ,DifferenceSquaredAdapter<T1,T2> > { public: typedef Dune::PDELab::GridFunctionTraits<typename T1::Traits::GridViewType, typename T1::Traits::RangeFieldType, 1,Dune::FieldVector<typename T1::Traits::RangeFieldType,1> > Traits; //! constructor DifferenceSquaredAdapter (const T1& t1_, const T2& t2_) : t1(t1_), t2(t2_) {} //! \copydoc GridFunctionBase::evaluate() inline void evaluate (const typename Traits::ElementType& e, const typename Traits::DomainType& x, typename Traits::RangeType& y) const