Simpatico  v1.10
CfbRebridgeBase.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 "CfbRebridgeBase.h"
9 #include <mcMd/mcSimulation/McSystem.h>
11 #include <mcMd/chemistry/Atom.h>
12 #include <mcMd/chemistry/Bond.h>
13 #include <util/global.h>
14 
15 namespace McMd
16 {
17 
18  using namespace Util;
19 
20  /*
21  * Constructor.
22  */
24  CfbEndBase(system),
25  length21_(1.0),
26  length10_(1.0),
27  kappa10_(0.0)
28  {
29  // Preconditions
30  #ifdef MCMD_NOMASKBONDED
31  UTIL_THROW("CfbRebridgeBase is unusable ifdef MCMD_NOMASKBONDED");
32  #endif
33  #ifdef SIMP_DIHEDRAL
34  if (system.hasDihedralPotential()) {
35  UTIL_THROW("CfbRebrigeBase is unusable with dihedrals");
36  }
37  #endif
38  }
39  /*
40  * Destructor.
41  */
43  {}
44 
45  /*
46  * Read parameters from file.
47  */
48  void CfbRebridgeBase::readParameters(std::istream& in)
49  {
50  // Number of trial configuration bias attempts.
51  read<int>(in, "nTrial", nTrial_);
52  if (nTrial_ <=0 || nTrial_ > MaxTrial_) {
53  UTIL_THROW("Invalid value input for nTrial");
54  }
55 
56  // Parameters needed by orientation bias.
57  read<double>(in, "length21", length21_);
58  read<double>(in, "length10", length10_);
59  read<double>(in, "kappa10", kappa10_);
60  }
61 
62  /*
63  * Load state from archive.
64  */
66  {
67  loadParameter<int>(ar, "nTrial", nTrial_);
68  loadParameter<double>(ar, "length21", length21_);
69  loadParameter<double>(ar, "length10", length10_);
70  loadParameter<double>(ar, "kappa10", kappa10_);
71 
72  // Validate
73  if (nTrial_ <=0 || nTrial_ > MaxTrial_) {
74  UTIL_THROW("Invalid value input for nTrial");
75  }
76  }
77 
78  /*
79  * Save state to archive.
80  */
82  {
83  ar & nTrial_;
84  ar & length21_;
85  ar & length10_;
86  ar & kappa10_;
87  }
88 
89  /*
90  * Initialize tables for spring constants and normalizations.
91  */
93  {
94  double l20;
95  double lmin, lmax, del, pi;
96  int i;
97 
98  pi = acos(-1.0);
99 
100  // Range of l_20; 2.0 is empirical.
101  lmax = 2.0 * (length10_ + length21_);
102 
103  // Fill table elements for: l_20 <= lmin
104  if (length21_ == length10_) {
105  // 0.1 is empirical.
106  lmin = length10_ / length21_ / sqrt(kappa10_) * 0.1;
107  l20Table[0] = lmin;
108  angTable[0] = pi/2.0;
109  kappaTable[0] = 0.0;
110  normalTable[0] = 2.0;
111  } else {
112  // 0.5 is empirical.
113  lmin = fabs(length10_ - length21_) * 0.5;
114  l20Table[0] = lmin;
115  orientationBiasTable(lmin, angTable[0], kappaTable[0], normalTable[0]);
116  }
117 
118  // Fill table elements for: lmin < l_20 < lmax
119  del = (lmax - lmin) / double(MaxBin_-2);
120  l20 = lmin - del/2.0;
121  for (i=1; i<MaxBin_-1; i++) {
122  l20 += del;
123  l20Table[i] = l20;
124  orientationBiasTable(l20, angTable[i], kappaTable[i], normalTable[i]);
125  }
126 
127  // Fill table elements for: l_20 >= lmax
128  l20Table[MaxBin_-1] = lmax;
129  angTable[MaxBin_-1] = 0.0;
130  kappaTable[MaxBin_-1] = kappa10_ * length21_ * lmax;
131  computeNormalization(angTable[MaxBin_-1], kappaTable[MaxBin_-1],
132  normalTable[MaxBin_-1]);
133  }
134 
135  /*
136  * Configuration bias algorithm for deleting the last particle of an interior
137  * bridge.
138  *
139  * 1
140  * o-----o 0
141  * /
142  * o
143  * 2
144  * 2 = prev, 0 = next, 1 = crank-shaft rotating
145  *
146  * Note that in the current implementation, the end atom position will be
147  * modified, so the calling subroutine is responsible for recovering the old
148  * position if necessary. This is similar to the implementation of
149  * CfbEndBase::deleteEndAtom.
150  */
152  Atom* partPtr, Atom* prevPtr, Atom* nextPtr,
153  int prevBType, int nextBType,
154  double &rosenbluth, double &energy)
155  {
156  Vector prevPos = prevPtr->position();
157  Vector nextPos = nextPtr->position();
158  Vector partPos = partPtr->position();
159  Vector bondVec, trialPos, u_20, u_21;
160  double trialEnergy, bondEnergy, wExt, length, lengthSq;
161  double l_20, l_21, bias;
162  double prefAng, kappaAng, normConst;
163  int iTrial;
164  bool ready;
165 
166  // Bond length and bonding vector 2 --> 0
167  lengthSq = boundary().distanceSq(nextPos, prevPos, u_20);
168  l_20 = sqrt(lengthSq);
169  u_20 /= l_20;
170 
171  // Bond length and bonding vector 2 --> 1 & bonding energy
172  lengthSq = boundary().distanceSq(partPos, prevPos, u_21);
173  l_21 = sqrt(lengthSq);
174  u_21 /= l_21;
175  energy = system().bondPotential().energy(lengthSq, prevBType);
176 
177  // Bond length between 1 and 0 & bonding energy
178  lengthSq = boundary().distanceSq(partPos, nextPos);
179  bondEnergy = system().bondPotential().energy(lengthSq, nextBType);
180  energy += bondEnergy;
181 
182  // Nonbonded pair energy of current position
183  #ifndef SIMP_NOPAIR
184  trialEnergy = system().pairPotential().atomEnergy(*partPtr);
185  #else
186  trialEnergy = 0.0;
187  #endif
188 
189  #ifdef SIMP_ANGLE
190  if (system().hasAnglePotential()) {
191  trialEnergy += system().anglePotential().atomEnergy(*partPtr);
192  }
193  #endif
194 
195  #ifdef SIMP_EXTERNAL
196  if (system().hasExternalPotential()) {
197  trialEnergy += system().externalPotential().atomEnergy(*partPtr);
198  }
199  #endif
200 
201  energy += trialEnergy;
202 
203  // Compute orientation/Angle bias factor and the normalization factor.
204  getAngKappaNorm(l_20, prefAng, kappaAng, normConst);
205  orientationBias(u_21, u_20, prefAng, kappaAng, bias);
206 
207  // remove normalized orientation bias
208  rosenbluth = normConst / bias;
209 
210  // start to accumulate Rosenbluth factor
211  wExt = boltzmann(trialEnergy + bondEnergy);
212 
213  // Generate "nTrial-1" trial positions based on 1-0 bonding.
214  length = l_21;
215  for (iTrial=0; iTrial < nTrial_ - 1; iTrial++) {
216  ready = false;
217  while (!ready) {
218  random().unitVector(bondVec);
219  bondVec *= length;
220  trialPos.add(prevPos, bondVec);
221  boundary().shift(trialPos);
222 
223  lengthSq = boundary().distanceSq(trialPos, prevPos, u_21);
224  l_21 = sqrt(lengthSq);
225  u_21 /= l_21;
226  orientationBias(u_21, u_20, prefAng, kappaAng, bias);
227 
228  // Rejection method
229  if (bias > random().uniform(0.0, 1.0)) {
230  ready = true;
231  }
232  }
233 
234  // Bond 1-0 potential energy
235  lengthSq = boundary().distanceSq(trialPos, nextPos);
236  bondEnergy = system().bondPotential().energy(lengthSq, nextBType);
237  partPtr->position() = trialPos;
238  #ifndef SIMP_NOPAIR
239  trialEnergy = system().pairPotential().atomEnergy(*partPtr);
240  #else
241  trialEnergy = 0.0;
242  #endif
243 
244  #ifdef SIMP_ANGLE
245  if (system().hasAnglePotential()) {
246  trialEnergy += system().anglePotential().atomEnergy(*partPtr);
247  }
248  #endif
249 
250  #ifdef SIMP_EXTERNAL
251  if (system().hasExternalPotential()) {
252  trialEnergy += system().externalPotential().atomEnergy(*partPtr);
253  }
254  #endif
255 
256  wExt += boltzmann(trialEnergy + bondEnergy);
257  }
258 
259  // Update Rosenbluth weight (orientation bias has been removed earlier)
260  rosenbluth *= wExt;
261 
262  }
263 
264  /*
265  * Configuration bias algorithm for adding the last particle of an interior
266  * bridge.
267  */
269  Atom* partPtr, Atom* prevPtr, Atom* nextPtr,
270  int prevBType, int nextBType,
271  double &rosenbluth, double &energy)
272  {
273  Vector prevPos = prevPtr->position();
274  Vector nextPos = nextPtr->position();
275  Vector u_20, u_21, bondVec;
276  Vector trialPos[MaxTrial_];
277  double trialEnergy[MaxTrial_], bondEnergy[MaxTrial_];
278  double trialProb[MaxTrial_], bias[MaxTrial_];
279  double l_20, l_21;
280  double beta, length, lengthSq, wExt;
281  double prefAng, kappaAng, normConst;
282  int iTrial;
283  bool ready;
284 
285  // Bond 2 --> 0
286  lengthSq = boundary().distanceSq(nextPos, prevPos, u_20);
287  l_20 = sqrt(lengthSq);
288  u_20 /= l_20;
289 
290  // Bond 2-1 & bonding energy
291  beta = energyEnsemble().beta();
292  length = system().bondPotential().
293  randomBondLength(&random(), beta, prevBType);
294  l_21 = length;
295  energy = system().bondPotential().energy(l_21*l_21, prevBType);
296 
297  // Loop over trial orientations
298  wExt = 0.0;
299 
300  // Compute normalization factor for the orientation bias.
301  getAngKappaNorm(l_20, prefAng, kappaAng, normConst);
302 
303  // Generating trial orientations
304  for (iTrial=0; iTrial < nTrial_; iTrial++) {
305  ready = false;
306  while (!ready) {
307  random().unitVector(bondVec);
308  bondVec *= length;
309  trialPos[iTrial].add(prevPos, bondVec);
310  boundary().shift(trialPos[iTrial]);
311 
312  lengthSq = boundary().distanceSq(trialPos[iTrial], prevPos, u_21);
313  l_21 = sqrt(lengthSq);
314  u_21 /= l_21;
315  orientationBias(u_21, u_20, prefAng, kappaAng, bias[iTrial]);
316 
317  // Rejection method
318  if (bias[iTrial] > random().uniform(0.0, 1.0)) {
319  ready = true;
320  }
321  }
322 
323  // Bond 1-0 potential energy
324  lengthSq = boundary().distanceSq(trialPos[iTrial], nextPos);
325  bondEnergy[iTrial] =
326  system().bondPotential().energy(lengthSq, nextBType);
327  partPtr->position() = trialPos[iTrial];
328 
329  #ifndef SIMP_NOPAIR
330  trialEnergy[iTrial] = system().pairPotential().atomEnergy(*partPtr);
331  #else
332  trialEnergy[iTrial] = 0.0;
333  #endif
334 
335  #ifdef SIMP_ANGLE
336  if (system().hasAnglePotential()) {
337  trialEnergy[iTrial] +=
338  system().anglePotential().atomEnergy(*partPtr);
339  }
340  #endif
341 
342  #ifdef SIMP_EXTERNAL
343  if (system().hasExternalPotential()) {
344  trialEnergy[iTrial] +=
345  system().externalPotential().atomEnergy(*partPtr);
346  }
347  #endif
348 
349  trialProb[iTrial] =
350  boltzmann(trialEnergy[iTrial] + bondEnergy[iTrial]);
351  wExt += trialProb[iTrial];
352  }
353 
354  // Normalize trial probabilities
355  for (iTrial=0; iTrial < nTrial_; iTrial++) {
356  trialProb[iTrial] = trialProb[iTrial] / wExt;
357  }
358 
359  // Choose trial position
360  iTrial = random().drawFrom(trialProb, nTrial_);
361 
362  // Add non-bonded pair energy for chosen trial
363  energy += trialEnergy[iTrial];
364 
365  // Add 1-0 bond energy
366  energy += bondEnergy[iTrial];
367 
368  // Copy trial position to newPos
369  partPtr->position() = trialPos[iTrial];
370 
371  // update Rosenbluth weight and remove the orientation bias
372  rosenbluth = wExt * normConst / bias[iTrial];
373  }
374 
375 
376  /*
377  * Delete a consequtive sequence of atoms.
378  */
379  void CfbRebridgeBase::deleteSequence(int nActive, int sign, Atom* endPtr,
380  int *bonds, double &rosenbluth, double &energy)
381  {
382  Atom *thisPtr;
383  Atom *prevPtr;
384  Atom *nextPtr;
385  int prevBType, nextBType;
386  double rosen_r, energy_r;
387 
388  // Initialize weight
389  rosenbluth = 1.0;
390  energy = 0.0;
391 
392  thisPtr = endPtr;
393  prevPtr = thisPtr - sign;
394  nextPtr = thisPtr + sign;
395  // Step 1: delete the last atom
396  if (nActive >= 1) {
397  nextBType = bonds[0];
398  prevBType = bonds[1];
399 
400  // Orientation biased trimer rebridge move
401  deleteMiddleAtom(thisPtr, prevPtr, nextPtr,
402  prevBType, nextBType, rosen_r, energy_r);
403  #ifndef SIMP_NOPAIR
404  system().pairPotential().deleteAtom(*thisPtr);
405  #endif
406  rosenbluth *= rosen_r;
407  energy += energy_r;
408  }
409 
410  // step 2: delete the remaining atoms
411  for (int i = 0; i < nActive - 1; ++i) {
412  thisPtr -= sign;
413  prevPtr -= sign;
414 
415  prevBType = bonds[i+2];
416  deleteEndAtom(thisPtr, prevPtr, prevBType, rosen_r, energy_r);
417  #ifndef SIMP_NOPAIR
418  system().pairPotential().deleteAtom(*thisPtr);
419  #endif
420 
421  rosenbluth *= rosen_r;
422  energy += energy_r;
423  }
424 
425  }
426 
427  /*
428  * Add a consequtive sequence of atoms.
429  */
430  void CfbRebridgeBase::addSequence(int nActive, int sign, Atom* beginPtr,
431  int *bonds, double &rosenbluth, double &energy)
432  {
433  Atom *thisPtr;
434  Atom *prevPtr;
435  Atom *nextPtr;
436  int prevBType, nextBType;
437  double rosen_f, energy_f;
438 
439  // Initialize weight
440  rosenbluth = 1.0;
441  energy = 0.0;
442 
443  // Step 1: grow the first nActive - 1 atoms
444  thisPtr = beginPtr;
445  prevPtr = thisPtr - sign;
446 
447  for (int i = 0; i < nActive - 1; ++i) {
448  prevBType = bonds[nActive - i];
449  addEndAtom(thisPtr, prevPtr, prevBType, rosen_f, energy_f);
450  #ifndef SIMP_NOPAIR
451  system().pairPotential().addAtom(*thisPtr);
452  #endif
453 
454  rosenbluth *= rosen_f;
455  energy += energy_f;
456 
457  thisPtr += sign;
458  prevPtr += sign;
459  }
460 
461  // Step 2: grow the last atoms
462  if (nActive >= 1) {
463  prevPtr = thisPtr - sign;
464  nextPtr = thisPtr + sign;
465  prevBType = bonds[1];
466  nextBType = bonds[0];
467 
468  // Invoke the orientation biased trimer re-bridging move
469  addMiddleAtom(thisPtr, prevPtr, nextPtr,
470  prevBType, nextBType, rosen_f, energy_f);
471  #ifndef SIMP_NOPAIR
472  system().pairPotential().addAtom(*thisPtr);
473  #endif
474 
475  rosenbluth *= rosen_f;
476  energy += energy_f;
477  }
478 
479  }
480 
481  /*
482  * First determine the preferential orientation angle and angle biasing
483  * spring constant; then compute the statistical weight for the biasing
484  * function using Simpson's rule:
485  *
486  * Note: the variou branches represent certain geometrical extreme
487  * situations.
488  */
489  void CfbRebridgeBase::orientationBiasTable
490  (double l_20, double &prefAng, double &kappaAng, double &normConst)
491  {
492  double cos_ang;
493 
494  // Preferential orientation & effective spring constant
495  if ( l_20 <= fabs(length21_ - length10_) ) {
496 
497  if (length21_ > length10_) {
498  prefAng = 0.0;
499  kappaAng = kappa10_ * (length21_ - l_20 - length10_);
500  kappaAng *= length21_ * l_20 / (length21_ - l_20);
501  } else if (length21_ == length10_) {
502  prefAng = acos(-1.0)/2.0;
503  kappaAng = 0.0;
504  } else {
505  prefAng = acos(-1.0);
506  kappaAng = kappa10_ * (length10_ - l_20 - length21_);
507  kappaAng *= length21_ * l_20 / (length21_ + l_20);
508  }
509 
510  } else if ( l_20 >= (length21_ + length10_) ) {
511 
512  prefAng = 0.0;
513  kappaAng = kappa10_ * (l_20 - length21_ - length10_) * length21_ * l_20
514  / (l_20 - length21_);
515 
516  } else {
517 
518  cos_ang = (l_20*l_20 + length21_*length21_ - length10_*length10_)
519  * 0.5 / length21_ / l_20;
520  prefAng = acos(cos_ang);
521  kappaAng = length21_ * l_20 / length10_;
522  kappaAng = kappa10_ * kappaAng * kappaAng * (1.0 - cos_ang*cos_ang);
523 
524  }
525 
526  // Calculate normalization factor.
527  if (kappaAng < 1.0E-7) {
528  normConst = 2.0;
529  } else {
530  computeNormalization(prefAng, kappaAng, normConst);
531  }
532  }
533 
534  /*
535  * Use Simpson's rule to compute the normalization factor
536  * int { exp(-0.5*beta*kappaAng*(x-prefAng)**2)*sin(x) , {x, 0, pi} }
537  */
538  void CfbRebridgeBase::computeNormalization
539  (double prefAng, double kappaAng, double &normConst)
540  {
541  int i, N; // N must be even
542  double delta, x, sum, tmp;
543 
544  // indices for Simpson's rule: 0,1,...,N
545  N = 400; // default value
546  tmp = 0.5*kappaAng;
547  delta = acos(-1.0)/double(N);
548 
549  // the end points contribute nothing since sin(0)=sin(pi)=0.
550  sum = 0.0;
551  x = -delta;
552  for (i=0; i < N-1; i=i+2) {
553  x += delta;
554  //sum += 2.0 * exp( -tmp * (x-prefAng)*(x-prefAng) ) * sin(x);
555  sum += 2.0 * boltzmann( tmp * (x-prefAng)*(x-prefAng) ) * sin(x);
556  x += delta;
557  //sum += 4.0 * exp( -tmp * (x-prefAng)*(x-prefAng) ) * sin(x);
558  sum += 4.0 * boltzmann( tmp * (x-prefAng)*(x-prefAng) ) * sin(x);
559  }
560  normConst = delta*sum/3.0;
561  }
562 
563 }
static const int MaxTrial_
Maximum allowed number of trial positions for a regrown atom.
Definition: CfbEndBase.h:111
virtual void setup()
Initialize the arrays for preferential angle, effective spring constant and normalization factor...
virtual ~CfbRebridgeBase()
Destructor.
A System for use in a Markov chain Monte Carlo simulation.
Definition: McSystem.h:52
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
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
void deleteMiddleAtom(Atom *partPtr, Atom *prevPtr, Atom *nextPtr, int prevBType, int nextBType, double &rosenbluth, double &energy)
Configuration bias algorithm for deleting a particle between two monomers and compute the correspondi...
void addAtom(Atom &atom)
Add an Atom to the CellList.
virtual void readParameters(std::istream &in)
Read species type, nTrial, and parameters needed to evaluate the orientation bias.
File containing preprocessor macros for error handling.
long drawFrom(double probability[], long size)
Choose one of several outcomes with a specified set of probabilities.
Definition: Random.h:237
double kappa10_
Spring constant (1-0 bond).
Saving / output archive for binary ostream.
void addMiddleAtom(Atom *partPtr, Atom *prevPtr, Atom *nextPtr, int prevBType, int nextBType, double &rosenbluth, double &energy)
Configuration bias algorithm for adding the last particle with special bias in favor of closing the b...
double boltzmann(double energy)
Boltzmann weight associated with an energy difference.
Definition: SystemMove.h:100
void addSequence(int nActive, int sign, Atom *beginPtr, int *bonds, double &rosenbluth, double &energy)
Configuration bias algorithm for adding a consequtive sequence of atoms.
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
virtual double atomEnergy(const Atom &atom) const
Calculate the covalent angle energy for one 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
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
McPairPotential & pairPotential() const
Return the McPairPotential by reference.
Definition: McSystem.h:388
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
virtual double energy(double rSq, int type) const =0
Returns potential energy for one bond.
void deleteSequence(int nActive, int sign, Atom *endPtr, int *bonds, double &rosenbluth, double &energy)
Configuration bias algorithm for deleting a consequtive sequence of atoms.
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
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
double length10_
Equilibrium bond lengths (1-0 bonds).
int nTrial_
Actual number of trial positions for each regrown atom.
Definition: CfbEndBase.h:114
AnglePotential & anglePotential() const
Return AnglePotential by reference.
Definition: McSystem.h:422
const Vector & position() const
Get the position Vector by const reference.
Base class for configuration bias (CFB) end regrowth moves.
Definition: CfbEndBase.h:31
CfbRebridgeBase(McSystem &system)
Constructor.
void deleteAtom(Atom &atom)
Remove an Atom from the CellList.
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
double length21_
Equilibrium bond lengths (2-1 bond).