Simpatico  v1.10
FeneBond.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
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 "FeneBond.h"
9 #include <util/random/Random.h>
10 #include <util/mpi/MpiLoader.h>
11 
12 namespace Simp
13 {
14 
15  using namespace Util;
16 
17  /*
18  * Constructor.
19  */
21  : nBondType_(0)
22  {
23  setClassName("FeneBond");
24  for (int i = 0; i < MaxNBondType; ++i) {
25  kappa_[i] = 0.0;
26  r0_[i] = 0.0;
27  r0Sq_[i] = 0.0;
28  r0SqInv_[i] = 0.0;
29  ce_[i] = 0.0;
30  rlSq_[i] = 0.0;
31  rl_[i] = 0.0;
32  energyCutoff_[i] = 0.0;
33  }
34  }
35 
36  /*
37  * Copy constructor.
38  */
40  : nBondType_(other.nBondType_)
41  {
42  for (int i = 0; i < nBondType_; ++i) {
43  kappa_[i] = other.kappa_[i];
44  r0_[i] = other.r0_[i];
45  r0Sq_[i] = other.r0Sq_[i];
46  r0SqInv_[i] = other.r0SqInv_[i];
47  ce_[i] = other.ce_[i];
48  rlSq_[i] = other.rlSq_[i];
49  rl_[i] = other.rl_[i];
50  energyCutoff_[i] = other.energyCutoff_[i];
51  }
52  }
53 
54  /*
55  * Assignment.
56  */
58  {
59  nBondType_ = other.nBondType_;
60  forceCutoff_ = other.forceCutoff_;
61  for (int i = 0; i < nBondType_; ++i) {
62  kappa_[i] = other.kappa_[i];
63  r0_[i] = other.r0_[i];
64  r0Sq_[i] = other.r0Sq_[i];
65  r0SqInv_[i] = other.r0SqInv_[i];
66  ce_[i] = other.ce_[i];
67  rlSq_[i] = other.rlSq_[i];
68  rl_[i] = other.rl_[i];
69  energyCutoff_[i] = other.energyCutoff_[i];
70  }
71  return *this;
72  }
73 
74  /*
75  * Set the nBondType_ member
76  */
77  void FeneBond::setNBondType(int nBondType)
78  {
79  UTIL_CHECK(nBondType <= MaxNBondType);
80  nBondType_ = nBondType;
81  }
82 
83  /*
84  * Read bond interaction parameters kappa and r0 from file
85  */
86  void FeneBond::readParameters(std::istream &in)
87  {
88  // Precondition
89  UTIL_CHECK(nBondType_ > 0);
90 
91  // Read parameters
92  readCArray<double>(in, "kappa", kappa_, nBondType_);
93  readCArray<double>(in, "r0", r0_, nBondType_);
94  read<double>(in, "forceCutoff", forceCutoff_);
95 
96  double y, g;
97  for (int i = 0; i < nBondType_; ++i) {
98  r0Sq_[i] = r0_[i]*r0_[i];
99  r0SqInv_[i] = 1.0/r0Sq_[i];
100  ce_[i] = -0.5*r0Sq_[i]*kappa_[i];
101  y = 0.5*kappa_[i]*r0_[i]/forceCutoff_;
102  rl_[i] = r0_[i]*(sqrt(1.0 + y*y) - y);
103  rlSq_[i] = rl_[i]*rl_[i];
104  g = 1.0 - rlSq_[i]*r0SqInv_[i];
105  energyCutoff_[i] = ce_[i]*log(g);
106  }
107  }
108 
109  /*
110  * Load internal state from an archive.
111  */
113  {
114  UTIL_CHECK(nBondType_ > 0);
115  loadCArray<double> (ar, "kappa", kappa_, nBondType_);
116  loadCArray<double>(ar, "r0", r0_, nBondType_);
117  loadParameter<double>(ar, "forceCutoff", forceCutoff_);
118  #ifdef UTIL_MPI
119  MpiLoader<Serializable::IArchive> loader(*this, ar);
120  loader.load(r0Sq_, nBondType_);
121  loader.load(r0SqInv_, nBondType_);
122  loader.load(ce_, nBondType_);
123  loader.load(rl_, nBondType_);
124  loader.load(rlSq_, nBondType_);
125  loader.load(energyCutoff_, nBondType_);
126  #else
127  ar.unpack(r0Sq_, nBondType_);
128  ar.unpack(r0SqInv_, nBondType_);
129  ar.unpack(ce_, nBondType_);
130  ar.unpack(rl_, nBondType_);
131  ar.unpack(rlSq_, nBondType_);
132  ar.unpack(energyCutoff_, nBondType_);
133  #endif
134  }
135 
136  /*
137  * Save internal state to an archive.
138  */
140  {
141  UTIL_CHECK(nBondType_ > 0);
142  ar.pack(kappa_, nBondType_);
143  ar.pack(r0_, nBondType_);
144  ar << forceCutoff_;
145  ar.pack(r0Sq_, nBondType_);
146  ar.pack(r0SqInv_, nBondType_);
147  ar.pack(ce_, nBondType_);
148  ar.pack(rl_, nBondType_);
149  ar.pack(rlSq_, nBondType_);
150  ar.pack(energyCutoff_, nBondType_);
151  }
152 
153  /*
154  * Generate a random bond length chosen from an equilibrium distribution for
155  * randomly oriented bonds.
156  *
157  * Algorithm:
158  *
159  * While trial not accepted:
160  *
161  * -Choose random trial vector of squared length rSq from the equilibrium
162  * distribution for a harmonic spring with the same spring constant.
163  * -Reject if rSq > r0Sq
164  * -Accept with probability exp[-beta[U_Fene(r) - U_Harmonic(r)].
165  */
167  Random *random, double beta, int type) const
168  {
169 
170  double x, y, z, sigSq, rSq, eHarm, eFene, ratio;
171  sigSq = 1.0/(beta*kappa_[type]);
172 
173  // Generate trials until one is accepted
174  for (;;) {
175  x = random->gaussian();
176  y = random->gaussian();
177  z = random->gaussian();
178  rSq = sqrt(x*x + y*y + z*z)*sigSq;
179  if (rSq >= r0Sq_[type]) continue;
180  eHarm = 0.5*kappa_[type]*rSq;
181  eFene = energy(rSq, type);
182  ratio = exp(-beta*(eFene - eHarm));
183  if (random->uniform(0.0,1.0) < ratio) {
184  return sqrt(rSq);
185  };
186  }
187  }
188 
189  /*
190  * Modify a parameter, identified by a string.
191  */
192  void FeneBond::set(std::string name, int type, double value)
193  {
194  if (name == "kappa") {
195  kappa_[type] = value;
196  } else
197  if (name == "r0") {
198  r0_[type] = value;
199  } else {
200  UTIL_THROW("Unrecognized parameter name");
201  }
202  r0Sq_[type] = r0_[type]*r0_[type];
203  r0SqInv_[type] = 1.0/r0Sq_[type];
204  ce_[type] = -0.5*r0Sq_[type]*kappa_[type];
205  double y = 0.5*kappa_[type]*r0_[type]/forceCutoff_;
206  rl_[type] = r0_[type]*(sqrt(1.0 + y*y) - y);
207  rlSq_[type] = rl_[type]*rl_[type];
208  double g = 1.0 - rlSq_[type]*r0SqInv_[type];
209  energyCutoff_[type] = ce_[type]*log(g);
210  }
211 
212  /*
213  * Get a parameter value, identified by a string.
214  */
215  double FeneBond::get(std::string name, int type) const
216  {
217  double value = 0.0;
218  if (name == "kappa") {
219  value = kappa_[type];
220  } else
221  if (name == "r0") {
222  value = r0_[type];
223  } else {
224  UTIL_THROW("Unrecognized parameter name");
225  }
226  return value;
227  }
228 
229 }
void readParameters(std::istream &in)
Read bond interaction parameters from input stream.
Definition: FeneBond.cpp:86
double energy(double rSq, int type) const
Returns potential energy for one bond.
Definition: FeneBond.h:192
A finitely-extensible nonlinear element (FENE) bond potential.
Definition: FeneBond.h:39
Classes used by all simpatico molecular simulations.
void setNBondType(int nBondType)
Set the number of bond types.
Definition: FeneBond.cpp:77
double uniform()
Return a random floating point number x, uniformly distributed in the range 0 <= x < 1...
Definition: Random.h:203
Saving / output archive for binary ostream.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
void pack(const T &data)
Pack one object of type T.
Utility classes for scientific computation.
Definition: accumulators.mod:1
double randomBondLength(Random *random, double beta, int type) const
Return bond length chosen from equilibrium distribution.
Definition: FeneBond.cpp:166
void set(std::string name, int type, double value)
Modify a parameter, identified by a string.
Definition: FeneBond.cpp:192
double gaussian(void)
Return a Gaussian random number with zero average and unit variance.
Definition: Random.cpp:92
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Definition: FeneBond.cpp:139
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
Definition: FeneBond.cpp:112
double get(std::string name, int type) const
Get a parameter value, identified by a string.
Definition: FeneBond.cpp:215
Saving archive for binary istream.
Provides methods for MPI-aware loading of data from input archive.
Definition: MpiLoader.h:43
FeneBond()
Default constructor.
Definition: FeneBond.cpp:20
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition: global.h:68
void setClassName(const char *className)
Set class name string.
Random number generator.
Definition: Random.h:46
FeneBond & operator=(const FeneBond &other)
Assignment.
Definition: FeneBond.cpp:57