Simpatico  v1.10
CfbReptateMove.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 "CfbReptateMove.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 
18 #include <simp/boundary/Boundary.h>
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  CfbLinear(system),
33  bondTypeId_(-1),
34  nJunction_(0),
35  junctions_(),
36  lTypes_(),
37  uTypes_(),
38  maskPolicy_(MaskBonded),
39  hasAutoCorr_(false),
40  autoCorrCapacity_(0),
41  outputFileName_(),
42  accumulators_()
43  { setClassName("CfbReptateMove"); }
44 
45  /*
46  * Read parameters and initialize.
47  */
48  void CfbReptateMove::readParameters(std::istream& in)
49  {
50  // Read parameters
51  readProbability(in);
52  CfbLinear::readParameters(in); // read speciesId_ and nTrial_
53 
54  hasAutoCorr_ = false; // default value
55  readOptional<bool>(in, "hasAutoCorr", hasAutoCorr_);
56  if (hasAutoCorr_) {
57  read<int>(in, "autoCorrCapacity", autoCorrCapacity_);
58  read<std::string>(in, "outputFileName", outputFileName_);
59  }
60 
61  // Identify bond type, check that it is same for all bonds
62  Species* speciesPtr = &simulation().species(speciesId());
63  int nBond = speciesPtr->nBond();
64  bondTypeId_ = speciesPtr->speciesBond(0).typeId();
65  for (int i = 1; i < nBond; ++i) {
66  if (bondTypeId_ != speciesPtr->speciesBond(i).typeId()) {
67  UTIL_THROW("Unequal bond type ids");
68  }
69  }
70 
71  #ifndef SIMP_NOPAIR
72  // Identify policy for masking nonbonded interactions.
73  maskPolicy_ = simulation().maskedPairPolicy();
74  #endif
75 
76  // Allocate memory for junction arrays
77  int nAtom = speciesPtr->nAtom();
78  junctions_.allocate(nAtom-1);
79  lTypes_.allocate(nAtom-1);
80  uTypes_.allocate(nAtom-1);
81 
82  // Identify junctions between atoms of different types
83  int lType, uType;
84  nJunction_ = 0;
85  for (int i = 0; i < nAtom - 1; ++i) {
86  lType = speciesPtr->atomTypeId(i);
87  uType = speciesPtr->atomTypeId(i+1);
88  if (lType != uType) {
89  junctions_[nJunction_] = i;
90  lTypes_[nJunction_] = lType;
91  uTypes_[nJunction_] = uType;
92  ++nJunction_;
93  }
94  }
95 
96  if (hasAutoCorr_) {
97  // Allocate memory for autocorrelation accumulators
98  int moleculeCapacity = simulation().species(speciesId()).capacity();
99  accumulators_.allocate(moleculeCapacity);
100  for (int i = 0; i < moleculeCapacity; i++) {
101  accumulators_[i].setParam(autoCorrCapacity_);
102  }
103  }
104 
105  }
106 
107  /*
108  * Load from archive.
109  */
111  {
112  // Read parameters
115 
116  // Read autocorrelation parameters
117  loadParameter<bool>(ar, "hasAutoCorr", hasAutoCorr_);
118  if (hasAutoCorr_) {
119  loadParameter<int>(ar, "autoCorrCapacity", autoCorrCapacity_);
120  loadParameter<std::string>(ar, "outputFileName", outputFileName_);
121  ar & accumulators_;
122  }
123  ar & bondTypeId_;
124  ar & maskPolicy_;
125  ar & nJunction_;
126  ar & junctions_;
127  ar & lTypes_;
128  ar & uTypes_;
129 
130  // Validate
131  Species* speciesPtr = &simulation().species(speciesId());
132  int nBond = speciesPtr->nBond();
133  for (int i = 0; i < nBond; ++i) {
134  if (bondTypeId_ != speciesPtr->speciesBond(i).typeId()) {
135  UTIL_THROW("Inconsistent or unequal bond type ids");
136  }
137  }
138  #ifndef SIMP_NOPAIR
139  if (maskPolicy_ != simulation().maskedPairPolicy()) {
140  UTIL_THROW("Inconsistent values of maskPolicy_");
141  }
142  #endif
143  }
144 
145  /*
146  * Save to archive.
147  */
149  {
150  McMove::save(ar);
151  CfbLinear::save(ar);
152  ar & hasAutoCorr_;
153  if (hasAutoCorr_) {
154  ar & autoCorrCapacity_;
155  ar & outputFileName_;
156  ar & accumulators_;
157  }
158  ar & bondTypeId_;
159  ar & maskPolicy_;
160  ar & nJunction_;
161  ar & junctions_;
162  ar & lTypes_;
163  ar & uTypes_;
164  }
165 
166  /*
167  * Generate, attempt and accept or reject a Monte Carlo move.
168  */
170  {
171  Vector oldPos, newPos;
172  double rosen_r, rosen_f, ratio;
173  double energy_r, energy_f;
174  Atom *tailPtr; // pointer to the tail atom (to be removed)
175  Atom *atomPtr; // resetable atom pointer
176  Molecule *molPtr; // pointer to chosen molecule
177  int nAtom, sign, headId, tailId, oldType, i;
178  bool accept;
179 
181 
182  // Choose a molecule of specific species at random
183  molPtr = &(system().randomMolecule(speciesId()));
184  nAtom = molPtr->nAtom();
185 
186  // Choose which chain end to regrow.
187  // "tail" = deletion end, "head" = addition end
188  if (random().uniform(0.0, 1.0) > 0.5) {
189  sign = +1;
190  headId = nAtom - 1;
191  tailId = 0;
192  } else {
193  sign = -1;
194  headId = 0;
195  tailId = nAtom - 1;
196  }
197 
198  // Store current position and type of tail atom
199  tailPtr = &(molPtr->atom(tailId));
200  oldPos = tailPtr->position();
201  oldType = tailPtr->typeId();
202 
203  // Delete tail atom
204  deleteAtom(*molPtr, tailId, -sign, rosen_r, energy_r);
205  #ifndef SIMP_NOPAIR
206  // Delete from McSystem cell list
207  system().pairPotential().deleteAtom(*tailPtr);
208  #endif
209 
210  // Regrow head, using tailPtr to store properties of the new head.
211  atomPtr = &(molPtr->atom(headId)); // new pivot atom
212  tailPtr->setTypeId(atomPtr->typeId()); // new head atom
213  tailPtr->mask().clear();
214  if (maskPolicy_ == MaskBonded) {
215  tailPtr->mask().append(*atomPtr);
216  }
217  addAtom(*molPtr, *tailPtr, *atomPtr, headId, sign, rosen_f, energy_f);
218 
219  // Calculate junction factor for heteropolymers.
220  double jFactor;
221  if (nJunction_ > 0) {
222  jFactor = junctionFactor(molPtr, sign);
223  // Upon return, type ids are restored to original values.
224  } else {
225  jFactor = 1.0;
226  }
227 
228  // Decide whether to accept or reject
229  ratio = jFactor * rosen_f / rosen_r;
230  accept = random().metropolis(ratio);
231 
232  // Restore original type and connectivity mask for tail Atom
233  tailPtr->setTypeId(oldType);
234  tailPtr->mask().clear();
235  if (maskPolicy_ == MaskBonded) {
236  atomPtr = tailPtr + sign;
237  tailPtr->mask().append(*atomPtr);
238  }
239 
240  if (accept) {
241 
242  // Store position of new head atom
243  newPos = tailPtr->position();
244 
245  // Shift position of tail
246  atomPtr = tailPtr + sign;
247  tailPtr->position() = atomPtr->position();
248  #ifndef SIMP_NOPAIR
249  // Add tail back to system cell list
250  system().pairPotential().addAtom(*tailPtr);
251  #endif
252 
253  // Shift atom positions towards the head
254  for (i = 1; i < nAtom - 1; ++i) {
255  atomPtr->position() = (atomPtr+sign)->position();
256  #ifndef SIMP_NOPAIR
257  system().pairPotential().updateAtomCell(*atomPtr);
258  #endif
259  atomPtr += sign;
260  }
261  assert(atomPtr == &molPtr->atom(headId));
262 
263  // Move head atom to new chosen position
264  atomPtr->position() = newPos;
265  #ifndef SIMP_NOPAIR
266  system().pairPotential().updateAtomCell(*atomPtr);
267  #endif
268 
269  // Increment the number of accepted moves.
271 
272  if (hasAutoCorr_) {
273  int molId = molPtr->id();
274  double rsign = (double) sign;
275  accumulators_[molId].sample(rsign);
276  //accumulators_[molPtr->id()].sample((double) sign);
277  }
278 
279  } else {
280 
281  // Restore old position of tail
282  tailPtr->position() = oldPos;
283  #ifndef SIMP_NOPAIR
284  // Add tail back to System cell list.
285  system().pairPotential().addAtom(*tailPtr);
286  #endif
287 
288  }
289 
290  return accept;
291  }
292 
296  double CfbReptateMove::junctionFactor(Molecule* molPtr, int sign)
297  {
298  double oldEnergy, newEnergy, factor;
299  Atom* hAtomPtr; // Pointer to atom nearer head
300  int hType; // type id of atom nearer head
301  int tType; // type id of atom nearer tail
302  int i; // junction index
303  int j; // id of atom at below junction (lower)
304 
305  // Calculate factor by looping over junctions
306  factor = 1.0;
307  for (i = 0; i < nJunction_; ++i) {
308  j = junctions_[i];
309  if (sign == 1) {
310  hAtomPtr = &(molPtr->atom(j+1));
311  tType = lTypes_[i];
312  } else {
313  hAtomPtr = &(molPtr->atom(j));
314  tType = uTypes_[i];
315  }
316 
317  #ifndef SIMP_NOPAIR
318  oldEnergy = system().pairPotential().atomEnergy(*hAtomPtr);
319  #else
320  oldEnergy = 0.0;
321  #endif
322  #ifdef SIMP_EXTERNAL
323  if (system().hasExternalPotential()) {
324  oldEnergy += system().externalPotential().atomEnergy(*hAtomPtr);
325  }
326  #endif
327 
328  #ifndef SIMP_NOPAIR
329  hAtomPtr->setTypeId(tType);
330  newEnergy = system().pairPotential().atomEnergy(*hAtomPtr);
331  #else
332  newEnergy = 0.0;
333  #endif
334  #ifdef SIMP_EXTERNAL
335  if (system().hasExternalPotential()) {
336  newEnergy += system().externalPotential().atomEnergy(*hAtomPtr);
337  }
338  #endif
339 
340  factor *= boltzmann(newEnergy - oldEnergy);
341  }
342 
343  // Revert modified atom type Ids to original values
344  #ifndef SIMP_NOPAIR
345  for (i = 0; i < nJunction_; ++i) {
346  j = junctions_[i];
347  if (sign == 1) {
348  hAtomPtr = &(molPtr->atom(j+1));
349  hType = uTypes_[i];
350  } else {
351  hAtomPtr = &(molPtr->atom(j));
352  hType = lTypes_[i];
353  }
354  hAtomPtr->setTypeId(hType);
355  }
356  return factor;
357 
358  #else //ifdef SIMP_NOPAIR
359  return 1.0;
360  #endif
361  }
362 
367  {
368  if (hasAutoCorr_) {
369  DArray< double > autoCorrAvg;
370  autoCorrAvg.allocate(autoCorrCapacity_);
371 
372  // Compute average autocorrelation function over molecules
373  for (int i = 0; i < autoCorrCapacity_; i++) {
374  int nAvg = 0;
375  autoCorrAvg[i] = 0;
376  for (int j = 0; j < system().nMolecule(speciesId()); j++) {
377  if (accumulators_[j].nSample() > i) {
378  nAvg++;
379  autoCorrAvg[i] += accumulators_[j].autoCorrelation(i);
380  }
381  }
382  autoCorrAvg[i] /= nAvg;
383  }
384 
385  // Write out average autocorrelation
386  std::ofstream outputFile;
387  std::string fileName = outputFileName_;
388  fileName += ".dat";
389  system().fileMaster().openOutputFile(fileName, outputFile);
390  for (int i = 0; i < autoCorrCapacity_; i++) {
391  outputFile << Int(i);
392  write<double>(outputFile, autoCorrAvg[i]);
393  outputFile << std::endl;
394  }
395  outputFile.close();
396 
397  // Sum over autocorrelation (only positive time lags)
398  // Count first element with a factor 1/2, due to symmetry
399  double acSum = 0;
400  acSum = 0.5*autoCorrAvg[0];
401  for (int i = 1; i < autoCorrCapacity_; i++) {
402  acSum += autoCorrAvg[i];
403  }
404 
405  // Write sum in .ave file
406  fileName = outputFileName_;
407  fileName += ".ave";
408  system().fileMaster().openOutputFile(fileName, outputFile);
409  outputFile << "autoCorrSum " << acSum << std::endl;
410  outputFile.close();
411  }
412  }
413 
414 }
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.
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
Include this file to include all MC potential energy classes at once.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
Definition: McMove.cpp:58
CfbReptateMove(McSystem &system)
Constructor.
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 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.
int id() const
Get the index for this Molecule (unique in species).
virtual void readParameters(std::istream &in)
Read and validate speciesId and nTrial.
Definition: CfbLinear.cpp:92
Base class for configuration bias (CFB) end regrowth moves.
Definition: CfbLinear.h:39
virtual void output()
Output statistics about accepted reptation steps.
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
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 speciesId() const
Get speciesId.
Definition: CfbLinear.h:187
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
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
void setTypeId(int typeId)
Set the atomic type index.
Saving archive for binary istream.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
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.
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.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
A Species represents a set of chemically similar molecules.
int nBond() const
Get number of bonds per molecule for this Species.
Species & species(int i)
Get a specific Species by reference.
virtual bool move()
Generate and accept or reject configuration bias move.
void deleteAtom(Atom &atom)
Remove an Atom from the CellList.
void updateAtomCell(Atom &atom)
Update the cell list to reflect a new position.
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.
virtual void readParameters(std::istream &in)
Read species to which displacement is applied.