00001 #ifndef DUNE_LOBATTOBASIS_HH
00002 #define DUNE_LOBATTOBASIS_HH
00003
00004 #include <fstream>
00005
00006 #include <dune/common/forloop.hh>
00007
00008 #include <dune/grid/common/topologyfactory.hh>
00009 #include <dune/grid/common/quadraturerules/lobattoquadrature.hh>
00010 #include <dune/grid/genericgeometry/referenceelements.hh>
00011 #include <dune/grid/genericgeometry/referencemappings.hh>
00012
00013 #include <dune/localfunctions/utility/lfematrix.hh>
00014 #include <dune/localfunctions/utility/field.hh>
00015 #include <dune/localfunctions/lagrange/lagrangecoefficients.hh>
00016 #include <dune/localfunctions/lagrange/emptypoints.hh>
00017
00018 namespace Dune
00019 {
00020
00021 template< class Field >
00022 struct LobattoPoints
00023 {
00024 LobattoPoints ( unsigned int order )
00025 : points_( 0 )
00026 {
00027 if( order < 2 )
00028 return;
00029 points_.resize(order-1);
00030 #if HAVE_ALGLIB
00031 typedef amp::ampf< Precision< Field >::value > MPField;
00032 #else
00033 typedef Field MPField;
00034 #endif
00035 GenericGeometry::LobattoPoints<MPField> lobatto(order+1);
00036
00037 for (unsigned int i=1;i<order;++i) {
00038 points_[i-1] = field_cast<Field>(lobatto[i].position());
00039 }
00040 }
00041
00042 const unsigned int size()
00043 {
00044 return points_.size();
00045 }
00046 const unsigned int order()
00047 {
00048 return points_.size()+1;
00049 }
00050 const Field &point(int i)
00051 {
00052 return points_[i];
00053 }
00054 std::vector<Field> points_;
00055 };
00056
00057 template <class Field,class Topology>
00058 struct LobattoInnerPoints;
00059
00060 template <class Field>
00061 struct LobattoInnerPoints<Field,GenericGeometry::Point>
00062 {
00063 static const unsigned int dimension = 0;
00064 static unsigned int size(const unsigned int order)
00065 {
00066 return 1;
00067 }
00068 template <unsigned int dim>
00069 static unsigned int setupSimplex(
00070 const unsigned int iup,
00071 const unsigned int dimStart,
00072 unsigned int startPos,
00073 const std::vector<Field> &points1D,
00074 LagrangePoint< Field, dim > *points )
00075 {
00076 const unsigned int order = points1D.size()+1;
00077 unsigned int i = order+1-iup;
00078 if (i-2>=points1D.size())
00079 {
00080 return startPos;
00081 }
00082 for ( unsigned int d=0;d<dimStart;++d )
00083 {
00084 points[startPos].point_[d] = -points1D[i-2];
00085 }
00086
00087 return startPos+1;
00088 }
00089 template <unsigned int dim>
00090 static void setup(const std::vector<Field> &points1D,
00091 LagrangePoint< Field, dim > *points )
00092 {
00093 points->point_[0] = Zero<Field>();
00094 }
00095 };
00096 template <class Field,class Base>
00097 struct LobattoInnerPoints<Field,GenericGeometry::Pyramid<Base> >
00098 {
00099 typedef LobattoInnerPoints<Field,Base> LobattoBase;
00100 static const unsigned int dimension = Base::dimension+1;
00101 static unsigned int size(const unsigned int order)
00102 {
00103 if (order<=dimension) return 0;
00104 unsigned int size=0;
00105 for (unsigned int o=0;o<order-dimension;++o)
00106 size += LobattoBase::size(o+dimension);
00107 return size;
00108 }
00109 template <unsigned int dim>
00110 static unsigned int setupSimplex(
00111 const unsigned int iup,
00112 const unsigned int dimStart,
00113 unsigned int startPos,
00114 const std::vector<Field> &points1D,
00115 LagrangePoint< Field, dim > *points )
00116 {
00117 const unsigned int order = points1D.size()+1;
00118 unsigned int endPos = startPos;
00119 for (unsigned int i=2;i<=order-iup;++i)
00120 {
00121 endPos = LobattoBase::template setupSimplex<dim>(iup+i-1,dimStart,startPos,points1D,points);
00122 for (unsigned int j=startPos;j<endPos;++j)
00123 {
00124 for (unsigned int d=0;d<dimStart;++d)
00125 {
00126 if ( d==dimStart-dimension )
00127 points[j].point_[d] += dimStart*points1D[i-2];
00128 else
00129 points[j].point_[d] -= points1D[i-2];
00130 }
00131 }
00132 startPos = endPos;
00133 }
00134 return endPos;
00135 }
00136 template <unsigned int dim>
00137 static void setup(const std::vector<Field> &points1D,
00138 LagrangePoint< Field, dim > *points )
00139 {
00140 const unsigned int order = points1D.size()+1;
00141 unsigned int startPos=0,endPos=0;
00142 for (unsigned int i=2;i<=order;++i)
00143 {
00144 endPos = LobattoBase::template setupSimplex<dim>(i-1,dimension,startPos,points1D,points);
00145
00146 for (unsigned int j=startPos;j<endPos;++j)
00147 {
00148 for (unsigned int d=0;d<dimension;++d)
00149 {
00150 if ( d==0 )
00151 points[j].point_[d] += 1.+int(dimension)*points1D[i-2];
00152 else
00153 points[j].point_[d] += 1.-points1D[i-2];
00154 points[j].point_[d] /= (dimension+1);
00155 }
00156 }
00157 startPos = endPos;
00158 }
00159 }
00160 };
00161 template <class Field,class Base>
00162 struct LobattoInnerPoints<Field,GenericGeometry::Prism<Base> >
00163 {
00164 typedef LobattoInnerPoints<Field,Base> LobattoBase;
00165 static const unsigned int dimension = Base::dimension+1;
00166 static unsigned int size(const unsigned int order)
00167 {
00168 return LobattoBase::size(order)*(order-1);
00169 }
00170 template <unsigned int dim>
00171 static unsigned int setupSimplex(
00172 const unsigned int iup,
00173 const unsigned int dimStart,
00174 unsigned int startPos,
00175 const std::vector<Field> &points1D,
00176 LagrangePoint< Field, dim > *points )
00177 {
00178 const unsigned int order = points1D.size()+1;
00179 unsigned int endPos = startPos;
00180 for (unsigned int i=2;i<=order-iup;++i)
00181 {
00182 endPos = LobattoBase::template setupSimplex<dim>(iup+i-1,dimStart,startPos,points1D,points);
00183 for (unsigned int j=startPos;j<endPos;++j)
00184 {
00185 for (unsigned int d=0;d<dimStart;++d)
00186 {
00187 if ( d==dimStart-dimension )
00188 points[j].point_[d] += dimStart*points1D[i-2];
00189 else
00190 points[j].point_[d] -= points1D[i-2];
00191 }
00192 }
00193 startPos = endPos;
00194 }
00195 return endPos;
00196 }
00197 template <unsigned int dim>
00198 static void setup(const std::vector<Field> &points1D,
00199 LagrangePoint< Field, dim > *points )
00200 {
00201 const unsigned int order = points1D.size()+1;
00202 assert(dim>=dimension);
00203 assert(points1D.size()==order-1);
00204 LobattoBase::template setup<dim>(points1D,points);
00205 const unsigned int baseSize = LobattoBase::size(order);
00206 for (unsigned int q=0;q<points1D.size();q++)
00207 {
00208 for (unsigned int i=0;i<baseSize;++i)
00209 {
00210 const unsigned int pos = q*baseSize+i;
00211 for (unsigned int d=0;d<dimension-1;++d)
00212 points[pos].point_[d] = points[i].point_[d];
00213 points[pos].point_[dimension-1]=points1D[q];
00214 }
00215 }
00216 }
00217 };
00218
00219 template< class F, unsigned int dim >
00220 struct LobattoPointSet : public EmptyPointSet<F,dim>
00221 {
00222
00223 static const unsigned int dimension = dim;
00224 typedef F Field;
00225 typedef EmptyPointSet<F,dim> Base;
00226 typedef typename Base::LagrangePoint Point;
00227 LobattoPointSet(unsigned int order)
00228 : Base(order)
00229 {
00230 }
00231
00232 template< class Topology >
00233 bool build ( )
00234 {
00235 unsigned int order = Base::order();
00236 LobattoPoints<Field> points1D(order);
00237 ForLoop<Setup<Topology>::template InitCodim,0,dimension>::
00238 apply(order,points1D.points_,points_);
00239 return true;
00240 }
00241 template< class Topology >
00242 static bool supports ( unsigned int order )
00243 {
00244 if ( GenericGeometry::IsSimplex< Topology >::value ||
00245 GenericGeometry::IsGeneralizedPrism< Topology >::value )
00246 return true;
00247 else
00248 return false;
00249 }
00250 protected:
00251 using Base::points_;
00252 private:
00253 template <class Topology>
00254 struct Setup
00255 {
00256 template <int pdim>
00257 struct InitCodim
00258 {
00259 static const unsigned int codim = dimension-pdim;
00260 static void apply(const unsigned int order,
00261 const std::vector<Field> &points1D,
00262 std::vector<Point> &points)
00263 {
00264 const unsigned int size = GenericGeometry::Size<Topology,codim>::value;
00265 ForLoop<InitSub,0,size-1>::apply(order,points1D,points);
00266 }
00267 template <int i>
00268 struct InitSub
00269 {
00270 typedef typename GenericGeometry::SubTopology<Topology,codim,i>::type SubTopology;
00271 static void apply(const unsigned int order,
00272 const std::vector<Field> &points1D,
00273 std::vector<Point> &points)
00274 {
00275 Setup<Topology>::template Init<SubTopology>::template apply<i>(order,points1D,points);
00276 }
00277 };
00278 };
00279 template <class SubTopology>
00280 struct Init
00281 {
00282 static const unsigned int codimension = dimension - SubTopology::dimension;
00283 typedef GenericGeometry::ReferenceMappings< Field, dimension > RefMappings;
00284 typedef typename RefMappings::Container RefMappingsContainer;
00285 typedef typename RefMappingsContainer::template Codim< codimension >::Mapping Mapping;
00286 typedef LobattoInnerPoints<Field,SubTopology> InnerPoints;
00287 template <unsigned int subEntity>
00288 static void apply(const unsigned int order,
00289 const std::vector<Field> &points1D,
00290 std::vector<Point> &points)
00291 {
00292 unsigned int oldSize = points.size();
00293 unsigned int size = InnerPoints::size(order);
00294 if (size==0)
00295 return;
00296 points.resize(oldSize+size);
00297 std::vector< LagrangePoint<Field,dimension-codimension> > subPoints(size);
00298
00299 InnerPoints::template setup<dimension-codimension>( points1D,&(subPoints[0]) );
00300
00301 const RefMappingsContainer &refMappings = RefMappings::container( Topology::id );
00302 const Mapping &mapping = refMappings.template mapping< codimension >( subEntity );
00303
00304 LagrangePoint<Field,dimension> *p = &(points[oldSize]);
00305 for ( unsigned int nr = 0; nr<size; ++nr, ++p)
00306 {
00307 p->point_ = mapping.global( subPoints[nr].point_ );
00308 p->localKey_ = LocalKey( subEntity, codimension, nr );
00309 #ifndef NDEBUG
00310 bool test = GenericGeometry::ReferenceElement<Topology,Field>::checkInside(p->point_);
00311 if (!test)
00312 std::cout << "not inside" << std::endl;
00313 #endif
00314 }
00315 }
00316 };
00317 };
00318
00319 };
00320 }
00321 #endif // DUNE_LOBATTOBASIS_HH
00322