tensor.hh

Go to the documentation of this file.
00001 #ifndef DUNE_TENSOR_HH
00002 #define DUNE_TENSOR_HH
00003 
00004 #include <vector>
00005 #include <ostream>
00006 
00007 #include <dune/localfunctions/utility/field.hh>
00008 #include <dune/common/fvector.hh>
00009 #include <dune/common/misc.hh>
00010 
00011 namespace Dune 
00012 {
00013   /***********************************************
00014    * The classes here are work in progress.
00015    * Basically they provide tensor structures for
00016    * higher order derivatives of vector valued function.
00017    * Two storage structures are provided 
00018    * (either based on the components of the vector valued
00019    * functions or on the order of the derivative).
00020    * Conversions are supplied between the two storage
00021    * structures and simple operations, which make the
00022    * code difficult to use and requires rewritting...
00023    ***************************************************/
00024 
00025   // Structure for scalar tensor of order deriv
00026   template <class F,int dimD,unsigned int deriv>
00027   class LFETensor
00028   {
00029     typedef LFETensor<F,dimD,deriv> This;
00030     typedef LFETensor<F,dimD-1,deriv> BaseDim;
00031     typedef LFETensor<F,dimD,deriv-1> BaseDeriv;
00032 
00033   public:
00034     typedef F field_type;
00035     static const unsigned int size = BaseDim::size+BaseDeriv::size;
00036     typedef Dune::FieldVector<F,size> Block;
00037 
00038     template< class FF >
00039     This &operator= ( const FF &f )
00040     {
00041       block() = field_cast< F >( f );
00042       return *this;
00043     }
00044 
00045     This &operator= ( const Block &b )
00046     {
00047       block() = b;
00048       return *this;
00049     }
00050 
00051     This &operator*= ( const field_type &f )
00052     {
00053       block() *= f;
00054       return *this;
00055     }
00056 
00057     const field_type &operator[] ( const unsigned int i ) const
00058     {
00059       return block()[ i ];
00060     }
00061 
00062     field_type &operator[] ( const unsigned int i )
00063     {
00064       return block()[ i ];
00065     }
00066 
00067     Block &block() 
00068     {
00069       return block_;
00070     }
00071     const Block &block() const
00072     {
00073       return block_;
00074     }
00075     void axpy(const F& a, const This &y)
00076     {
00077       block().axpy(a,y.block());
00078     }
00079     template <class Fy>
00080     void assign(const LFETensor<Fy,dimD,deriv> &y)
00081     {
00082       field_cast(y.block(),block());
00083     }
00084     Block block_;
00085   };
00086 
00087   // ******************************************
00088   template <class F,unsigned int deriv>
00089   struct LFETensor<F,0,deriv> 
00090   {
00091     static const int size = 0;
00092   };
00093 
00094   template <class F>
00095   struct LFETensor<F,0,0> 
00096   {
00097     static const int size = 1;
00098   };
00099 
00100   template <class F,int dimD>
00101   class LFETensor<F,dimD,0> 
00102   {
00103     typedef LFETensor<F,dimD,0> This;
00104 
00105   public:
00106     typedef F field_type;
00107     static const int size = 1;
00108     typedef Dune::FieldVector<F,size> Block;
00109 
00110     template< class FF >
00111     This &operator= ( const FF &f )
00112     {
00113       block() = field_cast< F >( f );
00114       return *this;
00115     }
00116 
00117     This &operator= ( const Block &b )
00118     {
00119       block() = b;
00120       return *this;
00121     }
00122 
00123     This &operator*= ( const field_type &f )
00124     {
00125       block() *= f;
00126       return *this;
00127     }
00128 
00129     const F &operator[] ( const unsigned int i ) const
00130     {
00131       return block()[ i ];
00132     }
00133 
00134     F &operator[] ( const unsigned int i )
00135     {
00136       return block()[ i ];
00137     }
00138 
00139     void axpy(const F& a, const This &y)
00140     {
00141       block().axpy(a,y.block());
00142     }
00143     template <class Fy>
00144     void assign(const LFETensor<Fy,dimD,0> &y)
00145     {
00146       field_cast(y.block(),block());
00147     }
00148 
00149     Block &block() 
00150     {
00151       return block_;
00152     }
00153     const Block &block() const
00154     {
00155       return block_;
00156     }
00157     Block block_;
00158   };
00159   // ***********************************************************
00160   // Structure for all derivatives up to order deriv
00161   // for vector valued function
00162   enum DerivativeLayout {value,derivative};
00163   template <class F,int dimD,int dimR,unsigned int deriv,
00164             DerivativeLayout layout>
00165   struct Derivatives;
00166 
00167   // Implemnetation for valued based layout
00168   template <class F,int dimD,int dimR,unsigned int deriv>
00169   struct Derivatives<F,dimD,dimR,deriv,value>
00170   : public Derivatives<F,dimD,dimR,deriv-1,value>
00171   {
00172     typedef Derivatives<F,dimD,dimR,deriv,value> This;
00173     typedef Derivatives<F,dimD,dimR,deriv-1,value> Base;
00174     typedef LFETensor<F,dimD,deriv> ThisLFETensor;
00175 
00176     typedef F Field;
00177     typedef F field_type;
00178 
00179     static const DerivativeLayout layout = value;
00180     static const unsigned int dimDomain = dimD;
00181     static const unsigned int dimRange = dimR;
00182     // size needs to be an anonymous enum value for gcc 3.4 compatibility
00183     enum { size = Base::size+ThisLFETensor::size*dimR };
00184     typedef Dune::FieldVector<F,size> Block;
00185  
00186     This &operator=(const F& f)
00187     {
00188       block() = f;
00189       return *this;
00190     }
00191     This &operator=(const Dune::FieldVector<ThisLFETensor,dimR> &t) 
00192     {
00193       tensor_ = t;
00194       return *this;
00195     }
00196     template <unsigned int dorder>
00197     This &operator=(const Dune::FieldVector<LFETensor<F,dimD,dorder>,dimR> &t) 
00198     {
00199       tensor<dorder>() = t;
00200       return *this;
00201     }
00202     This &operator=(const Block &t) 
00203     {
00204       block() = t;
00205       return *this;
00206     }
00207 
00208     This &operator*= ( const field_type &f )
00209     {
00210       block() *= f;
00211       return *this;
00212     }
00213 
00214     void axpy(const F &a, const This &y)
00215     {
00216       block().axpy(a,y.block());
00217     }
00218 
00219     // assign with same layout (only diffrent Field)
00220     template <class Fy>
00221     void assign(const Derivatives<Fy,dimD,dimR,deriv,value> &y) 
00222     {
00223       field_cast(y.block(),block());
00224     }
00225     // assign with diffrent layout (same dimRange)
00226     template <class Fy>
00227     void assign(const Derivatives<Fy,dimD,dimR,deriv,derivative> &y) 
00228     {
00229       Base::assign(y);
00230       for (int rr=0;rr<dimR;++rr)
00231         tensor_[rr] = y[rr].template tensor<deriv>()[0];
00232     }
00233     // assign with rth component of function
00234     template <class Fy,int dimRy>
00235     void assign(const Derivatives<Fy,dimD,dimRy,deriv,value> &y,unsigned int r) 
00236     {
00237       assign<Fy,dimRy>(y.block(),r);
00238     }
00239     // assign with scalar functions to component r
00240     template <class Fy>
00241     void assign(unsigned int r,const Derivatives<Fy,dimD,1,deriv,value> &y) 
00242     {
00243       assign(r,y.block());
00244     }
00245     template <class Fy>
00246     void assign(unsigned int r,const Derivatives<Fy,dimD,1,deriv,derivative> &y) 
00247     {
00248       assign(r,y[0]);
00249     }
00250 
00251     Block &block() 
00252     {
00253       return reinterpret_cast<Block&>(*this);
00254     }
00255     const Block &block() const
00256     {
00257       return reinterpret_cast<const Block&>(*this);
00258     }
00259 
00260     template <unsigned int dorder>
00261     const Dune::FieldVector<LFETensor<F,dimD,dorder>,dimR> &tensor() const
00262     {
00263       const Int2Type<dorder> a = Int2Type<dorder>();
00264       return tensor(a);
00265     }
00266     template <unsigned int dorder>
00267     Dune::FieldVector<LFETensor<F,dimD,dorder>,dimR> &tensor() 
00268     {
00269       return tensor(Int2Type<dorder>());
00270     }
00271     template <unsigned int dorder>
00272     const Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR> &block() const
00273     {
00274       const Int2Type<dorder> a = Int2Type<dorder>();
00275       return reinterpret_cast<const Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR>&>(tensor(a));
00276     }
00277     template <unsigned int dorder>
00278     Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR> &block() 
00279     {
00280       const Int2Type<dorder> a = Int2Type<dorder>();
00281       return reinterpret_cast<Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR>&>(tensor(a));
00282     }
00283     ThisLFETensor &operator[](int r) {
00284       return tensor_[r];
00285     }
00286     const ThisLFETensor &operator[](int r) const {
00287       return tensor_[r];
00288     }
00289     protected:
00290     template <class Fy,int dimRy>
00291     void assign(const FieldVector<Fy,size*dimRy> &y,unsigned int r)
00292     {
00293       Base::template assign<Fy,dimRy>(reinterpret_cast<const FieldVector<Fy,Base::size*dimRy>&>(y),r);
00294       tensor_[0] = reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&>(y[Base::size*dimRy+r*ThisLFETensor::size]);
00295     }
00296     template <class Fy>
00297     void assign(unsigned int r,const FieldVector<Fy,size/dimR> &y) 
00298     {
00299       Base::assign(r,reinterpret_cast<const FieldVector<Fy,Base::size/dimR>&>(y));
00300       tensor_[r] = reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&>(y[Base::size/dimR]);
00301     }
00302     // assign with diffrent layout (same dimRange)
00303     template <class Fy,unsigned int dy>
00304     void assign(const Derivatives<Fy,dimD,dimR,dy,derivative> &y) 
00305     {
00306       Base::assign(y);
00307       for (int rr=0;rr<dimR;++rr)
00308         tensor_[rr] = y[rr].template tensor<deriv>()[0];
00309     }
00310 
00311     template <int dorder>
00312     const Dune::FieldVector<LFETensor<F,dimD,dorder>,dimR> &tensor(const Int2Type<dorder> &dorderVar) const
00313     {
00314       return Base::tensor(dorderVar);
00315     }
00316     const Dune::FieldVector<LFETensor<F,dimD,deriv>,dimR> &tensor(const Int2Type<deriv> &dorderVar) const
00317     {
00318       return tensor_;
00319     }
00320     template <int dorder>
00321     Dune::FieldVector<LFETensor<F,dimD,dorder>,dimR> &tensor(const Int2Type<dorder> &dorderVar) 
00322     {
00323       return Base::tensor(dorderVar);
00324     }
00325     Dune::FieldVector<LFETensor<F,dimD,deriv>,dimR> &tensor(const Int2Type<deriv> &dorderVar) 
00326     {
00327       return tensor_;
00328     }
00329     Dune::FieldVector<ThisLFETensor,dimR> tensor_;
00330   };
00331 
00332   template <class F,int dimD,int dimR>
00333   struct Derivatives<F,dimD,dimR,0,value>
00334   {
00335     typedef Derivatives<F,dimD,dimR,0,value> This;
00336     typedef LFETensor<F,dimD,0> ThisLFETensor;
00337 
00338     typedef F Field;
00339     typedef F field_type;
00340 
00341     static const DerivativeLayout layout = value;
00342     static const unsigned int dimDomain = dimD;
00343     static const unsigned int dimRange = dimR;
00344     // size needs to be an anonymous enum value for gcc 3.4 compatibility
00345     enum { size = ThisLFETensor::size*dimR };
00346     typedef Dune::FieldVector<F,size> Block;
00347 
00348     template <class FF>
00349     This &operator=(const FF& f)
00350     {
00351       for (int r=0;r<dimR;++r)
00352         tensor_[r] = field_cast<F>(f);
00353       return *this;
00354     }
00355     This &operator=(const Dune::FieldVector<ThisLFETensor,dimR> &t) 
00356     {
00357       tensor_ = t;
00358       return *this;
00359     }
00360 
00361     This &operator=(const Block &t) 
00362     {
00363       block() = t;
00364       return *this;
00365     }
00366 
00367     This &operator*= ( const field_type &f )
00368     {
00369       block() *= f;
00370       return *this;
00371     }
00372 
00373     void axpy(const F &a, const This &y)
00374     {
00375       block().axpy(a,y.block());
00376     }
00377     template <class Fy>
00378     void assign(const Derivatives<Fy,dimD,dimR,0,value> &y) 
00379     {
00380       field_cast(y.block(),block());
00381     }
00382     template <class Fy>
00383     void assign(const Derivatives<Fy,dimD,dimR,0,derivative> &y) 
00384     {
00385       for (int rr=0;rr<dimR;++rr)
00386         tensor_[rr] = y[rr].template tensor<0>()[0];
00387     }
00388     template <class Fy,int dimRy>
00389     void assign(const Derivatives<Fy,dimD,dimRy,0,value> &y,unsigned int r) 
00390     {
00391       assign<Fy,dimRy>(y.block(),r);
00392     }
00393     template <class Fy>
00394     void assign(unsigned int r,const Derivatives<Fy,dimD,1,0,value> &y) 
00395     {
00396       tensor_[r].assign(y[0]);
00397     }
00398     template <class Fy>
00399     void assign(unsigned int r,const Derivatives<Fy,dimD,1,0,derivative> &y) 
00400     {
00401       tensor_[r].assign(y[0][0]);
00402     }
00403 
00404     Block &block() 
00405     {
00406       return reinterpret_cast<Block&>(*this);
00407     }
00408     const Block &block() const
00409     {
00410       return reinterpret_cast<const Block&>(*this);
00411     }
00412 
00413     ThisLFETensor &operator[](int r) {
00414       return tensor_[r];
00415     }
00416     const ThisLFETensor &operator[](int r) const {
00417       return tensor_[r];
00418     }
00419     template <int dorder>
00420     const Dune::FieldVector<LFETensor<F,dimD,0>,dimR> &tensor() const
00421     {
00422       return tensor_;
00423     }
00424     Dune::FieldVector<LFETensor<F,dimD,0>,dimR> &tensor() 
00425     {
00426       return tensor_;
00427     }
00428     template <unsigned int dorder>
00429     const Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR> &block() const
00430     {
00431       const Int2Type<dorder> a = Int2Type<dorder>();
00432       return reinterpret_cast<const Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR>&>(tensor(a));
00433     }
00434     template <unsigned int dorder>
00435     Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR> &block() 
00436     {
00437       const Int2Type<dorder> a = Int2Type<dorder>();
00438       return reinterpret_cast<Dune::FieldVector<F,LFETensor<F,dimD,dorder>::size*dimR>&>(tensor(a));
00439     }
00440 
00441     protected:
00442     const Dune::FieldVector<LFETensor<F,dimD,0>,dimR> &tensor(const Int2Type<0> &dorderVar) const
00443     {
00444       return tensor_;
00445     }
00446     Dune::FieldVector<LFETensor<F,dimD,0>,dimR> &tensor(const Int2Type<0> &dorderVar)
00447     {
00448       return tensor_;
00449     }
00450     template <class Fy,unsigned int dy>
00451     void assign(const Derivatives<Fy,dimD,dimR,dy,derivative> &y) 
00452     {
00453       for (int rr=0;rr<dimR;++rr)
00454         tensor_[rr] = y[rr].template tensor<0>()[0];
00455     }
00456     template <class Fy,int dimRy>
00457     void assign(const FieldVector<Fy,size*dimRy> &y,unsigned int r) 
00458     {
00459       tensor_[0] = reinterpret_cast<const FieldVector<Fy,ThisLFETensor::size>&>(y[r*ThisLFETensor::size]);
00460     }
00461     template <class Fy>
00462     void assign(unsigned int r,const FieldVector<Fy,size/dimR> &y) 
00463     {
00464       tensor_[r] = y;
00465     }
00466     Dune::FieldVector<ThisLFETensor,dimR> tensor_;
00467   };
00468 
00469   // Implemnetation for derivative based layout
00470   template <class F,int dimD,int dimR,unsigned int deriv>
00471   struct Derivatives<F,dimD,dimR,deriv,derivative>
00472   {
00473     typedef Derivatives<F,dimD,dimR,deriv,derivative> This;
00474     typedef Derivatives<F,dimD,1,deriv,value> ScalarDeriv;
00475 
00476     typedef F Field;
00477     typedef F field_type;
00478 
00479     static const DerivativeLayout layout = value;
00480     static const unsigned int dimDomain = dimD;
00481     static const unsigned int dimRange = dimR;
00482     // size needs to be an anonymous enum value for gcc 3.4 compatibility
00483     enum { size = ScalarDeriv::size*dimR };
00484     typedef Dune::FieldVector<F,size> Block;
00485 
00486     template <class FF>
00487     This &operator=(const FF& f)
00488     {
00489       block() = field_cast<F>(f);
00490       return *this;
00491     }
00492     This &operator=(const Block &t) 
00493     {
00494       block() = t;
00495       return *this;
00496     }
00497 
00498     This &operator*= ( const field_type &f )
00499     {
00500       block() *= f;
00501       return *this;
00502     }
00503 
00504     template <class FF>
00505     void axpy(const FF &a, const This &y)
00506     {
00507       block().axpy(field_cast<F>(a),y.block());
00508     }
00509     // assign with same layout (only diffrent Field)
00510     template <class Fy>
00511     void assign(const Derivatives<Fy,dimD,dimR,deriv,derivative> &y) 
00512     {
00513       field_cast(y.block(),block());
00514     }
00515     // assign with diffrent layout (same dimRange)
00516     template <class Fy>
00517     void assign(const Derivatives<Fy,dimD,dimR,deriv,value> &y) 
00518     {
00519       for (unsigned int rr=0;rr<dimR;++rr)
00520         deriv_[rr].assign(y,rr);
00521     }
00522     // assign with scalar functions to component r
00523     template <class Fy,DerivativeLayout layouty>
00524     void assign(unsigned int r,const Derivatives<Fy,dimD,1,deriv,layouty> &y) 
00525     {
00526       deriv_[r].assign(r,y);
00527     }
00528 
00529     Block &block() 
00530     {
00531       return reinterpret_cast<Block&>(*this);
00532     }
00533     const Block &block() const
00534     {
00535       return reinterpret_cast<const Block&>(*this);
00536     }
00537 
00538     ScalarDeriv &operator[](int r) {
00539       return deriv_[r];
00540     }
00541     const ScalarDeriv &operator[](int r) const {
00542       return deriv_[r];
00543     }
00544     protected:
00545     Dune::FieldVector<ScalarDeriv,dimR> deriv_;
00546   };
00547 
00548   // ******************************************
00549   // AXPY *************************************
00550   // ******************************************
00551   template <class Vec1,class Vec2,unsigned int deriv>
00552   struct LFETensorAxpy
00553   {
00554     template <class Field>
00555     static void apply(unsigned int r,const Field &a,
00556                       const Vec1 &x, Vec2 &y) 
00557     {
00558       y.axpy(a,x);
00559     }
00560   };
00561   template <class F1,int dimD,int dimR,
00562             unsigned int d,
00563             class Vec2,
00564             unsigned int deriv>
00565   struct LFETensorAxpy<Derivatives<F1,dimD,dimR,d,value>,Vec2,deriv>
00566   {
00567     typedef Derivatives<F1,dimD,dimR,d,value> Vec1;
00568     template <class Field>
00569     static void apply(unsigned int r,const Field &a,
00570                       const Vec1 &x, Vec2 &y) 
00571     {
00572       const FieldVector<F1,Vec2::size> &xx = x.template block<deriv>();
00573       for (int i=0;i<y.size;++i)
00574         y[i] += xx[i]*a;
00575     }
00576   };
00577   template <class F1,int dimD,int dimR,
00578             unsigned int d,
00579             class Vec2,
00580             unsigned int deriv>
00581   struct LFETensorAxpy<Derivatives<F1,dimD,dimR,d,derivative>,Vec2,deriv>
00582   {
00583     typedef Derivatives<F1,dimD,dimR,d,derivative> Vec1;
00584     template <class Field>
00585     static void apply(unsigned int r,const Field &a,
00586                       const Vec1 &x, Vec2 &y) 
00587     {
00588       for (int rr=0;rr<dimR;++rr)
00589         LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,
00590                    Vec2,deriv>::apply(rr,a,x[rr],y);
00591     }
00592   };
00593   template <class F1,int dimD,
00594             unsigned int d,
00595             class Vec2,
00596             unsigned int deriv>
00597   struct LFETensorAxpy<Derivatives<F1,dimD,1,d,derivative>,Vec2,deriv>
00598   {
00599     typedef Derivatives<F1,dimD,1,d,derivative> Vec1;
00600     template <class Field>
00601     static void apply(unsigned int r,const Field &a,
00602                       const Vec1 &x, Vec2 &y) 
00603     {
00604       LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,
00605                  Vec2,deriv>::apply(r,a,x[0],y);
00606     }
00607   };
00608   template <class F1,int dimD,
00609             unsigned int d,
00610             class Vec2,
00611             unsigned int deriv>
00612   struct LFETensorAxpy<Derivatives<F1,dimD,1,d,value>,Vec2,deriv>
00613   {
00614     typedef Derivatives<F1,dimD,1,d,value> Vec1;
00615     template <class Field>
00616     static void apply(unsigned int r,const Field &a,
00617                       const Vec1 &x, Vec2 &y) 
00618     {
00619       typedef LFETensor<F1,dimD,deriv> LFETensorType;
00620       const unsigned int rr = r*LFETensorType::size;
00621       const FieldVector<F1,LFETensorType::size> &xx = x.template block<deriv>();
00622       for (int i=0;i<xx.size;++i)
00623         y[rr+i] += xx[i]*a;
00624     }
00625   };
00626 
00627   // ***********************************************
00628   // Assign ****************************************
00629   // ***********************************************
00630   template <class Vec1,class Vec2>
00631   struct DerivativeAssign
00632   {
00633     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00634     {
00635       field_cast(vec1,vec2);
00636     }
00637   };
00638   template <int dimD,int dimR,unsigned int deriv, DerivativeLayout layout,
00639            class F1,class F2>
00640   struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,layout>,
00641                           Derivatives<F2,dimD,dimR,deriv,layout> > 
00642   {
00643     typedef Derivatives<F1,dimD,dimR,deriv,layout> Vec1;
00644     typedef Derivatives<F2,dimD,dimR,deriv,layout> Vec2;
00645     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00646     {
00647       field_cast(vec1.block(),vec2.block());
00648     }
00649   };
00650   template <int dimD,int dimR,unsigned int deriv,
00651            class F1, class F2>
00652   struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,value>,
00653                           Derivatives<F2,dimD,dimR,deriv,derivative> > 
00654   {
00655     typedef Derivatives<F1,dimD,dimR,deriv,value> Vec1;
00656     typedef Derivatives<F2,dimD,dimR,deriv,derivative> Vec2;
00657     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00658     {
00659       vec2.assign(vec1);
00660     }
00661   };
00662   template <int dimD,int dimR,unsigned int deriv,
00663            class F1, class F2>
00664   struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,derivative>,
00665                           Derivatives<F2,dimD,dimR,deriv,value> > 
00666   {
00667     typedef Derivatives<F1,dimD,dimR,deriv,derivative> Vec1;
00668     typedef Derivatives<F2,dimD,dimR,deriv,value> Vec2;
00669     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00670     {
00671       vec2.assign(vec1);
00672     }
00673   };
00674   template <int dimD,int dimR,unsigned int deriv,DerivativeLayout layout,
00675            class F1, class F2>
00676   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
00677                           Derivatives<F2,dimD,dimR,deriv,value> > 
00678   {
00679     typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
00680     typedef Derivatives<F2,dimD,dimR,deriv,value> Vec2;
00681     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00682     {
00683       vec2.assign(r,vec1);
00684     }
00685   };
00686   template <int dimD,int dimR,unsigned int deriv,DerivativeLayout layout,
00687            class F1, class F2>
00688   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
00689                           Derivatives<F2,dimD,dimR,deriv,derivative> > 
00690   {
00691     typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
00692     typedef Derivatives<F2,dimD,dimR,deriv,derivative> Vec2;
00693     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00694     {
00695       vec2.assign(r,vec1);
00696     }
00697   };
00698   template <int dimD,unsigned int deriv,
00699            class F1, class F2>
00700   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,
00701                           Derivatives<F2,dimD,1,deriv,value> > 
00702   {
00703     typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
00704     typedef Derivatives<F2,dimD,1,deriv,value> Vec2;
00705     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00706     {
00707       field_cast(vec1.block(),vec2.block());
00708     }
00709   };
00710   template <int dimD,unsigned int deriv,
00711            class F1, class F2>
00712   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,
00713                           Derivatives<F2,dimD,1,deriv,derivative> > 
00714   {
00715     typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
00716     typedef Derivatives<F2,dimD,1,deriv,derivative> Vec2;
00717     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00718     {
00719       field_cast(vec1.block(),vec2.block());
00720     }
00721   };
00722   template <int dimD,unsigned int deriv,
00723            class F1, class F2>
00724   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,
00725                           Derivatives<F2,dimD,1,deriv,value> > 
00726   {
00727     typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
00728     typedef Derivatives<F2,dimD,1,deriv,value> Vec2;
00729     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00730     {
00731       field_cast(vec1.block(),vec2.block());
00732     }
00733   };
00734   template <int dimD,unsigned int deriv,
00735            class F1, class F2>
00736   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,
00737                           Derivatives<F2,dimD,1,deriv,derivative> > 
00738   {
00739     typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
00740     typedef Derivatives<F2,dimD,1,deriv,derivative> Vec2;
00741     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00742     {
00743       field_cast(vec1.block(),vec2.block());
00744     }
00745   };
00746   template <int dimD,unsigned int deriv,DerivativeLayout layout,
00747            class F1, class F2>
00748   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,layout>,
00749                           F2 > 
00750   {
00751     typedef Derivatives<F1,dimD,1,deriv,layout> Vec1;
00752     typedef F2 Vec2;
00753     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00754     {
00755       field_cast(vec1.block(),vec2);
00756     }
00757   };
00758   template <int dimD,int dimR,
00759             class F1,unsigned int deriv,
00760             class F2>
00761   struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,value>,FieldVector<F2,dimR> >
00762   {
00763     typedef Derivatives<F1,dimD,dimR,deriv,value> Vec1;
00764     typedef FieldVector<F2,dimR> Vec2;
00765     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00766     {
00767       field_cast(vec1.template block<0>(),vec2);
00768     }
00769   };
00770   template <int dimD,int dimR,
00771             class F1,unsigned int deriv,
00772             class F2>
00773   struct DerivativeAssign<Derivatives<F1,dimD,dimR,deriv,derivative>,FieldVector<F2,dimR> >
00774   {
00775     typedef Derivatives<F1,dimD,dimR,deriv,derivative> Vec1;
00776     typedef FieldVector<F2,dimR> Vec2;
00777     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00778     {
00779       for (int rr=0;rr<dimR;++rr)
00780         field_cast(vec1[rr].template tensor<0>()[0].block(),vec2[rr]);
00781     }
00782   };
00783   template <int dimD,
00784             class F1,unsigned int deriv,
00785             class F2,int dimR>
00786   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,FieldVector<F2,dimR> >
00787   {
00788     typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
00789     typedef FieldVector<F2,dimR> Vec2;
00790     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00791     {
00792       field_cast(vec1.template tensor<0>()[0].block(),vec2[r]);
00793     }
00794   };
00795   template <int dimD,
00796             class F1,unsigned int deriv,
00797             class F2,int dimR>
00798   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,FieldVector<F2,dimR> >
00799   {
00800     typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
00801     typedef FieldVector<F2,dimR> Vec2;
00802     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00803     {
00804       field_cast(vec1[0].template tensor<0>()[0].block(),vec2[r]);
00805     }
00806   };
00807   template <int dimD,
00808             class F1,unsigned int deriv,
00809             class F2>
00810   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,value>,FieldVector<F2,1> >
00811   {
00812     typedef Derivatives<F1,dimD,1,deriv,value> Vec1;
00813     typedef FieldVector<F2,1> Vec2;
00814     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00815     {
00816       field_cast(vec1.template tensor<0>()[0].block(),vec2);
00817     }
00818   };
00819   template <int dimD,
00820             class F1,unsigned int deriv,
00821             class F2>
00822   struct DerivativeAssign<Derivatives<F1,dimD,1,deriv,derivative>,FieldVector<F2,1> >
00823   {
00824     typedef Derivatives<F1,dimD,1,deriv,derivative> Vec1;
00825     typedef FieldVector<F2,1> Vec2;
00826     static void apply(unsigned int r,const Vec1 &vec1,Vec2 &vec2) 
00827     {
00828       field_cast(vec1[0].template tensor<0>()[0].block(),vec2);
00829     }
00830   };
00831 
00832   // ***********************************************
00833   // IO ********************************************
00834   // ***********************************************
00835   template <class F,int dimD,unsigned int deriv>
00836   std::ostream &operator<< ( std::ostream &out, const LFETensor< F,dimD,deriv > &tensor )
00837   {
00838     return out << tensor.block();
00839   }
00840 #if 0
00841   template <class F,int dimD,unsigned int deriv>
00842   std::ostream &operator<< ( std::ostream &out, const ScalarDerivatives< F,dimD,deriv > &d )
00843   {
00844     out << static_cast<const ScalarDerivatives< F,dimD,deriv-1 > &>(d);
00845     out << " , " << d.tensor() << std::endl;
00846     return out;
00847   }
00848   template <class F,int dimD>
00849   std::ostream &operator<< ( std::ostream &out, const ScalarDerivatives< F,dimD,0 > &d )
00850   {
00851     out << d.tensor() << std::endl;
00852     return out;
00853   }
00854 #endif
00855   template <class F,int dimD,int dimR,unsigned int deriv>
00856   std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,deriv,derivative > &d )
00857   {
00858     out << " ( ";
00859     out << d[0];
00860     for (int r=1;r<dimR;++r) 
00861     {
00862       out << " , " << d[r];
00863     }
00864     out << " ) " << std::endl;
00865     return out;
00866   }
00867   template <class F,int dimD,int dimR,unsigned int deriv>
00868   std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,deriv,value > &d )
00869   {
00870     out << static_cast<const Derivatives< F,dimD,dimR,deriv-1,value > &>(d);
00871     out << " ( ";
00872     out << d[0];
00873     for (int r=1;r<dimR;++r) 
00874     {
00875       out << " , " << d[r];
00876     }
00877     out << " ) " << std::endl;
00878     return out;
00879   }
00880   template <class F,int dimD,int dimR>
00881   std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,0,derivative > &d )
00882   {
00883     out << " ( ";
00884     out << d[0];
00885     for (int r=1;r<dimR;++r) 
00886     {
00887       out << " , " << d[r];
00888     }
00889     out << " ) " << std::endl;
00890     return out;
00891   }
00892   template <class F,int dimD,int dimR>
00893   std::ostream &operator<< ( std::ostream &out, const Derivatives< F,dimD,dimR,0,value > &d )
00894   {
00895     out << " ( ";
00896     out << d[0];
00897     for (int r=1;r<dimR;++r) 
00898     {
00899       out << " , " << d[r];
00900     }
00901     out << " ) " << std::endl;
00902     return out;
00903   }
00904   template <class F,int dimD,int dimR,unsigned int deriv,DerivativeLayout layout>
00905   std::ostream &operator<< ( std::ostream &out, const std::vector<Derivatives< F,dimD,dimR,deriv,layout > > &y )
00906   {
00907     out << "Number of basis functions: " << y.size() << std::endl;
00908     for (unsigned int i=0;i<y.size();++i) 
00909     {
00910       out << "Base " << i << " : " << std::endl;
00911       out << y[i];
00912       out << std::endl;
00913     }
00914     return out;
00915   }
00916 }
00917 #endif // DUNE_TENSOR_HH
00918 
Generated on Sat Apr 24 11:15:35 2010 for dune-localfunctions by  doxygen 1.6.3