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
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
00161
00162 enum DerivativeLayout {value,derivative};
00163 template <class F,int dimD,int dimR,unsigned int deriv,
00164 DerivativeLayout layout>
00165 struct Derivatives;
00166
00167
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
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
00220 template <class Fy>
00221 void assign(const Derivatives<Fy,dimD,dimR,deriv,value> &y)
00222 {
00223 field_cast(y.block(),block());
00224 }
00225
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
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
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
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
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
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
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
00510 template <class Fy>
00511 void assign(const Derivatives<Fy,dimD,dimR,deriv,derivative> &y)
00512 {
00513 field_cast(y.block(),block());
00514 }
00515
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
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
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
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
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