Bridge++  Ver. 1.1.x
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
field.h
Go to the documentation of this file.
1 
15 #ifndef FIELD_INCLUDED
16 #define FIELD_INCLUDED
17 
18 #include <valarray>
19 #include <string>
20 #include <assert.h>
21 
22 #include "commonParameters.h"
23 #include "communicator.h"
24 #include "bridge_complex.h"
25 
26 //#define USE_EXPR_TEMPL
27 
29 
39 class Field {
40  // friend dcomplex ddotc_complex(Field&, Field&);
41 
42  public:
44 
45  protected:
46  std::valarray<double> field;
47  int m_Nvol; // lattice volume
48  int m_Nin; // internal d.o.f.
49  int m_Nex; // external d.o.f.
51  // total degree of freedom is Nin * Nsite * Nex.
52  int m_Ntot; // total d.o.f.
53 
54  int myindex(const int jin, const int site, const int jex)
55  const { return jin + m_Nin * (site + m_Nvol * jex); }
56 
58 
59  public:
60 
61  Field() :
62  m_Nvol(0), m_Nin(0), m_Nex(0), m_complexness(COMPLEX),
63  m_vl(CommonParameters::Vlevel()) { }
64 
65  Field(const int Nin, const int Nvol, const int Nex,
66  const complexness cmpl = COMPLEX) :
67  m_Nvol(Nvol), m_Nin(Nin), m_Nex(Nex), m_complexness(cmpl),
68  m_vl(CommonParameters::Vlevel())
69  {
70  m_Ntot = m_Nin * m_Nvol * m_Nex;
71  field.resize(m_Ntot);
72  }
73 
74  void reset(const int Nin, const int Nvol, const int Nex,
75  const complexness cmpl = COMPLEX)
76  {
77  m_Nin = Nin;
78  m_Nvol = Nvol;
79  m_Nex = Nex;
80  m_Ntot = m_Nin * m_Nvol * m_Nex;
81  m_complexness = cmpl;
82  field.resize(m_Ntot);
83  }
84 
85  int nin() const { return m_Nin; }
86  int nex() const { return m_Nex; }
87  int nvol() const { return m_Nvol; }
88  int ntot() const { return m_Ntot; }
89  int size() const { return m_Nin * m_Nvol * m_Nex; }
91 
92  double cmp(const int jin, const int site, const int jex) const
93  {
94  return field[myindex(jin, site, jex)];
95  }
96 
97  double cmp(const int i) const { return field[i]; }
98 
99  double *ptr(const int i) { return &field[i]; }
100 
101  void set(const int jin, const int site, const int jex, double v)
102  {
103  field[myindex(jin, site, jex)] = v;
104  }
105 
106  void set(const int i, double v) { field[i] = v; }
107 
108  void add(const int jin, const int site, const int jex, double v)
109  {
110  field[myindex(jin, site, jex)] += v;
111  }
112 
113  void add(const int i, double v) { field[i] += v; }
114 
115  void setpart_ex(int ex, const Field& w, int exw)
116  {
117  assert(ex < m_Nex);
118  assert(exw < w.nex());
119  for (int site = 0; site < m_Nvol; ++site) {
120  for (int jin = 0; jin < m_Nin; ++jin) {
121  field[myindex(jin, site, ex)] = w.field[myindex(jin, site, exw)];
122  }
123  }
124  }
125 
126  void addpart_ex(int ex, const Field& w, int exw)
127  {
128  assert(ex < m_Nex);
129  assert(exw < w.nex());
130  for (int site = 0; site < m_Nvol; ++site) {
131  for (int jin = 0; jin < m_Nin; ++jin) {
132  field[myindex(jin, site, ex)] += w.field[myindex(jin, site, exw)];
133  }
134  }
135  }
136 
137  void addpart_ex(int ex, const Field& w, int exw, double prf)
138  {
139  assert(ex < m_Nex);
140  assert(exw < w.nex());
141  for (int site = 0; site < m_Nvol; ++site) {
142  for (int jin = 0; jin < m_Nin; ++jin) {
143  field[myindex(jin, site, ex)]
144  += prf * w.field[myindex(jin, site, exw)];
145  }
146  }
147  }
148 
149  double norm() const
150  {
151  double a = (field * field).sum();
152  double b = Communicator::reduce_sum(a);
153 
154  return sqrt(b);
155  }
156 
157  // double norm2() const {
158  // double a = (field*field).sum();
159  // double b = Communicator::reduce_sum(a);
160  // return b;
161  // }
162 
163  // following several function was added to test the
164  // performance of the functions replacing expression
165  // templates. [8 Apr 2012 H.Matsufuru]
166 
167  double ddotc(const Field& x) const
168  {
169  double *yp = const_cast<Field *>(this)->ptr(0);
170  double *xp = const_cast<Field *>(&x)->ptr(0);
171  //#pragma disjoint(*yp,*xp) // for BG/Q
172  // __alignx(32,yp);
173  // __alignx(32,xp);
174  double a = 0.0;
175 
176  for (int i = 0; i < m_Ntot; ++i) {
177  a += yp[i] * xp[i];
178  }
179  double b = Communicator::reduce_sum(a);
180  return b;
181  }
182 
183  double norm2() const
184  {
185  // __alignx(32,&field[0]);
186  double a = 0.0;
187 
188  for (int i = 0; i < m_Ntot; ++i) {
189  a += field[i] * field[i];
190  }
191  double b = Communicator::reduce_sum(a);
192  return b;
193  }
194 
195  void daxpy(double a, const Field& x)
196  {
197  double *yp = ptr(0);
198  double *xp = const_cast<Field *>(&x)->ptr(0);
199 
200  //#pragma disjoint(*yp,*xp) // for BG/Q
201  // __alignx(32,yp);
202  // __alignx(32,xp);
203  for (int i = 0; i < m_Ntot; ++i) {
204  yp[i] += a * xp[i];
205  }
206  }
207 
208  void daxpy(dcomplex a, const Field& x)
209  {
210  double *yp = ptr(0);
211  double *xp = const_cast<Field *>(&x)->ptr(0);
212 
213  assert(x.ntot() == m_Ntot);
214  if (m_complexness == COMPLEX) {
215  double ar = real(a);
216  double ai = imag(a);
217  for (int k = 0; k < m_Ntot / 2; ++k) {
218  yp[2 * k] += ar * xp[2 * k] - ai * xp[2 * k + 1];
219  yp[2 * k + 1] += ai * xp[2 * k] + ar * xp[2 * k + 1];
220  }
221  } else if (m_complexness == REAL) {
222  double ar = real(a);
223  for (int k = 0; k < m_Ntot; ++k) {
224  yp[k] += ar * xp[k];
225  }
226  } else {
227  abort();
228  }
229  }
230 
231  void dscal(double a)
232  {
233  double *yp = ptr(0);
234 
235  // __alignx(32,yp);
236  for (int i = 0; i < m_Ntot; ++i) {
237  yp[i] *= a;
238  }
239  }
240 
241  void dcopy(const Field& x)
242  {
243  for (int i = 0; i < m_Ntot; ++i) {
244  field[i] = x.field[i];
245  }
246  }
247 
248  void dcopy(double a, const Field& x)
249  {
250  double *yp = ptr(0);
251  double *xp = const_cast<Field *>(&x)->ptr(0);
252 
253  //#pragma disjoint(*yp,*xp)
254  // __alignx(32,yp);
255  // __alignx(32,xp);
256  for (int i = 0; i < m_Ntot; ++i) {
257  yp[i] = a * xp[i];
258  }
259  }
260 
261  void clear()
262  {
263  for (int i = 0; i < m_Ntot; ++i) {
264  field[i] = 0.0;
265  }
266  }
267 
273  void stat(double& Fave, double& Fmax, double& Fdev);
274 
276  void write_text(std::string);
277 
282  void read_text(std::string);
283 
284 #ifdef USE_EXPR_TEMPL
285  template<typename T>
286  Field& operator=(const T& rhs)
287  {
288  *this = rhs.eval();
289  return *this;
290  }
291 
292  template<typename T>
293  Field& operator+=(const T& rhs)
294  {
295  *this += rhs.eval();
296  return *this;
297  }
298 
299  template<typename T>
300  Field& operator-=(const T& rhs)
301  {
302  *this -= rhs.eval();
303  return *this;
304  }
305 #endif
306 
307  Field& operator-();
308  Field& operator=(const double&);
309  Field& operator+=(const Field&);
310  Field& operator-=(const Field&);
311  Field& operator*=(const double&);
312  Field& operator/=(const double&);
313  double operator*(const Field& rhs);
314 };
315 
317 {
318  field = -field;
319  return *this;
320 }
321 
322 
323 inline Field& Field::operator=(const double& r)
324 {
325  field = r;
326  return *this;
327 }
328 
329 
330 inline Field& Field::operator+=(const Field& rhs)
331 {
332  field += rhs.field;
333  return *this;
334 }
335 
336 
337 inline Field& Field::operator-=(const Field& rhs)
338 {
339  field -= rhs.field;
340  return *this;
341 }
342 
343 
344 inline Field& Field::operator*=(const double& rhs)
345 {
346  field *= rhs;
347  return *this;
348 }
349 
350 
351 inline Field& Field::operator/=(const double& rhs)
352 {
353  field /= rhs;
354  return *this;
355 }
356 
357 
358 inline double Field::operator*(const Field& rhs)
359 {
360  double a = (field * rhs.field).sum();
361  double b = Communicator::reduce_sum(a);
362 
363  return b;
364 }
365 
366 
367 inline dcomplex ddotc_complex(const Field& y, const Field& x)
368 {
369  double *yp = const_cast<Field *>(&y)->ptr(0);
370  double *xp = const_cast<Field *>(&x)->ptr(0);
371  int Ntot = y.ntot();
372 
373  assert(x.ntot() == Ntot);
374 
375  if (y.field_complexness() == Field::COMPLEX) {
376  double prdr = 0.0;
377  double prdi = 0.0;
378  for (int k = 0; k < Ntot / 2; ++k) {
379  prdr += yp[2 * k] * xp[2 * k]
380  + yp[2 * k + 1] * xp[2 * k + 1];
381  prdi += yp[2 * k] * xp[2 * k + 1]
382  - yp[2 * k + 1] * xp[2 * k];
383  }
384  prdr = Communicator::reduce_sum(prdr);
385  prdi = Communicator::reduce_sum(prdi);
386  return cmplx(prdr, prdi);
387  } else if (y.field_complexness() == Field::REAL) {
388  double prdr = 0.0;
389  for (int k = 0; k < Ntot; ++k) {
390  prdr += yp[k] * xp[k];
391  }
392  prdr = Communicator::reduce_sum(prdr);
393  return cmplx(prdr, 0.0);
394  } else {
395  abort();
396  }
397 }
398 
399 
400 //----------------------------------------------------------------
401 
402 inline int exchange(int count, Field *recv_buf, Field *send_buf, int idir, int ipm, int tag)
403 {
404  return Communicator::exchange(count, recv_buf->ptr(0), send_buf->ptr(0), idir, ipm, tag);
405 }
406 
407 
408 inline int send_1to1(int count, Field *recv_buf, Field *send_buf, int p_to, int p_from, int tag)
409 {
410  return Communicator::send_1to1(count, recv_buf->ptr(0), send_buf->ptr(0), p_to, p_from, tag);
411 }
412 
413 
414 //----------------------------------------------------------------
415 
416 #ifdef USE_EXPR_TEMPL
417 
418 struct Add
419 {
420  static Field calc(const Field& lhs, const Field& rhs)
421  {
422  return Field(lhs) += rhs;
423  }
424 };
425 
426 struct Sub
427 {
428  static Field calc(const Field& lhs, const Field& rhs)
429  {
430  return Field(lhs) -= rhs;
431  }
432 };
433 
434 struct Mul
435 {
436  static Field calc(const Field& lhs, const double& rhs)
437  {
438  return Field(lhs) *= rhs;
439  }
440 
441  static Field calc(const double& lhs, const Field& rhs)
442  {
443  return Field(rhs) *= lhs;
444  }
445 };
446 
447 template<typename L, typename Op, typename R>
448 class AdSbMc {
449  private:
450  const L& lhs;
451  const R& rhs;
452  public:
453  AdSbMc(const L& Lhs, const R& Rhs) : lhs(Lhs), rhs(Rhs) {}
454  Field eval() const { return Op::calc(lhs.eval(), rhs.eval()); }
455 };
456 
457 template<typename L, typename Op>
458 class AdSbMc<L, Op, Field> {
459  private:
460  const L& lhs;
461  const Field& rhs;
462  public:
463  AdSbMc(const L& Lhs, const Field& Rhs) : lhs(Lhs), rhs(Rhs) {}
464  Field eval() const { return Op::calc(lhs.eval(), rhs); }
465 };
466 
467 template<typename Op, typename R>
468 class AdSbMc<Field, Op, R> {
469  private:
470  const Field& lhs;
471  const R& rhs;
472  public:
473  AdSbMc(const Field& Lhs, const R& Rhs) : lhs(Lhs), rhs(Rhs) {}
474  Field eval() const { return Op::calc(lhs, rhs.eval()); }
475 };
476 
477 template<typename L>
478 class AdSbMc<L, Mul, double> {
479  private:
480  const L& lhs;
481  const double& rhs;
482  public:
483  AdSbMc(const L& Lhs, const double& Rhs) : lhs(Lhs), rhs(Rhs) {}
484  Field eval() const { return Mul::calc(lhs.eval(), rhs); }
485 };
486 
487 template<>
488 class AdSbMc<Field, Mul, double> {
489  private:
490  const Field& lhs;
491  const double& rhs;
492  public:
493  AdSbMc(const Field& Lhs, const double& Rhs) : lhs(Lhs), rhs(Rhs) {}
494  Field eval() const { return Mul::calc(lhs, rhs); }
495 };
496 
497 template<typename R>
498 class AdSbMc<double, Mul, R> {
499  private:
500  const double& lhs;
501  const R& rhs;
502  public:
503  AdSbMc(const double& Lhs, const R& Rhs) : lhs(Lhs), rhs(Rhs) {}
504  Field eval() const { return Mul::calc(lhs, rhs.eval()); }
505 };
506 
507 template<>
508 class AdSbMc<double, Mul, Field> {
509  private:
510  const double& lhs;
511  const Field& rhs;
512  public:
513  AdSbMc(const double& Lhs, const Field& Rhs) : lhs(Lhs), rhs(Rhs) {}
514  Field eval() const { return Mul::calc(lhs, rhs); }
515 };
516 
517 template<typename Op>
518 class AdSbMc<Field, Op, Field> {
519  private:
520  const Field& lhs;
521  const Field& rhs;
522  public:
523  AdSbMc(const Field& Lhs, const Field& Rhs) : lhs(Lhs), rhs(Rhs) {}
524  Field eval() const { return Op::calc(lhs, rhs); }
525 };
526 
527 template<typename L, typename R>
528 AdSbMc<L, Add, R> operator+(const L& lhs, const R& rhs)
529 {
530  return AdSbMc<L, Add, R>(lhs, rhs);
531 }
532 
533 
534 template<typename L, typename R>
535 AdSbMc<L, Sub, R> operator-(const L& lhs, const R& rhs)
536 {
537  return AdSbMc<L, Sub, R>(lhs, rhs);
538 }
539 
540 
541 template<typename R>
542 AdSbMc<double, Mul, R> operator*(const double& lhs, const R& rhs)
543 {
544  return AdSbMc<double, Mul, R>(lhs, rhs);
545 }
546 
547 
548 #else // USE_EXPR_TEMPL
549 
550 inline Field operator*(const Field& v, const double s)
551 {
552  Field w(v);
553 
554  w *= s;
555  return w;
556 }
557 
558 
559 inline Field operator*(const double s, const Field& v)
560 {
561  return operator*(v, s);
562 }
563 
564 
565 inline Field operator+(const Field& lhs, const Field& rhs)
566 {
567  Field w(lhs);
568 
569  w += rhs;
570  return w;
571 }
572 
573 
574 inline Field operator-(const Field& lhs, const Field& rhs)
575 {
576  Field w(lhs);
577 
578  w -= rhs;
579  return w;
580 }
581 #endif // USE_EXPR_TEMPL
582 #endif