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 10479 : PLUMED_REGISTER_ACTION(ReadAnalysisFrames,"COLLECT_FRAMES") 40 : 41 31 : void ReadAnalysisFrames::registerKeywords( Keywords& keys ) { 42 31 : AnalysisBase::registerKeywords( keys ); 43 93 : keys.remove("SERIAL"); keys.remove("USE_OUTPUT_DATA_FROM"); keys.use("ARG"); 44 62 : keys.add("atoms-1","ATOMS","the atoms whose positions we are tracking for the purpose of analyzing the data"); 45 62 : keys.add("atoms-1","STRIDE","the frequency with which data should be stored for analysis. By default data is collected on every step"); 46 62 : keys.add("compulsory","CLEAR","0","the frequency with which data should all be deleted and restarted"); 47 62 : keys.add("optional","LOGWEIGHTS","list of actions that calculates log weights that should be used to weight configurations when calculating averages"); 48 31 : ActionWithValue::useCustomisableComponents( keys ); 49 31 : } 50 : 51 30 : ReadAnalysisFrames::ReadAnalysisFrames( const ActionOptions& ao ): 52 : Action(ao), 53 : AnalysisBase(ao), 54 30 : clearonnextstep(false), 55 30 : wham_pointer(NULL), 56 30 : weights_calculated(false) 57 : { 58 30 : parse("CLEAR",clearstride); 59 30 : if( clearstride!=0 ) log.printf(" clearing stored data every %u steps\n",clearstride); 60 : // Get the names of the argumes 61 30 : argument_names.resize( getNumberOfArguments() ); 62 64 : for(unsigned i=0; i<getNumberOfArguments(); ++i) argument_names[i]=getPntrToArgument(i)->getName(); 63 : // Find the atom numbers to read in 64 60 : parseAtomList("ATOMS",atom_numbers); 65 30 : if( atom_numbers.size()>0 ) { 66 5 : log.printf(" monitoring positions of atoms "); 67 79 : for(unsigned i=0; i<atom_numbers.size(); ++i) log.printf("%d ",atom_numbers[i].serial() ); 68 5 : log.printf("\n"); requestAtoms(atom_numbers); 69 : } 70 : 71 : // Get stuff for any reweighting that should go on 72 60 : std::vector<std::string> wwstr; parseVector("LOGWEIGHTS",wwstr); 73 30 : if( wwstr.size()>0 ) log.printf(" reweighting using weights from "); 74 30 : std::vector<Value*> arg( ActionWithArguments::getArguments() ); 75 42 : for(unsigned i=0; i<wwstr.size(); ++i) { 76 12 : ActionWithValue* val = plumed.getActionSet().selectWithLabel<ActionWithValue*>(wwstr[i]); 77 12 : if( !val ) error("could not find value named"); 78 12 : weight_vals.push_back( val->copyOutput(val->getLabel()) ); 79 12 : arg.push_back( val->copyOutput(val->getLabel()) ); 80 12 : log.printf("%s ",wwstr[i].c_str() ); 81 : } 82 30 : if( wwstr.size()>0 ) { 83 12 : log.printf("\n"); 84 12 : wham_pointer = dynamic_cast<bias::ReweightBase*>( weight_vals[0]->getPntrToAction() ); 85 12 : if( !wham_pointer ) wham_pointer = NULL; 86 12 : else if( !wham_pointer->buildsWeightStore() ) wham_pointer = NULL; 87 12 : if( wham_pointer && weight_vals.size()!=1 ) error("can only extract weights from one wham object"); 88 18 : } else log.printf(" weights are all equal to one\n"); 89 30 : requestArguments( arg ); 90 : 91 : // Now add fake components to the underlying ActionWithValue for the arguments 92 64 : for(unsigned i=0; i<argument_names.size(); ++i) { addComponent( argument_names[i] ); componentIsNotPeriodic( argument_names[i] ); } 93 30 : } 94 : 95 62 : std::vector<Value*> ReadAnalysisFrames::getArgumentList() { 96 62 : std::vector<Value*> arg_vals( ActionWithArguments::getArguments() ); 97 68 : for(unsigned i=0; i<weight_vals.size(); ++i) arg_vals.erase(arg_vals.end()-1); 98 62 : return arg_vals; 99 : } 100 : 101 5 : std::string ReadAnalysisFrames::getDissimilarityInstruction() const { 102 5 : return "TYPE=UNKNOWN"; 103 : } 104 : 105 12 : const std::vector<AtomNumber>& ReadAnalysisFrames::getAtomIndexes() const { 106 12 : return getAbsoluteIndexes(); 107 : } 108 : 109 26 : void ReadAnalysisFrames::calculateWeights() { 110 26 : weights_calculated=true; 111 26 : weights.resize( logweights.size() ); 112 26 : if( weight_vals.empty() ) { 113 3261 : for(unsigned i=0; i<logweights.size(); ++i) weights[i]=1.0; 114 : } else { 115 7 : if( wham_pointer ) { 116 7 : wham_pointer->calculateWeights( logweights.size() ); 117 2464 : for(unsigned i=0; i<logweights.size(); ++i) weights[i]=wham_pointer->getWeight(i); 118 : } else { 119 : // Find the maximum weight 120 0 : double maxweight=logweights[0]; 121 0 : for(unsigned i=1; i<getNumberOfDataPoints(); ++i) { 122 0 : if(logweights[i]>maxweight) maxweight=logweights[i]; 123 : } 124 : // Calculate weights (no memory) -- business here with maxweight is to prevent overflows 125 0 : for(unsigned i=0; i<logweights.size(); ++i) weights[i]=std::exp( logweights[i]-maxweight ); 126 : } 127 : } 128 26 : } 129 : 130 7500 : void ReadAnalysisFrames::update() { 131 7500 : if( getStep()==0 ) return; 132 : // Delete everything we stored now that it has been analyzed 133 7472 : if( clearonnextstep ) { 134 5 : my_data_stash.clear(); my_data_stash.resize(0); 135 10 : logweights.clear(); logweights.resize(0); 136 5 : if( wham_pointer ) wham_pointer->clearData(); 137 5 : clearonnextstep=false; 138 : } 139 : 140 : // Get the weight and store it in the weights array 141 11684 : double ww=0; for(unsigned i=0; i<weight_vals.size(); ++i) ww+=weight_vals[i]->get(); 142 7472 : weights_calculated=false; logweights.push_back(ww); 143 : 144 : // Now create the data collection object and push it back to be stored 145 7472 : unsigned index = my_data_stash.size(); my_data_stash.push_back( DataCollectionObject() ); 146 7472 : my_data_stash[index].setAtomNumbersAndArgumentNames( getLabel(), atom_numbers, argument_names ); 147 7472 : my_data_stash[index].setAtomPositions( getPositions() ); 148 16079 : for(unsigned i=0; i<argument_names.size(); ++i) my_data_stash[index].setArgument( argument_names[i], getArgument(i) ); 149 : 150 7472 : if( clearstride>0 ) { 151 475 : if( getStep()%clearstride==0 ) clearonnextstep=true; 152 : } 153 : } 154 : 155 : } 156 : }