Simpatico  v1.10
MonoclinicBoundary.cpp
1 /*
2 * Util Package - C++ Utilities for Scientific Computation
3 *
4 * Copyright 2010 - 2017, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "MonoclinicBoundary.h"
9 #include <util/space/Vector.h>
10 #include <util/space/Dimension.h>
11 #include <util/random/Random.h>
12 #include <util/math/Constants.h>
13 #include <util/math/feq.h>
14 #include <util/format/Dbl.h>
15 #include <util/global.h>
16 
17 namespace Simp
18 {
19 
20  /*
21  * Default constructor.
22  */
24  : lattice_(Monoclinic)
25  {
26  double twoPi = 2.0*Constants::Pi;
27  for (int i = 0; i < Dimension; ++i) {
28  minima_[i] = 0.0;
29  maxima_[i] = 1.0;
30  l_[i] = 1.0;
31  invL_[i] = 1.0;
32  halfL_[i] = 0.5;
33  lengths_[i] = 1.0;
34  bravaisBasisVectors_.append(Vector::Zero);
35  bravaisBasisVectors_[i][i] = l_[i];
36  reciprocalBasisVectors_.append(Vector::Zero);
37  reciprocalBasisVectors_[i][i] = twoPi / l_[i];
38  }
39  d_ = 0.0;
40  volume_ = 1.0;
41 
42  c3_ = 0.0;
43  e_ = 1.0;
44  minLength_ = 1.0;
45  }
46 
47  /*
48  * Set unit cell parameters and then call reset.
49  */
50  void MonoclinicBoundary::setMonoclinic(const Vector &lengths, const double d)
51  {
52  l_ = lengths;
53  d_ = d;
54  reset();
55  }
56 
57  /*
58  * Setup orthorhombic unit cell.
59  */
61  {
62  l_ = lengths;
63  d_ = 0.0;
64  reset();
65  }
66 
67  /*
68  * Reset all quantities that depend on unit cell lengths.
69  */
70  void MonoclinicBoundary::reset()
71  {
72  double twoPi = 2.0*Constants::Pi;
73  for (int i = 0; i < Dimension; ++i) {
74  minima_[i] = 0.0;
75  maxima_[i] = l_[i];
76  halfL_[i] = 0.5*l_[i];
77  invL_[i] = 1.0/l_[i];
78  bravaisBasisVectors_[i][i] = l_[i];
79  reciprocalBasisVectors_[i][i] = twoPi/l_[i];
80  }
81  bravaisBasisVectors_[1][2] = d_;
82  reciprocalBasisVectors_[2][1] = -twoPi*d_/(l_[1]*l_[2]);
83 
84  volume_ = l_[0] * l_[1] * l_[2];
85  e_ = sqrt(l_[1]*l_[1] + d_*d_);
86  c3_ = -d_/l_[1];
87 
88  lengths_[0] = l_[0];
89  lengths_[1] = l_[1];
90  lengths_[2] = l_[2] / sqrt(1.0 + c3_*c3_);
91 
92  minLength_ = lengths_[0];
93  for (int i = 1; i < Dimension; ++i) {
94  if (lengths_[i] < minLength_) {
95  minLength_ = lengths_[i];
96  }
97  }
98  }
99 
100  /*
101  * Generate a random Cartesian position within the primitive unit cell.
102  *
103  * \param random random number generator object
104  * \param r Vector of random Cartesian coordinates
105  */
107  {
108  Vector Rg;
109  for (int i=0; i < Dimension; ++i) {
110  Rg[i] = random.uniform(0.0, 1.0);
111  }
112  transformGenToCart(Rg, r);
113  }
114 
115  /*
116  * Check consistency of data.
117  */
119  {
120  double dot;
121  double twoPi = 2.0*Constants::Pi;
122  int i, j;
123  for (i = 0; i < Dimension; ++i) {
124  if (maxima_[i] <= minima_[i]) {
125  UTIL_THROW("maxima_[i] <= minima_[i]");
126  }
127  if (!feq(l_[i], maxima_[i] - minima_[i])) {
128  UTIL_THROW("l_[i] != maxima_[i] - minima_[i]");
129  }
130  if (!feq(halfL_[i], 0.5*l_[i])) {
131  UTIL_THROW("halfL_[i] != 0.5*l_[i]");
132  }
133  if (!feq(minima_[i], 0.0)) {
134  UTIL_THROW("minima_[i] != 0");
135  }
136  if (!feq(l_[i]*invL_[i], 1.0)) {
137  UTIL_THROW("invL_[i]*l_[i] != 1.0");
138  }
139  for (j = 0; j < Dimension; ++j) {
140  dot = bravaisBasisVectors_[i].dot(reciprocalBasisVectors_[j]);
141  if (i == j) {
142  if (!feq(dot, twoPi)) {
143  UTIL_THROW("a[i].b[i] != twoPi");
144  }
145  } else {
146  if (!feq(dot, 0.0)) {
147  UTIL_THROW("a[i].b[j] != 0 for i != j");
148  }
149  }
150  }
151  }
152  if (!feq(volume_, l_[0]*l_[1]*l_[2])) {
153  UTIL_THROW("volume_ != product of l_");
154  }
155  return true;
156  }
157 
158  /*
159  * Input a MonoclinicBoundary from an istream, without line breaks.
160  */
161  std::istream& operator >> (std::istream& in, MonoclinicBoundary &boundary)
162  {
163  LatticeSystem lattice;
164  in >> lattice;
165  if (lattice != Monoclinic) {
166  UTIL_THROW("Lattice must be Monoclinic");
167  }
168  in >> boundary.l_;
169  in >> boundary.d_;
170  boundary.reset();
171  return in;
172  }
173 
174  /*
175  * Output an MonoclinicBoundary to an ostream, without line breaks.
176  */
177  std::ostream&
178  operator << (std::ostream& out, const MonoclinicBoundary &boundary)
179  {
180  out << boundary.lattice_ << " ";
181  out << boundary.l_ << " ";
182  out << boundary.d_;
183  return out;
184  }
185 }
186 
187 #ifdef UTIL_MPI
188 namespace Util{
189 
190  using namespace Simp;
191 
192  template <>
193  void send<MonoclinicBoundary>(MPI::Comm& comm,
194  MonoclinicBoundary& data, int dest, int tag)
195  {
196  send<Vector>(comm, data.l_, dest, tag);
197  send<double>(comm, data.d_, dest, tag + 386);
198  }
199 
200  template <>
201  void recv<MonoclinicBoundary>(MPI::Comm& comm,
202  MonoclinicBoundary& data, int source, int tag)
203  {
204  Vector l;
205  double d;
206  recv<Vector>(comm, l, source, tag);
207  recv<double>(comm, d, source, tag + 386);
208  data.setMonoclinic(l, d);
209  }
210 
211  template <>
212  void bcast<MonoclinicBoundary>(MPI::Intracomm& comm,
213  MonoclinicBoundary& data, int root)
214  {
215  Vector l;
216  double d;
217  int rank = comm.Get_rank();
218  if (rank == root) {
219  l = data.l_;
220  d = data.d_;
221  }
222  bcast<Vector>(comm, l, root);
223  bcast<double>(comm, d, root);
224  if (rank != root) {
225  data.setMonoclinic(l, d);
226  }
227  }
228 
229  /*
230  * Initialize MPI Datatype.
231  */
232  MPI::Datatype MpiTraits<MonoclinicBoundary>::type = MPI::BYTE;
234 
235 }
236 #endif
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
friend std::ostream & operator<<(std::ostream &out, const MonoclinicBoundary &boundary)
ostream inserter
A Vector is a Cartesian vector.
Definition: Vector.h:75
static const Vector Zero
Zero Vector = {0.0, 0.0, 0.0}.
Definition: Vector.h:369
void transformGenToCart(const Vector &Rg, Vector &Rc) const
Transform Vector of generalized coordinates to Cartesian coordinates.
void setOrthorhombic(const Vector &lengths)
Invalid function for monoclinic - throws Exception.
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
double uniform()
Return a random floating point number x, uniformly distributed in the range 0 <= x < 1...
Definition: Random.h:203
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Utility classes for scientific computation.
Definition: accumulators.mod:1
Default MpiTraits class.
Definition: MpiTraits.h:39
friend std::istream & operator>>(std::istream &in, MonoclinicBoundary &boundary)
istream extractor
void setMonoclinic(const Vector &lengths, const double d)
Set unit cell dimensions for orthorhombic boundary.
LatticeSystem
Enumeration of the 7 possible Bravais lattice systems.
Definition: LatticeSystem.h:29
A monoclinic periodic unit cell.
static const double Pi
Trigonometric constant Pi.
Definition: Constants.h:35
void randomPosition(Random &random, Vector &r) const
Generate random Cartesian position within the primary unit cell.
bool isValid()
Return true if valid, or throw Exception.
Random number generator.
Definition: Random.h:46
const Vector & lengths() const
Get Vector of distances between faces of primitive cell.
bool feq(double x, double y, double eps=1.0E-10)
Are two floating point numbers equal to within round-off error?
Definition: feq.h:27