22 #include "CVs/CVManager.h" 
   23 #include "Drivers/DriverException.h" 
   24 #include "Validator/ObjectRequirement.h" 
   43         if(world_.rank() == 0)
 
   45             worldout_.open(filename_);
 
   50         auto cvs = cvmanager.
GetCVs(cvmask_);
 
   63         wdotp1_.setZero(dim_);
 
   64         wdotp2_.setZero(dim_);  
 
   82         auto cvs = cvmanager.
GetCVs(cvmask_);
 
   93         Eigen::MatrixXd J(dim_, 3*n);
 
   96         std::vector<double> cvVals(dim_);
 
   99         for(
int i = 0; i < dim_; ++i)
 
  101             auto& grad = cvs[i]->GetGradient();
 
  102             for(
size_t j = 0; j < n; ++j)
 
  103                 J.block<1, 3>(i,3*j) = grad[j];
 
  104             cvVals[i] = cvs[i]->GetValue();
 
  108         Eigen::MatrixXd Jmass = J.transpose();
 
  111             for(
size_t i = 0; i < forces.size(); ++i)
 
  112                 Jmass.block(3*i, 0, 3, dim_) = Jmass.block(3*i, 0, 3, dim_)/mass[i];
 
  115         Eigen::MatrixXd Minv = J*Jmass;
 
  116         MPI_Allreduce(MPI_IN_PLACE, Minv.data(), Minv.size(), MPI_DOUBLE, MPI_SUM, comm_);
 
  117         Eigen::MatrixXd Wt = Minv.inverse()*Jmass.transpose();  
 
  119         Eigen::VectorXd momenta(3*vels.size());
 
  120         for(
size_t i = 0; i < vels.size(); ++i)
 
  121             momenta.segment<3>(3*i) = mass[i]*vels[i];
 
  124         Eigen::VectorXd wdotp = Wt*momenta;
 
  128         MPI_Allreduce(MPI_IN_PLACE, wdotp.data(), wdotp.size(), MPI_DOUBLE, MPI_SUM, comm_);
 
  133         Eigen::VectorXd dwdotpdt = unitconv_*(1.5*wdotp - 2.0*wdotp1_ + 0.5*wdotp2_)/timestep_ + Fold_;
 
  136         if(boundsCheck(cvVals))
 
  138             for(
size_t i=0; i<dim_; ++i)
 
  139                 F_[i]->at(cvVals) += dwdotpdt[i];
 
  144         for(
size_t i=0; i<dim_; ++i)                
 
  145             MPI_Allreduce(F_[i]->data(), Fworld_[i]->data(), (F_[i]->size()), MPI_DOUBLE, MPI_SUM, world_); 
 
  146         MPI_Allreduce(N_->data(), Nworld_->data(), N_->size(), MPI_INT, MPI_SUM, world_);
 
  149         if(boundsCheck(cvVals))
 
  151             for(
size_t i=0; i < dim_; ++i)
 
  152                 Fold_[i] = Fworld_[i]->at(cvVals)/std::max(min_, Nworld_->at(cvVals));
 
  160         if(iteration_ % FBackupInterv_ == 0)
 
  165         CalcBiasForce(snapshot, cvs, cvVals);       
 
  169         for (
size_t j = 0; j < forces.size(); ++j)
 
  170             forces[j] += biases_[j];    
 
  179     void ABF::CalcBiasForce(
const Snapshot* snapshot, 
const CVList& cvs, 
const std::vector<double> &cvVals)
 
  183         for(
auto& b : biases_)
 
  187         if(boundsCheck(cvVals))
 
  189             for(
int i = 0; i < dim_; ++i)
 
  191                 auto& grad = cvs[i]->GetGradient();
 
  192                 for(
size_t j = 0; j < biases_.size(); ++j)
 
  193                     biases_[j] -= (Fworld_[i]->at(cvVals))*grad[j]/std::max(min_,Nworld_->at(cvVals));
 
  199             for(
int i = 0; i < dim_; ++i)
 
  201                 double cvVal = cvs[i]->GetValue();
 
  207                     double periodsize = periodicboundaries_[i][1]-periodicboundaries_[i][0];
 
  208                     double cvRestrMidpoint = (restraint_[i][1]+restraint_[i][0])/2;
 
  209                     while((cvVal-cvRestrMidpoint) > periodsize/2)
 
  211                     while((cvVal-cvRestrMidpoint) < -periodsize/2)
 
  215                 if(cvVal < restraint_[i][0] && restraint_[i][2] > 0)
 
  217                     k = restraint_[i][2];
 
  218                     x0 = restraint_[i][0];
 
  220                 else if (cvVal > restraint_[i][1] && restraint_[i][2] > 0)
 
  222                     k = restraint_[i][2];
 
  223                     x0 = restraint_[i][1];
 
  226                 auto& grad = cvs[i]->GetGradient();
 
  227                 for(
size_t j = 0; j < biases_.size(); ++j)
 
  228                     biases_[j] -= (cvVal - x0)*k*grad[j];
 
  235     void ABF::WriteData()
 
  238         if(world_.rank() != 0)
 
  242         Nworld_->WriteToFile(Nworld_filename_);
 
  243         for(
size_t i = 0 ; i < dim_; ++i)
 
  245             Fworld_[i]->WriteToFile(Fworld_filename_+std::to_string(i));
 
  251         for(
size_t i = 0 ; i < dim_; ++i)
 
  252             gridPoints = gridPoints * N_->GetNumPoints(i);
 
  254         worldout_.open(filename_,std::ios::out);
 
  255         worldout_ << std::endl;
 
  256         worldout_ << 
