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 105 : 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 { 82 0 : return true; 83 : } 84 0 : bool doWithTasks() const override { 85 38 : return !scalar_out; 86 : } 87 : std::vector<std::string> getComponentsPerLabel() const override ; 88 : void setPeriodicityForOutputs( ActionWithValue* action ) override; 89 : void calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const override; 90 : }; 91 : 92 : typedef FunctionShortcut<Sort> SortShortcut; 93 : PLUMED_REGISTER_ACTION(SortShortcut,"SORT") 94 : typedef FunctionOfScalar<Sort> ScalarSort; 95 : PLUMED_REGISTER_ACTION(ScalarSort,"SORT_SCALAR") 96 : typedef FunctionOfVector<Sort> VectorSort; 97 : PLUMED_REGISTER_ACTION(VectorSort,"SORT_VECTOR") 98 : 99 71 : void Sort::registerKeywords(Keywords& keys) { 100 71 : keys.setValueDescription("sorted"); 101 71 : keys.setComponentsIntroduction("The names of the components in this action will be customized in accordance with the contents of the input file. " 102 : "The largest value is called label.1th, the second largest label.2th, the third label.3th and so on"); 103 71 : } 104 : 105 : 106 17 : void Sort::read( ActionWithArguments* action ) { 107 17 : scalar_out = action->getNumberOfArguments()==1; 108 17 : nargs = action->getNumberOfArguments(); 109 17 : if( scalar_out ) { 110 11 : nargs = action->getPntrToArgument(0)->getNumberOfValues(); 111 : } 112 : 113 48 : for(unsigned i=0; i<action->getNumberOfArguments(); ++i) { 114 32 : if((action->getPntrToArgument(i))->isPeriodic()) { 115 2 : action->error("Cannot sort periodic values (check argument "+ (action->getPntrToArgument(i))->getName() +")"); 116 : } 117 : } 118 16 : } 119 : 120 16 : std::vector<std::string> Sort::getComponentsPerLabel() const { 121 : std::vector<std::string> comp; 122 : std::string num; 123 61 : for(unsigned i=0; i<nargs; ++i) { 124 45 : Tools::convert(i+1,num); 125 45 : comp.push_back( num ); 126 : } 127 16 : return comp; 128 0 : } 129 : 130 16 : void Sort::setPeriodicityForOutputs( ActionWithValue* action ) { 131 61 : for(unsigned i=0; i<nargs; ++i) { 132 : std::string num; 133 45 : Tools::convert(i+1,num); 134 45 : action->componentIsNotPeriodic( num ); 135 : } 136 16 : } 137 : 138 45 : void Sort::calc( const ActionWithArguments* action, const std::vector<double>& args, std::vector<double>& vals, Matrix<double>& derivatives ) const { 139 45 : std::vector<std::pair<double,int> > data(args.size()); 140 326 : for(unsigned i=0; i<args.size(); ++i) { 141 281 : data[i].first=args[i]; 142 : // In this manner I remember from which argument the component depends: 143 281 : data[i].second=i; 144 : } 145 : // STL sort sorts based on first element (value) then second (index) 146 45 : std::sort(data.begin(),data.end()); 147 : derivatives = 0; 148 326 : for(int i=0; i<vals.size(); ++i) { 149 281 : vals[i] = data[i].first; 150 281 : derivatives(i, data[i].second ) = 1; 151 : } 152 45 : } 153 : 154 : } 155 : } 156 : 157 :