Simpatico  v1.10
CfbLinear.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 <util/global.h>
9 
10 #include "CfbLinear.h"
11 #include <mcMd/mcSimulation/McSystem.h>
13 #include <mcMd/simulation/Simulation.h>
14 #include <mcMd/chemistry/Molecule.h>
15 #include <mcMd/chemistry/Atom.h>
16 
17 #include <simp/species/Species.h>
18 #include <simp/species/Linear.h>
19 #include <simp/boundary/Boundary.h>
20 
21 #include <util/space/Vector.h>
22 
23 namespace McMd
24 {
25 
26  using namespace Util;
27  using namespace Simp;
28 
29  /*
30  * Constructor
31  */
33  SystemMove(system),
34  speciesId_(-1),
35  nTrial_(-1)
36  {
37  #ifndef SIMP_BOND
38  UTIL_THROW("CfbLinear requires that bonds be enabled");
39  #endif
40  }
41 
42  /*
43  * Destructor
44  */
46  {}
47 
48  /*
49  * Read and validate parameters speciesId and nTrial.
50  */
51  void CfbLinear::processParameters()
52  {
53  if (speciesId_ < 0) {
54  UTIL_THROW("Negative speciesId");
55  }
56  if (speciesId_ >= simulation().nSpecies()) {
57  UTIL_THROW("speciesId > nSpecies");
58  }
59 
60  // Check that Species is a subclass of Linear
61  Species& species = simulation().species(speciesId_);
62  Linear* linearPtr = dynamic_cast<Linear*>(&species);
63  if (linearPtr == 0) {
64  UTIL_THROW("Species is not Linear in CfbLinear");
65  }
66 
67  #ifdef SIMP_ANGLE
68  hasAngles_ = system().hasAnglePotential() && species.nAngle() > 0;
69  #endif
70  #ifdef SIMP_DIHEDRAL
71  hasDihedrals_ = system().hasDihedralPotential() && species.nDihedral() > 0;
72  if (hasDihedrals_) {
73  UTIL_THROW("CfbLinear does not (yet) work with dihedrals");
74  }
75  #endif
76  #ifdef SIMP_EXTERNAL
77  hasExternal_ = system().hasExternalPotential();
78  #endif
79 
80  // Read and validate parameter nTrial.
81  if (nTrial_ <=0) {
82  UTIL_THROW("Invalid parameter value, nTrial <= 0");
83  }
84  if (nTrial_ > MaxTrial_) {
85  UTIL_THROW("Invalid parameter value, nTrial > MaxTrial_");
86  }
87  }
88 
89  /*
90  * Read and validate parameters speciesId and nTrial.
91  */
92  void CfbLinear::readParameters(std::istream& in)
93  {
94  read<int>(in, "speciesId", speciesId_);
95  read<int>(in, "nTrial", nTrial_);
96  processParameters();
97  }
98 
99  /*
100  * Load and validate parameters speciesId and nTrial.
101  */
103  {
104  loadParameter<int>(ar, "speciesId", speciesId_);
105  loadParameter<int>(ar, "nTrial", nTrial_);
106  processParameters();
107  }
108 
109  /*
110  * Save parameters speciesId and nTrial.
111  */
113  {
114  ar & speciesId_;
115  ar & nTrial_;
116  }
117 
118  /*
119  * Configuration bias algorithm for deleting one atom from chain end.
120  */
121  void
122  CfbLinear::deleteAtom(Molecule& molecule, int atomId,
123  int sign, double &rosenbluth, double &energy)
124  {
125  // sign == -1, shift == 0 -> atomId = 0, 1, 2, ...
126  // sign == +1, shift == 1 -> atomId = nAtom-1, nAtom-2, ...
127  assert(sign == 1 || sign == -1);
128  int shift = (sign == 1) ? 1 : 0;
129  Atom& atom0 = molecule.atom(atomId);
130  Atom& atom1 = molecule.atom(atomId - sign);
131  Vector& pos0 = atom0.position();
132  Vector& pos1 = atom1.position();
133 
134  // Calculate bond length, unit vector, and energy
135  Vector v1; // Vector between atoms 0 and 1
136  Vector u1; // Unit vector parallel to v1
137  double r1, bondEnergy;
138  int bondTypeId = molecule.bond(atomId - shift).typeId();
139  r1 = boundary().distanceSq(pos1, pos0, v1);
140  bondEnergy = system().bondPotential().energy(r1, bondTypeId);
141  r1 = sqrt(r1); // bond length
142  u1 = v1;
143  u1 /= r1; // bond unit vector
144 
145  #ifndef SIMP_NOPAIR
146  McPairPotential& pairPotential = system().pairPotential();
147  energy = pairPotential.atomEnergy(atom0);
148  #else
149  energy = 0.0;
150  #endif
151 
152  #ifdef SIMP_ANGLE
153  Vector u2;
154  AnglePotential* anglePotentialPtr = 0;
155  int angleTypeId;
156  bool hasAngle = false;
157  if (hasAngles_) {
158  int atom2Id = atomId - 2*sign;
159  if (shift) {
160  assert(sign == 1);
161  hasAngle = (atom2Id >= 0);
162  } else {
163  assert(sign == -1);
164  hasAngle = (atom2Id < molecule.nAtom());
165  }
166  if (hasAngle) {
167  Atom& atom2 = molecule.atom(atom2Id);
168  Vector* pos2Ptr = &(atom2.position());
169  Vector v2; // v2=p2-p1
170  double r2 = boundary().distanceSq(*pos2Ptr, pos1, v2);
171  r2 = sqrt(r2); // r2 = |v2| = length of bond 2
172  u2 = v2;
173  u2 /= r2; // unit vector
174  double cosTheta = u1.dot(u2);
175  angleTypeId = molecule.bond(atomId - 2*shift).typeId();
176  anglePotentialPtr = &system().anglePotential();
177  energy += anglePotentialPtr->energy(cosTheta, angleTypeId);
178  }
179  }
180  #endif
181 
182  #ifdef SIMP_EXTERNAL
183  ExternalPotential* externalPotentialPtr = 0;
184  if (hasExternal_) {
185  externalPotentialPtr = &system().externalPotential();
186  assert(externalPotentialPtr);
187  energy += externalPotentialPtr->atomEnergy(atom0);
188  }
189  #endif
190 
191  // Here: energy = total energy - bond energy
192  // Rosenbluth factor = exp(-beta*(pair + angle + external))
193  rosenbluth = boltzmann(energy);
194 
195  // Add bond energy to total energy in current position
196  energy += bondEnergy;
197 
198  // Loop over nTrial - 1 additional trial positions:
199  double trialEnergy;
200  for (int iTrial = 0; iTrial < nTrial_ - 1; ++iTrial) {
201 
202  // Generate trial position
203  random().unitVector(u1);
204  v1 = u1;
205  v1 *= r1;
206  pos0.subtract(pos1, v1);
207  boundary().shift(pos0);
208 
209  // Compute trial energy (excluding bond energy)
210  #ifndef SIMP_NOPAIR
211  trialEnergy = system().pairPotential().atomEnergy(atom0);
212  #else
213  trialEnergy = 0.0;
214  #endif
215  #ifdef SIMP_ANGLE
216  if (hasAngles_) {
217  if (hasAngle) {
218  assert(anglePotentialPtr);
219  double cosTheta = u1.dot(u2);
220  trialEnergy += anglePotentialPtr->energy(cosTheta, angleTypeId);
221  }
222  }
223  #endif
224  #ifdef SIMP_EXTERNAL
225  if (hasExternal_) {
226  assert(externalPotentialPtr);
227  trialEnergy += externalPotentialPtr->atomEnergy(atom0);
228  }
229  #endif
230 
231  rosenbluth += boltzmann(trialEnergy);
232  }
233 
234  }
235 
236  /*
237  * Configuration bias algorithm for adding one atom to a chain end.
238  */
239  void
240  CfbLinear::addAtom(Molecule& molecule, Atom& atom0, Atom& atom1, int atomId,
241  int sign, double &rosenbluth, double &energy)
242  {
243  // sign == -1, shift == 0 -> atomId = 0, 1, 2, ...
244  // sign == +1, shift == 1 -> atomId = nAtom-1, nAtom-2, ...
245  assert(sign == 1 || sign == -1);
246  int shift = (sign == 1) ? 1 : 0;
247 
248  assert(atom0.typeId() == molecule.species().atomTypeId(atomId));
249  Vector& pos0 = atom0.position();
250  Vector& pos1 = atom1.position();
251 
252  // Generate a random bond length r1
253  double beta, r1;
254  int bondTypeId, iTrial;
255  bondTypeId = molecule.bond(atomId - shift).typeId();
256  beta = energyEnsemble().beta();
257  r1 = system().bondPotential().randomBondLength(&random(), beta, bondTypeId);
258 
259  #ifndef SIMP_NOPAIR
260  McPairPotential& pairPotential = system().pairPotential();
261  #endif
262 
263  #ifdef SIMP_ANGLE
264  // Compute vector v2 = pos2 - pos1, r2 = |v2|
265  Vector u2;
266  AnglePotential* anglePotentialPtr = 0;
267  int angleTypeId;
268  bool hasAngle = false;
269  if (hasAngles_) {
270  int atom2Id = atomId - 2*sign;
271  if (shift) {
272  assert(sign == 1);
273  hasAngle = (atom2Id >= 0);
274  } else {
275  assert(sign == -1);
276  hasAngle = (atom2Id < molecule.nAtom());
277  }
278  if (hasAngle) {
279  Atom* atom2Ptr = &atom1 - sign;
280  Vector* pos2Ptr = &(atom2Ptr->position());
281  Vector v2;
282  double r2 = boundary().distanceSq(*pos2Ptr, pos1, v2);
283  r2 = sqrt(r2); // r2 = |v2| = |p2 - p1|
284  u2 = v2;
285  u2 /= r2; // unit vector
286  anglePotentialPtr = &system().anglePotential();
287  angleTypeId = molecule.bond(atomId - 2*shift).typeId();
288  }
289  }
290  #endif
291 
292  #ifdef SIMP_EXTERNAL
293  ExternalPotential* externalPotentialPtr = 0;
294  if (hasExternal_) {
295  externalPotentialPtr = &system().externalPotential();
296  assert(externalPotentialPtr);
297  }
298  #endif
299 
300  // Loop over nTrial trial positions:
301  Vector v1, u1;
302  Vector trialPos[MaxTrial_];
303  double trialProb[MaxTrial_], trialEnergy[MaxTrial_];
304  rosenbluth = 0.0;
305  for (iTrial = 0; iTrial < nTrial_; ++iTrial) {
306 
307  // Generate trial bond vector v1 and position pos0
308  random().unitVector(u1);
309  v1 = u1;
310  v1 *= r1;
311  trialPos[iTrial].subtract(pos1, v1);
312  boundary().shift(trialPos[iTrial]);
313  pos0 = trialPos[iTrial];
314 
315  // Compute trial energy (excluding bond energy)
316  #ifndef SIMP_NOPAIR
317  trialEnergy[iTrial] = pairPotential.atomEnergy(atom0);
318  #else
319  trialEnergy[iTrial] = 0.0;
320  #endif
321  #ifdef SIMP_ANGLE
322  if (hasAngles_) {
323  if (hasAngle) {
324  assert(anglePotentialPtr);
325  double cosTheta = u1.dot(u2);
326  trialEnergy[iTrial] +=
327  anglePotentialPtr->energy(cosTheta, angleTypeId);
328  }
329  }
330  #endif
331  #ifdef SIMP_EXTERNAL
332  if (hasExternal_) {
333  assert(externalPotentialPtr);
334  trialEnergy[iTrial] +=
335  externalPotentialPtr->atomEnergy(atom0);
336  }
337  #endif
338 
339  // Compute unnormalized probability, increment rosenbluth
340  trialProb[iTrial] = boltzmann(trialEnergy[iTrial]);
341  rosenbluth += trialProb[iTrial];
342  }
343 
344  // Normalize trial probabilities
345  for (iTrial = 0; iTrial < nTrial_; ++iTrial) {
346  trialProb[iTrial] = trialProb[iTrial]/rosenbluth;
347  }
348 
349  // Choose a trial
350  iTrial = random().drawFrom(trialProb, nTrial_);
351 
352  // Calculate total energy for chosen trial, including bond energy
353  energy = trialEnergy[iTrial];
354  energy += system().bondPotential().energy(r1*r1, bondTypeId);
355 
356  // Set position to chosen value
357  pos0 = trialPos[iTrial];
358  }
359 
360 }
Bond & bond(int localId)
Get a specific Bond in this Molecule by non-const reference.
A System for use in a Markov chain Monte Carlo simulation.
Definition: McSystem.h:52
A Vector is a Cartesian vector.
Definition: Vector.h:75
void addAtom(Molecule &molecule, Atom &atom0, Atom &atom1, int atomId, int sign, double &rosenbluth, double &energy)
Configuration bias algorithm for adding an atom to a Linear molecule.
Definition: CfbLinear.cpp:240
virtual double atomEnergy(const Atom &atom) const =0
Calculate the external energy for one Atom.
Interface for a Angle Interaction.
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
Include this file to include all MC potential energy classes at once.
BondPotential & bondPotential() const
Return the BondPotential by reference.
Definition: McSystem.h:405
bool hasDihedralPotential() const
Does a dihedral potential exist?.
Definition: McSystem.h:433
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
A PairPotential for MC simulations (abstract).
bool hasAnglePotential() const
Does angle potential exist?.
Definition: McSystem.h:416
Species & species() const
Get the molecular Species by reference.
int typeId() const
Get the typeId for this covalent group.
virtual void save(Serializable::OArchive &ar)
Save speciesId and nTrial.
Definition: CfbLinear.cpp:112
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
long drawFrom(double probability[], long size)
Choose one of several outcomes with a specified set of probabilities.
Definition: Random.h:237
virtual void readParameters(std::istream &in)
Read and validate speciesId and nTrial.
Definition: CfbLinear.cpp:92
Saving / output archive for binary ostream.
double boltzmann(double energy)
Boltzmann weight associated with an energy difference.
Definition: SystemMove.h:100
int nDihedral() const
Get number of dihedrals per molecule for this Species.
double beta() const
Return the inverse temperature.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
McSystem & system()
Get parent McSystem.
Definition: SystemMove.h:82
Abstract External Potential class.
int typeId() const
Get type index for this Atom.
ExternalPotential & externalPotential() const
Return ExternalPotential by reference.
Definition: McSystem.h:473
A point particle within a Molecule.
Utility classes for scientific computation.
Definition: accumulators.mod:1
An McMove that acts on one McSystem.
Definition: SystemMove.h:28
void shift(Vector &r) const
Shift Cartesian Vector r to its primary image.
int atomTypeId(int iAtom) const
Get atom type index for a specific atom, by local atom index.
Random & random()
Get Random number generator of parent Simulation.
Definition: McMove.h:209
virtual void loadParameters(Serializable::IArchive &ar)
Load and validate speciesId and nTrial.
Definition: CfbLinear.cpp:102
McPairPotential & pairPotential() const
Return the McPairPotential by reference.
Definition: McSystem.h:388
virtual double energy(double cosTheta, int type) const =0
Returns potential energy for one angle.
virtual double energy(double rSq, int type) const =0
Returns potential energy for one bond.
virtual ~CfbLinear()
Destructor.
Definition: CfbLinear.cpp:45
void deleteAtom(Molecule &molecule, int atomId, int sign, double &rosenbluth, double &energy)
CFB algorithm for deleting an end atom from a Linear molecule.
Definition: CfbLinear.cpp:122
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
bool hasExternalPotential() const
Does an external potential exist?.
Definition: McSystem.h:467
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
Definition: Vector.h:672
const Atom & atom(int localId) const
Get a specific Atom in this Molecule.
AnglePotential & anglePotential() const
Return AnglePotential by reference.
Definition: McSystem.h:422
CfbLinear(McSystem &system)
Constructor.
Definition: CfbLinear.cpp:32
Simulation & simulation()
Get parent Simulation object.
Definition: McMove.h:203
A physical molecule (a set of covalently bonded Atoms).
const Vector & position() const
Get the position Vector by const reference.
virtual double randomBondLength(Util::Random *random, double beta, int type) const =0
Return bond length chosen from equilibrium distribution.
A Species represents a set of chemically similar molecules.
int nAngle() const
Get number of angles per molecule for this Species.
Species & species(int i)
Get a specific Species by reference.
A Species of linear polymers (abstract).
Definition: Linear.h:36
EnergyEnsemble & energyEnsemble()
Get EnergyEnsemble object of parent McSystem.
Definition: SystemMove.h:94
int nAtom() const
Get the number of Atoms in this Molecule.
virtual double atomEnergy(const Atom &atom) const =0
Calculate the nonbonded pair energy for one Atom.
void unitVector(Vector &v)
Generate unit vector with uniform probability over the unit sphere.
Definition: Random.cpp:122
Boundary & boundary()
Get Boundary object of parent McSystem.
Definition: SystemMove.h:88