Simpatico  v1.10
Vector.h
1 #ifndef UTIL_VECTOR_H
2 #define UTIL_VECTOR_H
3 
4 /*
5 * Util Package - C++ Utilities for Scientific Computation
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/global.h>
12 #include <util/space/Dimension.h>
13 
14 #ifdef UTIL_MPI
15 #include <util/mpi/MpiTraits.h>
16 #endif
17 
18 #include <iostream>
19 #include <cmath>
20 
21 namespace Util
22 {
23 
75  class Vector
76  {
77 
78  public:
79 
81 
82 
86  Vector();
87 
93  Vector(const Vector& v);
94 
100  explicit Vector(double scalar);
101 
107  explicit Vector(const double* v);
108 
116  Vector(double x, double y, double z=0.0);
117 
119 
123  Vector& zero();
124 
131  template <class Archive>
132  void serialize(Archive& ar, const unsigned int version);
133 
135 
136 
142  Vector& operator = (const Vector& v);
143 
149  Vector& operator = (const double* v);
150 
152 
154 
162  void operator += (const Vector& dv);
163 
171  void operator -= (const Vector& dv);
172 
180  void operator *= (double s);
181 
189  void operator /= (double s);
190 
192 
194 
201  const double& operator [] (int i) const;
202 
209  double& operator [] (int i);
210 
212 
214 
220  double square() const;
221 
227  double abs() const;
228 
235  double dot(const Vector& v) const;
236 
243  double projection(const Vector& p) const;
244 
246 
248 
258  Vector& add(const Vector& v1, const Vector& v2);
259 
269  Vector& subtract(const Vector& v1, const Vector& v2);
270 
280  Vector& multiply(const Vector& v, double s);
281 
291  Vector& divide(const Vector& v, double s);
292 
302  Vector& cross(const Vector& v1, const Vector& v2);
303 
312  Vector& versor(const Vector& v);
313 
327  Vector& parallel(const Vector& v, const Vector& p);
328 
339  Vector& transverse(const Vector& v, const Vector& p);
340 
347  int minId(const Vector& v);
348 
355  int maxId(const Vector& v);
356 
358 
360 
364  static void initStatic();
365 
369  static const Vector Zero;
370 
371  #ifdef UTIL_MPI
372 
375  static void commitMpiType();
376  #endif
377 
379 
380  private:
381 
383  static const int Width = 24;
384 
386  static const int Precision = 16;
387 
389  double elem_[Dimension];
390 
391  //friends:
392 
393  friend bool operator == (const Vector& v1, const Vector& v2);
394 
395  friend bool operator == (const Vector& v1, const double* v2);
396 
397  friend
398  std::istream& operator >> (std::istream& in, Vector &vector);
399 
400  friend
401  std::ostream& operator << (std::ostream& out, const Vector &vector);
402 
403  };
404 
406  bool operator == (const Vector& v1, const Vector& v2);
407 
409  bool operator == (const Vector& v1, const double* v2);
410 
412  bool operator == (const double* v1, const Vector& v2);
413 
415  bool operator != (const Vector& v1, const Vector& v2);
416 
418  bool operator != (const Vector& v1, const double* v2);
419 
421  bool operator != (const double* v1, const Vector& v2);
422 
432  std::istream& operator >> (std::istream& in, Vector &vector);
433 
442  std::ostream& operator << (std::ostream& out, const Vector &vector);
443 
444  #ifdef UTIL_MPI
445 
448  template <>
450  {
451  public:
452  static MPI::Datatype type;
453  static bool hasType;
454  };
455  #endif
456 
457  // Inline methods
458 
459  /*
460  * Default constructor
461  */
462  inline
464  {}
465 
466  /*
467  * Copy constructor
468  */
469  inline
471  {
472  elem_[0] = v.elem_[0];
473  elem_[1] = v.elem_[1];
474  elem_[2] = v.elem_[2];
475  }
476 
477  /*
478  * Constructor, initialize all elements to a scalar value.
479  */
480  inline
481  Vector::Vector(double scalar)
482  {
483  elem_[0] = scalar;
484  elem_[1] = scalar;
485  elem_[2] = scalar;
486  }
487 
488  /*
489  * Construct Vector from C double[3] array.
490  */
491  inline
492  Vector::Vector(const double* v)
493  {
494  elem_[0] = v[0];
495  elem_[1] = v[1];
496  elem_[2] = v[2];
497  }
498 
499  /*
500  * Construct Vector from its coordinates.
501  */
502  inline
503  Vector::Vector(double x, double y, double z)
504  {
505  elem_[0] = x;
506  elem_[1] = y;
507  elem_[2] = z;
508  }
509 
510  /*
511  * Set all elements of a 3D vector to zero.
512  */
513  inline
515  {
516  elem_[0] = 0.0;
517  elem_[1] = 0.0;
518  elem_[2] = 0.0;
519  return *this;
520  }
521 
522  /*
523  * Assignment.
524  */
525  inline
527  {
528  elem_[0] = v.elem_[0];
529  elem_[1] = v.elem_[1];
530  elem_[2] = v.elem_[2];
531  return *this;
532  }
533 
534  /*
535  * Assignment from C double[] array.
536  */
537  inline
538  Vector& Vector::operator = (const double* v)
539  {
540  elem_[0] = v[0];
541  elem_[1] = v[1];
542  elem_[2] = v[2];
543  return *this;
544  }
545 
546  /*
547  * Add vector dv to this vector.
548  */
549  inline
550  void Vector::operator += (const Vector& dv)
551  {
552  elem_[0] += dv.elem_[0];
553  elem_[1] += dv.elem_[1];
554  elem_[2] += dv.elem_[2];
555  }
556 
557  /*
558  * Subtract vector dv from this vector.
559  */
560  inline
561  void Vector::operator -= (const Vector& dv)
562  {
563  elem_[0] -= dv.elem_[0];
564  elem_[1] -= dv.elem_[1];
565  elem_[2] -= dv.elem_[2];
566  }
567 
568  /*
569  * Multiply this vector by scalar s.
570  */
571  inline
572  void Vector::operator *= (double s)
573  {
574  elem_[0] *= s;
575  elem_[1] *= s;
576  elem_[2] *= s;
577  }
578 
579  /*
580  * Divide this vector by scalar s.
581  */
582  inline
583  void Vector::operator /= (double s)
584  {
585  elem_[0] /= s;
586  elem_[1] /= s;
587  elem_[2] /= s;
588  }
589 
590  /*
591  * Return one Cartesian element by value.
592  */
593  inline
594  const double& Vector::operator [] (int i) const
595  {
596  assert(i >=0);
597  assert(i < Dimension);
598  return elem_[i];
599  }
600 
601  /*
602  * Return a reference to one element of the vector.
603  */
604  inline
605  double& Vector::operator [] (int i)
606  {
607  assert(i >=0);
608  assert(i < Dimension);
609  return elem_[i];
610  }
611 
612  /*
613  * Return square magnitude of this vector.
614  */
615  inline
616  double Vector::square() const
617  {
618  return (elem_[0]*elem_[0] + elem_[1]*elem_[1] + elem_[2]*elem_[2]);
619  }
620 
621  /*
622  * Return absolute magnitude of this vector.
623  */
624  inline
625  double Vector::abs() const
626  { return sqrt(square()); }
627 
628  /*
629  * Return dot product of this vector and vector v.
630  */
631  inline
632  double Vector::dot(const Vector& v) const
633  {
634  return elem_[0]*v.elem_[0] + elem_[1]*v.elem_[1] + elem_[2]*v.elem_[2];
635  }
636 
637  /*
638  * Return projection of this vector along vector p.
639  */
640  inline
641  double Vector::projection(const Vector& p) const
642  {
643  double abs_p = p.abs();
644  if (abs_p > 1.0E-8) {
645  return dot(p)/abs_p;
646  } else {
647  return 0.0;
648  }
649  }
650 
651  /*
652  * Add vectors v1 and v2.
653  *
654  * Upon return, *this = v1 + v2.
655  */
656  inline
657  Vector& Vector::add(const Vector& v1, const Vector& v2)
658  {
659  elem_[0] = v1.elem_[0] + v2.elem_[0];
660  elem_[1] = v1.elem_[1] + v2.elem_[1];
661  elem_[2] = v1.elem_[2] + v2.elem_[2];
662  return *this;
663  }
664 
665  /*
666  * Subtract vector v2 from v1.
667  *
668  * Upon return, *this = v1 - v2.
669  * \return modified invoking vector
670  */
671  inline
672  Vector& Vector::subtract(const Vector& v1, const Vector& v2)
673  {
674  elem_[0] = v1.elem_[0] - v2.elem_[0];
675  elem_[1] = v1.elem_[1] - v2.elem_[1];
676  elem_[2] = v1.elem_[2] - v2.elem_[2];
677  return *this;
678  }
679 
680  /*
681  * Multiply a vector v by a scalar s.
682  *
683  * Upon return, *this = v*s.
684  */
685  inline
686  Vector& Vector::multiply(const Vector& v, double s)
687  {
688  elem_[0] = v.elem_[0]*s;
689  elem_[1] = v.elem_[1]*s;
690  elem_[2] = v.elem_[2]*s;
691  return *this;
692  }
693 
694  /*
695  * Divide vector v by scalar s.
696  *
697  * Upon return, *this = v/s;
698  */
699  inline
700  Vector& Vector::divide(const Vector& v, double s)
701  {
702  elem_[0] = v.elem_[0]/s;
703  elem_[1] = v.elem_[1]/s;
704  elem_[2] = v.elem_[2]/s;
705  return *this;
706  }
707 
708  /*
709  * Calculate cross product of vectors v1 and v2.
710  *
711  * Upon return, *this = v1 x v2.
712  */
713  inline
714  Vector& Vector::cross(const Vector& v1, const Vector& v2)
715  {
716  elem_[0] = v1.elem_[1]*v2.elem_[2] - v1.elem_[2]*v2.elem_[1];
717  elem_[1] = v1.elem_[2]*v2.elem_[0] - v1.elem_[0]*v2.elem_[2];
718  elem_[2] = v1.elem_[0]*v2.elem_[1] - v1.elem_[1]*v2.elem_[0];
719  return *this;
720  }
721 
722  /*
723  * Calculate unit vector parallel to v: this = v/|v|
724  */
725  inline
727  {
728  double vabs = v.abs();
729  if (vabs > 1.0E-8) {
730  vabs = 1.0/vabs;
731  elem_[0] = v.elem_[0]*vabs;
732  elem_[1] = v.elem_[1]*vabs;
733  elem_[2] = v.elem_[2]*vabs;
734  } else {
735  elem_[0] = 1.0;
736  elem_[1] = 0.0;
737  elem_[2] = 0.0;
738  };
739  return *this;
740  }
741 
742  /*
743  * Calculate component of vector v parallel to vector p.
744  *
745  * Upon return, the invoking vector is equal to the vector projection of
746  * vector v along a direction parallel to vector p.
747  */
748  inline
749  Vector& Vector::parallel(const Vector& v, const Vector& p)
750  {
751  double pp, fac;
752  pp = p.square();
753  if (pp > 1.0E-8) {
754  fac = v.dot(p)/pp;
755  } else {
756  fac = 0.0;
757  }
758  elem_[0] = p.elem_[0]*fac;
759  elem_[1] = p.elem_[1]*fac;
760  elem_[2] = p.elem_[2]*fac;
761  return *this;
762  }
763 
764  /*
765  * Calculate component of vector v transverse to vector p.
766  *
767  * Upon return, the invoking vector is equal to the vector
768  * projection of vector v perpendicular to vector p.
769  */
770  inline
771  Vector& Vector::transverse(const Vector& v, const Vector& p)
772  {
773  double pp, fac;
774  pp = p.square();
775  if (pp > 1.0E-8) {
776  fac = v.dot(p)/pp;
777  } else {
778  fac = 0.0;
779  }
780  elem_[0] = v.elem_[0] - p.elem_[0]*fac;
781  elem_[1] = v.elem_[1] - p.elem_[1]*fac;
782  elem_[2] = v.elem_[2] - p.elem_[2]*fac;
783  return *this;
784  }
785 
786  /*
787  * Compute the index corresponding to minimum element in a vector.
788  */
789  inline
790  int minId(const Vector& v)
791  {
792  int id = 0;
793  for (int i = 1; i < DimensionSq; i++) {
794  if (v[i] < v[id])
795  id = i;
796  }
797  return id;
798  }
799 
800  /*
801  * Compute the index corresponding to maximum element in a vector.
802  */
803  inline
804  int maxId(const Vector& v)
805  {
806  int id = 0;
807  for (int i = 1; i < DimensionSq; i++) {
808  if (v[i] > v[id])
809  id = i;
810  }
811  return id;
812  }
813 
814  /*
815  * Serialize to/from an archive.
816  */
817  template <class Archive>
818  inline void Vector::serialize(Archive& ar, const unsigned int version)
819  {
820  ar & elem_[0];
821  ar & elem_[1];
822  ar & elem_[2];
823  }
824 
825 }
826 #endif
int maxId(const Vector &v)
Computes the index corresponding to maximum element in a vector.
Vector & zero()
Set all elements of a 3D vector to zero.
Definition: Vector.h:514
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
static void commitMpiType()
Commit MPI datatype MpiTraits<Vector>::type.
Definition: Vector.cpp:97
A Vector is a Cartesian vector.
Definition: Vector.h:75
Vector & divide(const Vector &v, double s)
Divide vector v by scalar s.
Definition: Vector.h:700
void operator*=(double s)
Multiply this vector by scalar s.
Definition: Vector.h:572
Vector & add(const Vector &v1, const Vector &v2)
Add vectors v1 and v2.
Definition: Vector.h:657
const double & operator[](int i) const
Return one Cartesian element by value.
Definition: Vector.h:594
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
void operator/=(double s)
Divide this vector by scalar s.
Definition: Vector.h:583
Vector & multiply(const Vector &v, double s)
Multiply a vector v by a scalar s.
Definition: Vector.h:686
static const Vector Zero
Zero Vector = {0.0, 0.0, 0.0}.
Definition: Vector.h:369
File containing preprocessor macros for error handling.
static void initStatic()
Initialize Zero Vector.
Definition: Vector.cpp:119
int minId(const Vector &v)
Computes the index corresponding to minimum element in a vector.
friend std::ostream & operator<<(std::ostream &out, const Vector &vector)
ostream inserter for a Vector.
Definition: Vector.cpp:76
friend bool operator==(const Vector &v1, const Vector &v2)
Equality for Vectors.
Definition: Vector.cpp:26
void operator-=(const Vector &dv)
Subtract vector dv from this vector.
Definition: Vector.h:561
Vector & operator=(const Vector &v)
Copy assignment.
Definition: Vector.h:526
void serialize(Archive &ar, const unsigned int version)
Serialize to/from an archive.
Definition: Vector.h:818
Vector & parallel(const Vector &v, const Vector &p)
Calculate component of vector v parallel to vector p.
Definition: Vector.h:749
Vector & cross(const Vector &v1, const Vector &v2)
Calculate cross product of vectors v1 and v2.
Definition: Vector.h:714
Utility classes for scientific computation.
Definition: accumulators.mod:1
Default MpiTraits class.
Definition: MpiTraits.h:39
static bool hasType
Is the MPI type initialized?
Definition: Vector.h:453
friend std::istream & operator>>(std::istream &in, Vector &vector)
istream extractor for a Vector.
Definition: Vector.cpp:65
Vector & transverse(const Vector &v, const Vector &p)
Calculate component of vector v transverse to vector p.
Definition: Vector.h:771
void operator+=(const Vector &dv)
Add vector dv to this vector.
Definition: Vector.h:550
const int DimensionSq
Square of Dimensionality of space.
Definition: Dimension.h:26
double abs() const
Return absolute magnitude of this vector.
Definition: Vector.h:625
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
Definition: Vector.h:672
Vector()
Default constructor.
Definition: Vector.h:463
double projection(const Vector &p) const
Return projection of this vector along vector p.
Definition: Vector.h:641
static MPI::Datatype type
MPI Datatype.
Definition: Vector.h:452
Vector & versor(const Vector &v)
Calculate unit vector parallel to input vector v.
Definition: Vector.h:726
double square() const
Return square magnitude of this vector.
Definition: Vector.h:616
bool operator!=(const PointSymmetry &A, const PointSymmetry &B)
Are two PointSymmetry objects not equivalent?