00001
00002
00003 #ifndef DUNE_PQK_FACTORY_HH
00004 #define DUNE_PQK_FACTORY_HH
00005
00006 #include <map>
00007
00008 #include <dune/common/geometrytype.hh>
00009
00010 #include <dune/localfunctions/common/virtualinterface.hh>
00011 #include <dune/localfunctions/common/virtualwrappers.hh>
00012
00013 #include <dune/localfunctions/lagrange/p0.hh>
00014 #include <dune/localfunctions/lagrange/pk.hh>
00015 #include <dune/localfunctions/lagrange/q1.hh>
00016 #include <dune/localfunctions/lagrange/q22d.hh>
00017 #include <dune/localfunctions/lagrange/prismp1.hh>
00018 #include <dune/localfunctions/lagrange/prismp2.hh>
00019
00020 namespace Dune
00021 {
00022
00027 template<class D, class R, int d, int k>
00028 struct DimSpecificPQkLocalFiniteElementFactory
00029 {
00030 typedef typename FixedOrderLocalBasisTraits<typename P0LocalFiniteElement<D,R,d>::Traits::LocalBasisType::Traits,0>::Traits T;
00031
00033 static LocalFiniteElementVirtualInterface<T>* create(const GeometryType& gt)
00034 {
00035 return 0;
00036 }
00037 };
00038
00043 template<class D, class R, int k>
00044 struct DimSpecificPQkLocalFiniteElementFactory<D,R,2,k>
00045 {
00046 typedef typename FixedOrderLocalBasisTraits<typename P0LocalFiniteElement<D,R,2>::Traits::LocalBasisType::Traits,0>::Traits T;
00047 typedef Q22DLocalFiniteElement<D,R> Q22D;
00048
00050 static LocalFiniteElementVirtualInterface<T>* create(const GeometryType& gt)
00051 {
00052 if ((gt.basicType()==GeometryType::cube) and (k==2))
00053 return new LocalFiniteElementVirtualImp<Q22D>(Q22D());
00054 return 0;
00055 }
00056 };
00057
00062 template<class D, class R, int k>
00063 struct DimSpecificPQkLocalFiniteElementFactory<D,R,3,k>
00064 {
00065 typedef typename FixedOrderLocalBasisTraits<typename P0LocalFiniteElement<D,R,3>::Traits::LocalBasisType::Traits,0>::Traits T;
00066 typedef PrismP1LocalFiniteElement<D,R> PrismP1;
00067 typedef PrismP2LocalFiniteElement<D,R> PrismP2;
00068
00070 static LocalFiniteElementVirtualInterface<T>* create(const GeometryType& gt)
00071 {
00072 if ((gt.basicType()==GeometryType::prism) and (k==1))
00073 return new LocalFiniteElementVirtualImp<PrismP1>(PrismP1());
00074 if ((gt.basicType()==GeometryType::prism) and (k==2))
00075 return new LocalFiniteElementVirtualImp<PrismP2>(PrismP2());
00076 return 0;
00077 }
00078 };
00079
00080
00084 template<class D, class R, int dim, int k>
00085 struct PQkLocalFiniteElementFactory
00086 {
00087 typedef typename FixedOrderLocalBasisTraits<typename P0LocalFiniteElement<D,R,dim>::Traits::LocalBasisType::Traits,0>::Traits T;
00088 typedef LocalFiniteElementVirtualInterface<T> FiniteElementType;
00089 typedef P0LocalFiniteElement<D,R,dim> P0;
00090 typedef PkLocalFiniteElement<D,R,dim,k> Pk;
00091 typedef Q1LocalFiniteElement<D,R,dim> Q1;
00092
00093
00095 static FiniteElementType* create(const GeometryType& gt)
00096 {
00097 if (k==0)
00098 return new LocalFiniteElementVirtualImp<P0>(P0(gt.basicType()));
00099
00100 if (gt.basicType()==GeometryType::simplex)
00101 return new LocalFiniteElementVirtualImp<Pk>(Pk());
00102
00103 if ((gt.basicType()==GeometryType::cube) and (k==1))
00104 return new LocalFiniteElementVirtualImp<Q1>(Q1());
00105
00106 return DimSpecificPQkLocalFiniteElementFactory<D,R,dim,k>::create(gt);
00107 }
00108 };
00109
00110
00111
00122 template<class D, class R, int dim, int k>
00123 class PQkLocalFiniteElementCache
00124 {
00125 protected:
00126 typedef typename FixedOrderLocalBasisTraits<typename P0LocalFiniteElement<D,R,dim>::Traits::LocalBasisType::Traits,0>::Traits T;
00127 typedef LocalFiniteElementVirtualInterface<T> FE;
00128 typedef typename std::map<GeometryType,FE*> FEMap;
00129
00130 public:
00132 typedef FE FiniteElementType;
00133
00135 PQkLocalFiniteElementCache() {}
00136
00138 PQkLocalFiniteElementCache(const PQkLocalFiniteElementCache& other)
00139 {
00140 typename FEMap::iterator it = other.cache_.begin();
00141 typename FEMap::iterator end = other.cache_.end();
00142 for(; it!=end; ++it)
00143 cache_[it->first] = (it->second)->clone();
00144 }
00145
00146 ~PQkLocalFiniteElementCache()
00147 {
00148 typename FEMap::iterator it = cache_.begin();
00149 typename FEMap::iterator end = cache_.end();
00150 for(; it!=end; ++it)
00151 delete it->second;
00152 }
00153
00155 const FiniteElementType& get(const GeometryType& gt) const
00156 {
00157 typename FEMap::const_iterator it = cache_.find(gt);
00158 if (it==cache_.end())
00159 {
00160 FiniteElementType* fe = PQkLocalFiniteElementFactory<D,R,dim,k>::create(gt);
00161 if (fe==0)
00162 DUNE_THROW(Dune::NotImplemented,"No Pk/Qk like local finite element available for geometry type " << gt << " and order " << k);
00163
00164 cache_[gt] = fe;
00165 return *fe;
00166 }
00167 return *(it->second);
00168 }
00169
00170 protected:
00171 mutable FEMap cache_;
00172
00173 };
00174
00175 }
00176
00177 #endif