Simpatico  v1.10
CfbReptationMove.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 "CfbReptationMove.h"
9 #include <mcMd/mcSimulation/McSystem.h>
11 #include <mcMd/simulation/Simulation.h>
12 #include <mcMd/chemistry/Molecule.h>
13 #include <mcMd/chemistry/Atom.h>
14 #include <mcMd/chemistry/Bond.h>
15 
16 #include <simp/species/Linear.h>
17 #include <simp/boundary/Boundary.h>
18 
19 #include <util/space/Vector.h>
20 #include <util/global.h>
21 
22 namespace McMd
23 {
24 
25  using namespace Util;
26  using namespace Simp;
27 
28  /*
29  * Constructor
30  */
32  CfbEndBase(system),
33  speciesId_(-1),
34  bondTypeId_(-1),
35  nJunction_(0),
36  junctions_(),
37  lTypes_(),
38  uTypes_(),
39  maskPolicy_(MaskBonded),
40  hasAutoCorr_(0),
41  autoCorrCapacity_(0),
42  outputFileName_(),
43  acceptedStepsAccumulators_()
44  { setClassName("CfbReptationMove"); }
45 
46  /*
47  * Read parameters speciesId, nRegrow, and nTrial
48  * also read hasAutoCorr, which may be either 0 or 1
49  * if 1, also read autoCorrCapacity and autoCorrName
50  */
51  void CfbReptationMove::readParameters(std::istream& in)
52  {
53  // Read parameters
54  readProbability(in);
55  read<int>(in, "speciesId", speciesId_);
56  read<int>(in, "nTrial", nTrial_);
57 
58  // Check that 0 < nTrial_ <= MaxTrial
59  if (nTrial_ <=0 || nTrial_ > MaxTrial_) {
60  UTIL_THROW("Invalid value input for nTrial");
61  }
62 
63  // Check that the Species is a subclass of Linear
64  Linear* speciesPtr;
65  speciesPtr = dynamic_cast<Linear*>(&(simulation().species(speciesId_)));
66  if (!speciesPtr) {
67  UTIL_THROW("Species is not a subclass of Linear");
68  }
69 
70  // Identify bond type
71  bondTypeId_ = speciesPtr->speciesBond(0).typeId();
72 
73  // Check that bond type is the same for all bonds
74  int nBond = speciesPtr->nBond();
75  for (int i = 1; i < nBond; ++i) {
76  if (bondTypeId_ != speciesPtr->speciesBond(i).typeId()) {
77  UTIL_THROW("Unequal bond type ids");
78  }
79  }
80 
81  #ifndef SIMP_NOPAIR
82  // Identify policy for masking nonbonded interactions.
83  maskPolicy_ = simulation().maskedPairPolicy();
84  #endif
85 
86  // Allocate memory for junction arrays
87  int nAtom = speciesPtr->nAtom();
88  junctions_.allocate(nAtom-1);
89  lTypes_.allocate(nAtom-1);
90  uTypes_.allocate(nAtom-1);
91 
92  // Identify junctions between atoms of different types
93  int lType, uType;
94  nJunction_ = 0;
95  for (int i = 0; i < nAtom - 1; ++i) {
96  lType = speciesPtr->atomTypeId(i);
97  uType = speciesPtr->atomTypeId(i+1);
98  if (lType != uType) {
99  junctions_[nJunction_] = i;
100  lTypes_[nJunction_] = lType;
101  uTypes_[nJunction_] = uType;
102  //std::cout << nJunction_ << " " << i << " "
103  // << lType << " " << uType << std::endl;
104  ++nJunction_;
105  }
106  }
107 
108  read<int>(in, "hasAutoCorr", hasAutoCorr_);
109 
110  // Read autocorrelation parameters
111  if (hasAutoCorr_) {
112  read<int>(in, "autoCorrCapacity", autoCorrCapacity_);
113  read<std::string>(in, "autoCorrName", outputFileName_);
114 
115  // Allocate memory for autocorrelation function of reptation steps
116  int moleculeCapacity = simulation().species(speciesId_).capacity();
117  acceptedStepsAccumulators_.allocate(moleculeCapacity);
118  for (int i = 0; i < moleculeCapacity; i++)
119  {
120  acceptedStepsAccumulators_[i].setParam(autoCorrCapacity_);
121  }
122  }
123 
124  }
125 
126  /*
127  * Load from archive.
128  */
130  {
131  // Read parameters
133  loadParameter<int>(ar, "speciesId", speciesId_);
134  loadParameter<int>(ar, "nTrial", nTrial_);
135  ar & bondTypeId_;
136  ar & maskPolicy_;
137 
138  // Validate
139  if (nTrial_ <=0 || nTrial_ > MaxTrial_) {
140  UTIL_THROW("Invalid value input for nTrial");
141  }
142  Linear* speciesPtr;
143  speciesPtr = dynamic_cast<Linear*>(&(simulation().species(speciesId_)));
144  if (!speciesPtr) {
145  UTIL_THROW("Species is not a subclass of Linear");
146  }
147  int nBond = speciesPtr->nBond();
148  for (int i = 0; i < nBond; ++i) {
149  if (bondTypeId_ != speciesPtr->speciesBond(i).typeId()) {
150  UTIL_THROW("Inconsistent or unequal bond type ids");
151  }
152  }
153  #ifndef SIMP_NOPAIR
154  if (maskPolicy_ != simulation().maskedPairPolicy()) {
155  UTIL_THROW("Inconsistent values of maskPolicy_");
156  }
157  #endif
158 
159  ar & junctions_;
160  ar & lTypes_;
161  ar & uTypes_;
162 
163  // Read autocorrelation parameters
164  loadParameter<int>(ar, "hasAutoCorr", hasAutoCorr_);
165  if (hasAutoCorr_) {
166  loadParameter<int>(ar, "autoCorrCapacity", autoCorrCapacity_);
167  loadParameter<std::string>(ar, "autoCorrName", outputFileName_);
168  ar & acceptedStepsAccumulators_;
169  }
170 
171  }
172 
173  /*
174  * Load from archive.
175  */
177  {
178  McMove::save(ar);
179  ar & speciesId_;
180  ar & nTrial_;
181  ar & bondTypeId_;
182  ar & maskPolicy_;
183  ar & junctions_;
184  ar & lTypes_;
185  ar & uTypes_;
186  ar & hasAutoCorr_;
187  if (hasAutoCorr_) {
188  ar & autoCorrCapacity_;
189  ar & outputFileName_;
190  ar & acceptedStepsAccumulators_;
191  }
192  }
193 
194  /*
195  * Generate, attempt and accept or reject a Monte Carlo move.
196  */
198  {
199  Vector oldPos, newPos;
200  double rosen_r, rosen_f, ratio;
201  double energy_r, energy_f;
202  Atom *tailPtr; // pointer to the tail atom (to be removed)
203  Atom *atomPtr; // resetable atom pointer
204  Molecule *molPtr; // pointer to randomly chosen molecule
205  int length, sign, headId, tailId, oldType, i;
206  bool accept;
207 
209 
210  // Choose a molecule at random
211  molPtr = &(system().randomMolecule(speciesId_));
212  length = molPtr->nAtom();
213 
214  // Choose which chain end to regrow
215  if (random().uniform(0.0, 1.0) > 0.5) {
216  sign = +1;
217  headId = length - 1;
218  tailId = 0;
219  } else {
220  sign = -1;
221  headId = 0;
222  tailId = length - 1;
223  }
224 
225  // Store current position and type of tail atom
226  tailPtr = &(molPtr->atom(tailId));
227  oldPos = tailPtr->position();
228  oldType = tailPtr->typeId();
229 
230  // Delete tail atom
231  atomPtr = tailPtr + sign;
232  deleteEndAtom(tailPtr, atomPtr, bondTypeId_, rosen_r, energy_r);
233  #ifndef SIMP_NOPAIR
234  // Delete from McSystem cell list
235  system().pairPotential().deleteAtom(*tailPtr);
236  #endif
237 
238  // Regrow head, using tailPtr to store properties of the new head.
239  atomPtr = &(molPtr->atom(headId));
240  tailPtr->setTypeId(atomPtr->typeId());
241  tailPtr->mask().clear();
242  if (maskPolicy_ == MaskBonded) {
243  tailPtr->mask().append(*atomPtr);
244  }
245  addEndAtom(tailPtr, atomPtr, bondTypeId_, rosen_f, energy_f);
246 
247  // Calculate junction factor for heteropolymers.
248  double jFactor = 1.0;
249  if (nJunction_ > 0) {
250  jFactor = junctionFactor(molPtr, sign);
251  // Upon return, type ids are restored to original values.
252  }
253 
254  // Decide whether to accept or reject
255  ratio = jFactor * rosen_f / rosen_r;
256  accept = random().metropolis(ratio);
257 
258  // Restore original type and connectivity mask for tail Atom
259  tailPtr->setTypeId(oldType);
260  tailPtr->mask().clear();
261  if (maskPolicy_ == MaskBonded) {
262  atomPtr = tailPtr + sign;
263  tailPtr->mask().append(*atomPtr);
264  }
265 
266  if (accept) {
267 
268  // Store new head position
269  newPos = tailPtr->position();
270 
271  // Shift position of tail
272  atomPtr = tailPtr + sign;
273  tailPtr->position() = atomPtr->position();
274 
275  #ifndef SIMP_NOPAIR
276  // Add tail back to system cell list
277  system().pairPotential().addAtom(*tailPtr);
278  #endif
279 
280  // Shift atom positions towards the head
281  for (i=1; i < length - 1; ++i) {
282  //system().moveAtom(*atomPtr, (atomPtr+sign)->position());
283  atomPtr->position() = (atomPtr+sign)->position();
284  #ifndef SIMP_NOPAIR
285  system().pairPotential().updateAtomCell(*atomPtr);
286  #endif
287  atomPtr += sign;
288  }
289 
290  // Move head atom to new chosen position
291  // system().moveAtom(*atomPtr, newPos);
292  atomPtr->position() = newPos;
293  #ifndef SIMP_NOPAIR
294  system().pairPotential().updateAtomCell(*atomPtr);
295  #endif
296 
297  // Increment the number of accepted moves.
299 
300  if (hasAutoCorr_)
301  {
302  // Store step direction in autocorrelator
303  acceptedStepsAccumulators_[molPtr->id()].sample((double) sign);
304  }
305  } else {
306 
307  // Restore old position of tail
308  tailPtr->position() = oldPos;
309 
310  #ifndef SIMP_NOPAIR
311  // Add tail back to System cell list.
312  system().pairPotential().addAtom(*tailPtr);
313  #endif
314 
315  }
316 
317  return accept;
318 
319  }
320 
324  double CfbReptationMove::junctionFactor(Molecule* molPtr, int sign)
325  {
326 
327  double oldEnergy, newEnergy, factor;
328  Atom* hAtomPtr; // Pointer to atom nearer head
329  int hType; // type id of atom nearer head
330  int tType; // type id of atom nearer tail
331  int i; // junction index
332  int j; // id of atom at below junction (lower)
333 
334 
335  // Calculate factor by looping over junctions
336  factor = 1.0;
337  for (i = 0; i < nJunction_; ++i) {
338  j = junctions_[i];
339  if (sign == 1) {
340  hAtomPtr = &(molPtr->atom(j+1));
341  tType = lTypes_[i];
342  } else {
343  hAtomPtr = &(molPtr->atom(j));
344  tType = uTypes_[i];
345  }
346 
347  #ifndef SIMP_NOPAIR
348  oldEnergy = system().pairPotential().atomEnergy(*hAtomPtr);
349  #endif
350 
351  #ifdef SIMP_EXTERNAL
352  if (system().hasExternalPotential()) {
353  oldEnergy += system().externalPotential().atomEnergy(*hAtomPtr);
354  }
355  #endif
356 
357  #ifndef SIMP_NOPAIR
358  hAtomPtr->setTypeId(tType);
359  newEnergy = system().pairPotential().atomEnergy(*hAtomPtr);
360  #endif
361 
362  #ifdef SIMP_EXTERNAL
363  if (system().hasExternalPotential()) {
364  newEnergy += system().externalPotential().atomEnergy(*hAtomPtr);
365  }
366  #endif
367 
368  #ifndef SIMP_NOPAIR
369  factor *= boltzmann(newEnergy - oldEnergy);
370  #endif
371  }
372 
373  // Revert modified atom type Ids to original values
374  #ifndef SIMP_NOPAIR
375  for (i = 0; i < nJunction_; ++i) {
376  j = junctions_[i];
377  if (sign == 1) {
378  hAtomPtr = &(molPtr->atom(j+1));
379  hType = uTypes_[i];
380  } else {
381  hAtomPtr = &(molPtr->atom(j));
382  hType = lTypes_[i];
383  }
384  hAtomPtr->setTypeId(hType);
385  }
386  return factor;
387 
388  #else //ifdef SIMP_NOPAIR
389  return 1.0;
390  #endif
391  }
392 
397  {
398  if (hasAutoCorr_)
399  {
400  DArray< double > autoCorrAvg;
401  autoCorrAvg.allocate(autoCorrCapacity_);
402 
403  // Calculate average autocorrelation function over all
404  // accumulators
405  for (int i = 0; i < autoCorrCapacity_; i++) {
406  int nAvg = 0;
407  autoCorrAvg[i] = 0;
408  for (int j = 0; j < system().nMolecule(speciesId_); j++)
409  {
410  if (acceptedStepsAccumulators_[j].nSample() > i)
411  {
412  nAvg++;
413  autoCorrAvg[i] += acceptedStepsAccumulators_[j].
414  autoCorrelation(i);
415  }
416  }
417  autoCorrAvg[i] /= nAvg;
418  }
419 
420  std::ofstream outputFile;
421 
422  // Write out average autocorrelation
423  system().fileMaster().openOutputFile(outputFileName_+".dat",
424  outputFile);
425 
426  for (int i = 0; i < autoCorrCapacity_; i++)
427  {
428  outputFile << Int(i);
429  write<double>(outputFile, autoCorrAvg[i]);
430  outputFile << std::endl;
431  }
432 
433  outputFile.close();
434 
435  // Sum over autocorrelation (only positive time lags)
436  // Count first element with a factor 1/2, due to symmetry
437  double acSum = 0;
438  acSum = 0.5*autoCorrAvg[0];
439  for (int i = 1; i < autoCorrCapacity_; i++)
440  acSum += autoCorrAvg[i];
441 
442  // write sum in .ave file
443  system().fileMaster().openOutputFile(outputFileName_+".ave",
444  outputFile);
445  outputFile << "autoCorrSum " << acSum << std::endl;
446  outputFile.close();
447  }
448  }
449 
450 }
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
FileMaster & fileMaster() const
Get the associated FileMaster by reference.
Definition: System.h:1113
void incrementNAttempt()
Increment the number of attempted moves.
Definition: McMove.h:191
int nAtom() const
Get number of atoms per molecule for this Species.
Include this file to include all MC potential energy classes at once.
virtual void output()
Output statistics about accepted reptation steps.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Definition: McMove.cpp:58
void addAtom(Atom &atom)
Add an Atom to the CellList.
void openOutputFile(const std::string &filename, std::ofstream &out, std::ios_base::openmode mode=std::ios_base::out) const
Open an output file.
Definition: FileMaster.cpp:290
Mask & mask()
Get the associated Mask by reference.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
Definition: McMove.cpp:48
MaskPolicy maskedPairPolicy() const
Return the value of the mask policy (MaskNone or MaskBonded).
virtual void readParameters(std::istream &in)
Read species to which displacement is applied.
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
int id() const
Get the index for this Molecule (unique in species).
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Saving / output archive for binary ostream.
double boltzmann(double energy)
Boltzmann weight associated with an energy difference.
Definition: SystemMove.h:100
const SpeciesBond & speciesBond(int iBond) const
Get a specific SpeciesBond object, by local bond index.
int nMolecule(int speciesId) const
Get the number of molecules of one Species in this System.
Definition: System.h:1128
#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
Molecule & randomMolecule(int speciesId)
Get a random Molecule of a specified species in this System.
Definition: System.cpp:1200
void incrementNAccept()
Increment the number of accepted moves.
Definition: McMove.h:197
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.
void clear()
Clear the mask set (remove all atoms).
Utility classes for scientific computation.
Definition: accumulators.mod:1
CfbReptationMove(McSystem &system)
Constructor.
int typeId() const
Get the type id for this covalent group.
Definition: SpeciesGroup.h:189
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
int atomTypeId(int iAtom) const
Get atom type index for a specific atom, by local atom index.
virtual bool move()
Generate and accept or reject configuration bias move.
Random & random()
Get Random number generator of parent Simulation.
Definition: McMove.h:209
McPairPotential & pairPotential() const
Return the McPairPotential by reference.
Definition: McSystem.h:388
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
void setTypeId(int typeId)
Set the atomic type index.
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
void readProbability(std::istream &in)
Read the probability from file.
Definition: McMove.cpp:42
void setClassName(const char *className)
Set class name string.
const Atom & atom(int localId) const
Get a specific Atom in this Molecule.
int capacity() const
Maximum allowed number of molecules for this Species.
int nTrial_
Actual number of trial positions for each regrown atom.
Definition: CfbEndBase.h:114
bool metropolis(double ratio)
Metropolis algorithm for whether to accept a MC move.
Definition: Random.h:260
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
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.
Base class for configuration bias (CFB) end regrowth moves.
Definition: CfbEndBase.h:31
int nBond() const
Get number of bonds per molecule for this Species.
Species & species(int i)
Get a specific Species by reference.
void deleteAtom(Atom &atom)
Remove an Atom from the CellList.
void updateAtomCell(Atom &atom)
Update the cell list to reflect a new position.
A Species of linear polymers (abstract).
Definition: Linear.h:36
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 append(const Atom &atom)
Add an Atom to the masked set.