"Iteration: " << iteration_ << std::endl;          
 
  257         worldout_ << 
"Printing out the current Adaptive Biasing Vector Field." << std::endl;
 
  258         worldout_ << 
"First (Nr of CVs) columns are the coordinates, the next (Nr of CVs) columns are components of the Adaptive Force vector at that point." << std::endl;
 
  259         worldout_ << 
"The columns are " << gridPoints << 
" long, mapping out a surface of ";
 
  261         for(
size_t i = 0 ; i < dim_-1; ++i)
 
  262             worldout_ << (N_->GetNumPoints())[i] << 
" by " ;
 
  263         worldout_ << (N_->GetNumPoints(dim_-1)) << 
" points in " << dim_ << 
" dimensions." << std::endl;
 
  264         worldout_ << std::endl; 
 
  266         std::vector<int> printCoords(dim_);
 
  269         std::vector<double> tempcoord(dim_);
 
  270         for(
size_t i = 0; i < gridPoints; ++i)
 
  272             printCoords[0] = i%(Nworld_->GetNumPoints(0));
 
  274             for(
size_t j = 1; j < dim_; ++j)
 
  276                 div = div * Nworld_->GetNumPoints(j);
 
  277                 printCoords[j]=i/div;                       
 
  279             for(
size_t j = 0; j < dim_; ++j)
 
  281                 worldout_ << std::setw(10) << (printCoords[j]+0.5)*((Nworld_->GetUpper(j)-Nworld_->GetLower(j))/Nworld_->GetNumPoints(j)) + Nworld_->GetLower(j) << 
" ";
 
  282                 tempcoord[j] = ((printCoords[j]+0.5)*((Nworld_->GetUpper(j)-Nworld_->GetLower(j))/Nworld_->GetNumPoints(j)) + Nworld_->GetLower(j));
 
  284             for(
size_t j = 0; j < dim_; ++j)
 
  286                 worldout_ <<  std::setw(10) << (Fworld_[j]->at(tempcoord))/std::max(Nworld_->at(tempcoord),min_)<< 
