1 /* ---------------------------------------------------------------------- 2 This is the 3 4 ██╗ ██╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗████████╗███████╗ 5 ██║ ██║██╔════╝ ██╔════╝ ██╔════╝ ██║ ██║╚══██╔══╝██╔════╝ 6 ██║ ██║██║ ███╗██║ ███╗██║ ███╗███████║ ██║ ███████╗ 7 ██║ ██║██║ ██║██║ ██║██║ ██║██╔══██║ ██║ ╚════██║ 8 ███████╗██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ██║ ██║ ███████║ 9 ╚══════╝╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝® 10 11 DEM simulation engine, released by 12 DCS Computing Gmbh, Linz, Austria 13 http://www.dcs-computing.com, office@dcs-computing.com 14 15 LIGGGHTS® is part of CFDEM®project: 16 http://www.liggghts.com | http://www.cfdem.com 17 18 Core developer and main author: 19 Christoph Kloss, christoph.kloss@dcs-computing.com 20 21 LIGGGHTS® is open-source, distributed under the terms of the GNU Public 22 License, version 2 or later. It is distributed in the hope that it will 23 be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 24 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. You should have 25 received a copy of the GNU General Public License along with LIGGGHTS®. 26 If not, see http://www.gnu.org/licenses . See also top-level README 27 and LICENSE files. 28 29 LIGGGHTS® and CFDEM® are registered trade marks of DCS Computing GmbH, 30 the producer of the LIGGGHTS® software and the CFDEM®coupling software 31 See http://www.cfdem.com/terms-trademark-policy for details. 32 33 ------------------------------------------------------------------------- 34 Contributing author and copyright for this file: 35 36 Richard Berger (JKU Linz) 37 38 Copyright 2012-2014 JKU Linz 39 ------------------------------------------------------------------------- */ 40 41 #ifndef SETTINGS_H_ 42 #define SETTINGS_H_ 43 44 #include "pointers.h" 45 #include <string> 46 #include <set> 47 #include <map> 48 #include <sstream> 49 #include <stdlib.h> 50 51 using namespace LAMMPS_NS; 52 53 template<typename T> 54 class ValuePropagator { 55 public: registerTarget(T & target)56 void registerTarget(T & target) 57 { 58 targets.insert(&target); 59 target = currentValue; 60 } 61 setValue(T value)62 void setValue(T value) 63 { 64 currentValue = value; 65 66 for(typename std::set<T*>::iterator it = targets.begin(); it != targets.end(); ++it) { 67 *(*it) = value; 68 } 69 } 70 getValue()71 T getValue() const { 72 return currentValue; 73 } 74 75 private: 76 T currentValue; 77 std::set<T*> targets; 78 }; 79 80 class Setting { 81 public: Setting(std::string name,int num_params)82 Setting(std::string name, int num_params) : name(name), num_params(num_params) 83 { 84 } ~Setting()85 virtual ~Setting(){} 86 87 // subclasses implement this method and return the amount of arguments have 88 // been consumed. 89 virtual int parseArguments(char ** args) = 0; 90 91 virtual void print_value(FILE * out) = 0; 92 93 std::string name; 94 int num_params; 95 std::string error_message; 96 }; 97 98 template<typename T> 99 class EnumSetting : public Setting 100 { 101 public: 102 typedef T value_type; 103 EnumSetting(std::string name)104 EnumSetting(std::string name) : Setting(name, 1) 105 { 106 } 107 ~EnumSetting()108 virtual ~EnumSetting(){} 109 addOption(std::string option,T value)110 void addOption(std::string option, T value) 111 { 112 options[option] = value; 113 } 114 setDefault(std::string option)115 void setDefault(std::string option){ 116 current.setValue(options[option]); 117 } 118 registerTarget(T & target)119 void registerTarget(T & target) { 120 current.registerTarget(target); 121 } 122 parseArguments(char ** args)123 int parseArguments(char ** args) { 124 if(name != args[0]) return 0; // argument not consumed 125 std::string selected(args[1]); 126 if(options.find(selected) != options.end()){ 127 current.setValue(options[selected]); 128 return 2; // argument consumed 129 } else { 130 std::stringstream ss; 131 ss << "while parsing '" << name << "' argument: "; 132 ss << "unknown option or wrong keyword order: '" << args[1] << "'"; 133 error_message = ss.str(); 134 } 135 return -1; // error while parsing argument 136 } 137 print_value(FILE * out)138 virtual void print_value(FILE* out) { 139 T value = current.getValue(); 140 for(typename std::map<std::string, T>::iterator it = options.begin(); it != options.end(); ++it) { 141 if(it->second == value) { 142 fprintf(out, "%s", it->first.c_str()); 143 return; 144 } 145 } 146 fprintf(out, "BAD_VALUE"); 147 } 148 149 private: 150 ValuePropagator<T> current; 151 std::map<std::string, T> options; 152 }; 153 154 class DoubleSetting : public Setting 155 { 156 public: 157 typedef double value_type; 158 DoubleSetting(std::string name,double default_value)159 DoubleSetting(std::string name, double default_value) : Setting(name, 1) 160 { 161 setDefault(default_value); 162 } 163 ~DoubleSetting()164 virtual ~DoubleSetting(){} 165 setDefault(double d)166 void setDefault(double d){ 167 current.setValue(d); 168 } 169 registerTarget(double & target)170 void registerTarget(double & target) { 171 current.registerTarget(target); 172 } 173 parseArguments(char ** args)174 int parseArguments(char ** args) { 175 if(name != args[0]) return 0; 176 current.setValue(atof(args[1])); 177 return 2; 178 } 179 print_value(FILE * out)180 void print_value(FILE* out) { 181 fprintf(out, "%g", current.getValue()); 182 } 183 184 private: 185 ValuePropagator<double> current; 186 }; 187 188 class OnOffSetting : public EnumSetting<bool> { 189 public: OnOffSetting(std::string name,bool default_value)190 OnOffSetting(std::string name, bool default_value) : EnumSetting<bool>(name) 191 { 192 addOption("off", false); 193 addOption("on", true); 194 if(default_value) setDefault("on"); 195 else setDefault("off"); 196 } 197 ~OnOffSetting()198 virtual ~OnOffSetting(){} 199 }; 200 201 class YesNoSetting : public EnumSetting<bool> { 202 public: YesNoSetting(std::string name,bool default_value)203 YesNoSetting(std::string name, bool default_value) : EnumSetting<bool>(name) 204 { 205 addOption("no", false); 206 addOption("yes", true); 207 if(default_value) setDefault("yes"); 208 else setDefault("no"); 209 } ~YesNoSetting()210 virtual ~YesNoSetting(){} 211 }; 212 213 class Settings : protected Pointers 214 { 215 typedef std::map<std::string, Setting*> SettingMap; 216 SettingMap settings; 217 218 template<typename SettingType> registerSetting(std::string name,typename SettingType::value_type & variable,typename SettingType::value_type default_value)219 void registerSetting(std::string name, typename SettingType::value_type & variable, typename SettingType::value_type default_value) { 220 if(settings.find(name) == settings.end()) { 221 settings[name] = new SettingType(name, default_value); 222 } 223 SettingType * setting = dynamic_cast<SettingType*>(settings[name]); 224 if(setting) setting->registerTarget(variable); 225 } 226 227 public: 228 std::string error_message; 229 Settings(LAMMPS * lmp)230 Settings(LAMMPS * lmp) : Pointers(lmp) {} ~Settings()231 ~Settings() { 232 for(SettingMap::iterator it = settings.begin(); it != settings.end(); ++it) { 233 delete it->second; 234 } 235 } 236 237 void registerOnOff(std::string name, bool & variable, bool default_value = false) 238 { 239 registerSetting<OnOffSetting>(name, variable, default_value); 240 } 241 242 void registerYesNo(std::string name, bool & variable, bool default_value = false) { 243 registerSetting<YesNoSetting>(name, variable, default_value); 244 } 245 246 void registerDoubleSetting(std::string name, double & variable, double default_value = 0.0) 247 { 248 registerSetting<DoubleSetting>(name, variable, default_value); 249 } 250 parseArguments(int nargs,char ** args)251 bool parseArguments(int nargs, char ** args) { 252 bool found = false; 253 int remaining = nargs; 254 char ** remaining_args = args; 255 int consumed = 0; 256 257 while(remaining > 0) { 258 found = false; 259 260 for(SettingMap::iterator it = settings.begin(); it != settings.end(); ++it) { 261 consumed = it->second->parseArguments(remaining_args); 262 if(consumed > 0) { 263 found = true; 264 break; 265 } else if(consumed < 0) { 266 error_message = it->second->error_message; 267 return false; 268 } 269 } 270 271 if(found) { 272 remaining -= consumed; 273 remaining_args = &remaining_args[consumed]; 274 } else { 275 std::stringstream ss; 276 ss << "Unknown argument or wrong keyword order: '" << remaining_args[0] << "'"; 277 error_message = ss.str(); 278 return false; 279 } 280 } 281 return true; 282 } 283 print_all(FILE * out)284 void print_all(FILE * out) 285 { 286 for(SettingMap::iterator it = settings.begin(); it != settings.end(); ++it) { 287 fprintf(out, " %s = ", it->first.c_str()); 288 it->second->print_value(out); 289 fprintf(out, "\n"); 290 } 291 } 292 }; 293 294 #endif /* SETTINGS_H_ */ 295