PSCF v1.1
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
21namespace 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
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
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
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
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
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
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
static MPI::Datatype type
MPI Datatype.
Definition: Vector.h:452
static bool hasType
Is the MPI type initialized?
Definition: Vector.h:453
Default MpiTraits class.
Definition: MpiTraits.h:40
A Vector is a Cartesian vector.
Definition: Vector.h:76
double square() const
Return square magnitude of this vector.
Definition: Vector.h:616
Vector & operator=(const Vector &v)
Copy assignment.
Definition: Vector.h:526
static const Vector Zero
Zero Vector = {0.0, 0.0, 0.0}.
Definition: Vector.h:369
static void commitMpiType()
Commit MPI datatype MpiTraits<Vector>::type.
Definition: Vector.cpp:97
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
Vector & versor(const Vector &v)
Calculate unit vector parallel to input vector v.
Definition: Vector.h:726
int maxId(const Vector &v)
Computes the index corresponding to maximum element in a vector.
Vector & add(const Vector &v1, const Vector &v2)
Add vectors v1 and v2.
Definition: Vector.h:657
Vector & multiply(const Vector &v, double s)
Multiply a vector v by a scalar s.
Definition: Vector.h:686
void operator+=(const Vector &dv)
Add vector dv to this vector.
Definition: Vector.h:550
int minId(const Vector &v)
Computes the index corresponding to minimum element in a vector.
friend bool operator==(const Vector &v1, const Vector &v2)
Equality for Vectors.
Definition: Vector.cpp:26
Vector & divide(const Vector &v, double s)
Divide vector v by scalar s.
Definition: Vector.h:700
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
Definition: Vector.h:672
void operator*=(double s)
Multiply this vector by scalar s.
Definition: Vector.h:572
friend std::ostream & operator<<(std::ostream &out, const Vector &vector)
ostream inserter for a Vector.
Definition: Vector.cpp:76
Vector & parallel(const Vector &v, const Vector &p)
Calculate component of vector v parallel to vector p.
Definition: Vector.h:749
double projection(const Vector &p) const
Return projection of this vector along vector p.
Definition: Vector.h:641
void serialize(Archive &ar, const unsigned int version)
Serialize to/from an archive.
Definition: Vector.h:818
Vector & zero()
Set all elements of a 3D vector to zero.
Definition: Vector.h:514
friend std::istream & operator>>(std::istream &in, Vector &vector)
istream extractor for a Vector.
Definition: Vector.cpp:65
Vector()
Default constructor.
Definition: Vector.h:463
Vector & transverse(const Vector &v, const Vector &p)
Calculate component of vector v transverse to vector p.
Definition: Vector.h:771
const double & operator[](int i) const
Return one Cartesian element by value.
Definition: Vector.h:594
Vector & cross(const Vector &v1, const Vector &v2)
Calculate cross product of vectors v1 and v2.
Definition: Vector.h:714
static void initStatic()
Initialize Zero Vector.
Definition: Vector.cpp:119
void operator-=(const Vector &dv)
Subtract vector dv from this vector.
Definition: Vector.h:561
void operator/=(double s)
Divide this vector by scalar s.
Definition: Vector.h:583
double abs() const
Return absolute magnitude of this vector.
Definition: Vector.h:625
File containing preprocessor macros for error handling.
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
const int DimensionSq
Square of Dimensionality of space.
Definition: Dimension.h:26
Utility classes for scientific computation.
Definition: accumulators.mod:1
bool operator==(Polynomial< T > const &a, Polynomial< T > const &b)
Equality operator for polynomials.
Definition: Polynomial.h:675
std::istream & operator>>(std::istream &in, Pair< Data > &pair)
Input a Pair from an istream.
Definition: Pair.h:44
std::ostream & operator<<(std::ostream &out, const Pair< Data > &pair)
Output a Pair to an ostream, without line breaks.
Definition: Pair.h:57
bool operator!=(Polynomial< T > const &a, Polynomial< T > const &b)
Inequality operator for polynomials.
Definition: Polynomial.h:694