" ";
 
  288             worldout_ << std::endl;
 
  292         worldout_ << std::endl;
 
  293         worldout_ << std::endl;
 
  298     bool ABF::boundsCheck(
const std::vector<double> &CVs)
 
  300         for(
size_t i = 0; i < dim_ ; ++i)
 
  302             if((CVs[i] < N_->GetLower(i)) || (CVs[i] > N_->GetUpper(i)))
 
  311     ABF* ABF::Build(
const Value& json, 
 
  312                         const MPI_Comm& world,
 
  313                         const MPI_Comm& comm,
 
  314                         const std::string& path)
 
  320         reader.parse(JsonSchema::ABFMethod, schema);
 
  321         validator.
Parse(schema, path);
 
  328         uint wid = mxx::comm(world).rank()/mxx::comm(comm).size(); 
 
  333         std::vector<double> minsCV;
 
  334         for(
auto& mins : json[
"CV_lower_bounds"])
 
  337                 throw BuildException({
"Separate inputs for multi-walker not fully implemented. Please use global entries for CV ranges"});
 
  343                 minsCV.push_back(mins.asDouble());
 
  346         std::vector<double> maxsCV;
 
  347         for(
auto& maxs : json[
"CV_upper_bounds"])
 
  354                 maxsCV.push_back(maxs.asDouble());
 
  357         std::vector<int> binsCV;
 
  358         for(
auto& bins : json[
"CV_bins"])
 
  359             binsCV.push_back(bins.asInt());
 
  362         std::vector<double> minsrestCV;
 
  363         for(
auto& mins : json[
"CV_restraint_minimums"])
 
  370                 minsrestCV.push_back(mins.asDouble());
 
  373         std::vector<double> maxsrestCV;
 
  374         for(
auto& maxs : json[
"CV_restraint_maximums"])
 
  381                 maxsrestCV.push_back(maxs.asDouble());
 
  384         std::vector<double> springkrestCV;
 
  385         for(
auto& bins : json[
"CV_restraint_spring_constants"])
 
  386             springkrestCV.push_back(bins.asDouble());
 
  389         std::vector<bool> isperiodic;
 
  390         for(
auto& isperCV : json[
"CV_isperiodic"])
 
  391             isperiodic.push_back(isperCV.asBool());
 
  394         std::vector<double> minperboundaryCV;
 
  395         for(
auto& minsperCV : json[
"CV_periodic_boundary_lower_bounds"])
 
  396             minperboundaryCV.push_back(minsperCV.asDouble());
 
  399         std::vector<double> maxperboundaryCV;
 
  400         for(
auto& maxsperCV : json[
"CV_periodic_boundary_upper_bounds"])
 
  401             maxperboundaryCV.push_back(maxsperCV.asDouble());
 
  404         if(!((   minsCV.size() == maxsCV.size() && 
 
  405              maxsCV.size() == minsrestCV.size() &&
 
  406              minsrestCV.size() == maxsrestCV.size()) &&
 
  407             (binsCV.size() == springkrestCV.size() &&
 
  408              springkrestCV.size() == isperiodic.size())))       
 
  409             throw BuildException({
"CV lower bounds, upper bounds, restrain minimums, restrains maximums must match in size. Bins, spring constants and periodicity info must match in size."});
 
  412         bool anyperiodic=
false;
 
  413         for(
size_t i = 0; i<isperiodic.size(); ++i)
 
  417                 if(!(isperiodic.size() == minperboundaryCV.size() &&
 
  418                      minperboundaryCV.size() == maxperboundaryCV.size()))
 
  419                     throw BuildException({
"If any CV is defined as periodic, please define the full upper and lower bound vectors. They should both have the same number of entries as CV lower bounds, upper bounds... Entries corresponding to non-periodic CVs will not be used."});
 
  422         int dim = binsCV.size();
 
  425         auto FBackupInterv = json.get(
"output_frequency", 1000).asInt();
 
  426         auto unitconv = json.get(
"unit_conversion", 0).asDouble();
 
  427         auto timestep = json.get(
"timestep", 2).asDouble();
 
  428         auto min = json.get(
"minimum_count", 200).asDouble();
 
  429         auto massweigh = json.get(
"mass_weighing",
false).asBool();          
 
  431         std::vector<std::vector<double>> histdetails;
 
  432         std::vector<std::vector<double>> restraint;
 
  433         std::vector<std::vector<double>> periodicboundaries;
 
  434         std::vector<double> temp1(3);
 
  435         std::vector<double> temp2(3);
 
  436         std::vector<double> temp3(2);
 
  438         auto freq = json.get(
"frequency", 1).asInt();
 
  439         auto filename = json.get(
"output_file", 
"F_out").asString();
 
  440         auto Nworld_filename = json.get(
"Nworld_output_file", 
"Nworld").asString();
 
  441         auto Fworld_filename = json.get(
"Fworld_output_file", 
"Fworld_cv").asString();
 
  446         std::vector<Grid<double>*> F(dim);
 
  447         std::vector<Grid<double>*> Fworld(dim);
 
  489             N= 
