Simpatico  v1.10
CfbEndBase.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 "CfbEndBase.h"
9 #include <mcMd/mcSimulation/McSystem.h>
11 
12 #include <mcMd/chemistry/getAtomGroups.h>
13 #include <mcMd/chemistry/Molecule.h>
14 #include <mcMd/chemistry/Bond.h>
15 #include <mcMd/chemistry/Atom.h>
16 #include <simp/boundary/Boundary.h>
17 #include <util/space/Vector.h>
18 #include <util/global.h>
19 
20 namespace McMd
21 {
22 
23  using namespace Util;
24  using namespace Simp;
25 
26  /*
27  * Constructor
28  */
30  SystemMove(system),
31  nTrial_(-1)
32  {
33  // Precondition
34  #ifdef SIMP_DIHEDRAL
35  if (system.hasDihedralPotential()) {
36  UTIL_THROW("CfbEndBase is unusable with dihedrals");
37  }
38  #endif
39  }
40 
41  /*
42  * Destructor
43  */
45  {}
46 
47  /*
48  * Read parameter nTrial.
49  */
50  void CfbEndBase::readParameters(std::istream& in)
51  {
52  read<int>(in, "nTrial", nTrial_);
53  if (nTrial_ <=0 || nTrial_ > MaxTrial_) {
54  UTIL_THROW("Invalid value input for nTrial");
55  }
56  }
57 
58  /*
59  * Configuration bias algorithm for deleting one atom from chain end.
60  */
61  void
62  CfbEndBase::deleteEndAtom(Atom* endPtr, Atom* pvtPtr, int bondType,
63  double &rosenbluth, double &energy)
64  {
65  Vector bondVec;
66  Vector pvtPos = pvtPtr->position();
67  double trialEnergy, lengthSq, length;
68 
69  // Calculate bond length of pvt-end bond
70  lengthSq = boundary().distanceSq(pvtPos, endPtr->position());
71  length = sqrt(lengthSq);
72 
73  // Calculate current nonbonded pair energy of end atom
74  #ifndef SIMP_NOPAIR
75  energy = system().pairPotential().atomEnergy(*endPtr);
76  #else
77  energy = 0.0;
78  #endif
79 
80  #ifdef SIMP_ANGLE
81  AtomAngleArray angles;
82  const Angle *anglePtr;
83  const Atom *pvtPtr2(NULL);
84  Vector dr1, dr2;
85  int iAngle, angleTypeId(0);
86  double rsq1, rsq2, cosTheta;
87 
88  if (system().hasAnglePotential()) {
89 
90  // Get the angle type and pointers of atoms forming the angle.
91  getAtomAngles(*endPtr, angles);
92  for (iAngle = 0; iAngle < angles.size(); ++iAngle) {
93  anglePtr = angles[iAngle];
94  if (&anglePtr->atom(1) == pvtPtr) {
95  if (&anglePtr->atom(0) == endPtr) {
96  pvtPtr2 = &anglePtr->atom(2);
97  } else {
98  pvtPtr2 = &anglePtr->atom(0);
99  }
100  angleTypeId = anglePtr->typeId();
101  }
102  }
103 
104  // Calculate angle energy.
105  rsq1 = boundary().distanceSq(pvtPtr->position(),
106  pvtPtr2->position(), dr1);
107  rsq2 = boundary().distanceSq(endPtr->position(),
108  pvtPtr->position(), dr2);
109  cosTheta = dr1.dot(dr2) / sqrt(rsq1 * rsq2);
110 
111  energy += system().anglePotential().energy(cosTheta, angleTypeId);
112 
113  }
114  #endif
115 
116  #ifdef SIMP_EXTERNAL
117  if (system().hasExternalPotential()) {
118  energy += system().externalPotential().atomEnergy(*endPtr);
119  }
120  #endif
121 
122  // Rosenbluth factor = exp(-beta*(pair + angle + external))
123  rosenbluth = boltzmann(energy);
124 
125  // Add bond energy of current pvt-end bond to energy.
126  // This is the final value of inout energy parameter.
127  energy += system().bondPotential().energy(lengthSq, bondType);
128 
129  // Loop over nTrial - 1 additional trial positions:
130  for (int iTrial=0; iTrial < nTrial_ - 1; ++iTrial) {
131 
132  random().unitVector(bondVec);
133  bondVec *= length;
134  endPtr->position().add(pvtPos, bondVec);
135  boundary().shift(endPtr->position());
136 
137  #ifndef SIMP_NOPAIR
138  trialEnergy = system().pairPotential().atomEnergy(*endPtr);
139  #else
140  trialEnergy = 0.0;
141  #endif
142 
143  #ifdef SIMP_ANGLE
144  if (system().hasAnglePotential()) {
145 
146  // Get the angle type and atom pointer at the angle.
147  getAtomAngles(*endPtr, angles);
148  for (iAngle = 0; iAngle < angles.size(); ++iAngle) {
149  anglePtr = angles[iAngle];
150  if (&anglePtr->atom(1) == pvtPtr) {
151  if (&anglePtr->atom(0) == endPtr) {
152  pvtPtr2 = &anglePtr->atom(2);
153  } else {
154  pvtPtr2 = &anglePtr->atom(0);
155  }
156  angleTypeId = anglePtr->typeId();
157  }
158  }
159 
160  // Calculate energy.
161  rsq1 = boundary().distanceSq(pvtPtr->position(),
162  pvtPtr2->position(), dr1);
163  rsq2 = boundary().distanceSq(endPtr->position(),
164  pvtPtr->position(), dr2);
165  cosTheta = dr1.dot(dr2) / sqrt(rsq1 * rsq2);
166 
167  trialEnergy += system().anglePotential()
168  .energy(cosTheta, angleTypeId);
169  }
170  #endif
171 
172  #ifdef SIMP_EXTERNAL
173  if (system().hasExternalPotential()) {
174  trialEnergy +=
175  system().externalPotential().atomEnergy(*endPtr);
176  }
177  #endif
178 
179  rosenbluth += boltzmann(trialEnergy);
180  }
181 
182  }
183 
184 
185  /*
186  * Configuration bias algorithm for adding one atom to a chain end.
187  */
188  void
189  CfbEndBase::addEndAtom(Atom* endPtr, Atom* pvtPtr, int bondType,
190  double &rosenbluth, double &energy)
191  {
192  Vector trialPos[MaxTrial_];
193  Vector bondVec;
194  Vector pvtPos = pvtPtr->position();
195  double trialProb[MaxTrial_], trialEnergy[MaxTrial_];
196  double beta, length;
197  int iTrial;
198 
199  #ifdef SIMP_ANGLE
200  AtomAngleArray angles;
201  const Angle *anglePtr;
202  const Atom *pvtPtr2(NULL);
203  Vector dr1, dr2;
204  int iAngle, angleTypeId(0);
205  double rsq1, rsq2, cosTheta;
206  #endif
207 
208  // Generate a random bond length
209  beta = energyEnsemble().beta();
210  length =
211  system().bondPotential().randomBondLength(&random(), beta, bondType);
212 
213  // Loop over nTrial trial positions:
214  rosenbluth = 0.0;
215  for (iTrial=0; iTrial < nTrial_; ++iTrial) {
216  random().unitVector(bondVec);
217  bondVec *= length;
218  // trialPos = pvtPos + bondVec
219  trialPos[iTrial].add(pvtPos, bondVec);
220  boundary().shift(trialPos[iTrial]);
221  endPtr->position() = trialPos[iTrial];
222  #ifndef SIMP_NOPAIR
223  trialEnergy[iTrial] = system().pairPotential().atomEnergy(*endPtr);
224  #else
225  trialEnergy[iTrial] = 0.0;
226  #endif
227 
228  #ifdef SIMP_ANGLE
229  if (system().hasAnglePotential()) {
230 
231  getAtomAngles(*endPtr, angles);
232  for (iAngle = 0; iAngle < angles.size(); ++iAngle) {
233  anglePtr = angles[iAngle];
234  if (&anglePtr->atom(1) == pvtPtr) {
235  if (&anglePtr->atom(0) == endPtr) {
236  pvtPtr2 = &anglePtr->atom(2);
237  } else {
238  pvtPtr2 = &anglePtr->atom(0);
239  }
240  angleTypeId = anglePtr->typeId();
241  }
242  }
243 
244  // Get the angle spanned.
245  rsq1 = boundary().distanceSq(pvtPtr->position(),
246  pvtPtr2->position(), dr1);
247  rsq2 = boundary().distanceSq(endPtr->position(),
248  pvtPtr->position(), dr2);
249  cosTheta = dr1.dot(dr2) / sqrt(rsq1 * rsq2);
250 
251  trialEnergy[iTrial] += system().anglePotential().
252  energy(cosTheta, angleTypeId);
253  }
254  #endif
255 
256  #ifdef SIMP_EXTERNAL
257  if (system().hasExternalPotential()) {
258  trialEnergy[iTrial] +=
259  system().externalPotential().atomEnergy(*endPtr);
260  }
261  #endif
262 
263  trialProb[iTrial] = boltzmann(trialEnergy[iTrial]);
264  rosenbluth += trialProb[iTrial];
265  }
266 
267  // Normalize trial probabilities
268  for (iTrial = 0; iTrial < nTrial_; ++iTrial) {
269  trialProb[iTrial] = trialProb[iTrial]/rosenbluth;
270  }
271 
272  // Choose trial position
273  iTrial = random().drawFrom(trialProb, nTrial_);
274 
275  // Calculate total energy for chosen trial.
276  energy = system().bondPotential().energy(length*length, bondType);
277  energy += trialEnergy[iTrial];
278 
279  // Set position of new end atom to chosen value
280  endPtr->position() = trialPos[iTrial];
281 
282  }
283 
284 }
static const int MaxTrial_
Maximum allowed number of trial positions for a regrown atom.
Definition: CfbEndBase.h:111
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
virtual double atomEnergy(const Atom &atom) const =0
Calculate the external energy for one Atom.
void addEndAtom(Atom *endPtr, Atom *pvtPtr, int bondType, double &rosenbluth, double &energy)
Configuration bias algorithm for adding an atom to a chain end.
Definition: CfbEndBase.cpp:189
Vector & add(const Vector &v1, const Vector &v2)
Add vectors v1 and v2.
Definition: Vector.h:657
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
int typeId() const
Get the typeId for this covalent group.
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
double boltzmann(double energy)
Boltzmann weight associated with an energy difference.
Definition: SystemMove.h:100
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
double beta() const
Return the inverse temperature.
void getAtomAngles(const Atom &atom, AtomAngleArray &groups)
Fill an array of pointers to Angles that contain an Atom.
#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
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.
Random & random()
Get Random number generator of parent Simulation.
Definition: McMove.h:209
Atom & atom(int i)
Get a specific Atom in the Group by reference.
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.
void deleteEndAtom(Atom *endPtr, Atom *pvtPtr, int bondType, double &rosenbluth, double &energy)
CFB algorithm for deleting an end atom from a flexible chain.
Definition: CfbEndBase.cpp:62
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
CfbEndBase(McSystem &system)
Constructor.
Definition: CfbEndBase.cpp:29
virtual ~CfbEndBase()
Destructor.
Definition: CfbEndBase.cpp:44
A sequence of NAtom covalently interacting atoms.
int nTrial_
Actual number of trial positions for each regrown atom.
Definition: CfbEndBase.h:114
virtual void readParameters(std::istream &in)
Read parameter nTrial.
Definition: CfbEndBase.cpp:50
AnglePotential & anglePotential() const
Return AnglePotential by reference.
Definition: McSystem.h:422
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.
int size() const
Return logical size of this array (i.e., number of elements).
Definition: FSArray.h:207
EnergyEnsemble & energyEnsemble()
Get EnergyEnsemble object of parent McSystem.
Definition: SystemMove.h:94
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