Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2015-2023 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 "ReadAnalysisFrames.h" 23 : #include "core/PlumedMain.h" 24 : #include "core/ActionSet.h" 25 : #include "core/ActionRegister.h" 26 : 27 : //+PLUMEDOC ANALYSIS COLLECT_FRAMES 28 : /* 29 : This allows you to convert a trajectory and a dissimilarity matrix into a dissimilarity object 30 : 31 : \par Examples 32 : 33 : */ 34 : //+ENDPLUMEDOC 35 : 36 : namespace PLMD { 37 : namespace analysis { 38 : 39 13845 : PLUMED_REGISTER_ACTION(ReadAnalysisFrames,"COLLECT_FRAMES") 40 : 41 34 : void ReadAnalysisFrames::registerKeywords( Keywords& keys ) { 42 34 : AnalysisBase::registerKeywords( keys ); 43 34 : keys.remove("SERIAL"); 44 34 : keys.remove("USE_OUTPUT_DATA_FROM"); 45 34 : keys.use("ARG"); 46 68 : keys.add("atoms-1","ATOMS","the atoms whose positions we are tracking for the purpose of analyzing the data"); 47 68 : keys.add("atoms-1","STRIDE","the frequency with which data should be stored for analysis. By default data is collected on every step"); 48 68 : keys.add("compulsory","CLEAR","0","the frequency with which data should all be deleted and restarted"); 49 68 : keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages"); 50 34 : ActionWithValue::useCustomisableComponents( keys ); 51 34 : } 52 : 53 30 : ReadAnalysisFrames::ReadAnalysisFrames( const ActionOptions& ao ): 54 : Action(ao), 55 : AnalysisBase(ao), 56 30 : clearonnextstep(false), 57 30 : wham_pointer(NULL), 58 30 : weights_calculated(false) { 59 30 : parse("CLEAR",clearstride); 60 30 : if( clearstride!=0 ) { 61 5 : log.printf(" clearing stored data every %u steps\n",clearstride); 62 : } 63 : // Get the names of the argumes 64 30 : argument_names.resize( getNumberOfArguments() ); 65 64 : for(unsigned i=0; i<getNumberOfArguments(); ++i) { 66 : argument_names[i]=getPntrToArgument(i)->getName(); 67 : } 68 : // Find the atom numbers to read in 69 60 : parseAtomList("ATOMS",atom_numbers); 70 30 : if( atom_numbers.size()>0 ) { 71 5 : log.printf(" monitoring positions of atoms "); 72 79 : for(unsigned i=0; i<atom_numbers.size(); ++i) { 73 74 : log.printf("%d ",atom_numbers[i].serial() ); 74 : } 75 5 : log.printf("\n"); 76 5 : requestAtoms(atom_numbers); 77 : } 78 : 79 : // Get stuff for any reweighting that should go on 80 : std::vector<std::string> wwstr; 81 60 : parseVector("LOGWEIGHTS",wwstr); 82 30 : if( wwstr.size()>0 ) { 83 12 : log.printf(" reweighting using weights from "); 84 : } 85 30 : std::vector<Value*> arg( ActionWithArguments::getArguments() ); 86 42 : for(unsigned i=0; i<wwstr.size(); ++i) { 87 12 : ActionWithValue* val = plumed.getActionSet().selectWithLabel<ActionWithValue*>(wwstr[i]); 88 12 : if( !val ) { 89 0 : error("could not find value named"); 90 : } 91 12 : weight_vals.push_back( val->copyOutput(val->getLabel()) ); 92 12 : arg.push_back( val->copyOutput(val->getLabel()) ); 93 12 : log.printf("%s ",wwstr[i].c_str() ); 94 : } 95 30 : if( wwstr.size()>0 ) { 96 12 : log.printf("\n"); 97 12 : wham_pointer = dynamic_cast<bias::ReweightBase*>( weight_vals[0]->getPntrToAction() ); 98 12 : if( !wham_pointer ) { 99 0 : wham_pointer = NULL; 100 12 : } else if( !wham_pointer->buildsWeightStore() ) { 101 0 : wham_pointer = NULL; 102 : } 103 12 : if( wham_pointer && weight_vals.size()!=1 ) { 104 0 : error("can only extract weights from one wham object"); 105 : } 106 : } else { 107 18 : log.printf(" weights are all equal to one\n"); 108 : } 109 30 : requestArguments( arg ); 110 : 111 : // Now add fake components to the underlying ActionWithValue for the arguments 112 64 : for(unsigned i=0; i<argument_names.size(); ++i) { 113 34 : addComponent( argument_names[i] ); 114 34 : componentIsNotPeriodic( argument_names[i] ); 115 : } 116 30 : } 117 : 118 62 : std::vector<Value*> ReadAnalysisFrames::getArgumentList() { 119 62 : std::vector<Value*> arg_vals( ActionWithArguments::getArguments() ); 120 68 : for(unsigned i=0; i<weight_vals.size(); ++i) { 121 : arg_vals.erase(arg_vals.end()-1); 122 : } 123 62 : return arg_vals; 124 : } 125 : 126 5 : std::string ReadAnalysisFrames::getDissimilarityInstruction() const { 127 5 : return "TYPE=UNKNOWN"; 128 : } 129 : 130 12 : const std::vector<AtomNumber>& ReadAnalysisFrames::getAtomIndexes() const { 131 12 : return getAbsoluteIndexes(); 132 : } 133 : 134 26 : void ReadAnalysisFrames::calculateWeights() { 135 26 : weights_calculated=true; 136 26 : weights.resize( logweights.size() ); 137 26 : if( weight_vals.empty() ) { 138 3261 : for(unsigned i=0; i<logweights.size(); ++i) { 139 3242 : weights[i]=1.0; 140 : } 141 : } else { 142 7 : if( wham_pointer ) { 143 7 : wham_pointer->calculateWeights( logweights.size() ); 144 2464 : for(unsigned i=0; i<logweights.size(); ++i) { 145 2457 : weights[i]=wham_pointer->getWeight(i); 146 : } 147 : } else { 148 : // Find the maximum weight 149 0 : double maxweight=logweights[0]; 150 0 : for(unsigned i=1; i<getNumberOfDataPoints(); ++i) { 151 0 : if(logweights[i]>maxweight) { 152 : maxweight=logweights[i]; 153 : } 154 : } 155 : // Calculate weights (no memory) -- business here with maxweight is to prevent overflows 156 0 : for(unsigned i=0; i<logweights.size(); ++i) { 157 0 : weights[i]=std::exp( logweights[i]-maxweight ); 158 : } 159 : } 160 : } 161 26 : } 162 : 163 7500 : void ReadAnalysisFrames::update() { 164 7500 : if( getStep()==0 ) { 165 28 : return; 166 : } 167 : // Delete everything we stored now that it has been analyzed 168 7472 : if( clearonnextstep ) { 169 5 : my_data_stash.clear(); 170 5 : my_data_stash.resize(0); 171 5 : logweights.clear(); 172 5 : logweights.resize(0); 173 5 : if( wham_pointer ) { 174 0 : wham_pointer->clearData(); 175 : } 176 5 : clearonnextstep=false; 177 : } 178 : 179 : // Get the weight and store it in the weights array 180 7472 : double ww=0; 181 11684 : for(unsigned i=0; i<weight_vals.size(); ++i) { 182 4212 : ww+=weight_vals[i]->get(); 183 : } 184 7472 : weights_calculated=false; 185 7472 : logweights.push_back(ww); 186 : 187 : // Now create the data collection object and push it back to be stored 188 : unsigned index = my_data_stash.size(); 189 7472 : my_data_stash.push_back( DataCollectionObject() ); 190 7472 : my_data_stash[index].setAtomNumbersAndArgumentNames( getLabel(), atom_numbers, argument_names ); 191 7472 : my_data_stash[index].setAtomPositions( getPositions() ); 192 16079 : for(unsigned i=0; i<argument_names.size(); ++i) { 193 8607 : my_data_stash[index].setArgument( argument_names[i], getArgument(i) ); 194 : } 195 : 196 7472 : if( clearstride>0 ) { 197 475 : if( getStep()%clearstride==0 ) { 198 9 : clearonnextstep=true; 199 : } 200 : } 201 : } 202 : 203 : } 204 : }