new Grid<int>(binsCV, minsCV, maxsCV, isperiodic);
 
  490             Nworld= 
new Grid<int>(binsCV, minsCV, maxsCV, isperiodic);
 
  494                 grid= 
new Grid<double>(binsCV, minsCV, maxsCV, isperiodic);
 
  496             for(
auto& grid : Fworld)
 
  498                 grid= 
new Grid<double>(binsCV, minsCV, maxsCV, isperiodic);
 
  501             for(
size_t i=0; i<dim; ++i)
 
  503                 temp1 = {minsCV[i], maxsCV[i], binsCV[i]};
 
  504                 temp2 = {minsrestCV[i], maxsrestCV[i], springkrestCV[i]};
 
  505                 histdetails.push_back(temp1);
 
  506                 restraint.push_back(temp2);
 
  509                     temp3 = {minperboundaryCV[i], maxperboundaryCV[i]};
 
  510                     periodicboundaries.push_back(temp3);
 
  516         if(std::ifstream(Nworld_filename) && std::ifstream(Fworld_filename+std::to_string(0)) && wid == 0)
 
  518             std::cout << 
"Attempting to load data from a previous run of ABF." << std::endl;
 
  520             for(
size_t i=0; i<dim; ++i)
 
  521                 if(std::ifstream(Fworld_filename+std::to_string(i)))
 
  522                     F[i]->LoadFromFile(Fworld_filename+std::to_string(i));
 
  524                     throw BuildException({
"Some, but not all Fworld outputs were found. Please check that these are appropriate inputs, or clean the working directory of other Fworld and Nworld inputs."});
 
  528         auto* m = 
new ABF(world, comm, N, Nworld, F, Fworld, restraint, isperiodic, periodicboundaries, min, massweigh, filename, Nworld_filename, Fworld_filename, histdetails, FBackupInterv, unitconv, timestep, freq);
 
  531         if(json.isMember(
"iteration"))
 
  532             m->SetIteration(json.get(
"iteration",0).asInt());
 
bool HasErrors()
Check if errors have occured. 
Collective variable manager. 
unsigned GetNumAtoms() const 
Get number of atoms in this snapshot. 
std::vector< CollectiveVariable * > CVList
List of Collective Variables. 
Class containing a snapshot of the current simulation in time. 
virtual void Parse(Value json, const std::string &path) override
Parse JSON value to generate Requirement(s). 
Exception to be thrown when building the Driver fails. 
std::vector< std::string > GetErrors()
Get list of error messages. 
std::vector< CollectiveVariable * > GetCVs(const std::vector< uint > &mask=std::vector< uint >()) const 
Get CV iterator. 
const std::vector< double > & GetMasses() const 
Const access to the particle masses. 
Adaptive Biasing Force Algorithm. 
Requirements on an object. 
Eigen::Vector3d Vector3
Three-dimensional vector. 
const std::vector< Vector3 > & GetVelocities() const 
Access the particle velocities. 
void LoadFromFile(const std::string &filename)
Builds a grid from file. 
const std::vector< Vector3 > & GetForces() const 
Access the per-particle forces. 
const std::vector< Vector3 > & GetPositions() const 
Access the particle positions. 
virtual void Validate(const Value &json, const std::string &path) override
Validate JSON value.