SSAGES  0.9.3
Software Suite for Advanced General Ensemble Simulations
ForwardFlux.cpp
1 
23 #include "ForwardFlux.h"
24 #include "DirectForwardFlux.h"
25 #include "FileContents.h"
26 #include "CVs/CVManager.h"
27 #include "Validator/ObjectRequirement.h"
28 #include "Drivers/DriverException.h"
29 #include "Snapshot.h"
30 #include "schema.h"
31 #include "sys/stat.h"
32 #include <iostream>
33 #include <queue>
34 
35 using namespace Json;
36 
37 namespace SSAGES
38 {
39  void ForwardFlux::PreSimulation(Snapshot* /* snap */, const CVManager& cvmanager)
40  {
41  auto cvs = cvmanager.GetCVs(cvmask_);
42  if(cvs.size() > 1)
43  throw BuildException({"Forwardflux currently only works with one cv."});
44 
45  std::cout << "\nWARNING! MAKE SURE LAMMPS GIVES A DIFFERENT RANDOM SEED TO EACH PROCESSOR, OTHERWISE EACH FFS TRAJ WILL BE IDENTICAL!\n";
46  }
47 
48  void ForwardFlux::PostSimulation(Snapshot* snapshot, const CVManager&)
49  {
50  std::cout << "Post simulation\n";
51 
52  ComputeCommittorProbability(snapshot);
53  ComputeTransitionProbabilities();
54 
55  if (_saveTrajectories)
56  ReconstructTrajectories(snapshot);
57 
58  MPI_Abort(world_, EXIT_FAILURE); //more elegant solution?
59  }
60 
61  void ForwardFlux::CheckInitialStructure(const CVList& cvs)
62  {
63  if (_initialFluxFlag)
64  {
65  std::cout << "Running initial Flux calculations" << std::endl;
66 
67  // Check if we are in State A
68  _cvvalue = cvs[0]->GetValue();
69  _cvvalue_previous = _cvvalue;
70  double _firstInterfaceLocation = _interfaces[0];
71  if ( _cvvalue > _firstInterfaceLocation)
72  {
73  std::cerr << "Please provide an initial configuration in State A. Exiting ...." << std::endl;
74  MPI_Abort(world_, EXIT_FAILURE);
75  }
76  }
77  }
78 
79  int ForwardFlux::HasCrossedInterface(double current, double prev, unsigned int i)
80  {
81  double interface_location = _interfaces[i];
82  if (_interfaces_increase)
83  {
84  if ((prev <= interface_location) && (current >= interface_location))
85  return 1;
86  else if ((prev >= interface_location) && (current <= interface_location))
87  return -1;
88  else
89  return 0;
90  }
91  else
92  {
93  if ((prev >= interface_location) && (current <= interface_location))
94  return 1;
95  else if ((prev <= interface_location) && (current >= interface_location))
96  return -1;
97  else
98  return 0;
99  }
100  }
101 
102  bool ForwardFlux::HasReturnedToA(double current)
103  {
104  double interface_location = _interfaces[0];
105  if (_interfaces_increase)
106  {
107  if (current < interface_location) return true;
108  else return false;
109  }
110  else
111  {
112  if (current > interface_location) return true;
113  else return false;
114  }
115  }
116 
117  void ForwardFlux::ComputeInitialFlux(Snapshot* snapshot, const CVList& cvs)
118  {
119  _cvvalue = cvs[0]->GetValue();
120 
121  //check if we've crossed the first interface (lambda 0)
122  int hascrossed = HasCrossedInterface(_cvvalue, _cvvalue_previous, 0);
123  unsigned int success_local = false;
124  std::vector<unsigned int> successes (world_.size(),0);
125 
126  if (hascrossed == 1)
127  success_local = true;
128 
129  //for each traj that crossed to lambda0 in forward direction, we need to write it to disk (FFSConfigurationFile)
130  MPI_Allgather(&success_local,1,MPI_UNSIGNED,successes.data(),1,MPI_UNSIGNED,world_);
131 
132  int success_count = 0;
133  for (int i = 0; i < world_.size(); i++)
134  {
135  // Since we are in State A, the values of lprev, nprev, aprev are all zero.
136  if (successes[i] == true)
137  {
138  if (i == world_.rank())
139  {
140  int l,n,a,lprev,nprev,aprev;
141  //update ffsconfigid's l,n,a
142  //note lprev == l for initial interface
143  l = 0;
144  n = _N[0] + success_count;
145  a = 0;
146  lprev = l;
147  nprev = n;
148  aprev = a;
149 
150  FFSConfigID newid = FFSConfigID(l,n,a,lprev,nprev,aprev);
151  Lambda0ConfigLibrary.emplace_back(l,n,a,lprev,nprev,aprev);
152  WriteFFSConfiguration(snapshot,newid,1);
153  }
154  success_count++;
155  }
156  }
157 
158  // all procs update correctly
159  _N[0] += success_count;
160 
161  // If not in B, increment the time
162  double N0SimTime_local = 0;
163  double N0SimTime;
164  int reachedB = HasCrossedInterface(_cvvalue, _cvvalue_previous, _ninterfaces-1);
165  // Question: This condition says that if we cross the last interface-> stop counting. We need to stop counting as long as we are in state B.
166  if (!(reachedB == 1) && (_cvvalue < _interfaces.back()))
167  N0SimTime_local++; //or += frequency if FFS isn't called on every step!
168 
169  // Allreduce then increment total
170  MPI_Allreduce(&N0SimTime_local, &N0SimTime, 1, MPI_DOUBLE, MPI_SUM,world_);
171  _N0TotalSimTime += N0SimTime;
172 
173  //print some info
174  if (success_local)
175  {
176  std::cout << "Iteration: "<< iteration_ << ", proc " << world_.rank() << std::endl;
177  std::cout << "Successful attempt. (cvvalue_previous: " << _cvvalue_previous << " cvvalue " << _cvvalue << " )" << std::endl;
178  std::cout << "# of successes: " << _N[0] << std::endl;
179  std::cout << "required # of configurations: " << _N0Target << std::endl;
180  }
181 
182  // Check if the required number of initial configurations are created, if so print a message, and compute the initial flux.
183  if (_N[0] >= _N0Target)
184  {
185  std::cout << "Initial flux calculation was successfully completed" << std::endl;
186  // Call a function to compute the actual flux and output the data
187  WriteInitialFlux();
188  //responsible for setting _initialFluxFlag = false when finished
189  _initialFluxFlag = false;
190  }
191 
192  _cvvalue_previous = _cvvalue;
193  iteration_++;
194  }
195 
196  void ForwardFlux::WriteInitialFlux()
197  {
198  std::ofstream file;
199  std::string filename = _output_directory + "/initial_flux_value.dat";
200  file.open(filename.c_str());
201  if(!file)
202  {
203  std::cerr << "Error! Unable to write " << filename << std::endl;
204  MPI_Abort(world_, EXIT_FAILURE);
205  }
206  _fluxA0 = (double) (_N[0] / _N0TotalSimTime);
207  file << "number of walkers: " << world_.size() << std::endl;
208  file << "number of iterations: " << iteration_ << std::endl;
209  file << "Total simulation time: " << _N0TotalSimTime << std::endl;
210  file << "Initial flux: " << _fluxA0 << std::endl;
211  file.close();
212  }
213 
214  void ForwardFlux::ComputeTransitionProbabilities()
215  {
216  double Ptotal = 1;
217  for (unsigned int i = 0; i < _ninterfaces -1; i++)
218  Ptotal *= _P[i];
219 
220  _rate = Ptotal*_fluxA0;
221 
222  //write file
223  std::ofstream file;
224  std::string filename = _output_directory + "/rate.dat";
225  file.open(filename.c_str());
226  if (!file) {std::cerr << "Error! Unable to write " << filename << "\n"; exit(1);}
227  file << _rate << "\n";
228  file.close();
229  }
230 
231  void ForwardFlux::WriteFFSConfiguration(Snapshot* snapshot, FFSConfigID& ffsconfig, bool wassuccess)
232  {
233  const auto& positions = snapshot->GetPositions();
234  const auto& velocities = snapshot->GetVelocities();
235  const auto& atomID = snapshot->GetAtomIDs();
236  //unsigned natoms = snapshot->GetNumAtoms();
237  //const auto& dumpfilename = snapshot->GetSnapshotID();
238 
239  // Write the dump file out
240  std::ofstream file;
241  std::string filename;
242  if (wassuccess)
243  filename = _output_directory + "/l" + std::to_string(ffsconfig.l) + "-n" + std::to_string(ffsconfig.n) + ".dat";
244  else
245  filename = _output_directory + "/fail-l" + std::to_string(ffsconfig.l) + "-n" + std::to_string(ffsconfig.n) + ".dat";
246 
247  file.open(filename.c_str());
248  if(!file)
249  {
250  std::cerr << "Error! Unable to write " << filename << "\n";
251  MPI_Abort(world_, EXIT_FAILURE);
252  }
253 
254  //first line gives ID of where it came from
255  file << ffsconfig.lprev << " " << ffsconfig.nprev << " " << ffsconfig.aprev << "\n";
256 
257  // Then write positions and velocities
258  for(size_t i = 0; i< atomID.size(); i++)
259  //for(size_t i = 0; i< natoms; i++)
260  {
261  file<<atomID[i]<<" ";
262  file<<positions[i][0]<<" "<<positions[i][1]<<" "<<positions[i][2]<<" ";
263  file<<velocities[i][0]<<" "<<velocities[i][1]<<" "<<velocities[i][2]<<std::endl;
264  }
265  }
266 
267  void ForwardFlux::OpenTrajectoryFile(std::ofstream& file)
268  {
269  FFSConfigID ffsconfig = myFFSConfigID;
270  std::string filename = _output_directory + "/traj-l" + std::to_string(ffsconfig.l) + "-n" + std::to_string(ffsconfig.n) + "-a" + std::to_string(ffsconfig.a) + ".xyz";
271  file.open(filename.c_str());
272  if (!file)
273  {
274  std::cerr << "Error! Unable to write " << filename << "\n";
275  MPI_Abort(world_, EXIT_FAILURE);
276  }
277  }
278 
279  void ForwardFlux::AppendTrajectoryFile(Snapshot* snapshot, std::ofstream& file)
280  {
281  const auto& positions = snapshot->GetPositions();
282  const auto& velocities = snapshot->GetVelocities();
283  const auto& atomID = snapshot->GetAtomIDs();
284 
285  //first line gives number of atoms
286  file << atomID.size() << "\n\n";
287 
288  // Then write positions and velocities
289  for(size_t i = 0; i< atomID.size(); i++)
290  {
291  file<<atomID[i]<<" ";
292  file<<positions[i][0]<<" "<<positions[i][1]<<" "<<positions[i][2]<<" ";
293  file<<velocities[i][0]<<" "<<velocities[i][1]<<" "<<velocities[i][2]<<std::endl;
294  }
295  }
296 
297  void ForwardFlux::ReadFFSConfiguration(Snapshot* snapshot, FFSConfigID& ffsconfig, bool wassuccess)
298  {
299  auto& positions = snapshot->GetPositions();
300  auto& velocities = snapshot->GetVelocities();
301  auto& atomID = snapshot->GetAtomIDs();
302  auto& forces = snapshot->GetForces();
303  //auto& ID = snapshot->GetSnapshotID();
304 
305  std::ifstream file;
306  std::string filename;
307  if (wassuccess)
308  filename = _output_directory + "/l"+ std::to_string(ffsconfig.l) +"-n"+ std::to_string(ffsconfig.n) + ".dat";
309  else
310  filename = _output_directory + "/fail-l"+ std::to_string(ffsconfig.l) +"-n"+ std::to_string(ffsconfig.n) + ".dat";
311 
312  std::string line;
313  file.open(filename);
314  if(!file)
315  {
316  std::cerr << "Error! Unable to read " << filename << "\n";
317  MPI_Abort(world_, EXIT_FAILURE);
318  }
319 
320  unsigned int line_count = 0;
321  while(!std::getline(file,line).eof())
322  {
323  int atomindex = -1;
324 
325  //parse line into tokens
326  std::string buf; // Have a buffer string
327  std::stringstream ss(line); // Insert the string into a stream
328  std::vector<std::string> tokens; // Create vector to hold our words
329  while (ss >> buf)
330  tokens.push_back(buf);
331 
332  // first line contains the previous ffsconfig information
333  if ((line_count == 0) && (tokens.size() == 3))
334  {
335  ffsconfig.lprev = std::stoi(tokens[0]);
336  ffsconfig.nprev = std::stoi(tokens[1]);
337  ffsconfig.aprev = std::stoi(tokens[2]);
338  }
339  // all other lines contain config information
340  else if ((line_count != 0) && (tokens.size() == 7))
341  {
342  //FIXME: try using snapshot->GetLocalIndex()
343 
344  //copied from Ben's previous implementation
345  for(size_t i=0; i < atomID.size(); i++)
346  {
347  if(atomID[i] == std::stoi(tokens[0]))
348  atomindex = i;
349  }
350 
351  if(atomindex < 0)
352  {
353  std::cout<<"error, could not locate atomID "<<tokens[0]<<" from dumpfile"<<std::endl;
354  MPI_Abort(world_, EXIT_FAILURE);
355  }
356 
357  positions[atomindex][0] = std::stod(tokens[1]);
358  positions[atomindex][1] = std::stod(tokens[2]);
359  positions[atomindex][2] = std::stod(tokens[3]);
360  velocities[atomindex][0] = std::stod(tokens[4]);
361  velocities[atomindex][1] = std::stod(tokens[5]);
362  velocities[atomindex][2] = std::stod(tokens[6]);
363 
364  for(auto& force : forces)
365  force.setZero();
366  }
367  // else throw error
368  else
369  {
370  std::cout<<"ERROR: incorrect line format in "<< filename <<" on line" << line_count << ":\n";
371  std::cout<<line<<std::endl;
372  MPI_Abort(world_, EXIT_FAILURE);
373  }
374  line_count++;
375  }
376  file.close();
377  }
378 
379  void ForwardFlux::PrintQueue()
380  {
381  for (unsigned int i =0 ;i < FFSConfigIDQueue.size(); i++)
382  {
383  std::cout << i <<" "
384  <<FFSConfigIDQueue[i].l <<" "
385  <<FFSConfigIDQueue[i].n <<" "
386  <<FFSConfigIDQueue[i].a <<" "
387  <<FFSConfigIDQueue[i].lprev <<" "
388  <<FFSConfigIDQueue[i].nprev <<" "
389  <<FFSConfigIDQueue[i].aprev <<"\n";
390  }
391  }
392 
393  void ForwardFlux::PopQueueMPI(Snapshot* snapshot, const CVList& cvs, unsigned int shouldpop_local)
394  {
395  std::vector<unsigned int> shouldpop (world_.size(),0);
396  MPI_Allgather(&shouldpop_local,1,MPI_UNSIGNED,shouldpop.data(),1,MPI_UNSIGNED,world_);
397 
398  // I don't pass the queue information between procs, but I do syncronize 'shouldpop'.
399  // As a result, all proc should have the same queue throughout the simulation.
400  for (int i=0;i<world_.size();i++)
401  {
402  if (shouldpop[i] == true)
403  {
404  if (i == world_.rank())
405  { //if rank matches read and pop
406  if (!FFSConfigIDQueue.empty())
407  { //if queue has tasks
408  myFFSConfigID = FFSConfigIDQueue.front();
409  ReadFFSConfiguration (snapshot, myFFSConfigID,true);
410 
411  //open new trajectory file, write first frame
412  if (_saveTrajectories)
413  {
414  OpenTrajectoryFile(_trajectory_file);
415  AppendTrajectoryFile(snapshot,_trajectory_file);
416  }
417 
418  //Trigger a rebuild of the CVs since we reset the positions
419  cvs[0]->Evaluate(*snapshot);
420  _cvvalue = cvs[0]->GetValue();
421  _cvvalue_previous = _cvvalue;
422 
423  _pop_tried_but_empty_queue = false;
424  FFSConfigIDQueue.pop_front();
425  }
426  else
427  { //queue is empty, need to wait for new tasks to come in
428  _pop_tried_but_empty_queue = true;
429  }
430  }
431  else
432  { //else if rank doesnt match, just pop
433  if (!FFSConfigIDQueue.empty())
434  FFSConfigIDQueue.pop_front();
435  }
436  }
437  }
438  // ==============================
439  }
440 
441  void ForwardFlux::ComputeCommittorProbability(Snapshot *snapshot)
442  {
443  // two dim vectors, first dim is lambda, second is N
444  // this counts the number of atempts from this config eventually reached A (for nA) or B (for nB)
445  // used to compute _pB via: _pB = nB / (nA + nB)
446  std::vector<std::vector<unsigned int>> nA;
447  std::vector<std::vector<unsigned int>> nB;
448  nA.resize(_ninterfaces);
449  nB.resize(_ninterfaces);
450  for (unsigned int i=0; i<_ninterfaces;i++)
451  {
452  nA[i].resize(_N[i],0);
453  nB[i].resize(_N[i],0);
454  }
455 
456 
457  //Snapshot* snapshot_empty;
458  FFSConfigID ffsconfig;
459 
460  //populate nB
461  unsigned int nsuccess = _N[_ninterfaces-1]; //note -1
462  for(unsigned int i = 0; i < nsuccess ; i++)
463  {
464  ffsconfig.l = _ninterfaces-1;
465  ffsconfig.n = i;
466  ffsconfig.a = 0;
467  bool flag = true;
468  //recursively trace successful path and update all the configs it came from
469  while (flag)
470  {
471  if(ffsconfig.l == 0) flag = false;
472 
473  //this is just to populate ffsconfig.{lprev,nprev,aprev}
474  ReadFFSConfiguration(snapshot,ffsconfig,true);
475 
476  //update nB
477  nB[ffsconfig.l][ffsconfig.n]++;
478  ffsconfig.l = ffsconfig.lprev;
479  ffsconfig.n = ffsconfig.nprev;
480  ffsconfig.a = ffsconfig.aprev;
481  }
482  }
483 
484  //now populate nA (very similar to nB)
485  unsigned int nfail = _nfailure_total;
486  for(unsigned int i = 0; i < nfail ; i++)
487  {
488  ffsconfig.l = 0; //only fail at lambda0 in absence of pruning
489  ffsconfig.n = i;
490  ffsconfig.a = 0;
491  bool flag = true;
492  //this is just to populate ffsconfig.{lprev,nprev,aprev}
493  ReadFFSConfiguration(snapshot,ffsconfig,false);
494 
495  //recursively trace successful path and update all the configs it came from
496  while (flag)
497  {
498  if ((ffsconfig.l == 0) && (ffsconfig.lprev==0))
499  flag = false;
500 
501  //update nA
502  nA[ffsconfig.l][ffsconfig.n]++;
503 
504  ReadFFSConfiguration(snapshot,ffsconfig,true);
505  ffsconfig.l = ffsconfig.lprev;
506  ffsconfig.n = ffsconfig.nprev;
507  ffsconfig.a = ffsconfig.aprev;
508  }
509  }
510 
511  //Compute _pB
512  _pB.resize(_ninterfaces);
513  unsigned int Nmax = 0;
514  for(unsigned int i = 0; i<_ninterfaces ; i++)
515  {
516  _pB[i].resize(_N[i],0);
517  for(unsigned int j = 0; j<_N[i] ; j++)
518  {
519  int denom = nA[i][j] + nB[i][j];
520  if(denom != 0)
521  _pB[i][j] = (double)nB[i][j] / denom;
522  }
523  if (_N[i] > Nmax)
524  Nmax = _N[i];
525  }
526 
527  //print pB
528  //rows are lambda, cols are n. Thats why its looks complicated
529  std::ofstream file;
530  std::string filename;
531  filename = _output_directory +"/commitor_probabilities.dat";
532  file.open(filename.c_str());
533  if (!file)
534  {
535  std::cerr << "Error! Unable to write " << filename << "\n";
536  MPI_Abort(world_, EXIT_FAILURE);
537  }
538 
539  for(unsigned int i = 0; i<Nmax ; i++)
540  {
541  for(unsigned int j = 0; j<_ninterfaces ; j++)
542  {
543  if (i < _N[j])
544  file << _pB[j][i] << " ";
545  else
546  file << "none ";
547  }
548  file << "\n";
549  }
550  }
551 
552  void ForwardFlux::ReconstructTrajectories(Snapshot *snapshot)
553  {
554  //this only reconstructs successful trajectories
555  //its pretty straightforward to reconstruct failed trajectories, but I dont do it here
556  int nsuccess = _S[_ninterfaces-2]; //note -2, no attempts from _ninterfaces-1
557 
558  //Snapshot* snapshot_empty;
559  FFSConfigID ffsconfig;
560 
561  for(int i = 0; i < nsuccess ; i++)
562  {
563  std::deque<FFSConfigID> path;
564 
565  ffsconfig.l = _ninterfaces-1;
566  ffsconfig.n = i;
567  ffsconfig.a = 0;
568  bool flag = true;
569 
570  while (flag)
571  {
572  if (ffsconfig.l == 0){ flag = false;}
573 
574  //this is just to populate ffsconfig.{lprev,nprev,aprev}
575  //ReadFFSConfiguration(snapshot_empty,ffsconfig);
576  ReadFFSConfiguration(snapshot,ffsconfig,true);
577 
578  //path.emplace_front(ffsconfig); //not sure if new constructor will work
579  path.emplace_front(ffsconfig.l,ffsconfig.n, ffsconfig.a, ffsconfig.lprev, ffsconfig.nprev, ffsconfig.aprev);
580 
581  ffsconfig.l = ffsconfig.lprev;
582  ffsconfig.n = ffsconfig.nprev;
583  ffsconfig.a = ffsconfig.aprev;
584  }
585  //the last element is the last lambda, which doesn't have a trajectory, so delete it
586  path.pop_back();
587 
588  //now path should contain all of the FFSConfigID's from B back to A
589  //reverse pop it and splice all traj- files into a new traj-full- file
590 
591  //output file
592  std::ofstream ofile;
593  std::string ofilename;
594  ofilename = _output_directory +"/traj-full-" + std::to_string(i) + ".xyz";
595  ofile.open(ofilename.c_str());
596  if(!ofile)
597  {
598  std::cerr << "Error! Unable to write " << ofilename << "\n";
599  MPI_Abort(world_, EXIT_FAILURE);
600  }
601 
602  while(!path.empty())
603  {
604  ffsconfig = path.front();
605  path.pop_front();
606 
607  //input file
608  std::ifstream ifile;
609  std::string ifilename;
610 
611  ifilename = _output_directory + "/traj-l" + std::to_string(ffsconfig.l) + "-n" + std::to_string(ffsconfig.n) + "-a" + std::to_string(ffsconfig.a) + ".xyz";
612 
613  ifile.open(ifilename.c_str());
614  if(!ifile)
615  {
616  std::cerr << "Error! Unable to read " << ifilename << "\n";
617  MPI_Abort(world_, EXIT_FAILURE);
618  }
619  //write entire ifile to ofile
620  std::string line;
621  while(!std::getline(ifile,line).eof())
622  ofile << line << "\n";
623  }
624  ofile.close();
625  }
626  }
627 
628  ForwardFlux* ForwardFlux::Build(const Json::Value& json,
629  const MPI_Comm& world,
630  const MPI_Comm& comm,
631  const std::string& path)
632  {
633  ObjectRequirement validator;
634  Value schema;
635  CharReaderBuilder rbuilder;
636  CharReader* reader = rbuilder.newCharReader();
637 
638  reader->parse(JsonSchema::ForwardFluxMethod.c_str(),
639  JsonSchema::ForwardFluxMethod.c_str() + JsonSchema::ForwardFluxMethod.size(),
640  &schema, nullptr);
641  validator.Parse(schema, path);
642 
643  // Validate inputs.
644  validator.Validate(json, path);
645  if(validator.HasErrors())
646  throw BuildException(validator.GetErrors());
647 
648  double ninterfaces = json.get("nInterfaces", 2).asDouble();
649  std::vector<double> interfaces;
650  for(auto& s : json["interfaces"])
651  interfaces.push_back(s.asDouble());
652 
653  std::vector<unsigned int> M;
654  for(auto& s : json["trials"])
655  M.push_back(s.asInt());
656 
657  if ((ninterfaces != interfaces.size()) || (ninterfaces != M.size()))
658  throw BuildException({"The size of \"interfaces\" and \"trials\" must be equal to \"nInterfaces\". See documentation for more information"});
659 
660  auto N0Target = json.get("N0Target", 1).asInt();
661  auto initialFluxFlag = json.get("computeInitialFlux", true).asBool();
662  auto saveTrajectories = json.get("saveTrajectories", true).asBool();
663  auto currentInterface = json.get("currentInterface", 0).asInt();
664  auto freq = json.get("frequency", 1).asInt();
665  auto flavor = json.get("flavor", "none").asString();
666  auto output_directory = json.get("outputDirectoryName", "FFSoutput").asString();
667 
668  // TODO: Implement multiple processes per walker
669  if(mxx::comm(comm).size() > 1)
670  {
671  throw BuildException({"Forward Flux currently only works with 1 process per walker."});
672  }
673 
674  if(flavor == "DirectForwardFlux")
675  {
676  return new DirectForwardFlux(world, comm, ninterfaces, interfaces, N0Target, M, initialFluxFlag, saveTrajectories, currentInterface, output_directory, freq);
677  }
678  else
679  {
680  throw BuildException({"Unknown flavor of forward flux. The options are \"DirectForwardFlux\""});
681  }
682  }
683 }
Requirements on an object.
virtual void Parse(Value json, const std::string &path) override
Parse JSON value to generate Requirement(s).
virtual void Validate(const Value &json, const std::string &path) override
Validate JSON value.
std::vector< std::string > GetErrors()
Get list of error messages.
Definition: Requirement.h:92
bool HasErrors()
Check if errors have occured.
Definition: Requirement.h:86
Exception to be thrown when building the Driver fails.
Collective variable manager.
Definition: CVManager.h:43
CVList GetCVs(const std::vector< unsigned int > &mask=std::vector< unsigned int >()) const
Get CV iterator.
Definition: CVManager.h:81
ForwardFlux sampling method.
Nested class to store different FFS Config IDs.
Definition: ForwardFlux.h:43
unsigned int lprev
Previous Interface number (i.e. traj I came from)
Definition: ForwardFlux.h:48
unsigned int aprev
Previous Attempt number.
Definition: ForwardFlux.h:50
unsigned int nprev
Previous Configuration Number.
Definition: ForwardFlux.h:49
unsigned int a
Attempt number.
Definition: ForwardFlux.h:47
unsigned int n
Configuration Number.
Definition: ForwardFlux.h:46
unsigned int l
Interface number.
Definition: ForwardFlux.h:45
ForwardFlux sampling method.
Definition: ForwardFlux.h:39
Class containing a snapshot of the current simulation in time.
Definition: Snapshot.h:48
const std::vector< Vector3 > & GetForces() const
Access the per-particle forces.
Definition: Snapshot.h:351
const std::vector< Vector3 > & GetPositions() const
Access the particle positions.
Definition: Snapshot.h:325
const Label & GetAtomIDs() const
Access the atom IDs.
Definition: Snapshot.h:505
const std::vector< Vector3 > & GetVelocities() const
Access the particle velocities.
Definition: Snapshot.h:338
std::vector< CollectiveVariable * > CVList
List of Collective Variables.
Definition: types.h:51