Line data Source code
1 : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 : Copyright (c) 2013-2019 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(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 : static class classname##RegisterMe{ \ 65 : static std::unique_ptr<ReferenceConfiguration> create(const PLMD::ReferenceConfigurationOptions&ro){return std::unique_ptr<ReferenceConfiguration>( new 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 518877 : std::unique_ptr<T> MetricRegister::create( const std::string& type ) { 73 : std::string ftype; 74 518877 : if( type.find("MULTI-")!=std::string::npos ) { 75 : ftype="MULTI"; 76 : } else { 77 518872 : std::size_t dash=type.find("-FAST"); // We must remove the fast label 78 1037744 : ftype=type.substr(0,dash); 79 : } 80 1037754 : plumed_massert( check(ftype), "metric " + ftype + " does not exist" ); 81 518877 : ReferenceConfigurationOptions ro( type ); 82 : // put immediately the result in a safe pointer 83 518877 : std::unique_ptr<ReferenceConfiguration> conf( m[ftype]( ro ) ); 84 : // try conversion 85 134 : 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 518877 : if(!ptr ) plumed_merror( type + " metric is not valid in this context"); 90 : // release ownership in order to transfer it to returned pointer 91 : conf.release(); 92 : // notice that I should pass ptr here rather than conf.release(), 93 : // since the type is different 94 518877 : return std::unique_ptr<T>(ptr); 95 : } 96 : 97 : template <class T> 98 518821 : std::unique_ptr<T> MetricRegister::create( const std::string& type, const PDB& pdb ) { 99 : std::string rtype; 100 518821 : if( type.length()==0 ) { 101 20 : rtype=pdb.getMtype(); 102 10 : plumed_massert(rtype.length()>0, "TYPE not specified in pdb input file"); 103 : } else { 104 : rtype=type; 105 : } 106 518821 : std::unique_ptr<T> confout( create<T>( rtype ) ); 107 518821 : confout->read( pdb ); 108 518817 : return confout; 109 : } 110 : 111 : } 112 : #endif