Simpatico  v1.10
ddMd/simulation/Simulation.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 "Simulation.h"
9 #include <ddMd/storage/AtomIterator.h>
10 #include <ddMd/storage/GhostIterator.h>
11 #include <ddMd/storage/GroupStorage.tpp>
12 #include <ddMd/integrators/Integrator.h>
13 #include <ddMd/integrators/IntegratorFactory.h>
14 #include <ddMd/configIos/ConfigIo.h>
15 #include <ddMd/configIos/ConfigIoFactory.h>
16 #include <ddMd/configIos/DdMdConfigIo.h>
17 #include <ddMd/configIos/SerializeConfigIo.h>
18 #include <ddMd/analyzers/AnalyzerManager.h>
19 #ifdef DDMD_MODIFIERS
20 #include <ddMd/modifiers/ModifierManager.h>
21 #endif
22 
23 #include <ddMd/potentials/pair/PairPotential.h>
24 #include <ddMd/potentials/pair/PairFactory.h>
25 #ifdef SIMP_BOND
26 #include <ddMd/potentials/bond/BondPotential.h>
27 #include <ddMd/potentials/bond/BondFactory.h>
28 #endif
29 #ifdef SIMP_ANGLE
30 #include <ddMd/potentials/angle/AnglePotential.h>
31 #include <ddMd/potentials/angle/AngleFactory.h>
32 #endif
33 #ifdef SIMP_DIHEDRAL
34 #include <ddMd/potentials/dihedral/DihedralPotential.h>
35 #include <ddMd/potentials/dihedral/DihedralFactory.h>
36 #endif
37 #ifdef SIMP_EXTERNAL
38 #include <ddMd/potentials/external/ExternalPotential.h>
39 #include <ddMd/potentials/external/ExternalPotentialImpl.h>
40 #include <ddMd/potentials/external/ExternalFactory.h>
41 #endif
42 
43 // namespace Simp
44 #include <simp/ensembles/EnergyEnsemble.h>
45 #include <simp/ensembles/BoundaryEnsemble.h>
46 
47 // namespace Util
48 #include <util/misc/FileMaster.h>
49 #include <util/space/Vector.h>
50 #include <util/space/IntVector.h>
51 #include <util/space/Tensor.h>
52 #include <util/param/Factory.h>
53 #include <util/misc/Log.h>
54 #include <util/misc/Memory.h>
55 #include <util/mpi/MpiSendRecv.h>
56 #include <util/misc/Timer.h>
57 #include <util/misc/Bit.h>
58 #include <util/misc/initStatic.h>
59 #include <util/format/Int.h>
60 #include <util/format/Dbl.h>
61 #include <util/format/Str.h>
62 #include <util/misc/ioUtil.h>
63 
64 // std headers
65 #include <fstream>
66 #include <unistd.h>
67 #include <stdlib.h>
68 
69 namespace DdMd
70 {
71 
72  using namespace Util;
73  using namespace Simp;
74 
75  /*
76  * Constructor.
77  */
78  #ifdef UTIL_MPI
79  Simulation::Simulation(MPI::Intracomm& communicator)
80  #else
82  #endif
83  : atomStorage_(),
84  #ifdef SIMP_BOND
85  bondStorage_(),
86  #endif
87  #ifdef SIMP_ANGLE
88  angleStorage_(),
89  #endif
90  #ifdef SIMP_DIHEDRAL
91  dihedralStorage_(),
92  #endif
93  boundary_(),
94  atomTypes_(),
95  domain_(),
96  buffer_(),
97  exchanger_(),
98  random_(),
99  maxBoundary_(),
100  kineticEnergy_(0.0),
101  pairPotentialPtr_(0),
102  #ifdef SIMP_BOND
103  bondPotentialPtr_(0),
104  #endif
105  #ifdef SIMP_ANGLE
106  anglePotentialPtr_(0),
107  #endif
108  #ifdef SIMP_DIHEDRAL
109  dihedralPotentialPtr_(0),
110  #endif
111  #ifdef SIMP_EXTERNAL
112  externalPotentialPtr_(0),
113  #endif
114  integratorPtr_(0),
115  energyEnsemblePtr_(0),
116  boundaryEnsemblePtr_(0),
117  fileMasterPtr_(0),
118  configIoPtr_(0),
119  serializeConfigIoPtr_(0),
120  #ifdef DDMD_MODIFIERS
121  modifierManagerPtr_(0),
122  #endif
123  analyzerManagerPtr_(0),
124  pairFactoryPtr_(0),
125  #ifdef SIMP_BOND
126  bondFactoryPtr_(0),
127  #endif
128  #ifdef SIMP_ANGLE
129  angleFactoryPtr_(0),
130  #endif
131  #ifdef SIMP_DIHEDRAL
132  dihedralFactoryPtr_(0),
133  #endif
134  #ifdef SIMP_EXTERNAL
135  externalFactoryPtr_(0),
136  #endif
137  integratorFactoryPtr_(0),
138  configIoFactoryPtr_(0),
139  pairStyle_(),
140  #ifdef SIMP_BOND
141  bondStyle_(),
142  #endif
143  #ifdef SIMP_ANGLE
144  angleStyle_(),
145  #endif
146  #ifdef SIMP_DIHEDRAL
147  dihedralStyle_(),
148  #endif
149  #ifdef SIMP_EXTERNAL
150  externalStyle_(),
151  #endif
152  nAtomType_(0),
153  #ifdef SIMP_BOND
154  nBondType_(0),
155  #endif
156  #ifdef SIMP_ANGLE
157  nAngleType_(0),
158  #endif
159  #ifdef SIMP_DIHEDRAL
160  nDihedralType_(0),
161  #endif
162  #ifdef SIMP_EXTERNAL
163  hasExternal_(false),
164  #endif
165  hasAtomContext_(false),
166  maskedPairPolicy_(MaskBonded),
167  reverseUpdateFlag_(false),
168  #ifdef UTIL_MPI
169  communicator_(communicator),
170  #endif
171  isInitialized_(false),
172  isRestarting_(false)
173  {
175  setClassName("Simulation");
176 
177  #ifdef UTIL_MPI
178  if (!MPI::Is_initialized()) {
179  UTIL_THROW("MPI is not initialized");
180  }
184 
185  setIoCommunicator(communicator);
186  domain_.setGridCommunicator(communicator);
187  #else
188  domain_.setRank(0);
189  #endif
190 
191  // Set connections between member objects
192  domain_.setBoundary(boundary_);
193  exchanger_.associate(domain_, boundary_, atomStorage_, buffer_);
194  atomStorage_.associate(domain_, boundary_, buffer_);
195  #ifdef SIMP_BOND
196  bondStorage_.associate(domain_, atomStorage_, buffer_);
197  #endif
198  #ifdef SIMP_ANGLE
199  angleStorage_.associate(domain_, atomStorage_, buffer_);
200  #endif
201  #ifdef SIMP_DIHEDRAL
202  dihedralStorage_.associate(domain_, atomStorage_, buffer_);
203  #endif
204 
205  fileMasterPtr_ = new FileMaster;
206  energyEnsemblePtr_ = new EnergyEnsemble;
207  boundaryEnsemblePtr_ = new BoundaryEnsemble;
208  #ifdef DDMD_MODIFIERS
209  modifierManagerPtr_ = new ModifierManager(*this);
210  #endif
211  analyzerManagerPtr_ = new AnalyzerManager(*this);
212  }
213 
214  /*
215  * Destructor.
216  */
218  {
219  if (pairFactoryPtr_) {
220  delete pairFactoryPtr_;
221  }
222  if (pairPotentialPtr_) {
223  delete pairPotentialPtr_;
224  }
225  #ifdef SIMP_BOND
226  if (bondFactoryPtr_) {
227  delete bondFactoryPtr_;
228  }
229  if (bondPotentialPtr_) {
230  delete bondPotentialPtr_;
231  }
232  #endif
233  #ifdef SIMP_ANGLE
234  if (angleFactoryPtr_) {
235  delete angleFactoryPtr_;
236  }
237  if (anglePotentialPtr_) {
238  delete anglePotentialPtr_;
239  }
240  #endif
241  #ifdef SIMP_DIHEDRAL
242  if (dihedralFactoryPtr_) {
243  delete dihedralFactoryPtr_;
244  }
245  if (dihedralPotentialPtr_) {
246  delete dihedralPotentialPtr_;
247  }
248  #endif
249  #ifdef SIMP_EXTERNAL
250  if (externalFactoryPtr_) {
251  delete externalFactoryPtr_;
252  }
253  if (externalPotentialPtr_) {
254  delete externalPotentialPtr_;
255  }
256  #endif
257  if (configIoFactoryPtr_) {
258  delete configIoFactoryPtr_;
259  }
260  if (configIoPtr_) {
261  delete configIoPtr_;
262  }
263  if (serializeConfigIoPtr_) {
264  delete serializeConfigIoPtr_;
265  }
266  if (integratorFactoryPtr_) {
267  delete integratorFactoryPtr_;
268  }
269  if (integratorPtr_) {
270  delete integratorPtr_;
271  }
272  if (analyzerManagerPtr_) {
273  delete analyzerManagerPtr_;
274  }
275  #ifdef DDMD_MODIFIERS
276  if (modifierManagerPtr_) {
277  delete modifierManagerPtr_;
278  }
279  #endif
280  if (fileMasterPtr_) {
281  delete fileMasterPtr_;
282  }
283  if (energyEnsemblePtr_) {
284  delete energyEnsemblePtr_;
285  }
286  if (boundaryEnsemblePtr_) {
287  delete boundaryEnsemblePtr_;
288  }
289 
290  #ifdef UTIL_MPI
291  if (logFile_.is_open()) {
292  logFile_.close();
293  }
294  #endif
295  }
296 
297  /*
298  * Process command line options.
299  */
300  void Simulation::setOptions(int argc, char * const * argv)
301  {
302  bool qFlag = false; // output compile time options
303  bool eFlag = false; // echo
304  bool sFlag = false; // split communicator
305  bool pFlag = false; // param file name
306  bool rFlag = false; // restart file name
307  bool cFlag = false; // command file name
308  bool iFlag = false; // input prefix string
309  bool oFlag = false; // output prefix string
310  char* sArg = 0;
311  char* rArg = 0;
312  char* pArg = 0;
313  char* cArg = 0;
314  char* iArg = 0;
315  char* oArg = 0;
316  int nSystem = 1;
317 
318  // Read and store all command-line arguments
319  int c;
320  opterr = 0;
321  while ((c = getopt(argc, argv, "qes:p:r:c:i:o:")) != -1) {
322  switch (c) {
323  case 'q': // output compile time options
324  qFlag = true;
325  break;
326  case 'e': // echo parameters
327  eFlag = true;
328  break;
329  case 's': // split communicator
330  sFlag = true;
331  sArg = optarg;
332  nSystem = atoi(sArg);
333  break;
334  case 'p': // parameter file
335  pFlag = true;
336  pArg = optarg;
337  break;
338  case 'r': // restart file
339  rFlag = true;
340  rArg = optarg;
341  break;
342  case 'c': // command file
343  cFlag = true;
344  cArg = optarg;
345  break;
346  case 'i': // input prefix
347  iFlag = true;
348  iArg = optarg;
349  break;
350  case 'o': // output prefix
351  oFlag = true;
352  oArg = optarg;
353  break;
354  case '?': {
355  char optChar = optopt;
356  Log::file() << "Unknown option -" << optChar << std::endl;
357  }
358  }
359  }
360 
361  // If option -s, split the communicator
362  if (sFlag) {
363  if (nSystem <= 1) {
364  UTIL_THROW("nSystem must be greater than 1");
365  }
366  int worldRank = communicator_.Get_rank();
367  int worldSize = communicator_.Get_size();
368  if (worldSize % nSystem != 0) {
369  UTIL_THROW("World communicator size not a multiple of nSystem");
370  }
371 
372  // Split the communicator
373  int systemSize = worldSize/nSystem;
374  int systemId = worldRank/systemSize;
375  communicator_ = communicator_.Split(systemId, worldRank);
376 
377  // Set param and grid communicators
378  setIoCommunicator(communicator_);
379  domain_.setGridCommunicator(communicator_);
380  fileMaster().setDirectoryId(systemId);
381 
382  // Set log file for processor n to a new file named "n/log".
383  // Relies on initialization of outputPrefix to empty string "".
384  fileMaster().openOutputFile("log", logFile_);
385  Log::setFile(logFile_);
386  }
387 
388  // If option -q, output compile time options to log
389  if (qFlag) {
390  if (communicator_.Get_rank() == 0) {
391  outputOptions(Log::file());
392  }
393  }
394 
395  // If option -e, enable echoing of parameters as they are read
396  if (eFlag) {
398  }
399 
400  // If option -p, set parameter file name
401  if (pFlag) {
402  if (rFlag) {
403  UTIL_THROW("Cannot have both parameter and restart files");
404  }
405  fileMaster().setParamFileName(std::string(pArg));
406  }
407 
408  // If option -r, load state from a restart file.
409  if (rFlag) {
410  if (isIoProcessor()) {
411  Log::file() << "Begin reading restart, base file name "
412  << std::string(rArg) << std::endl;
413  }
414  load(std::string(rArg));
415  if (isIoProcessor()) {
416  Log::file() << "Done reading restart file" << std::endl;
417  Log::file() << std::endl;
418  }
419  }
420 
421  // The -c, -i, and -o options are applied after the -r option
422  // so that they override any paths set in the restart file.
423 
424  // If option -c, set command file name
425  if (cFlag) {
426  fileMaster().setCommandFileName(std::string(cArg));
427  }
428 
429  // If option -i, set path prefix for input files
430  if (iFlag) {
431  fileMaster().setInputPrefix(std::string(iArg));
432  }
433 
434  // If option -o, set path prefix for output files
435  if (oFlag) {
436  fileMaster().setOutputPrefix(std::string(oArg));
437  }
438 
439  }
440 
441  /*
442  * Read parameter block, including begin and end.
443  */
444  void Simulation::readParam(std::istream& in)
445  {
446  if (!isRestarting_) {
447  readBegin(in, className().c_str());
448  readParameters(in);
449  readEnd(in);
450  }
451 
452  /*
453  * Note that if isRestarting_ is set to true, this function does
454  * nothing and returns immediately. If the ddSim program is
455  * invoked with a -r option, the setOptions() function sets
456  * isRestarting_ to true and then reads the restart file whose
457  * name is specified as a command line argument. Because the
458  * main ddSim program calls setOptions() before readParam(),
459  * and because the restart file contains all the information
460  * that would otherwise be given in a parameter file, there
461  * is thus no need to read a parameter file during a restart.
462  */
463  }
464 
465  /*
466  * Read parameters from default parameter file.
467  */
469  {
470  if (!isRestarting_) {
471  readParam(fileMaster().paramFile());
472  }
474  }
475 
476  /*
477  * Read parameters, allocate memory and initialize.
478  */
479  void Simulation::readParameters(std::istream& in)
480  {
481  if (isInitialized_) {
482  UTIL_THROW("Error: Called Simulation::readParameters when isInitialized");
483  }
484 
485  // Read Domain and FileMaster
486  readParamComposite(in, domain_);
487  readFileMaster(in);
488 
489  // Read numbers of types
490  read<int>(in, "nAtomType", nAtomType_);
491  #ifdef SIMP_BOND
492  nBondType_ = 0;
493  readOptional<int>(in, "nBondType", nBondType_);
494  if (nBondType_) {
495  exchanger_.addGroupExchanger(bondStorage_);
496  }
497  #endif
498  #ifdef SIMP_ANGLE
499  nAngleType_ = 0;
500  readOptional<int>(in, "nAngleType", nAngleType_);
501  if (nAngleType_) {
502  exchanger_.addGroupExchanger(angleStorage_);
503  }
504  #endif
505  #ifdef SIMP_DIHEDRAL
506  nDihedralType_ = 0;
507  readOptional<int>(in, "nDihedralType", nDihedralType_);
508  if (nDihedralType_) {
509  exchanger_.addGroupExchanger(dihedralStorage_);
510  }
511  #endif
512  #ifdef SIMP_EXTERNAL
513  hasExternal_ = false;
514  readOptional<bool>(in, "hasExternal", hasExternal_);
515  #endif
516 
517  hasAtomContext_ = false;
518  readOptional<bool>(in, "hasAtomContext", hasAtomContext_);
519  Atom::setHasAtomContext(hasAtomContext_);
520 
521  // Read array of atom type descriptors
522  atomTypes_.allocate(nAtomType_);
523  for (int i = 0; i < nAtomType_; ++i) {
524  atomTypes_[i].setId(i);
525  }
526  readDArray<AtomType>(in, "atomTypes", atomTypes_, nAtomType_);
527 
528  // Read storage capacities
529  readParamComposite(in, atomStorage_);
530  #ifdef SIMP_BOND
531  if (nBondType_) {
532  readParamComposite(in, bondStorage_);
533  }
534  #endif
535  #ifdef SIMP_ANGLE
536  if (nAngleType_) {
537  readParamComposite(in, angleStorage_);
538  }
539  #endif
540  #ifdef SIMP_DIHEDRAL
541  if (nDihedralType_) {
542  readParamComposite(in, dihedralStorage_);
543  }
544  #endif
545 
546  readParamComposite(in, buffer_);
547  readPotentialStyles(in);
548 
549  // Create and read potential energy classes
550 
551  // Pair Potential
552  assert(pairPotentialPtr_ == 0);
553  pairPotentialPtr_ = pairFactory().factory(pairStyle());
554  if (!pairPotentialPtr_) {
555  UTIL_THROW("Unknown pairStyle");
556  }
557  pairPotential().setReverseUpdateFlag(reverseUpdateFlag_);
558  readParamComposite(in, *pairPotentialPtr_);
559 
560  #ifdef SIMP_BOND
561  // Bond Potential
562  assert(bondPotentialPtr_ == 0);
563  if (nBondType_) {
564  bondPotentialPtr_ = bondFactory().factory(bondStyle());
565  if (!bondPotentialPtr_) {
566  UTIL_THROW("Unknown bondStyle");
567  }
568  readParamComposite(in, *bondPotentialPtr_);
569  }
570  #endif
571 
572  #ifdef SIMP_ANGLE
573  // Angle potential
574  assert(anglePotentialPtr_ == 0);
575  if (nAngleType_) {
576  anglePotentialPtr_ = angleFactory().factory(angleStyle());
577  if (!anglePotentialPtr_) {
578  UTIL_THROW("Unknown angleStyle");
579  }
580  readParamComposite(in, *anglePotentialPtr_);
581  }
582  #endif
583 
584  #ifdef SIMP_DIHEDRAL
585  // Dihedral potential
586  assert(dihedralPotentialPtr_ == 0);
587  if (nDihedralType_) {
588  dihedralPotentialPtr_ = dihedralFactory().factory(dihedralStyle());
589  if (!dihedralPotentialPtr_) {
590  UTIL_THROW("Unknown dihedralStyle");
591  }
592  readParamComposite(in, *dihedralPotentialPtr_);
593  }
594  #endif
595 
596  #ifdef SIMP_EXTERNAL
597  // External potential
598  if (hasExternal_) {
599  assert(externalPotentialPtr_ == 0);
600  externalPotentialPtr_ = externalFactory().factory(externalStyle());
601  if (!externalPotentialPtr_) {
602  UTIL_THROW("Unknown externalStyle");
603  }
604  readParamComposite(in, *externalPotentialPtr_);
605  }
606  #endif
607 
608  readEnsembles(in);
609 
610  // Integrator
611  std::string className;
612  bool isEnd;
613  assert(integratorPtr_ == 0);
614  integratorPtr_ =
615  integratorFactory().readObject(in, *this, className, isEnd);
616  if (!integratorPtr_) {
617  std::string msg("Unknown Integrator subclass name: ");
618  msg += className;
619  UTIL_THROW("msg.c_str()");
620  }
621  #ifdef DDMD_MODIFIERS
622  readParamCompositeOptional(in, *modifierManagerPtr_);
623  #endif
624  readParamComposite(in, random_);
625  readParamComposite(in, *analyzerManagerPtr_);
626 
627  // Finished reading parameter file. Now finish initialization:
628 
629  exchanger_.setPairCutoff(pairPotential().cutoff());
630  exchanger_.allocate();
631 
632  // Set signal observers (i.e., call-back functions for Signal::notify)
633  modifySignal().addObserver(*this, &Simulation::unsetKineticEnergy);
634  modifySignal().addObserver(*this, &Simulation::unsetKineticStress);
635  modifySignal().addObserver(*this, &Simulation::unsetPotentialEnergies);
636  modifySignal().addObserver(*this, &Simulation::unsetVirialStress);
637 
638  velocitySignal().addObserver(*this, &Simulation::unsetKineticEnergy);
639  velocitySignal().addObserver(*this, &Simulation::unsetKineticStress);
640 
641  positionSignal().addObserver(*this, &Simulation::unsetPotentialEnergies);
642  positionSignal().addObserver(*this, &Simulation::unsetVirialStress);
643  #ifdef SIMP_BOND
644  if (nBondType_) {
645  void (BondStorage::*memberPtr)() = &BondStorage::unsetNTotal;
646  exchangeSignal().addObserver(bondStorage_, memberPtr);
647  }
648  #endif
649  #ifdef SIMP_ANGLE
650  if (nAngleType_) {
651  void (AngleStorage::*memberPtr)() = &AngleStorage::unsetNTotal;
652  exchangeSignal().addObserver(angleStorage_, memberPtr);
653  }
654  #endif
655  #ifdef SIMP_DIHEDRAL
656  if (nDihedralType_) {
657  void (DihedralStorage::*memberPtr)() = &DihedralStorage::unsetNTotal;
658  exchangeSignal().addObserver(dihedralStorage_, memberPtr);
659  }
660  #endif
661 
662  isInitialized_ = true;
663  }
664 
665  /*
666  * Read parameters, allocate memory and initialize.
667  */
669  {
670  if (isInitialized_) {
671  UTIL_THROW("Error: Called loadParameters when already initialized");
672  }
673  if (!hasIoCommunicator()) {
674  UTIL_THROW("Error: No IoCommunicator is set");
675  }
676  isRestarting_ = true;
677 
678  loadParamComposite(ar, domain_);
679  loadFileMaster(ar);
680 
681  // Load types
682  loadParameter<int>(ar, "nAtomType", nAtomType_);
683  #ifdef SIMP_BOND
684  nBondType_ = 0;
685  loadParameter<int>(ar, "nBondType", nBondType_, false); // optional
686  if (nBondType_) {
687  exchanger_.addGroupExchanger(bondStorage_);
688  }
689  #endif
690  #ifdef SIMP_ANGLE
691  nAngleType_ = 0;
692  loadParameter<int>(ar, "nAngleType", nAngleType_, false); // opt
693  if (nAngleType_) {
694  exchanger_.addGroupExchanger(angleStorage_);
695  }
696  #endif
697  #ifdef SIMP_DIHEDRAL
698  nDihedralType_ = 0;
699  loadParameter<int>(ar, "nDihedralType", nDihedralType_, false); // opt
700  if (nDihedralType_) {
701  exchanger_.addGroupExchanger(dihedralStorage_);
702  }
703  #endif
704  #ifdef SIMP_EXTERNAL
705  hasExternal_ = false;
706  loadParameter<bool>(ar, "hasExternal", hasExternal_, false); // opt
707  #endif
708 
709  hasAtomContext_ = false;
710  loadParameter<bool>(ar, "hasAtomContext", hasAtomContext_, false); // opt
711  Atom::setHasAtomContext(hasAtomContext_);
712 
713  atomTypes_.allocate(nAtomType_);
714  for (int i = 0; i < nAtomType_; ++i) {
715  atomTypes_[i].setId(i);
716  }
717  loadDArray<AtomType>(ar, "atomTypes", atomTypes_, nAtomType_);
718 
719  // Load storage capacities
720  loadParamComposite(ar, atomStorage_);
721  #ifdef SIMP_BOND
722  if (nBondType_) {
723  loadParamComposite(ar, bondStorage_);
724  }
725  #endif
726  #ifdef SIMP_ANGLE
727  if (nAngleType_) {
728  loadParamComposite(ar, angleStorage_);
729  }
730  #endif
731  #ifdef SIMP_DIHEDRAL
732  if (nDihedralType_) {
733  loadParamComposite(ar, dihedralStorage_);
734  }
735  #endif
736  loadParamComposite(ar, buffer_);
737 
738  // Load potentials styles and parameters
739  loadPotentialStyles(ar);
740 
741  // Pair Potential
742  assert(pairPotentialPtr_ == 0);
743  pairPotentialPtr_ = pairFactory().factory(pairStyle());
744  if (!pairPotentialPtr_) {
745  UTIL_THROW("Unknown pairStyle");
746  }
747  loadParamComposite(ar, *pairPotentialPtr_);
748  pairPotential().setReverseUpdateFlag(reverseUpdateFlag_);
749 
750  #ifdef SIMP_BOND
751  // Bond Potential
752  assert(bondPotentialPtr_ == 0);
753  if (nBondType_) {
754  bondPotentialPtr_ = bondFactory().factory(bondStyle());
755  if (!bondPotentialPtr_) {
756  UTIL_THROW("Unknown bondStyle");
757  }
758  loadParamComposite(ar, *bondPotentialPtr_);
759  }
760  #endif
761 
762  #ifdef SIMP_ANGLE
763  // Angle potential
764  assert(anglePotentialPtr_ == 0);
765  if (nAngleType_) {
766  anglePotentialPtr_ = angleFactory().factory(angleStyle());
767  if (!anglePotentialPtr_) {
768  UTIL_THROW("Unknown angleStyle");
769  }
770  loadParamComposite(ar, *anglePotentialPtr_);
771  }
772  #endif
773 
774  #ifdef SIMP_DIHEDRAL
775  // Dihedral potential
776  assert(dihedralPotentialPtr_ == 0);
777  if (nDihedralType_) {
778  dihedralPotentialPtr_ = dihedralFactory().factory(dihedralStyle());
779  if (!dihedralPotentialPtr_) {
780  UTIL_THROW("Unknown dihedralStyle");
781  }
782  loadParamComposite(ar, *dihedralPotentialPtr_);
783  }
784  #endif
785 
786  #ifdef SIMP_EXTERNAL
787  // External potential
788  assert(externalPotentialPtr_ == 0);
789  if (hasExternal_) {
790  externalPotentialPtr_ = externalFactory().factory(externalStyle());
791  if (!externalPotentialPtr_) {
792  UTIL_THROW("Unknown externalStyle");
793  }
794  loadParamComposite(ar, *externalPotentialPtr_);
795  }
796  #endif
797 
798  loadEnsembles(ar);
799 
800  // Integrator
801  assert(integratorPtr_ == 0);
802  std::string className;
803  integratorPtr_ =
804  integratorFactory().loadObject(ar, *this, className);
805  if (!integratorPtr_) {
806  std::string msg("Unknown Integrator subclass name: ");
807  msg += className;
808  UTIL_THROW("msg.c_str()");
809  }
810  #ifdef DDMD_MODIFIERS
811  loadParamCompositeOptional(ar, *modifierManagerPtr_);
812  #endif
813  loadParamComposite(ar, random_);
814  loadParamComposite(ar, *analyzerManagerPtr_);
815 
816  // Finished loading data from archive. Now finish initialization:
817 
818  exchanger_.setPairCutoff(pairPotential().cutoff());
819  exchanger_.allocate();
820 
821  // Set signal observers (i.e., call-back functions for Signal::notify)
822  modifySignal().addObserver(*this, &Simulation::unsetKineticEnergy);
823  modifySignal().addObserver(*this, &Simulation::unsetKineticStress);
824  modifySignal().addObserver(*this, &Simulation::unsetPotentialEnergies);
825  modifySignal().addObserver(*this, &Simulation::unsetVirialStress);
826 
827  velocitySignal().addObserver(*this, &Simulation::unsetKineticEnergy);
828  velocitySignal().addObserver(*this, &Simulation::unsetKineticStress);
829 
830  positionSignal().addObserver(*this, &Simulation::unsetPotentialEnergies);
831  positionSignal().addObserver(*this, &Simulation::unsetVirialStress);
832  #ifdef SIMP_BOND
833  if (nBondType_) {
834  void (BondStorage::*memberPtr)() = &BondStorage::unsetNTotal;
835  exchangeSignal().addObserver(bondStorage_, memberPtr);
836  }
837  #endif
838  #ifdef SIMP_ANGLE
839  if (nAngleType_) {
840  void (AngleStorage::*memberPtr)() = &AngleStorage::unsetNTotal;
841  exchangeSignal().addObserver(angleStorage_, memberPtr);
842  }
843  #endif
844  #ifdef SIMP_DIHEDRAL
845  if (nDihedralType_) {
846  void (DihedralStorage::*memberPtr)() = &DihedralStorage::unsetNTotal;
847  exchangeSignal().addObserver(dihedralStorage_, memberPtr);
848  }
849  #endif
850 
851  isInitialized_ = true;
852 
853  // Load the configuration (boundary + positions + groups)
854  serializeConfigIo().loadConfig(ar, maskedPairPolicy_);
855 
856  // There are no ghosts yet, so exchange.
857  exchanger_.exchange();
858  isValid();
859  }
860 
861  // ---- Serialization -----------------------------------------------
862 
863  /*
864  * Load state from a restart file (open file, call load, close file)
865  */
866  void Simulation::load(const std::string& filename)
867  {
868  if (isInitialized_) {
869  UTIL_THROW("Error: Called load when already initialized");
870  }
871  if (!hasIoCommunicator()) {
872  UTIL_THROW("Error: No IoCommunicator is set");
873  }
874 
876  if (isIoProcessor()) {
877  std::ios_base::openmode mode = std::ios_base::in | std::ios_base::binary;
878  fileMaster().openRestartIFile(filename, ar.file(), mode);
879  }
880  // ParamComposite::load() calls Simulation::loadParameters()
881  load(ar);
882  if (isIoProcessor()) {
883  ar.file().close();
884  }
885 
886  }
887 
888  /*
889  * Serialize internal state to an archive.
890  *
891  * Call only on IoProcessor of IoCommunicator.
892  */
894  {
895  domain_.save(ar);
896  saveFileMaster(ar);
897 
898  // Read types
899  ar << nAtomType_;
900  #ifdef SIMP_BOND
901  Parameter::saveOptional(ar, nBondType_, (bool)nBondType_);
902  #endif
903  #ifdef SIMP_ANGLE
904  Parameter::saveOptional(ar, nAngleType_, (bool)nAngleType_);
905  #endif
906  #ifdef SIMP_DIHEDRAL
907  Parameter::saveOptional(ar, nDihedralType_, (bool)nDihedralType_);
908  #endif
909  #ifdef SIMP_EXTERNAL
910  Parameter::saveOptional(ar, hasExternal_, hasExternal_);
911  #endif
912  Parameter::saveOptional(ar, hasAtomContext_, hasAtomContext_);
913  ar << atomTypes_;
914 
915  // Read storage capacities
916  atomStorage_.save(ar);
917  #ifdef SIMP_BOND
918  if (nBondType_) {
919  bondStorage_.save(ar);
920  }
921  #endif
922  #ifdef SIMP_ANGLE
923  if (nAngleType_) {
924  angleStorage_.save(ar);
925  }
926  #endif
927  #ifdef SIMP_DIHEDRAL
928  if (nDihedralType_) {
929  dihedralStorage_.save(ar);
930  }
931  #endif
932 
933  buffer_.save(ar);
934 
935  // Potential energy styles and potential classes
936  savePotentialStyles(ar);
937  pairPotential().save(ar);
938  #ifdef SIMP_BOND
939  if (nBondType_) {
940  bondPotential().save(ar);
941  }
942  #endif
943  #ifdef SIMP_ANGLE
944  if (nAngleType_) {
945  anglePotential().save(ar);
946  }
947  #endif
948  #ifdef SIMP_DIHEDRAL
949  if (nDihedralType_) {
950  dihedralPotential().save(ar);
951  }
952  #endif
953  #ifdef SIMP_EXTERNAL
954  if (hasExternal_) {
955  externalPotential().save(ar);
956  }
957  #endif
958 
959  // Save ensembles, integrator, modifiers, random, analyzers
960  saveEnsembles(ar);
961  std::string name = integrator().className();
962  ar << name;
963  integrator().save(ar);
964  #ifdef DDMD_MODIFIERS
965  modifierManager().saveOptional(ar);
966  #endif
967  random_.save(ar);
968  analyzerManager().save(ar);
969  }
970 
971  /*
972  * Save state to file (open file, call save(), close file).
973  */
974  void Simulation::save(const std::string& filename)
975  {
976  // Update statistics (call on all processors).
977  atomStorage_.computeStatistics(domain_.communicator());
978  #ifdef SIMP_BOND
979  if (nBondType_) {
980  bondStorage_.computeStatistics(domain_.communicator());
981  }
982  #endif
983  #ifdef SIMP_ANGLE
984  if (nAngleType_) {
985  angleStorage_.computeStatistics(domain_.communicator());
986  }
987  #endif
988  #ifdef SIMP_DIHEDRAL
989  if (nDihedralType_) {
990  dihedralStorage_.computeStatistics(domain_.communicator());
991  }
992  #endif
993  buffer_.computeStatistics(domain_.communicator());
994  if (integratorPtr_) {
995  integrator().computeStatistics();
996  }
997 
998  // Save parameters (only on ioProcessor)
1000  if (isIoProcessor()) {
1001  std::ios_base::openmode mode = std::ios_base::out | std::ios_base::binary;
1002  fileMaster().openRestartOFile(filename, ar.file(), mode);
1003  save(ar);
1004  }
1005 
1006  // Save configuration (call on all processors)
1007  serializeConfigIo().saveConfig(ar);
1008 
1009  if (isIoProcessor()) {
1010  ar.file().close();
1011  }
1012  }
1013 
1014  // --- Protected read, load and save methods ------------------------
1015 
1016  /*
1017  * Read the FileMaster parameters.
1018  */
1019  void Simulation::readFileMaster(std::istream &in)
1020  {
1021  assert(fileMasterPtr_);
1022  readParamComposite(in, *fileMasterPtr_);
1023  assert(fileMasterPtr_->hasIoCommunicator());
1024  }
1025 
1026  /*
1027  * Load the FileMaster.
1028  */
1030  {
1031  assert(fileMasterPtr_);
1032  loadParamComposite(ar, *fileMasterPtr_);
1033  assert(fileMasterPtr_->hasIoCommunicator());
1034  }
1035 
1036  /*
1037  * Save the FileMaster.
1038  */
1040  { fileMasterPtr_->save(ar); }
1041 
1042  /*
1043  * Read potential style strings and maskedPairPolicy.
1044  */
1045  void Simulation::readPotentialStyles(std::istream &in)
1046  {
1047  read<std::string>(in, "pairStyle", pairStyle_);
1048  #ifdef SIMP_BOND
1049  if (nBondType_) {
1050  read<std::string>(in, "bondStyle", bondStyle_);
1051  }
1052  #endif
1053  #ifdef SIMP_ANGLE
1054  if (nAngleType_) {
1055  read<std::string>(in, "angleStyle", angleStyle_);
1056  }
1057  #endif
1058  #ifdef SIMP_DIHEDRAL
1059  if (nDihedralType_) {
1060  read<std::string>(in, "dihedralStyle", dihedralStyle_);
1061  }
1062  #endif
1063  #ifdef SIMP_EXTERNAL
1064  if (hasExternal_) {
1065  read<std::string>(in, "externalStyle", externalStyle_);
1066  }
1067  #endif
1068 
1069  // Read policy regarding whether to excluded pair interactions
1070  // between covalently bonded pairs.
1071  read<MaskPolicy>(in, "maskedPairPolicy", maskedPairPolicy_);
1072 
1073  // Reverse communication (true) or not (false)?
1074  read<bool>(in, "reverseUpdateFlag", reverseUpdateFlag_);
1075 
1076  }
1077 
1078  /*
1079  * Load potential style strings.
1080  */
1082  {
1083  loadParameter<std::string>(ar, "pairStyle", pairStyle_);
1084  #ifdef SIMP_BOND
1085  if (nBondType_) {
1086  loadParameter<std::string>(ar, "bondStyle", bondStyle_);
1087  }
1088  #endif
1089  #ifdef SIMP_ANGLE
1090  if (nAngleType_) {
1091  loadParameter<std::string>(ar, "angleStyle", angleStyle_);
1092  }
1093  #endif
1094  #ifdef SIMP_DIHEDRAL
1095  if (nDihedralType_) {
1096  loadParameter<std::string>(ar, "dihedralStyle", dihedralStyle_);
1097  }
1098  #endif
1099  #ifdef SIMP_EXTERNAL
1100  if (hasExternal_) {
1101  loadParameter<std::string>(ar, "externalStyle", externalStyle_);
1102  }
1103  #endif
1104  loadParameter<MaskPolicy>(ar, "maskedPairPolicy", maskedPairPolicy_);
1105  loadParameter<bool>(ar, "reverseUpdateFlag", reverseUpdateFlag_);
1106 
1107  isInitialized_ = true;
1108  }
1109 
1110  /*
1111  * Save potential style strings.
1112  */
1114  {
1115  ar << pairStyle_;
1116  #ifdef SIMP_BOND
1117  if (nBondType_) {
1118  ar << bondStyle_;
1119  }
1120  #endif
1121  #ifdef SIMP_ANGLE
1122  if (nAngleType_) {
1123  ar << angleStyle_;
1124  }
1125  #endif
1126  #ifdef SIMP_DIHEDRAL
1127  if (nDihedralType_) {
1128  ar << dihedralStyle_;
1129  }
1130  #endif
1131  #ifdef SIMP_EXTERNAL
1132  if (hasExternal_) {
1133  ar << externalStyle_;
1134  }
1135  #endif
1136  ar << maskedPairPolicy_;
1137  ar << reverseUpdateFlag_;
1138  }
1139 
1140  /*
1141  * Read EnergyEnsemble and BoundaryEnsemble
1142  */
1143  void Simulation::readEnsembles(std::istream &in)
1144  {
1145  readParamComposite(in, *energyEnsemblePtr_);
1146  readParamComposite(in, *boundaryEnsemblePtr_);
1147  }
1148 
1149  /*
1150  * Load EnergyEnsemble and BoundaryEnsemble.
1151  */
1153  {
1154  loadParamComposite(ar, *energyEnsemblePtr_);
1155  loadParamComposite(ar, *boundaryEnsemblePtr_);
1156  }
1157 
1158  /*
1159  * Save EnergyEnsemble and BoundaryEnsemble.
1160  */
1162  {
1163  energyEnsemblePtr_->save(ar);
1164  boundaryEnsemblePtr_->save(ar);
1165  }
1166 
1167  // --- readCommands and run-time actions ---------------------------
1168 
1169  /*
1170  * Read and implement commands in an input script.
1171  */
1172  void Simulation::readCommands(std::istream &in)
1173  {
1174  std::string command;
1175  std::string filename;
1176  std::ifstream inputFile;
1177  std::ofstream outputFile;
1178 
1179  #ifdef UTIL_MPI
1180  std::stringstream inBuffer;
1181  std::string line;
1182  #else
1183  std::istream& inBuffer = in;
1184  #endif
1185 
1186  bool readNext = true;
1187  while (readNext) {
1188 
1189  // Precondition: Check atomic coordinate system
1190  if (atomStorage().isCartesian()) {
1191  UTIL_THROW("Error: Storage set for Cartesian atom coordinates");
1192  }
1193 
1194  #ifdef UTIL_MPI
1195  // Read and broadcast command line
1196  if (!hasIoCommunicator() || isIoProcessor()) {
1197  getNextLine(in, line);
1198  Log::file() << line << std::endl;
1199  }
1200  if (hasIoCommunicator()) {
1201  bcast<std::string>(domain_.communicator(), line, 0);
1202  }
1203  #else // ifndef UTIL_MPI
1204  getNextLine(in, line);
1205  Log::file() << line << std::endl;
1206  #endif
1207  inBuffer.clear();
1208  for (unsigned i=0; i < line.size(); ++i) {
1209  inBuffer.put(line[i]);
1210  }
1211 
1212  inBuffer >> command;
1213  if (isRestarting_) {
1214 
1215  if (command == "RESTART") {
1216  int endStep;
1217  inBuffer >> endStep;
1218  int iStep = integrator().iStep();
1219  int nStep = endStep - iStep;
1220  if (isIoProcessor()) {
1221  Log::file() << "Running from iStep =" << iStep << " to "
1222  << endStep << std::endl;
1223  }
1224  integrator().run(nStep);
1225  isRestarting_ = false;
1226  } else {
1227  UTIL_THROW("Missing RESTART command when restarting");
1228  }
1229 
1230  } else {
1231 
1232  if (command == "READ_CONFIG") {
1233  // Read configuration (boundary + positions + topology).
1234  // Use current ConfigIo, if set, or create default.
1235  inBuffer >> filename;
1236  readConfig(filename);
1237  } else
1238  if (command == "THERMALIZE") {
1239  double temperature;
1240  inBuffer >> temperature;
1241  setBoltzmannVelocities(temperature);
1242  removeDriftVelocity();
1243  } else
1244  if (command == "SIMULATE") {
1245  int nStep;
1246  inBuffer >> nStep;
1247  if (domain_.isMaster()) {
1248  Log::file() << std::endl;
1249  }
1250  integrator().run(nStep);
1251  } else
1252  if (command == "OUTPUT_ANALYZERS") {
1253  analyzerManager().output();
1254  } else
1255  if (command == "OUTPUT_INTEGRATOR_STATS") {
1256  // Output statistics about time usage during simulation.
1257  integrator().computeStatistics();
1258  if (domain_.isMaster()) {
1259  integrator().outputStatistics(Log::file());
1260  }
1261  } else
1262  if (command == "OUTPUT_EXCHANGER_STATS") {
1263  // Output detailed statistics about time usage by Exchanger.
1264  integrator().computeStatistics();
1265  #ifdef UTIL_MPI
1266  exchanger().timer().reduce(domain().communicator());
1267  #endif
1268  if (domain_.isMaster()) {
1269  int iStep = integrator().iStep();
1270  double time = integrator().time();
1271  exchanger_.outputStatistics(Log::file(), time, iStep);
1272  }
1273  } else
1274  if (command == "OUTPUT_MEMORY_STATS") {
1275  // Output statistics about memory usage during simulation.
1276  // Also clears statistics after printing output
1277  atomStorage().computeStatistics(domain_.communicator());
1278  #ifdef SIMP_BOND
1279  if (nBondType_) {
1280  bondStorage().computeStatistics(domain_.communicator());
1281  }
1282  #endif
1283  #ifdef SIMP_ANGLE
1284  if (nAngleType_) {
1285  angleStorage().computeStatistics(domain_.communicator());
1286  }
1287  #endif
1288  #ifdef SIMP_DIHEDRAL
1289  if (nDihedralType_) {
1290  dihedralStorage().computeStatistics(domain_.communicator());
1291  }
1292  #endif
1293  pairPotential().pairList()
1294  .computeStatistics(domain_.communicator());
1295  buffer().computeStatistics(domain_.communicator());
1296  int maxMemory = Memory::max(domain_.communicator());
1297  if (domain_.isMaster()) {
1298  atomStorage().outputStatistics(Log::file());
1299  #ifdef SIMP_BOND
1300  if (nBondType_) {
1301  bondStorage().outputStatistics(Log::file());
1302  }
1303  #endif
1304  #ifdef SIMP_ANGLE
1305  if (nAngleType_) {
1306  angleStorage().outputStatistics(Log::file());
1307  }
1308  #endif
1309  #ifdef SIMP_DIHEDRAL
1310  if (nDihedralType_) {
1311  dihedralStorage().outputStatistics(Log::file());
1312  }
1313  #endif
1314  buffer().outputStatistics(Log::file());
1315  pairPotential().pairList().outputStatistics(Log::file());
1316  Log::file() << std::endl;
1317  Log::file() << "Memory: maximum allocated for arrays = "
1318  << maxMemory << " bytes" << std::endl;
1319  Log::file() << std::endl;
1320  }
1321 
1322  atomStorage().clearStatistics();
1323  #ifdef SIMP_BOND
1324  if (nBondType_) {
1325  bondStorage().clearStatistics();
1326  }
1327  #endif
1328  #ifdef SIMP_ANGLE
1329  if (nAngleType_) {
1330  angleStorage().clearStatistics();
1331  }
1332  #endif
1333  #ifdef SIMP_DIHEDRAL
1334  if (nDihedralType_) {
1335  dihedralStorage().clearStatistics();
1336  }
1337  #endif
1338  buffer().clearStatistics();
1339  pairPotential().pairList().clearStatistics();
1340 
1341  } else
1342  if (command == "CLEAR_INTEGRATOR") {
1343  // Clear timing, memory statistics, analyzer accumulators.
1344  // Also resets integrator iStep() to zero
1345  integrator().clear();
1346  } else
1347  if (command == "WRITE_CONFIG") {
1348  // Write current configuration to file.
1349  // Use current ConfigIo, if set.
1350  // Otherwise, create instance of default ConfigIo class.
1351  inBuffer >> filename;
1352  writeConfig(filename);
1353  } else
1354  if (command == "WRITE_PARAM") {
1355  // Write params file, using current variable values.
1356  inBuffer >> filename;
1357  if (isIoProcessor()) {
1358  fileMaster().openOutputFile(filename, outputFile);
1359  writeParam(outputFile);
1360  outputFile.close();
1361  }
1362  } else
1363  if (command == "SET_CONFIG_IO") {
1364  // Create a ConfigIo object of specified subclass.
1365  // This gives file format for later reads and writes.
1366  std::string classname;
1367  inBuffer >> classname;
1368  setConfigIo(classname);
1369  } else
1370  if (command == "SET_INPUT_PREFIX") {
1371  // Set the FileMaster inputPrefix, which is used to
1372  // construct paths to input files.
1373  std::string prefix;
1374  inBuffer >> prefix;
1375  fileMaster().setInputPrefix(prefix);
1376  } else
1377  if (command == "SET_OUTPUT_PREFIX") {
1378  // Set the FileMaster outputPrefix, which is used to
1379  // construct paths to output files.
1380  std::string prefix;
1381  inBuffer >> prefix;
1382  fileMaster().setOutputPrefix(prefix);
1383  } else
1384  if (command == "SET_PAIR") {
1385  // Modify one parameter of a pair interaction.
1386  std::string paramName;
1387  int typeId1, typeId2;
1388  double value;
1389  inBuffer >> paramName >> typeId1 >> typeId2 >> value;
1390  pairPotential().set(paramName, typeId1, typeId2, value);
1391  } else
1392  #ifdef SIMP_BOND
1393  if (command == "SET_BOND") {
1394  if (nBondType_ == 0) {
1395  UTIL_THROW("SET_BOND command with nBondType = 0");
1396  }
1397  // Modify one parameter of a bond interaction.
1398  std::string paramName;
1399  int typeId;
1400  double value;
1401  inBuffer >> paramName >> typeId >> value;
1402  bondPotential().set(paramName, typeId, value);
1403  } else
1404  #endif
1405  #ifdef SIMP_ANGLE
1406  if (command == "SET_ANGLE") {
1407  if (nAngleType_ == 0) {
1408  UTIL_THROW("SET_ANGLE command with nAngleType = 0");
1409  }
1410  // Modify one parameter of an angle interaction.
1411  std::string paramName;
1412  int typeId;
1413  double value;
1414  inBuffer >> paramName >> typeId >> value;
1415  anglePotential().set(paramName, typeId, value);
1416  } else
1417  #endif
1418  #ifdef SIMP_DIHEDRAL
1419  if (command == "SET_DIHEDRAL") {
1420  if (nDihedralType_ == 0) {
1421  UTIL_THROW("SET_DIHEDRAL command with nDihedralType = 0");
1422  }
1423  // Modify one parameter of a dihedral interaction.
1424  std::string paramName;
1425  int typeId;
1426  double value;
1427  inBuffer >> paramName >> typeId >> value;
1428  dihedralPotential().set(paramName, typeId, value);
1429  } else
1430  #endif
1431  if (command == "SET_GROUP") {
1432  setGroup(inBuffer);
1433  } else
1434  if (command == "FINISH") {
1435  // Terminate loop over commands.
1436  readNext = false;
1437  } else {
1438  Log::file() << "Error: Unknown command " << std::endl;
1439  readNext = false;
1440  }
1441  }
1442 
1443  }
1444  }
1445 
1446  /*
1447  * Read and implement commands from the default command file.
1448  */
1450  {
1451  if (fileMaster().commandFileName().empty()) {
1452  UTIL_THROW("Empty command file name");
1453  }
1454  readCommands(fileMaster().commandFile());
1455  }
1456 
1457  /*
1458  * Set flag to specify if reverse communication is enabled.
1459  */
1460  void Simulation::setReverseUpdateFlag(bool reverseUpdateFlag)
1461  {
1462  reverseUpdateFlag_ = reverseUpdateFlag;
1463  if (pairPotentialPtr_) {
1464  pairPotential().setReverseUpdateFlag(reverseUpdateFlag);
1465  }
1466  }
1467 
1468  /*
1469  * Choose velocities from a Boltzmann distribution.
1470  */
1471  void Simulation::setBoltzmannVelocities(double temperature)
1472  {
1473  double mass;
1474  double scale;
1475  AtomIterator atomIter;
1476  int i;
1477  atomStorage_.begin(atomIter);
1478  for( ; atomIter.notEnd(); ++atomIter){
1479  mass = atomType(atomIter->typeId()).mass();
1480  assert(mass > 0);
1481  scale = sqrt(temperature/mass);
1482  for (i = 0; i < Dimension; ++i) {
1483  atomIter->velocity()[i] = scale*random_.gaussian();
1484  }
1485  }
1486 
1487  // Publish notification of change in velocities
1488  velocitySignal().notify();
1489  }
1490 
1491  /*
1492  * Remove the drift velocity
1493  */
1495  {
1496  Vector momentum(0.0); // atom momentum
1497  Vector momentumLocal(0.0); // sum of momenta on processor
1498  Vector momentumTotal(0.0); // total momentum of system
1499  double mass; // atom mass
1500  double massLocal = 0.0; // sum of masses on processor
1501  double massTotal = 0.0; // total momentum of system
1502  int j;
1503 
1504  // Calculate total momentum and mass on processor
1505  AtomIterator atomIter;
1506  atomStorage_.begin(atomIter);
1507  for( ; atomIter.notEnd(); ++atomIter){
1508  mass = atomType(atomIter->typeId()).mass();
1509  massLocal = massLocal + mass;
1510  for(j = 0; j<Dimension; ++j) {
1511  momentum[j] = atomIter->velocity()[j];
1512  momentum[j] *= mass;
1513  }
1514  momentumLocal += momentum;
1515  }
1516 
1517  // Compute total momentum and mass for system, by MPI all reduce
1518  domain_.communicator().Allreduce(&massLocal, &massTotal, 1,
1519  MPI::DOUBLE, MPI::SUM);
1520  domain_.communicator().Allreduce(&momentumLocal[0],
1521  &momentumTotal[0], Dimension,
1522  MPI::DOUBLE, MPI::SUM);
1523 
1524  // Subtract average drift velocity
1525  Vector drift = momentumTotal;
1526  drift /= massTotal;
1527  atomStorage_.begin(atomIter);
1528  for( ; atomIter.notEnd(); ++atomIter) {
1529  atomIter->velocity() -= drift;
1530  }
1531 
1532  // Publish notification of change in velocities
1533  velocitySignal().notify();
1534 
1535  return drift;
1536  }
1537 
1538  /*
1539  * Set forces on all atoms to zero.
1540  *
1541  * If reverseUpdateFlag() is true, zero local and ghost
1542  * atom forces, otherwise only local atoms.
1543  */
1545  { atomStorage_.zeroForces(reverseUpdateFlag_); }
1546 
1547  /*
1548  * Compute forces for all atoms.
1549  */
1551  {
1552  zeroForces();
1553  pairPotential().computeForces();
1554  #ifdef SIMP_BOND
1555  if (nBondType_) {
1556  bondPotential().computeForces();
1557  }
1558  #endif
1559  #ifdef SIMP_ANGLE
1560  if (nAngleType_) {
1561  anglePotential().computeForces();
1562  }
1563  #endif
1564  #ifdef SIMP_DIHEDRAL
1565  if (nDihedralType_) {
1566  dihedralPotential().computeForces();
1567  }
1568  #endif
1569  #ifdef SIMP_EXTERNAL
1570  if (hasExternal_) {
1571  externalPotential().computeForces();
1572  }
1573  #endif
1574 
1575  // Reverse communication (if any)
1576  if (reverseUpdateFlag_) {
1577  exchanger_.reverseUpdate();
1578  }
1579  }
1580 
1581  /*
1582  * Compute forces for all atoms and virial stress contributions.
1583  */
1585  {
1586  zeroForces();
1587  pairPotential().computeForcesAndStress(domain_.communicator());
1588  #ifdef SIMP_BOND
1589  if (nBondType_) {
1590  bondPotential().computeForcesAndStress(domain_.communicator());
1591  }
1592  #endif
1593  #ifdef SIMP_ANGLE
1594  if (nAngleType_) {
1595  anglePotential().computeForcesAndStress(domain_.communicator());
1596  }
1597  #endif
1598  #ifdef SIMP_DIHEDRAL
1599  if (nDihedralType_) {
1600  dihedralPotential().computeForcesAndStress(domain_.communicator());
1601  }
1602  #endif
1603  #ifdef SIMP_EXTERNAL
1604  if (hasExternal_) {
1605  externalPotential().computeForces();
1606  }
1607  #endif
1608 
1609  // Reverse communication (if any)
1610  if (reverseUpdateFlag_) {
1611  exchanger_.reverseUpdate();
1612  }
1613  }
1614 
1615  // --- Kinetic Energy methods ---------------------------------------
1616 
1617  /*
1618  * Calculate total kinetic energy (call on all processors).
1619  */
1621  {
1622  // Do nothing if kinetic energy is already set.
1623  if (kineticEnergy_.isSet()) return;
1624 
1625  double localEnergy = 0.0;
1626  double mass;
1627  int typeId;
1628 
1629  // Add kinetic energies of local atoms on this processor
1630  AtomIterator atomIter;
1631  atomStorage_.begin(atomIter);
1632  for( ; atomIter.notEnd(); ++atomIter){
1633  typeId = atomIter->typeId();
1634  mass = atomTypes_[typeId].mass();
1635  localEnergy += mass*(atomIter->velocity().square());
1636  }
1637  localEnergy = 0.5*localEnergy;
1638 
1639  #ifdef UTIL_MPI
1640  // Sum values from all processors.
1641  double totalEnergy = 0.0;
1642  domain_.communicator().Reduce(&localEnergy, &totalEnergy, 1,
1643  MPI::DOUBLE, MPI::SUM, 0);
1644  if (domain_.communicator().Get_rank() != 0) {
1645  totalEnergy = 0.0;
1646  }
1647  kineticEnergy_.set(totalEnergy);
1648  #else
1649  kineticEnergy_.set(localEnergy);
1650  #endif
1651  }
1652 
1653  /*
1654  * Return total kinetic energy (on master processor).
1655  *
1656  * Call only on master processor.
1657  */
1659  { return kineticEnergy_.value(); }
1660 
1661  /*
1662  * Mark kinetic energy as unknown.
1663  */
1665  { kineticEnergy_.unset(); }
1666 
1667  // --- Kinetic Stress methods ---------------------------------------
1668 
1669  /*
1670  * Compute total kinetic stress, store on master proc.
1671  *
1672  * Call on all processors.
1673  */
1675  {
1676 
1677  // Do nothing and return if kinetic stress is already set
1678  if (kineticStress_.isSet()) return;
1679 
1680  Tensor localStress;
1681  double mass;
1682  Vector velocity;
1683  int typeId, i, j;
1684 
1685  localStress.zero();
1686 
1687  // For each local atoms on this processor, stress(i, j) += m*v[i]*v[j]
1688  AtomIterator atomIter;
1689  atomStorage_.begin(atomIter);
1690  for( ; atomIter.notEnd(); ++atomIter){
1691  typeId = atomIter->typeId();
1692  velocity = atomIter->velocity();
1693  mass = atomTypes_[typeId].mass();
1694  for (i = 0; i < Dimension; ++i) {
1695  for (j = 0; j < Dimension; ++j) {
1696  localStress(i, j) += mass*velocity[i]*velocity[j];
1697  }
1698  }
1699  }
1700 
1701  // Divide dyad sum by system volume
1702  localStress /= boundary().volume();
1703 
1704  #ifdef UTIL_MPI
1705  // Sum values from all processors
1706  Tensor totalStress;
1707  domain_.communicator().Reduce(&localStress(0, 0), &totalStress(0, 0),
1708  Dimension*Dimension, MPI::DOUBLE, MPI::SUM, 0);
1709  if (domain_.communicator().Get_rank() != 0) {
1710  totalStress.zero();
1711  }
1712  kineticStress_.set(totalStress);
1713  #else
1714  kineticStress_.set(localStress);
1715  #endif
1716  }
1717 
1718  /*
1719  * Return total kinetic stress (on master processor).
1720  */
1722  { return kineticStress_.value(); }
1723 
1724  /*
1725  * Return total kinetic pressure (on master processor).
1726  */
1728  {
1729  double pressure = 0.0;
1730  for (int i = 0; i < Dimension; ++i) {
1731  pressure += kineticStress_.value()(i, i);
1732  }
1733  pressure /= 3.0;
1734  return pressure;
1735  }
1736 
1737  /*
1738  * Mark kinetic stress as unknown.
1739  */
1741  { kineticStress_.unset(); }
1742 
1743  // --- Potential Energy Methods -------------------------------------
1744 
1745  #ifdef UTIL_MPI
1746  /*
1747  * Compute all potential energy contributions.
1748  */
1750  {
1751  pairPotential().computeEnergy(domain_.communicator());
1752  #ifdef SIMP_BOND
1753  if (nBondType_) {
1754  bondPotential().computeEnergy(domain_.communicator());
1755  }
1756  #endif
1757  #ifdef SIMP_ANGLE
1758  if (nAngleType_) {
1759  anglePotential().computeEnergy(domain_.communicator());
1760  }
1761  #endif
1762  #ifdef SIMP_DIHEDRAL
1763  if (nDihedralType_) {
1764  dihedralPotential().computeEnergy(domain_.communicator());
1765  }
1766  #endif
1767  #ifdef SIMP_EXTERNAL
1768  if (hasExternal_) {
1769  externalPotential().computeEnergy(domain_.communicator());
1770  }
1771  #endif
1772  }
1773 
1774  #else
1775  /*
1776  * Compute all potential energy contributions.
1777  */
1779  {
1780  pairPotential().computeEnergy();
1781  #ifdef SIMP_BOND
1782  if (nBondType_) {
1783  bondPotential().computeEnergy();
1784  }
1785  #endif
1786  #ifdef SIMP_ANGLE
1787  if (nAngleType_) {
1788  anglePotential().computeEnergy();
1789  }
1790  #endif
1791  #ifdef SIMP_DIHEDRAL
1792  if (nDihedralType_) {
1793  dihedralPotential().computeEnergy();
1794  }
1795  #endif
1796  #ifdef SIMP_EXTERNAL
1797  if (hasExternal_) {
1798  externalPotential().computeEnergy();
1799  }
1800  #endif
1801  }
1802  #endif
1803 
1804  /*
1805  * Methods computePotentialEnergies and computeStress rely on use
1806  * of lazy (as-needed) evaluation within the compute methods of
1807  * each of the potential energy classes: Each potential energy or
1808  * virial contribution is actually computed only if it has been
1809  * unset since the last evaluation. Lazy evaluation is implemented
1810  * explicitly in the Simulation class only for the kinetic energy
1811  * and kinetic stress, which are stored as members of Simulation.
1812  */
1813 
1814  /*
1815  * Return sum of potential energy contributions.
1816  */
1818  {
1819  double energy = 0.0;
1820  energy += pairPotential().energy();
1821  #ifdef SIMP_BOND
1822  if (nBondType_) {
1823  energy += bondPotential().energy();
1824  }
1825  #endif
1826  #ifdef SIMP_ANGLE
1827  if (nAngleType_) {
1828  energy += anglePotential().energy();
1829  }
1830  #endif
1831  #ifdef SIMP_DIHEDRAL
1832  if (nDihedralType_) {
1833  energy += dihedralPotential().energy();
1834  }
1835  #endif
1836  #ifdef SIMP_EXTERNAL
1837  if (hasExternal_) {
1838  energy += externalPotential().energy();
1839  }
1840  #endif
1841  return energy;
1842  }
1843 
1844  /*
1845  * Mark all potential energies as unknown.
1846  */
1848  {
1849  pairPotential().unsetEnergy();
1850  #ifdef SIMP_BOND
1851  if (nBondType_) {
1852  bondPotential().unsetEnergy();
1853  }
1854  #endif
1855  #ifdef SIMP_ANGLE
1856  if (nAngleType_) {
1857  anglePotential().unsetEnergy();
1858  }
1859  #endif
1860  #ifdef SIMP_DIHEDRAL
1861  if (nDihedralType_) {
1862  dihedralPotential().unsetEnergy();
1863  }
1864  #endif
1865  #ifdef SIMP_EXTERNAL
1866  if (hasExternal_) {
1867  externalPotential().unsetEnergy();
1868  }
1869  #endif
1870  }
1871 
1872  // --- Virial Stress Methods ----------------------------------------
1873 
1874  #ifdef UTIL_MPI
1875  /*
1876  * Compute all virial stress contributions.
1877  */
1879  {
1880  pairPotential().computeStress(domain_.communicator());
1881  #ifdef SIMP_BOND
1882  if (nBondType_) {
1883  bondPotential().computeStress(domain_.communicator());
1884  }
1885  #endif
1886  #ifdef SIMP_ANGLE
1887  if (nAngleType_) {
1888  anglePotential().computeStress(domain_.communicator());
1889  }
1890  #endif
1891  #ifdef SIMP_DIHEDRAL
1892  if (nDihedralType_) {
1893  dihedralPotential().computeStress(domain_.communicator());
1894  }
1895  #endif
1896  }
1897  #else
1898  /*
1899  * Return stored value of virial stress (call only on master).
1900  */
1902  {
1903  pairPotential().computeStress();
1904  #ifdef SIMP_BOND
1905  if (nBondType_) {
1906  bondPotential().computeStress();
1907  }
1908  #endif
1909  #ifdef SIMP_ANGLE
1910  if (nAngleType_) {
1911  anglePotential().computeStress();
1912  }
1913  #endif
1914  #ifdef SIMP_DIHEDRAL
1915  if (nDihedralType_) {
1916  dihedralPotential().computeStress();
1917  }
1918  #endif
1919  }
1920  #endif
1921 
1922  /*
1923  * Return total virial stress.
1924  */
1926  {
1927  Tensor stress;
1928  stress.zero();
1929  stress += pairPotential().stress();
1930  #ifdef SIMP_BOND
1931  if (nBondType_) {
1932  stress += bondPotential().stress();
1933  }
1934  #endif
1935  #ifdef SIMP_ANGLE
1936  if (nAngleType_) {
1937  stress += anglePotential().stress();
1938  }
1939  #endif
1940  #ifdef SIMP_DIHEDRAL
1941  if (nDihedralType_) {
1942  stress += dihedralPotential().stress();
1943  }
1944  #endif
1945  return stress;
1946  }
1947 
1948  /*
1949  * Return total virial pressure contribution.
1950  */
1952  {
1953  double pressure;
1954  pressure = 0;
1955  pressure += pairPotential().pressure();
1956  #ifdef SIMP_BOND
1957  if (nBondType_) {
1958  pressure += bondPotential().pressure();
1959  }
1960  #endif
1961  #ifdef SIMP_ANGLE
1962  if (nAngleType_) {
1963  pressure += anglePotential().pressure();
1964  }
1965  #endif
1966  #ifdef SIMP_DIHEDRAL
1967  if (nDihedralType_) {
1968  pressure += dihedralPotential().pressure();
1969  }
1970  #endif
1971  return pressure;
1972  }
1973 
1974  #ifdef UTIL_MPI
1975  /*
1976  * Compute all pair energy contributions.
1977  */
1979  { pairPotential().computePairEnergies(domain_.communicator()); }
1980  #else
1981  /*
1982  * Compute all pair energy contributions.
1983  */
1985  { pairPotential().computePairEnergies(); }
1986  #endif
1987 
1988  /*
1989  * Return pair energies contributions.
1990  */
1992  {
1993  DMatrix<double> pairEnergies;
1994  pairEnergies.allocate(nAtomType_, nAtomType_);
1995  pairEnergies = pairPotential().pairEnergies();
1996  return pairEnergies;
1997  }
1998 
1999  /*
2000  * Mark all potential energies as unknown.
2001  */
2003  {
2004  pairPotential().unsetStress();
2005  #ifdef SIMP_BOND
2006  if (nBondType_) {
2007  bondPotential().unsetStress();
2008  }
2009  #endif
2010  #ifdef SIMP_ANGLE
2011  if (nAngleType_) {
2012  anglePotential().unsetStress();
2013  }
2014  #endif
2015  #ifdef SIMP_DIHEDRAL
2016  if (nDihedralType_) {
2017  dihedralPotential().unsetStress();
2018  }
2019  #endif
2020  }
2021 
2022  // --- ConfigIo Accessors -------------------------------------------
2023 
2024  /*
2025  * Return the ConfigIo (create default if necessary).
2026  */
2027  ConfigIo& Simulation::configIo()
2028  {
2029  if (configIoPtr_ == 0) {
2030  if (Atom::hasAtomContext()) {
2031  // DdMdConfigIo format with hasMolecules = true
2032  configIoPtr_ = new DdMdConfigIo(*this, true);
2033  } else {
2034  // DdMdConfigIo format with hasMolecules = false
2035  configIoPtr_ = new DdMdConfigIo(*this, false);
2036  }
2037  }
2038  return *configIoPtr_;
2039  }
2040 
2041  /*
2042  * Return a SerialConfigIo (create if necessary).
2043  */
2044  SerializeConfigIo& Simulation::serializeConfigIo()
2045  {
2046  if (serializeConfigIoPtr_ == 0) {
2047  serializeConfigIoPtr_ = new SerializeConfigIo(*this);
2048  }
2049  return *serializeConfigIoPtr_;
2050  }
2051 
2052  // --- Config File Read and Write -----------------------------------
2053 
2054  /*
2055  * Read configuration file on master and distribute atoms.
2056  */
2057  void Simulation::readConfig(const std::string& filename)
2058  {
2059  std::ifstream inputFile;
2060  if (domain_.isMaster()) {
2061  fileMaster().openInputFile(filename, inputFile);
2062  }
2063  configIo().readConfig(inputFile, maskedPairPolicy_);
2064  exchanger_.exchange();
2065  if (domain_.isMaster()) {
2066  inputFile.close();
2067  }
2068  }
2069 
2070  /*
2071  * Write configuration file on master.
2072  */
2073  void Simulation::writeConfig(const std::string& filename)
2074  {
2075  std::ofstream outputFile;
2076  if (domain_.isMaster()) {
2077  fileMaster().openOutputFile(filename, outputFile);
2078  }
2079  configIo().writeConfig(outputFile);
2080  if (domain_.isMaster()) {
2081  outputFile.close();
2082  }
2083  }
2084 
2085  // --- Potential Factories and Styles -------------------------------
2086 
2087  /*
2088  * Return the PairFactory by reference.
2089  */
2091  {
2092  if (!pairFactoryPtr_) {
2093  pairFactoryPtr_ = new PairFactory(*this);
2094  }
2095  assert(pairFactoryPtr_);
2096  return *pairFactoryPtr_;
2097  }
2098 
2099  /*
2100  * Get the pair style string.
2101  */
2102  std::string Simulation::pairStyle() const
2103  { return pairStyle_; }
2104 
2105  #ifdef SIMP_BOND
2106  /*
2107  * Return the BondFactory by reference.
2108  */
2110  {
2111  if (!bondFactoryPtr_) {
2112  bondFactoryPtr_ = new BondFactory(*this);
2113  }
2114  assert(bondFactoryPtr_);
2115  return *bondFactoryPtr_;
2116  }
2117 
2118  /*
2119  * Get the bond style string.
2120  */
2121  std::string Simulation::bondStyle() const
2122  { return bondStyle_; }
2123  #endif
2124 
2125  #ifdef SIMP_ANGLE
2126  /*
2127  * Return the AngleFactory by reference.
2128  */
2130  {
2131  if (angleFactoryPtr_ == 0) {
2132  angleFactoryPtr_ = new AngleFactory(*this);
2133  }
2134  assert(angleFactoryPtr_);
2135  return *angleFactoryPtr_;
2136  }
2137 
2138  /*
2139  * Get the angle style string.
2140  */
2141  std::string Simulation::angleStyle() const
2142  { return angleStyle_; }
2143  #endif
2144 
2145  #ifdef SIMP_DIHEDRAL
2146  /*
2147  * Return the DihedralFactory by reference.
2148  */
2150  {
2151  if (dihedralFactoryPtr_ == 0) {
2152  dihedralFactoryPtr_ = new DihedralFactory(*this);
2153  }
2154  assert(dihedralFactoryPtr_);
2155  return *dihedralFactoryPtr_;
2156  }
2157 
2158  /*
2159  * Get the dihedral style string.
2160  */
2161  std::string Simulation::dihedralStyle() const
2162  { return dihedralStyle_; }
2163  #endif
2164 
2165  #ifdef SIMP_EXTERNAL
2166  /*
2167  * Return the ExternalFactory by reference.
2168  */
2170  {
2171  if (externalFactoryPtr_ == 0) {
2172  externalFactoryPtr_ = new ExternalFactory(*this);
2173  }
2174  assert(externalFactoryPtr_);
2175  return *externalFactoryPtr_;
2176  }
2177 
2178  /*
2179  * Get the external style string.
2180  */
2181  std::string Simulation::externalStyle() const
2182  { return externalStyle_; }
2183  #endif
2184 
2185  // --- Integrator and ConfigIo Management ---------------------------
2186 
2187  /*
2188  * Return the IntegratorFactory by reference.
2189  */
2191  {
2192  if (integratorFactoryPtr_ == 0) {
2193  integratorFactoryPtr_ = new IntegratorFactory(*this);
2194  }
2195  assert(integratorFactoryPtr_);
2196  return *integratorFactoryPtr_;
2197  }
2198 
2199  /*
2200  * Return the ConfigIoFactory by reference.
2201  */
2203  {
2204  if (configIoFactoryPtr_ == 0) {
2205  configIoFactoryPtr_ = new ConfigIoFactory(*this);
2206  }
2207  assert(configIoFactoryPtr_);
2208  return *configIoFactoryPtr_;
2209  }
2210 
2211  /*
2212  * Set the ConfigIo, identified by subclass name.
2213  */
2214  void Simulation::setConfigIo(std::string& classname)
2215  {
2216  ConfigIo* ptr = configIoFactory().factory(classname);
2217  if (!ptr) {
2218  UTIL_THROW("Unrecognized ConfigIo subclass name");
2219  }
2220  if (configIoPtr_) {
2221  delete configIoPtr_;
2222  }
2223  configIoPtr_ = ptr;
2224  }
2225 
2226  // --- Group Management ---------------------------------------------
2227 
2228  /*
2229  * Return true if this Simulation is valid, or throw an Exception.
2230  */
2231  void Simulation::setGroup(std::stringstream& inBuffer)
2232  {
2233 
2234  // Read groupId and create a corresponding bit mask
2235  unsigned int groupId;
2236  inBuffer >> groupId;
2237  Bit bit(groupId);
2238 
2239  // Read the group style
2240  std::string groupStyle;
2241  inBuffer >> groupStyle;
2242 
2243  AtomIterator iter;
2244  if (groupStyle == "delete") {
2245  for (atomStorage_.begin(iter) ; iter.notEnd(); ++iter) {
2246  bit.clear(iter->groups());
2247  }
2248  } else
2249  if (groupStyle == "all") {
2250  for (atomStorage_.begin(iter) ; iter.notEnd(); ++iter) {
2251  bit.set(iter->groups());
2252  }
2253  } else
2254  if (groupStyle == "atomType") {
2255  int typeId;
2256  inBuffer >> typeId;
2257  for (atomStorage_.begin(iter) ; iter.notEnd(); ++iter) {
2258  if (iter->typeId() == typeId) {
2259  bit.set(iter->groups());
2260  }
2261  }
2262  } else
2263  if (groupStyle == "species") {
2264  if (!Atom::hasAtomContext()) {
2265  UTIL_THROW("AtomContext is not enabled");
2266  }
2267  int speciesId;
2268  inBuffer >> speciesId;
2269  for (atomStorage_.begin(iter) ; iter.notEnd(); ++iter) {
2270  if (iter->context().speciesId == speciesId) {
2271  bit.set(iter->groups());
2272  }
2273  }
2274  } else {
2275  std::string msg = "SET_GROUP command with unknown group style ";
2276  msg += groupStyle;
2277  UTIL_THROW(msg.c_str());
2278  }
2279  }
2280 
2281  // --- Miscellaneous ----------------------------------------------
2282 
2283  /*
2284  * Output a list of enabled and disabled compile time options.
2285  */
2286  void Simulation::outputOptions(std::ostream& out) const
2287  {
2288  #ifdef UTIL_DEBUG
2289  out << "-g Debugging ON " << std::endl;
2290  #else
2291  out << "-g Debugging OFF" << std::endl;
2292  #endif
2293  #ifdef UTIL_MPI
2294  out << "-m MPI ON " << std::endl;
2295  #else
2296  out << "-m MPI OFF" << std::endl;
2297  #endif
2298  #ifdef SIMP_COULOMB
2299  out << "-c Coulomb ON " << std::endl;
2300  #else
2301  out << "-c Coulomb OFF" << std::endl;
2302  #endif
2303  #ifndef SIMP_NOPAIR
2304  out << "-np Pairs ON " << std::endl;
2305  #else
2306  out << "-np Pairs OFF" << std::endl;
2307  #endif
2308  #ifdef SIMP_BOND
2309  out << "-b Bonds ON " << std::endl;
2310  #else
2311  out << "-b Bonds OFF" << std::endl;
2312  #endif
2313  #ifdef SIMP_ANGLE
2314  out << "-a Angles ON " << std::endl;
2315  #else
2316  out << "-a Angles OFF" << std::endl;
2317  #endif
2318  #ifdef SIMP_DIHEDRAL
2319  out << "-d Dihedrals ON " << std::endl;
2320  #else
2321  out << "-d Dihedrals OFF" << std::endl;
2322  #endif
2323  #ifdef SIMP_EXTERNAL
2324  out << "-e External ON " << std::endl;
2325  #else
2326  out << "-e External OFF" << std::endl;
2327  #endif
2328  #ifdef SIMP_SPECIAL
2329  out << "-s Special ON " << std::endl;
2330  #else
2331  out << "-s Special OFF" << std::endl;
2332  #endif
2333  }
2334 
2335  /*
2336  * Return true if this Simulation is valid, or throw an Exception.
2337  */
2339  {
2340  #ifdef UTIL_MPI
2341  atomStorage_.isValid(domain_.communicator());
2342  #else
2343  atomStorage_.isValid();
2344  #endif
2345 
2346  // Determine if there are any ghosts on any processor
2347  int nGhost = atomStorage_.nGhost();
2348  int nGhostAll = 0;
2349  #ifdef UTIL_MPI
2350  domain_.communicator().Reduce(&nGhost, &nGhostAll, 1,
2351  MPI::INT, MPI::SUM, 0);
2352  bcast(domain_.communicator(), nGhostAll, 0);
2353  #else
2354  nGhostAll = nGhost;
2355  #endif
2356  bool hasGhosts = bool(nGhostAll);
2357 
2358  // Test Group storage containers
2359  #ifdef UTIL_MPI
2360  #ifdef SIMP_BOND
2361  if (nBondType_) {
2362  bondStorage_.isValid(atomStorage_, domain_.communicator(), hasGhosts);
2363  }
2364  #endif
2365  #ifdef SIMP_ANGLE
2366  if (nAngleType_) {
2367  angleStorage_.isValid(atomStorage_, domain_.communicator(), hasGhosts);
2368  }
2369  #endif
2370  #ifdef SIMP_DIHEDRAL
2371  if (nDihedralType_) {
2372  dihedralStorage_.isValid(atomStorage_, domain_.communicator(),
2373  hasGhosts);
2374  }
2375  #endif
2376  #else // ifdef UTIL_MPI
2377  #ifdef SIMP_BOND
2378  if (nBondType_) {
2379  bondStorage_.isValid(atomStorage_, hasGhosts);
2380  }
2381  #endif
2382  #ifdef SIMP_ANGLE
2383  if (nAngleType_) {
2384  angleStorage_.isValid(atomStorage_, hasGhosts);
2385  }
2386  #endif
2387  #ifdef SIMP_DIHEDRAL
2388  if (nDihedralType_) {
2389  dihedralStorage_.isValid(atomStorage_, hasGhosts);
2390  }
2391  #endif
2392  #endif // ifdef UTIL_MPI
2393 
2394  // Test consistency of computed potential energies and stresses
2395  #ifdef UTIL_MPI
2396  pairPotential().isValid(domain_.communicator());
2397  #ifdef SIMP_BOND
2398  if (nBondType_) {
2399  bondPotential().isValid(domain_.communicator());
2400  }
2401  #endif
2402  #ifdef SIMP_ANGLE
2403  if (nAngleType_) {
2404  anglePotential().isValid(domain_.communicator());
2405  }
2406  #endif
2407  #ifdef SIMP_DIHEDRAL
2408  if (nDihedralType_) {
2409  dihedralPotential().isValid(domain_.communicator());
2410  }
2411  #endif
2412  #ifdef SIMP_EXTERNAL
2413  if (hasExternal_) {
2414  externalPotential().isValid(domain_.communicator());
2415  }
2416  #endif
2417  #endif // ifdef UTIL_MPI
2418 
2419  return true;
2420  }
2421 
2422 }
void writeConfig(const std::string &filename)
Write configuration file.
void computeForcesAndVirial()
Compute forces for all local atoms and virial stress.
void readPotentialStyles(std::istream &in)
Read potential styles and maskedPairPolicy.
void loadEnsembles(Serializable::IArchive &ar)
Load energy and boundary ensembles from an input archive.
void set(unsigned int &flags) const
Set this bit in the flags parameter.
Definition: Bit.h:80
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
static void commitMpiType()
Commit MPI datatype MpiTraits<Vector>::type.
Definition: Vector.cpp:97
A Vector is a Cartesian vector.
Definition: Vector.h:75
static void commitMpiType()
Commit MPI datatype MpiTraits<IntVector>::type.
Definition: IntVector.cpp:92
virtual void loadParameters(Serializable::IArchive &ar)
Load parameters from a restart archive.
void setConfigIo(std::string &classname)
Create a new configuration file reader/writer.
void setBoltzmannVelocities(double temperature)
Set random velocities chosen from a Boltzmann distribution.
Factory< ConfigIo > & configIoFactory()
Get the configuration file reader/writer factory by reference.
virtual void readParameters(std::istream &in)
Read body of the parameter block, allocate memory and initialize.
void computeForces()
Compute forces for all local atoms.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition: DMatrix.h:170
void readConfig(const std::string &filename)
Read configuration file on master and distribute atoms.
double kineticEnergy()
Return precomputed total kinetic energy.
Factory< DihedralPotential > & dihedralFactory()
Get the associated Dihedral Factory by reference.
Default Factory for subclasses of ConfigIo.
virtual void readParam()
Read parameters from default parameter file.
static void initStatic()
Call this to guarantee initialization of static data.
Manager for a list of Analyzer objects.
double kineticPressure() const
Return total kinetic pressure.
Factory for PairPotential objects.
DMatrix< double > pairEnergies() const
Return precomputed pair energies.
Statistical ensemble for changes in the periodic unit cell size.
static void setEcho(bool echo=true)
Enable or disable echoing for all subclasses of ParamComponent.
void unsetPotentialEnergies()
Mark all potential energies as unknown.
Tensor & zero()
Set all elements of this tensor to zero.
Definition: Tensor.h:441
void zeroForces()
Set forces for all atoms to zero.
Parallel domain decomposition (DD) MD simulation.
Classes used by all simpatico molecular simulations.
void initStatic()
Guarantee initialization of all static class members in Util namespace.
void readCommands()
Read and execute commands from the default command file.
Factory< BondPotential > & bondFactory()
Get the Factory<BondPotential> by reference.
double virialPressure() const
Return total virial pressure.
void outputOptions(std::ostream &out) const
Output a list of options enabled & disabled during compilation.
Native / default format for configuration files.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
void clear(unsigned int &flags) const
Clear this bit in the flags parameter.
Definition: Bit.h:86
void unsetVirialStress()
Mark all virial stress contributions as unknown.
void load(const std::string &filename)
Load internal state from a restart file.
void saveEnsembles(Serializable::OArchive &ar)
Save energy and boundary ensembles to archive.
void unsetNTotal()
Mark nTotal as unknown.
static void setFile(std::ofstream &file)
Set the log ostream to a file.
Definition: Log.cpp:36
Saving / output archive for binary ostream.
bool getNextLine(std::istream &in, std::string &line)
Read the next non-empty line into a string, strip trailing whitespace.
Definition: ioUtil.cpp:79
Factory< ExternalPotential > & externalFactory()
Get the associated External Factory by reference.
A statistical ensemble for energy.
void unsetKineticStress()
Mark kinetic stress as unknown.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
void unsetKineticEnergy()
Mark kinetic energy as unknown.
Factory for BondPotential objects.
void bcast(MPI::Intracomm &comm, T &data, int root)
Broadcast a single T value.
Definition: MpiSendRecv.h:134
std::string bondStyle() const
Return covalent bond style string.
Factory for subclasses of Integrator (i.e., MD integrators).
void computePotentialEnergies()
Calculate and store total potential energy on all processors.
Factory< Integrator > & integratorFactory()
Get the Integrator factory by reference.
void saveFileMaster(Serializable::OArchive &ar)
Save FileMaster to archive.
Factory for ExternalPotential objects.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
Definition: accumulators.mod:1
void computePairEnergies()
Compute pair energies for each pair of atom types.
static bool hasAtomContext()
Is AtomContext data enabled?
void loadPotentialStyles(Serializable::IArchive &ar)
Load potential styles.
Tensor kineticStress() const
Return total kinetic stress.
Factory for DihedralPotential objects.
void readEnsembles(std::istream &in)
Read energy and boundary ensembles.
void readFileMaster(std::istream &in)
Read the FileMaster.
void setReverseUpdateFlag(bool reverseUpdateFlag)
Set flag to identify if reverse communication is enabled.
void setOptions(int argc, char *const *argv)
Process command line options.
void computeVirialStress()
Calculate and store all virial stress contributions.
Factory< AnglePotential > & angleFactory()
Get the AngleFactory by reference.
static std::ostream & file()
Get log ostream by reference.
Definition: Log.cpp:57
Factory< PairPotential > & pairFactory()
Get the Factory<PairPotential> by reference.
A FileMaster manages input and output files for a simulation.
Definition: FileMaster.h:142
double potentialEnergy() const
Return sum of precomputed total potential energies.
Manager for a set of Modifier objects.
Saving archive for binary istream.
Abstract reader/writer for configuration files.
static void setHasAtomContext(bool hasAtomContext)
Enable (true) or disable (false) use of AtomContext data.
std::ifstream & file()
Get the underlying ifstream by reference.
Container for Group<3> (angle) objects.
Definition: AngleStorage.h:25
Save / load configuration from / to an archive.
static int max()
Return the maximum amount of allocated heap memory thus far.
Definition: Memory.cpp:52
This file contains templates for global functions send<T>, recv<T> and bcast<T>.
Vector removeDriftVelocity()
Subtract system center of mass velocity from atom velocities.
Factory for AnglePotential objects.
std::string pairStyle() const
Return nonbonded pair style string.
Represents a specific bit location within an unsigned int.
Definition: Bit.h:21
Container for Group<4> (dihedral) objects.
std::string dihedralStyle() const
Return dihedral potential style string.
bool isValid()
Return true if this Simulation is valid, or throw an Exception.
void computeKineticEnergy()
Compute total kinetic energy.
void savePotentialStyles(Serializable::OArchive &ar)
Save potential styles to archive.
Tensor virialStress() const
Return total virial stress.
Iterator for all atoms owned by an AtomStorage.
Definition: AtomIterator.h:24
void save(const std::string &filename)
Save state to a restart file.
std::ofstream & file()
Get the underlying ifstream by reference.
static void saveOptional(Serializable::OArchive &ar, Type &value, bool isActive)
Save an optional parameter value to an output archive.
Definition: Parameter.h:224
void loadFileMaster(Serializable::IArchive &ar)
Load FileMaster from an archive.
void computeKineticStress()
Calculate and store kinetic stress.
std::string externalStyle() const
Return external potential style string.
Simulation(MPI::Intracomm &communicator=MPI::COMM_WORLD)
Constructor.
Container for for Group<2> (bond) objects.
Definition: BondStorage.h:25
std::string angleStyle() const
Return angle potential style string.