Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2012-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 "FunctionShortcut.h" 23 : #include "FunctionOfScalar.h" 24 : #include "FunctionOfVector.h" 25 : #include "core/ActionRegister.h" 26 : #include "FunctionTemplateBase.h" 27 : 28 : namespace PLMD { 29 : namespace function { 30 : 31 : //+PLUMEDOC FUNCTION SORT 32 : /* 33 : This function can be used to sort colvars according to their magnitudes. 34 : 35 : \par Description of components 36 : 37 : This function sorts its arguments according to their magnitudes. The lowest argument will be 38 : labelled <em>label</em>.1, the second lowest will be labelled <em>label</em>.2 and so on. 39 : 40 : \par Examples 41 : 42 : The following input tells plumed to print the distance of the closest and of 43 : the farthest atoms to atom 1, chosen among atoms from 2 to 5 44 : \plumedfile 45 : d12: DISTANCE ATOMS=1,2 46 : d13: DISTANCE ATOMS=1,3 47 : d14: DISTANCE ATOMS=1,4 48 : d15: DISTANCE ATOMS=1,5 49 : sort: SORT ARG=d12,d13,d14,d15 50 : PRINT ARG=sort.1,sort.4 51 : \endplumedfile 52 : 53 : */ 54 : //+ENDPLUMEDOC 55 : 56 : //+PLUMEDOC FUNCTION SORT_SCALAR 57 : /* 58 : Sort the input scalars in a vector according to their magnitudes 59 : 60 : \par Examples 61 : 62 : */ 63 : //+ENDPLUMEDOC 64 : 65 : //+PLUMEDOC FUNCTION SORT_VECTOR 66 : /* 67 : Sort the elements in a vector according to their magnitudes 68 : 69 : \par Examples 70 : 71 : */ 72 : //+ENDPLUMEDOC 73 : 74 99 : class Sort : public FunctionTemplateBase { 75 : private: 76 : bool scalar_out; 77 : unsigned nargs; 78 : public: 79 : void registerKeywords(Keywords& keys) override ; 80 : void read( ActionWithArguments* action ) override; 81 0 : bool zeroRank() const override { return true; } 82 38 : bool doWithTasks() const override { return !scalar_out; } 83 : std::vector<std::string> getComponentsPerLabel() const override ; 84 : void setPeriodicityForOutputs( ActionWithValue* action ) override; 85 : void calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const override; 86 : }; 87 : 88 : typedef FunctionShortcut<Sort> SortShortcut; 89 : PLUMED_REGISTER_ACTION(SortShortcut,"SORT") 90 : typedef FunctionOfScalar<Sort> ScalarSort; 91 : PLUMED_REGISTER_ACTION(ScalarSort,"SORT_SCALAR") 92 : typedef FunctionOfVector<Sort> VectorSort; 93 : PLUMED_REGISTER_ACTION(VectorSort,"SORT_VECTOR") 94 : 95 65 : void Sort::registerKeywords(Keywords& keys) { 96 130 : keys.setValueDescription("vector","sorted"); 97 65 : keys.setComponentsIntroduction("The names of the components in this action will be customized in accordance with the contents of the input file. " 98 : "The largest value is called label.1th, the second largest label.2th, the third label.3th and so on"); 99 65 : } 100 : 101 : 102 17 : void Sort::read( ActionWithArguments* action ) { 103 17 : scalar_out = action->getNumberOfArguments()==1; nargs = action->getNumberOfArguments(); if( scalar_out ) nargs = action->getPntrToArgument(0)->getNumberOfValues(); 104 : 105 48 : for(unsigned i=0; i<action->getNumberOfArguments(); ++i) { 106 33 : if((action->getPntrToArgument(i))->isPeriodic()) action->error("Cannot sort periodic values (check argument "+ (action->getPntrToArgument(i))->getName() +")"); 107 : } 108 16 : } 109 : 110 16 : std::vector<std::string> Sort::getComponentsPerLabel() const { 111 : std::vector<std::string> comp; std::string num; 112 61 : for(unsigned i=0; i<nargs; ++i) { 113 45 : Tools::convert(i+1,num); comp.push_back( num ); 114 : } 115 16 : return comp; 116 0 : } 117 : 118 16 : void Sort::setPeriodicityForOutputs( ActionWithValue* action ) { 119 61 : for(unsigned i=0; i<nargs; ++i) { std::string num; Tools::convert(i+1,num); action->componentIsNotPeriodic( num ); } 120 16 : } 121 : 122 45 : void Sort::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const { 123 45 : std::vector<std::pair<double,int> > data(args.size()); 124 326 : for(unsigned i=0; i<args.size(); ++i) { 125 281 : data[i].first=args[i]; 126 : // In this manner I remember from which argument the component depends: 127 281 : data[i].second=i; 128 : } 129 : // STL sort sorts based on first element (value) then second (index) 130 45 : std::sort(data.begin(),data.end()); derivatives = 0; 131 326 : for(int i=0; i<vals.size(); ++i) { vals[i] = data[i].first; derivatives(i, data[i].second ) = 1; } 132 45 : } 133 : 134 : } 135 : } 136 : 137 :