Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-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 : #ifndef __PLUMED_reference_MetricRegister_h 23 : #define __PLUMED_reference_MetricRegister_h 24 : 25 : #include <string> 26 : #include <cstring> 27 : #include <vector> 28 : #include <map> 29 : #include "tools/Exception.h" 30 : #include "tools/Tools.h" 31 : #include "tools/PDB.h" 32 : #include "ReferenceConfiguration.h" 33 : 34 : namespace PLMD { 35 : 36 : class PDB; 37 : 38 : class MetricRegister { 39 : private: 40 : /// Pointer to a function which, given the type for a ReferenceConfiguration, creates it 41 : typedef std::unique_ptr<ReferenceConfiguration> (*creator_pointer)(const ReferenceConfigurationOptions&); 42 : /// The set of possible distribution functions we can work with 43 : std::map<std::string,creator_pointer> m; 44 : public: 45 : /// The destructor 46 : ~MetricRegister(); 47 : /// Add a new metric to the register of metrics 48 : void add( std::string type, creator_pointer ); 49 : /// Remove a metric from the register of metrics 50 : void remove(creator_pointer f); 51 : /// Verify if a particular metric type is present in the register 52 : bool check(const std::string & type); 53 : /// Create a reference configuration and don't set a point of reference 54 : template <class T> 55 : std::unique_ptr<T> create( const std::string& type ); 56 : /// Create a reference configuration and set the point of reference from the pdb 57 : template <class T> 58 : std::unique_ptr<T> create( const std::string& type, const PDB& pdb ); 59 : }; 60 : 61 : MetricRegister& metricRegister(); 62 : 63 : #define PLUMED_REGISTER_METRIC(classname,type) \ 64 : namespace { class classname##RegisterMe{ \ 65 : static std::unique_ptr<ReferenceConfiguration> create(const PLMD::ReferenceConfigurationOptions&ro){return PLMD::Tools::make_unique<classname>(ro);} \ 66 : public: \ 67 : classname##RegisterMe(){PLMD::metricRegister().add(type,create);}; \ 68 : ~classname##RegisterMe(){PLMD::metricRegister().remove(create);}; \ 69 : } classname##RegisterMeObject; } 70 : 71 : template <class T> 72 518906 : std::unique_ptr<T> MetricRegister::create( const std::string& type ) { 73 : std::string ftype; 74 518906 : if( type.find("MULTI-")!=std::string::npos ) { 75 : ftype="MULTI"; 76 : } else { 77 518901 : std::size_t dash=type.find("-FAST"); // We must remove the fast label 78 1037802 : ftype=type.substr(0,dash); 79 : } 80 518906 : plumed_massert( check(ftype), "metric " + ftype + " does not exist" ); 81 518906 : ReferenceConfigurationOptions ro( type ); 82 : // put immediately the result in a safe pointer 83 518906 : std::unique_ptr<ReferenceConfiguration> conf( m[ftype]( ro ) ); 84 : // try conversion 85 163 : T*ptr=dynamic_cast<T*>( conf.get() ); 86 : // if this throws, the unique_ptr conf is deleted. 87 : // Notice that with the original version of the code (2.4) an error here 88 : // would have lead to a memory leak. 89 518906 : if(!ptr ) { 90 0 : plumed_merror( type + " metric is not valid in this context"); 91 : } 92 : // release ownership in order to transfer it to returned pointer 93 : conf.release(); 94 : // notice that I should pass ptr here rather than conf.release(), 95 : // since the type is different 96 : // cppcheck-suppress returnDanglingLifetime 97 518906 : return std::unique_ptr<T>(ptr); 98 518906 : } 99 : 100 : template <class T> 101 518823 : std::unique_ptr<T> MetricRegister::create( const std::string& type, const PDB& pdb ) { 102 : std::string rtype; 103 518823 : if( type.length()==0 ) { 104 20 : rtype=pdb.getMtype(); 105 10 : plumed_massert(rtype.length()>0, "TYPE not specified in pdb input file"); 106 : } else { 107 : rtype=type; 108 : } 109 518823 : std::unique_ptr<T> confout( create<T>( rtype ) ); 110 518823 : confout->read( pdb ); 111 518823 : return confout; 112 0 : } 113 : 114 : } 115 : #endif