All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Tensor.h
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 The plumed team
3  (see the PEOPLE file at the root of the distribution for a list of names)
4 
5  See http://www.plumed-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
8 
9  plumed is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  plumed is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #ifndef __PLUMED_tools_Tensor_h
23 #define __PLUMED_tools_Tensor_h
24 
26 #include "Vector.h"
27 
28 namespace PLMD{
29 
30 /**
31 \ingroup TOOLBOX
32 Class implementing fixed size matrices of doubles
33 
34 \tparam n The number rows
35 \tparam m The number columns
36 
37 This class implements a matrix of doubles with size fixed at
38 compile time. It is useful for small fixed size objects (e.g.
39 3x3 tensors) as it does not waste space to store the vector size.
40 Moreover, as the compiler knows the size, it can be completely
41 opimized inline.
42 Matrix elements are initialized to zero by default. Notice that
43 this means that constructor is a bit slow. This point might change
44 in future if we find performance issues.
45 It takes advantage of MatrixSquareBracketsAccess to provide both
46 () and [] syntax for access.
47 Several functions are declared as friends even if not necessary so as to
48 properly appear in Doxygen documentation.
49 
50 Aliases are defined to simplify common declarations (Tensor, Tensor2d, Tensor3d, Tensor4d).
51 Also notice that some operations are only available for 3x3 tensors.
52 
53 Example of usage
54 \verbatim
55 
56 #include "Tensor.h"
57 
58 using namespace PLMD;
59 
60 int main(){
61  Tensor a;
62  TensorGeneric<3,2> b;
63  TensorGeneric<3,2> c=matmul(a,b);
64  return 0;
65 }
66 
67 \endverbatim
68 */
69 template <unsigned n,unsigned m>
71  public MatrixSquareBracketsAccess<TensorGeneric<n,m>,double>
72 {
73  double d[n*m];
74 public:
75 /// initialize the tensor to zero
76  TensorGeneric();
77 /// initialize a tensor as an external product of two Vector
79 /// initialize a tensor with 4 values, in standard C order
80  TensorGeneric(double,double,double,double);
81 /// initialize a tensor with 9 values, in standard C order
82  TensorGeneric(double,double,double,double,double,double,double,double,double);
83 /// set it to zero
84  void zero();
85 /// access element
86  double & operator() (unsigned i,unsigned j);
87 /// access element
88  const double & operator() (unsigned i,unsigned j)const;
89 /// increment
91 /// decrement
93 /// multiply
94  TensorGeneric& operator *=(double);
95 /// divide
96  TensorGeneric& operator /=(double);
97 /// return +t
99 /// return -t
100  TensorGeneric operator -()const;
101 /// set j-th column
102  TensorGeneric& setCol(unsigned j,const VectorGeneric<n> & c);
103 /// set i-th row
104  TensorGeneric& setRow(unsigned i,const VectorGeneric<m> & r);
105 /// get j-th column
106  VectorGeneric<n> getCol(unsigned j)const;
107 /// get i-th row
108  VectorGeneric<m> getRow(unsigned i)const;
109 /// return t1+t2
110  template<unsigned n_,unsigned m_>
112 /// return t1+t2
113  template<unsigned n_,unsigned m_>
115 /// scale the tensor by a factor s
116  template<unsigned n_,unsigned m_>
118 /// scale the tensor by a factor s
119  template<unsigned n_,unsigned m_>
120  friend TensorGeneric<n_,m_> operator*(const TensorGeneric<n_,m_>&,double s);
121 /// scale the tensor by a factor 1/s
122  template<unsigned n_,unsigned m_>
123  friend TensorGeneric<n_,m_> operator/(const TensorGeneric<n_,m_>&,double s);
124 /// returns the determinant
125  double determinant()const;
126 /// return an identity tensor
127  static TensorGeneric<n,n> identity();
128 /// return the matrix inverse
129  TensorGeneric inverse()const;
130 /// return the transpose matrix
132 /// matrix-matrix multiplication
133  template<unsigned n_,unsigned m_,unsigned l_>
135 /// matrix-vector multiplication
136  template<unsigned n_,unsigned m_>
138 /// vector-matrix multiplication
139  template<unsigned n_,unsigned m_>
141 /// matrix-matrix-matrix multiplication
142  template<unsigned n_,unsigned m_,unsigned l_,unsigned i_>
144 /// matrix-matrix-vector multiplication
145  template<unsigned n_,unsigned m_,unsigned l_>
147 /// vector-matrix-matrix multiplication
148  template<unsigned n_,unsigned m_,unsigned l_>
150 /// returns the determinant of a tensor
151  friend double determinant(const TensorGeneric<3,3>&);
152 /// returns the inverse of a tensor (same as inverse())
154 /// returns the transpose of a tensor (same as transpose())
155  template<unsigned n_,unsigned m_>
157 /// returns the transpose of a tensor (same as TensorGeneric(const VectorGeneric&,const VectorGeneric&))
158  template<unsigned n_,unsigned m_>
162 };
163 
164 template<unsigned n,unsigned m>
166  for(unsigned i=0;i<n*m;i++)d[i]=0.0;
167 }
168 
169 template<unsigned n,unsigned m>
171  for(unsigned i=0;i<n;i++)for(unsigned j=0;j<m;j++)d[i*m+j]=v1[i]*v2[j];
172 }
173 
174 template<>
175 inline
176 TensorGeneric<2,2>::TensorGeneric(double d00,double d01,double d10,double d11){
177  d[0]=d00;
178  d[1]=d01;
179  d[2]=d10;
180  d[3]=d11;
181 }
182 
183 template<>
184 inline
185 TensorGeneric<3,3>::TensorGeneric(double d00,double d01,double d02,double d10,double d11,double d12,double d20,double d21,double d22){
186  d[0]=d00;
187  d[1]=d01;
188  d[2]=d02;
189  d[3]=d10;
190  d[4]=d11;
191  d[5]=d12;
192  d[6]=d20;
193  d[7]=d21;
194  d[8]=d22;
195 }
196 
197 template<unsigned n,unsigned m>
199  for(unsigned i=0;i<n*m;i++)d[i]=0.0;
200 }
201 
202 template<unsigned n,unsigned m>
203 double & TensorGeneric<n,m>::operator() (unsigned i,unsigned j){
204  return d[m*i+j];
205 }
206 
207 template<unsigned n,unsigned m>
208 const double & TensorGeneric<n,m>::operator() (unsigned i,unsigned j)const{
209  return d[m*i+j];
210 }
211 
212 template<unsigned n,unsigned m>
214  for(unsigned i=0;i<n*m;i++)d[i]+=b.d[i];
215  return *this;
216 }
217 
218 template<unsigned n,unsigned m>
220  for(unsigned i=0;i<n*m;i++)d[i]-=b.d[i];
221  return *this;
222 }
223 
224 template<unsigned n,unsigned m>
226  for(unsigned i=0;i<n*m;i++)d[i]*=s;
227  return *this;
228 }
229 
230 template<unsigned n,unsigned m>
232  return (*this)*=1.0/s;
233 }
234 
235 template<unsigned n,unsigned m>
237  return *this;
238 }
239 
240 template<unsigned n,unsigned m>
243  for(unsigned i=0;i<n*m;i++)r.d[i]=-d[i];
244  return r;
245 }
246 
247 template<unsigned n,unsigned m>
249  for(unsigned i=0;i<n;++i) (*this)(i,j)=c(i);
250  return *this;
251 }
252 
253 template<unsigned n,unsigned m>
255  for(unsigned j=0;j<m;++j) (*this)(i,j)=r(j);
256  return *this;
257 }
258 
259 template<unsigned n,unsigned m>
262  for(unsigned i=0;i<n;++i) v(i)=(*this)(i,j);
263  return v;
264 }
265 
266 template<unsigned n,unsigned m>
269  for(unsigned j=0;j<m;++j) v(j)=(*this)(i,j);
270  return v;
271 }
272 
273 template<unsigned n,unsigned m>
275  TensorGeneric<n,m> t(t1);
276  t+=t2;
277  return t;
278 }
279 
280 template<unsigned n,unsigned m>
282  TensorGeneric<n,m> t(t1);
283  t-=t2;
284  return t;
285 }
286 
287 template<unsigned n,unsigned m>
289  TensorGeneric<n,m> t(t1);
290  t*=s;
291  return t;
292 }
293 
294 template<unsigned n,unsigned m>
296  return t1*s;
297 }
298 
299 template<unsigned n,unsigned m>
301  return t1*(1.0/s);
302 }
303 
304 template<>
305 inline
307  return
308  d[0]*d[4]*d[8]
309  + d[1]*d[5]*d[6]
310  + d[2]*d[3]*d[7]
311  - d[0]*d[5]*d[7]
312  - d[1]*d[3]*d[8]
313  - d[2]*d[4]*d[6];
314 }
315 
316 template<unsigned n,unsigned m>
317 inline
320  for(unsigned i=0;i<n;i++) t(i,i)=1.0;
321  return t;
322 }
323 
324 template<unsigned n,unsigned m>
327  for(unsigned i=0;i<n;i++)for(unsigned j=0;j<m;j++) t(i,j)=(*this)(j,i);
328  return t;
329 }
330 
331 template<>
332 inline
334  TensorGeneric t;
335  double invdet=1.0/determinant();
336  for(unsigned i=0;i<3;i++) for(unsigned j=0;j<3;j++)
337  t(j,i)=invdet*( (*this)((i+1)%3,(j+1)%3)*(*this)((i+2)%3,(j+2)%3)
338  -(*this)((i+1)%3,(j+2)%3)*(*this)((i+2)%3,(j+1)%3));
339  return t;
340 }
341 
342 template<unsigned n,unsigned m,unsigned l>
345  for(unsigned i=0;i<n;i++) for(unsigned j=0;j<l;j++) for(unsigned k=0;k<m;k++) {
346  t(i,j)+=a(i,k)*b(k,j);
347  }
348  return t;
349 }
350 
351 template<unsigned n,unsigned m>
354  for(unsigned i=0;i<n;i++) for(unsigned j=0;j<m;j++) t(i)+=a(i,j)*b(j);
355  return t;
356 }
357 
358 template<unsigned n,unsigned m>
361  for(unsigned i=0;i<n;i++) for(unsigned j=0;j<m;j++) t(i)+=a(j)*b(j,i);
362  return t;
363 }
364 
365 template<unsigned n,unsigned m,unsigned l,unsigned i>
367  return matmul(matmul(a,b),c);
368 }
369 
370 template<unsigned n,unsigned m,unsigned l>
372  return matmul(matmul(a,b),c);
373 }
374 
375 template<unsigned n,unsigned m,unsigned l>
377  return matmul(matmul(a,b),c);
378 }
379 
380 inline
382  return t.determinant();
383 }
384 
385 inline
387  return t.inverse();
388 }
389 
390 template<unsigned n,unsigned m>
392  return t.transpose();
393 }
394 
395 template<unsigned n,unsigned m>
397  return TensorGeneric<n,m>(v1,v2);
398 }
399 
400 inline
402  (void) v1; // this is to avoid warnings. still the syntax of this function is a bit dummy...
403  return TensorGeneric<3,3>(
404  0.0, v2[2],-v2[1],
405  -v2[2], 0.0, v2[0],
406  v2[1],-v2[0], 0.0);
407 }
408 
409 inline
411  (void) v2; // this is to avoid warnings. still the syntax of this function is a bit dummy...
412  return TensorGeneric<3,3>(
413  0.0,-v1[2],v1[1],
414  v1[2],0.0,-v1[0],
415  -v1[1],v1[0],0.0);
416 }
417 
418 /// \ingroup TOOLBOX
420 /// \ingroup TOOLBOX
422 /// \ingroup TOOLBOX
424 /// \ingroup TOOLBOX
425 typedef Tensor3d Tensor;
426 
427 
428 
429 
430 
431 }
432 
433 #endif
434 
void zero()
set it to zero
Definition: Tensor.h:198
TensorGeneric< 3, 3 > dcrossDv2(const VectorGeneric< 3 > &v1, const VectorGeneric< 3 > &v2)
Definition: Tensor.h:410
double determinant(const TensorGeneric< 3, 3 > &t)
Definition: Tensor.h:381
VectorGeneric< n > getCol(unsigned j) const
get j-th column
Definition: Tensor.h:260
double d[n *m]
Definition: Tensor.h:73
TensorGeneric< 3, 3 > inverse(const TensorGeneric< 3, 3 > &t)
Definition: Tensor.h:386
TensorGeneric< m, n > transpose() const
return the transpose matrix
Definition: Tensor.h:325
Class implementing fixed size matrices of doubles.
Definition: Tensor.h:70
TensorGeneric< n, l > matmul(const TensorGeneric< n, m > &a, const TensorGeneric< m, l > &b)
Definition: Tensor.h:343
Class implementing fixed size vectors of doubles.
Definition: Vector.h:74
TensorGeneric & setCol(unsigned j, const VectorGeneric< n > &c)
set j-th column
Definition: Tensor.h:248
friend TensorGeneric< 3, 3 > dcrossDv2(const VectorGeneric< 3 > &, const VectorGeneric< 3 > &)
Definition: Tensor.h:410
Utility class to add [][] access.
TensorGeneric< n, m > operator*(const TensorGeneric< n, m > &t1, double s)
Definition: Tensor.h:288
void const char const char int * n
Definition: Matrix.h:42
void transpose(const Matrix< T > &A, Matrix< T > &AT)
Definition: Matrix.h:185
TensorGeneric< n, m > operator/(const TensorGeneric< n, m > &t1, double s)
Definition: Tensor.h:300
double & operator()(unsigned i, unsigned j)
access element
Definition: Tensor.h:203
double determinant() const
returns the determinant
static TensorGeneric< n, n > identity()
return an identity tensor
Definition: Tensor.h:318
TensorGeneric< 2, 2 > Tensor2d
Definition: Tensor.h:419
TensorGeneric< 3, 3 > dcrossDv1(const VectorGeneric< 3 > &v1, const VectorGeneric< 3 > &v2)
Definition: Tensor.h:401
friend TensorGeneric< n_, l_ > matmul(const TensorGeneric< n_, m_ > &, const TensorGeneric< m_, l_ > &)
matrix-matrix multiplication
TensorGeneric< n, m > operator-(const TensorGeneric< n, m > &t1, const TensorGeneric< n, m > &t2)
Definition: Tensor.h:281
TensorGeneric()
initialize the tensor to zero
Definition: Tensor.h:165
TensorGeneric & operator/=(double)
divide
Definition: Tensor.h:231
friend TensorGeneric< n_, m_ > extProduct(const VectorGeneric< n > &, const VectorGeneric< m > &)
returns the transpose of a tensor (same as TensorGeneric(const VectorGeneric&,const VectorGeneric&)) ...
Definition: Tensor.h:396
friend TensorGeneric< n_, m_ > operator/(const TensorGeneric< n_, m_ > &, double s)
scale the tensor by a factor 1/s
TensorGeneric & operator+=(const TensorGeneric< n, m > &b)
increment
Definition: Tensor.h:213
TensorGeneric & operator-=(const TensorGeneric< n, m > &b)
decrement
Definition: Tensor.h:219
TensorGeneric operator-() const
return -t
Definition: Tensor.h:241
TensorGeneric & operator*=(double)
multiply
Definition: Tensor.h:225
TensorGeneric< n, m > extProduct(const VectorGeneric< n > &v1, const VectorGeneric< m > &v2)
Definition: Tensor.h:396
TensorGeneric< n, m > operator+(const TensorGeneric< n, m > &t1, const TensorGeneric< n, m > &t2)
Definition: Tensor.h:274
void const char const char int double int double double int int double int * m
Definition: Matrix.h:42
TensorGeneric< 4, 4 > Tensor4d
Definition: Tensor.h:423
Tensor3d Tensor
Definition: Tensor.h:425
TensorGeneric & setRow(unsigned i, const VectorGeneric< m > &r)
set i-th row
Definition: Tensor.h:254
TensorGeneric< 3, 3 > Tensor3d
Definition: Tensor.h:421
void const char const char int double * a
Definition: Matrix.h:42
friend TensorGeneric< 3, 3 > dcrossDv1(const VectorGeneric< 3 > &, const VectorGeneric< 3 > &)
Definition: Tensor.h:401
VectorGeneric< m > getRow(unsigned i) const
get i-th row
Definition: Tensor.h:267
TensorGeneric inverse() const
return the matrix inverse
TensorGeneric operator+() const
return +t
Definition: Tensor.h:236
friend TensorGeneric< n_, m_ > operator*(double, const TensorGeneric< n_, m_ > &)
scale the tensor by a factor s