Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2017-2019 The plumed team 3 : (see the PEOPLE file at the root of the distribution for a list of names) 4 : 5 : See http://www.plumed.org for more information. 6 : 7 : This file is part of plumed, version 2. 8 : 9 : plumed is free software: you can redistribute it and/or modify 10 : it under the terms of the GNU Lesser General Public License as published by 11 : the Free Software Foundation, either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : plumed is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU Lesser General Public License for more details. 18 : 19 : You should have received a copy of the GNU Lesser General Public License 20 : along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 : #include "ReweightBase.h" 23 : #include "core/ActionRegister.h" 24 : #include "tools/Communicator.h" 25 : 26 : //+PLUMEDOC REWEIGHTING REWEIGHT_WHAM 27 : /* 28 : 29 : \par Examples 30 : 31 : */ 32 : //+ENDPLUMEDOC 33 : 34 : namespace PLMD { 35 : namespace bias { 36 : 37 36 : class ReweightWham : public ReweightBase { 38 : private: 39 : double thresh; 40 : unsigned nreplicas; 41 : unsigned maxiter; 42 : bool weightsCalculated; 43 : std::vector<double> stored_biases; 44 : std::vector<double> final_weights; 45 : public: 46 : static void registerKeywords(Keywords&); 47 : explicit ReweightWham(const ActionOptions&ao); 48 12 : bool buildsWeightStore() const override { return true; } 49 : void calculateWeights( const unsigned& nframes ) override; 50 : void clearData() override; 51 : double getLogWeight() override; 52 : double getWeight( const unsigned& iweight ) const override; 53 : }; 54 : 55 7856 : PLUMED_REGISTER_ACTION(ReweightWham,"REWEIGHT_WHAM") 56 : 57 13 : void ReweightWham::registerKeywords(Keywords& keys ) { 58 26 : ReweightBase::registerKeywords( keys ); keys.remove("ARG"); 59 65 : keys.add("compulsory","ARG","*.bias","the biases that must be taken into account when reweighting"); 60 65 : keys.add("compulsory","MAXITER","1000","maximum number of iterations for WHAM algorithm"); 61 65 : keys.add("compulsory","WHAMTOL","1e-10","threshold for convergence of WHAM algorithm"); 62 13 : } 63 : 64 12 : ReweightWham::ReweightWham(const ActionOptions&ao): 65 : Action(ao), 66 : ReweightBase(ao), 67 12 : weightsCalculated(false) 68 : { 69 36 : parse("MAXITER",maxiter); parse("WHAMTOL",thresh); 70 12 : if(comm.Get_rank()==0) nreplicas=multi_sim_comm.Get_size(); 71 12 : comm.Bcast(nreplicas,0); 72 12 : } 73 : 74 4224 : double ReweightWham::getLogWeight() { 75 4224 : if( getStep()==0 ) return 1.0; // This is here as first step is ignored in all analyses 76 4212 : weightsCalculated=false; 77 8424 : double bias=0.0; for(unsigned i=0; i<getNumberOfArguments(); ++i) bias+=getArgument(i); 78 : 79 4212 : std::vector<double> biases(nreplicas,0.0); 80 4212 : if(comm.Get_rank()==0) multi_sim_comm.Allgather(bias,biases); 81 4212 : comm.Bcast(biases,0); 82 54756 : for(unsigned i=0; i<biases.size(); i++) stored_biases.push_back( biases[i] ); 83 : return 1.0; 84 : } 85 : 86 0 : void ReweightWham::clearData() { 87 0 : stored_biases.resize(0); 88 0 : } 89 : 90 2457 : double ReweightWham::getWeight( const unsigned& iweight ) const { 91 : plumed_dbg_assert( weightsCalculated && iweight<final_weights.size() ); 92 4914 : return final_weights[iweight]; 93 : } 94 : 95 7 : void ReweightWham::calculateWeights( const unsigned& nframes ) { 96 7 : if( stored_biases.size()!=nreplicas*nframes ) error("wrong number of weights stored"); 97 : // Get the minimum value of the bias 98 14 : double minv = *min_element(std::begin(stored_biases), std::end(stored_biases)); 99 : // Resize final weights array 100 7 : plumed_assert( stored_biases.size()%nreplicas==0 ); 101 7 : final_weights.resize( stored_biases.size() / nreplicas, 1.0 ); 102 : // Offset and exponential of the bias 103 7 : std::vector<double> expv( stored_biases.size() ); 104 29498 : for(unsigned i=0; i<expv.size(); ++i) expv[i] = exp( (-stored_biases[i]+minv) / simtemp ); 105 : // Initialize Z 106 7 : std::vector<double> Z( nreplicas, 1.0 ), oldZ( nreplicas ); 107 : // Now the iterative loop to calculate the WHAM weights 108 2674 : for(unsigned iter=0; iter<maxiter; ++iter) { 109 : // Store Z 110 34762 : for(unsigned j=0; j<Z.size(); ++j) oldZ[j]=Z[j]; 111 : // Recompute weights 112 : double norm=0; 113 1879822 : for(unsigned j=0; j<final_weights.size(); ++j) { 114 : double ew=0; 115 23464350 : for(unsigned k=0; k<Z.size(); ++k) ew += expv[j*Z.size()+k] / Z[k]; 116 1877148 : final_weights[j] = 1.0 / ew; norm += final_weights[j]; 117 : } 118 : // Normalize weights 119 1879822 : for(unsigned j=0; j<final_weights.size(); ++j) final_weights[j] /= norm; 120 : // Recompute Z 121 34762 : for(unsigned j=0; j<Z.size(); ++j) Z[j] = 0.0; 122 1879822 : for(unsigned j=0; j<final_weights.size(); ++j) { 123 23464350 : for(unsigned k=0; k<Z.size(); ++k) Z[k] += final_weights[j]*expv[j*Z.size()+k]; 124 : } 125 : // Normalize Z and compute change in Z 126 34762 : double change=0; norm=0; for(unsigned k=0; k<Z.size(); ++k) norm+=Z[k]; 127 34762 : for(unsigned k=0; k<Z.size(); ++k) { 128 48132 : Z[k] /= norm; double d = std::log( Z[k] / oldZ[k] ); change += d*d; 129 : } 130 2681 : if( change<thresh ) { weightsCalculated=true; return; } 131 : } 132 0 : error("Too many iterations in WHAM" ); 133 : } 134 : 135 : } 136 5874 : }