21 #include "BasisFunc.h"
22 #include "Validator/ObjectRequirement.h"
23 #include "Drivers/DriverException.h"
24 #include "CVs/CVManager.h"
38 auto cvs = cvmanager.
GetCVs(cvmask_);
47 cyclefreqTmp_ = cyclefreq_;
51 if(h_->GetDimension() != cvs.size())
53 std::cerr<<
"ERROR: Grid dimensions doesn't match number of CVS."<<std::endl;
54 MPI_Abort(world_, EXIT_FAILURE);
59 unbias_.resize(h_->size(),0);
60 std::fill(unbias_.begin(),unbias_.end(),1.0);
63 for (
auto &val : *h_) {
68 for (
auto &val : *f_) {
69 for (
size_t i = 0; i <val.size(); i++) {
75 for (
auto &val : *b_) {
83 auto cvs = cvmanager.
GetCVs(cvmask_);
84 std::vector<double> x(cvs.size(),0);
90 for(
size_t i = 0; i < cvs.size(); ++i)
92 x[i] = cvs[i]->GetValue();
97 if (bounds_) {h_->at(x) += 1;}
102 if(steps % cyclefreq_ == 0) {
104 cyclefreq_ = cyclefreqTmp_;
106 beta = 1.0 / (temperature_ * snapshot->
GetKb());
113 ProjectBias(cvs,beta);
114 std::cout<<
"Node: ["<<mpiid_<<
"]"<<std::setw(10)<<
"\tSweep: "<<iteration_<<std::endl;
118 std::vector<double> bias_grad(cvs.size(),0);
122 auto& bias = f_->at(x);
123 for (
size_t ii = 0; ii<bias.size(); ii++)
124 bias_grad[ii] = bias[ii];
129 for(
size_t j = 0; j < cvs.size(); ++j)
131 if(!h_->GetPeriodic(j))
133 if(x[j] > boundUp_[j])
134 bias_grad[j] = -restraint_[j] * (x[j] - boundUp_[j]);
135 else if(x[j] < boundLow_[j])
136 bias_grad[j] = restraint_[j] * (x[j] - boundLow_[j]);
144 for(
size_t i = 0; i < cvs.size(); ++i)
146 auto& grad = cvs[i]->GetGradient();
147 auto& boxgrad = cvs[i]->GetBoxGradient();
152 for (
size_t j = 0; j < forces.size(); ++j)
153 forces[j] += bias_grad[i]*grad[j];
155 virial -= bias_grad[i]*boxgrad;
162 std::cout<<
"Run has finished"<<std::endl;
166 void BFS::ProjectBias(
const CVList& cvs,
const double beta)
174 MPI_Allreduce(histlocal.
data(), h_->data(), h_->size(), MPI_INT, MPI_SUM, world_);
185 unbias_[i] += (*it2) * exp(beta * b_->at(it2.coordinates()));
189 for (
auto &val : *h_) {
194 std::vector<double> z (unbias_.size(),0);
195 for (i = 0; i < unbias_.size(); i++)
197 z[i] = 1.0/beta*log(unbias_[i] * weight_);
200 sum = evaluator_.UpdateCoeff(z,h_);
201 coeffArr_ = evaluator_.GetCoeff();
203 evaluator_.UpdateBias(b_,f_);
205 if(IsMasterRank(world_)) {
207 std::cout<<
"Coefficient difference is: " <<sum<<std::endl;
214 std::cout<<
"System has converged"<<std::endl;
217 std::cout<<
"User has elected to exit. System is now exiting"<<std::endl;
227 void BFS::PrintBias(
const CVList& cvs,
const double beta)
230 std::string filename1 =
"basis"+bnme_+
".out";
231 std::string filename2 =
"restart"+bnme_+
".out";
232 std::ofstream basisout;
233 std::ofstream coeffout;
234 basisout.precision(5);
235 coeffout.precision(5);
236 basisout.open(filename1.c_str());
237 coeffout.open(filename2.c_str());
240 basisout <<
"The information stored in this file is the output of a Basis Function Sampling run" << std::endl;
241 basisout <<
"CV Values" << std::setw(15*cvs.size()) <<
"Basis Set Bias" << std::setw(15) <<
"PMF Estimate" << std::endl;
242 coeffout <<
"The information stored in this file is for the purpose of restarting simulations with BFS" << std::endl;
243 coeffout <<
"***COEFFICIENTS***" << std::endl;
248 for(
size_t k = 0; k < cvs.size(); ++k)
251 basisout << it.coordinate(k) << std::setw(15);
253 basisout << -(*it) << std::setw(15) <<
254 -1.0/beta*log(unbias_[j]) <<
258 std::vector<double> coeff = evaluator_.GetCoeff();
259 for (
auto& val : coeff) {
260 coeffout << val << std::endl;
262 coeffout <<
"***HISTOGRAM***" << std::endl;
263 for (
auto& val : unbias_) {
264 coeffout << val << std::endl;
274 std::vector<double> x (cvs.size(),0);
276 for (
size_t j = 0; j < cvs.size(); ++j)
278 x[j] = cvs[j]->GetValue();
279 double min = h_->GetLower(j);
280 double max = h_->GetUpper(j);
282 if(!h_->GetPeriodic(j))
285 if(x[j] > max && bounds_)
292 else if(x[j] < min && bounds_)
299 else if(x[j] < max && x[j] > min && !bounds_)
308 BFS* BFS::Build(
const Json::Value& json,
309 const MPI_Comm& world,
310 const MPI_Comm& comm,
311 const std::string& path)
315 CharReaderBuilder rbuilder;
316 CharReader* reader = rbuilder.newCharReader();
318 reader->parse(JsonSchema::BFSMethod.c_str(),
319 JsonSchema::BFSMethod.c_str() + JsonSchema::BFSMethod.size(),
321 validator.
Parse(schema, path);
328 std::vector<double> restrCV(0);
329 for(
auto& restr : json[
"CV_restraint_spring_constants"])
330 restrCV.push_back(restr.asDouble());
332 std::vector<double> boundLow(0);
333 for(
auto& bndl : json[
"CV_restraint_minimums"])
334 boundLow.push_back(bndl.asDouble());
336 std::vector<double> boundUp(0);
337 for(
auto& bndu : json[
"CV_restraint_maximums"])
338 boundUp.push_back(bndu.asDouble());
340 auto cyclefreq = json.get(
"cycle_frequency", 100000).asInt();
341 auto freq = json.get(
"frequency", 1).asInt();
342 auto wght = json.get(
"weight", 1.0).asDouble();
343 auto bnme = json.get(
"basis_filename",
"").asString();
344 auto temp = json.get(
"temperature", 0.0).asDouble();
345 auto tol = json.get(
"tolerance", 1e-6).asDouble();
346 auto conv = json.get(
"convergence_exit",
false).asBool();
349 json.get(
"grid", Json::Value()) );
352 json.get(
"grid", Json::Value()) );
355 json.get(
"grid", Json::Value()) );
358 std::vector<BasisFunction*> functions;
359 for(
auto& m : json[
"basis_functions"])
361 auto *bf = BasisFunction::Build(m, path, b->
GetNumPoints(ii));
362 functions.push_back(bf);
367 if (restrCV.size() == 0) {
369 for(
size_t i = 0; i<functions.size(); i++)
370 restrCV.push_back(0);
374 if (boundLow.size() == 0) {
376 for(
size_t i = 0; i<functions.size(); i++)
377 boundLow.push_back(0);
381 if (boundUp.size() == 0) {
383 for(
size_t i = 0; i<functions.size(); i++)
384 boundUp.push_back(0);
388 if (boundUp.size() != boundLow.size() && boundLow.size() != restrCV.size()) {
389 std::cerr<<
"ERROR: Number of restraint boundaries do not match number of spring constants."<<std::endl;
390 std::cerr<<
"Boundary size is " << boundUp.size() <<
" boundary low size is " << boundLow.size() <<
" restraints size is" << restrCV.size() << std::endl;
391 MPI_Abort(world, EXIT_FAILURE);
394 auto* m =
new BFS(world, comm, h, f, b, functions, restrCV, boundUp, boundLow,
395 cyclefreq, freq, bnme, temp, tol, wght,
398 if(json.isMember(
"iteration"))
399 m->SetIteration(json.get(
"iteration",0).asInt());
402 std::ifstream restrFile;
403 restrFile.open(
"restart"+bnme+
".out");
404 if(restrFile.is_open())
407 std::vector<double> coeff;
408 std::vector<double> unbias;
409 bool coeffFlag =
false;
410 bool basisFlag =
false;
411 std::cout <<
"Attempting to load data from a previous run of BFS." << std::endl;
413 while(!std::getline(restrFile,line).eof())
415 if(line.find(
"COEFFICIENTS") != std::string::npos) {
416 std::getline(restrFile,line);
419 else if (line.find(
"HISTOGRAM") != std::string::npos) {
420 std::getline(restrFile,line);
425 coeff.push_back(std::stod(line));
427 else if (basisFlag) {
428 unbias.push_back(std::stod(line));
431 m->SetBasis(coeff, unbias);
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.
Basis Function Sampling Algorithm.
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.
T * data()
Get pointer to the internal data storage vector.
const std::vector< int > GetNumPoints() const
Get the number of points for all dimensions.
iterator begin()
Return iterator at first grid point.
Class containing a snapshot of the current simulation in time.
double GetKb() const
Get system Kb.
const Matrix3 & GetVirial() const
Get box virial.
const std::vector< Vector3 > & GetForces() const
Access the per-particle forces.
size_t GetIteration() const
Get the current iteration.
unsigned GetWalkerID() const
Get walker ID.
std::vector< CollectiveVariable * > CVList
List of Collective Variables.