23 #include "ForwardFlux.h"
24 #include "DirectForwardFlux.h"
26 #include "CVs/CVManager.h"
27 #include "Validator/ObjectRequirement.h"
28 #include "Drivers/DriverException.h"
41 auto cvs = cvmanager.
GetCVs(cvmask_);
43 throw BuildException({
"Forwardflux currently only works with one cv."});
45 std::cout <<
"\nWARNING! MAKE SURE LAMMPS GIVES A DIFFERENT RANDOM SEED TO EACH PROCESSOR, OTHERWISE EACH FFS TRAJ WILL BE IDENTICAL!\n";
50 std::cout <<
"Post simulation\n";
52 ComputeCommittorProbability(snapshot);
53 ComputeTransitionProbabilities();
55 if (_saveTrajectories)
56 ReconstructTrajectories(snapshot);
58 MPI_Abort(world_, EXIT_FAILURE);
61 void ForwardFlux::CheckInitialStructure(
const CVList& cvs)
65 std::cout <<
"Running initial Flux calculations" << std::endl;
68 _cvvalue = cvs[0]->GetValue();
69 _cvvalue_previous = _cvvalue;
70 double _firstInterfaceLocation = _interfaces[0];
71 if ( _cvvalue > _firstInterfaceLocation)
73 std::cerr <<
"Please provide an initial configuration in State A. Exiting ...." << std::endl;
74 MPI_Abort(world_, EXIT_FAILURE);
79 int ForwardFlux::HasCrossedInterface(
double current,
double prev,
unsigned int i)
81 double interface_location = _interfaces[i];
82 if (_interfaces_increase)
84 if ((prev <= interface_location) && (current >= interface_location))
86 else if ((prev >= interface_location) && (current <= interface_location))
93 if ((prev >= interface_location) && (current <= interface_location))
95 else if ((prev <= interface_location) && (current >= interface_location))
102 bool ForwardFlux::HasReturnedToA(
double current)
104 double interface_location = _interfaces[0];
105 if (_interfaces_increase)
107 if (current < interface_location)
return true;
112 if (current > interface_location)
return true;
119 _cvvalue = cvs[0]->GetValue();
122 int hascrossed = HasCrossedInterface(_cvvalue, _cvvalue_previous, 0);
123 unsigned int success_local =
false;
124 std::vector<unsigned int> successes (world_.size(),0);
127 success_local =
true;
130 MPI_Allgather(&success_local,1,MPI_UNSIGNED,successes.data(),1,MPI_UNSIGNED,world_);
132 int success_count = 0;
133 for (
int i = 0; i < world_.size(); i++)
136 if (successes[i] ==
true)
138 if (i == world_.rank())
140 int l,n,a,lprev,nprev,aprev;
144 n = _N[0] + success_count;
151 Lambda0ConfigLibrary.emplace_back(l,n,a,lprev,nprev,aprev);
152 WriteFFSConfiguration(snapshot,newid,1);
159 _N[0] += success_count;
162 double N0SimTime_local = 0;
164 int reachedB = HasCrossedInterface(_cvvalue, _cvvalue_previous, _ninterfaces-1);
166 if (!(reachedB == 1) && (_cvvalue < _interfaces.back()))
170 MPI_Allreduce(&N0SimTime_local, &N0SimTime, 1, MPI_DOUBLE, MPI_SUM,world_);
171 _N0TotalSimTime += N0SimTime;
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;
183 if (_N[0] >= _N0Target)
185 std::cout <<
"Initial flux calculation was successfully completed" << std::endl;
189 _initialFluxFlag =
false;
192 _cvvalue_previous = _cvvalue;
196 void ForwardFlux::WriteInitialFlux()
199 std::string filename = _output_directory +
"/initial_flux_value.dat";
200 file.open(filename.c_str());
203 std::cerr <<
"Error! Unable to write " << filename << std::endl;
204 MPI_Abort(world_, EXIT_FAILURE);
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;
214 void ForwardFlux::ComputeTransitionProbabilities()
217 for (
unsigned int i = 0; i < _ninterfaces -1; i++)
220 _rate = Ptotal*_fluxA0;
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";
241 std::string filename;
243 filename = _output_directory +
"/l" + std::to_string(ffsconfig.
l) +
"-n" + std::to_string(ffsconfig.
n) +
".dat";
245 filename = _output_directory +
"/fail-l" + std::to_string(ffsconfig.
l) +
"-n" + std::to_string(ffsconfig.
n) +
".dat";
247 file.open(filename.c_str());
250 std::cerr <<
"Error! Unable to write " << filename <<
"\n";
251 MPI_Abort(world_, EXIT_FAILURE);
255 file << ffsconfig.
lprev <<
" " << ffsconfig.
nprev <<
" " << ffsconfig.
aprev <<
"\n";
258 for(
size_t i = 0; i< atomID.size(); i++)
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;
267 void ForwardFlux::OpenTrajectoryFile(std::ofstream& file)
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());
274 std::cerr <<
"Error! Unable to write " << filename <<
"\n";
275 MPI_Abort(world_, EXIT_FAILURE);
279 void ForwardFlux::AppendTrajectoryFile(
Snapshot* snapshot, std::ofstream& file)
286 file << atomID.size() <<
"\n\n";
289 for(
size_t i = 0; i< atomID.size(); i++)
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;
306 std::string filename;
308 filename = _output_directory +
"/l"+ std::to_string(ffsconfig.
l) +
"-n"+ std::to_string(ffsconfig.
n) +
".dat";
310 filename = _output_directory +
"/fail-l"+ std::to_string(ffsconfig.
l) +
"-n"+ std::to_string(ffsconfig.
n) +
".dat";
316 std::cerr <<
"Error! Unable to read " << filename <<
"\n";
317 MPI_Abort(world_, EXIT_FAILURE);
320 unsigned int line_count = 0;
321 while(!std::getline(file,line).eof())
327 std::stringstream ss(line);
328 std::vector<std::string> tokens;
330 tokens.push_back(buf);
333 if ((line_count == 0) && (tokens.size() == 3))
335 ffsconfig.
lprev = std::stoi(tokens[0]);
336 ffsconfig.
nprev = std::stoi(tokens[1]);
337 ffsconfig.
aprev = std::stoi(tokens[2]);
340 else if ((line_count != 0) && (tokens.size() == 7))
345 for(
size_t i=0; i < atomID.size(); i++)
347 if(atomID[i] == std::stoi(tokens[0]))
353 std::cout<<
"error, could not locate atomID "<<tokens[0]<<
" from dumpfile"<<std::endl;
354 MPI_Abort(world_, EXIT_FAILURE);
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]);
364 for(
auto& force : forces)
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);
379 void ForwardFlux::PrintQueue()
381 for (
unsigned int i =0 ;i < FFSConfigIDQueue.size(); 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";
393 void ForwardFlux::PopQueueMPI(
Snapshot* snapshot,
const CVList& cvs,
unsigned int shouldpop_local)
395 std::vector<unsigned int> shouldpop (world_.size(),0);
396 MPI_Allgather(&shouldpop_local,1,MPI_UNSIGNED,shouldpop.data(),1,MPI_UNSIGNED,world_);
400 for (
int i=0;i<world_.size();i++)
402 if (shouldpop[i] ==
true)
404 if (i == world_.rank())
406 if (!FFSConfigIDQueue.empty())
408 myFFSConfigID = FFSConfigIDQueue.front();
409 ReadFFSConfiguration (snapshot, myFFSConfigID,
true);
412 if (_saveTrajectories)
414 OpenTrajectoryFile(_trajectory_file);
415 AppendTrajectoryFile(snapshot,_trajectory_file);
419 cvs[0]->Evaluate(*snapshot);
420 _cvvalue = cvs[0]->GetValue();
421 _cvvalue_previous = _cvvalue;
423 _pop_tried_but_empty_queue =
false;
424 FFSConfigIDQueue.pop_front();
428 _pop_tried_but_empty_queue =
true;
433 if (!FFSConfigIDQueue.empty())
434 FFSConfigIDQueue.pop_front();
441 void ForwardFlux::ComputeCommittorProbability(
Snapshot *snapshot)
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++)
452 nA[i].resize(_N[i],0);
453 nB[i].resize(_N[i],0);
461 unsigned int nsuccess = _N[_ninterfaces-1];
462 for(
unsigned int i = 0; i < nsuccess ; i++)
464 ffsconfig.
l = _ninterfaces-1;
471 if(ffsconfig.
l == 0) flag =
false;
474 ReadFFSConfiguration(snapshot,ffsconfig,
true);
477 nB[ffsconfig.
l][ffsconfig.
n]++;
478 ffsconfig.
l = ffsconfig.
lprev;
479 ffsconfig.
n = ffsconfig.
nprev;
480 ffsconfig.
a = ffsconfig.
aprev;
485 unsigned int nfail = _nfailure_total;
486 for(
unsigned int i = 0; i < nfail ; i++)
493 ReadFFSConfiguration(snapshot,ffsconfig,
false);
498 if ((ffsconfig.
l == 0) && (ffsconfig.
lprev==0))
502 nA[ffsconfig.
l][ffsconfig.
n]++;
504 ReadFFSConfiguration(snapshot,ffsconfig,
true);
505 ffsconfig.
l = ffsconfig.
lprev;
506 ffsconfig.
n = ffsconfig.
nprev;
507 ffsconfig.
a = ffsconfig.
aprev;
512 _pB.resize(_ninterfaces);
513 unsigned int Nmax = 0;
514 for(
unsigned int i = 0; i<_ninterfaces ; i++)
516 _pB[i].resize(_N[i],0);
517 for(
unsigned int j = 0; j<_N[i] ; j++)
519 int denom = nA[i][j] + nB[i][j];
521 _pB[i][j] = (double)nB[i][j] / denom;
530 std::string filename;
531 filename = _output_directory +
"/commitor_probabilities.dat";
532 file.open(filename.c_str());
535 std::cerr <<
"Error! Unable to write " << filename <<
"\n";
536 MPI_Abort(world_, EXIT_FAILURE);
539 for(
unsigned int i = 0; i<Nmax ; i++)
541 for(
unsigned int j = 0; j<_ninterfaces ; j++)
544 file << _pB[j][i] <<
" ";
552 void ForwardFlux::ReconstructTrajectories(
Snapshot *snapshot)
556 int nsuccess = _S[_ninterfaces-2];
561 for(
int i = 0; i < nsuccess ; i++)
563 std::deque<FFSConfigID> path;
565 ffsconfig.
l = _ninterfaces-1;
572 if (ffsconfig.
l == 0){ flag =
false;}
576 ReadFFSConfiguration(snapshot,ffsconfig,
true);
579 path.emplace_front(ffsconfig.
l,ffsconfig.
n, ffsconfig.
a, ffsconfig.
lprev, ffsconfig.
nprev, ffsconfig.
aprev);
581 ffsconfig.
l = ffsconfig.
lprev;
582 ffsconfig.
n = ffsconfig.
nprev;
583 ffsconfig.
a = ffsconfig.
aprev;
593 std::string ofilename;
594 ofilename = _output_directory +
"/traj-full-" + std::to_string(i) +
".xyz";
595 ofile.open(ofilename.c_str());
598 std::cerr <<
"Error! Unable to write " << ofilename <<
"\n";
599 MPI_Abort(world_, EXIT_FAILURE);
604 ffsconfig = path.front();
609 std::string ifilename;
611 ifilename = _output_directory +
"/traj-l" + std::to_string(ffsconfig.
l) +
"-n" + std::to_string(ffsconfig.
n) +
"-a" + std::to_string(ffsconfig.
a) +
".xyz";
613 ifile.open(ifilename.c_str());
616 std::cerr <<
"Error! Unable to read " << ifilename <<
"\n";
617 MPI_Abort(world_, EXIT_FAILURE);
621 while(!std::getline(ifile,line).eof())
622 ofile << line <<
"\n";
629 const MPI_Comm& world,
630 const MPI_Comm& comm,
631 const std::string& path)
635 CharReaderBuilder rbuilder;
636 CharReader* reader = rbuilder.newCharReader();
638 reader->parse(JsonSchema::ForwardFluxMethod.c_str(),
639 JsonSchema::ForwardFluxMethod.c_str() + JsonSchema::ForwardFluxMethod.size(),
641 validator.
Parse(schema, path);
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());
653 std::vector<unsigned int> M;
654 for(
auto& s : json[
"trials"])
655 M.push_back(s.asInt());
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"});
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();
669 if(mxx::comm(comm).size() > 1)
671 throw BuildException({
"Forward Flux currently only works with 1 process per walker."});
674 if(flavor ==
"DirectForwardFlux")
676 return new DirectForwardFlux(world, comm, ninterfaces, interfaces, N0Target, M, initialFluxFlag, saveTrajectories, currentInterface, output_directory, freq);
680 throw BuildException({
"Unknown flavor of forward flux. The options are \"DirectForwardFlux\""});
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.
bool HasErrors()
Check if errors have occured.
Exception to be thrown when building the Driver fails.
Collective variable manager.
CVList GetCVs(const std::vector< unsigned int > &mask=std::vector< unsigned int >()) const
Get CV iterator.
ForwardFlux sampling method.
Nested class to store different FFS Config IDs.
unsigned int lprev
Previous Interface number (i.e. traj I came from)
unsigned int aprev
Previous Attempt number.
unsigned int nprev
Previous Configuration Number.
unsigned int a
Attempt number.
unsigned int n
Configuration Number.
unsigned int l
Interface number.
ForwardFlux sampling method.
Class containing a snapshot of the current simulation in time.
const std::vector< Vector3 > & GetForces() const
Access the per-particle forces.
const std::vector< Vector3 > & GetPositions() const
Access the particle positions.
const Label & GetAtomIDs() const
Access the atom IDs.
const std::vector< Vector3 > & GetVelocities() const
Access the particle velocities.
std::vector< CollectiveVariable * > CVList
List of Collective Variables.