$extrastylesheet
00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_PARAMETERS_H 00021 #define LIBMESH_PARAMETERS_H 00022 00023 // C++ includes 00024 #include <typeinfo> 00025 #include <string> 00026 #include <map> 00027 00028 // Local includes 00029 #include "libmesh/libmesh_common.h" 00030 #include "libmesh/reference_counted_object.h" 00031 #include "libmesh/print_trace.h" 00032 00033 // C++ includes 00034 #include <cstddef> 00035 #include <map> 00036 #include <string> 00037 #include <typeinfo> 00038 #include <sstream> 00039 00040 namespace libMesh 00041 { 00045 template<typename P> 00046 void print_helper(std::ostream& os, const P* param); 00047 00048 template<typename P> 00049 void print_helper(std::ostream& os, const std::vector<P>* param); 00050 00061 // ------------------------------------------------------------ 00062 // Parameters class definition 00063 class Parameters 00064 { 00065 public: 00066 00070 Parameters () {} 00071 00075 Parameters (const Parameters&); 00076 00080 virtual ~Parameters (); 00081 00086 virtual Parameters& operator= (const Parameters& source); 00087 00093 virtual Parameters& operator+= (const Parameters& source); 00094 00102 template <typename T> 00103 bool have_parameter (const std::string&) const; 00104 00109 template <typename T> 00110 const T& get (const std::string&) const; 00111 00117 template <typename T> 00118 void insert (const std::string&); 00119 00126 template <typename T> 00127 T& set (const std::string&); 00128 00133 virtual void set_attributes(const std::string&, bool /*inserted_only*/) {} 00134 00138 void remove (const std::string&); 00139 00143 std::size_t n_parameters () const { return _values.size(); } 00144 00145 #ifdef LIBMESH_HAVE_RTTI 00146 00149 template <typename T> 00150 unsigned int n_parameters () const; 00151 #endif // LIBMESH_HAVE_RTTI 00152 00156 virtual void clear (); 00157 00161 void print (std::ostream& os=libMesh::out) const; 00162 00163 private: 00164 00168 class Value : public ReferenceCountedObject<Value> 00169 { 00170 public: 00171 00175 virtual ~Value() {} 00176 00177 #ifdef LIBMESH_HAVE_RTTI 00178 00182 virtual std::string type () const = 0; 00183 #endif // LIBMESH_HAVE_RTTI 00184 00189 virtual void print(std::ostream&) const = 0; 00190 00195 virtual Value* clone () const = 0; 00196 }; 00197 00198 public: 00199 00204 template <typename T> 00205 class Parameter : public Value 00206 { 00207 public: 00208 00212 const T& get () const { return _value; } 00213 00217 T& set () { return _value; } 00218 00219 #ifdef LIBMESH_HAVE_RTTI 00220 00223 virtual std::string type () const; 00224 #endif // LIBMESH_HAVE_RTTI 00225 00229 virtual void print(std::ostream&) const; 00230 00234 virtual Value* clone () const; 00235 00236 private: 00240 T _value; 00241 }; 00242 00246 typedef std::map<std::string, Value*>::iterator iterator; 00247 00251 typedef std::map<std::string, Value*>::const_iterator const_iterator; 00252 00256 iterator begin(); 00257 00261 const_iterator begin() const; 00262 00266 iterator end(); 00267 00271 const_iterator end() const; 00272 00273 protected: 00274 00278 std::map<std::string, Value*> _values; 00279 00280 }; 00281 00282 // ------------------------------------------------------------ 00283 // Parameters::Parameter<> class inline methods 00284 00285 // This only works with Run-Time Type Information, even though 00286 // typeid(T) *should* be determinable at compile time regardless... 00287 #ifdef LIBMESH_HAVE_RTTI 00288 template <typename T> 00289 inline 00290 std::string Parameters::Parameter<T>::type () const 00291 { 00292 return demangle(typeid(T).name()); 00293 } 00294 #endif 00295 00296 template <typename T> 00297 inline 00298 void Parameters::Parameter<T>::print (std::ostream& os) const 00299 { 00300 // Call helper function overloaded for basic scalar and vector types 00301 print_helper(os, static_cast<const T*>(&_value)); 00302 } 00303 00304 template <typename T> 00305 inline 00306 Parameters::Value* Parameters::Parameter<T>::clone () const 00307 { 00308 // No good for Solaris C++! - BSK 00309 // Parameters::Parameter<T> 00310 // *copy = new Parameters::Parameter<T>; 00311 Parameter<T> 00312 *copy = new Parameter<T>; 00313 00314 libmesh_assert(copy); 00315 00316 copy->_value = _value; 00317 00318 return copy; 00319 } 00320 00321 00322 // ------------------------------------------------------------ 00323 // Parameters class inline methods 00324 inline 00325 void Parameters::clear () // since this is inline we must define it 00326 { // before its first use (for some compilers) 00327 while (!_values.empty()) 00328 { 00329 Parameters::iterator it = _values.begin(); 00330 00331 delete it->second; 00332 it->second = NULL; 00333 00334 _values.erase(it); 00335 } 00336 } 00337 00338 00339 00340 inline 00341 Parameters& Parameters::operator= (const Parameters& source) 00342 { 00343 this->clear(); 00344 *this += source; 00345 00346 return *this; 00347 } 00348 00349 inline 00350 Parameters& Parameters::operator+= (const Parameters& source) 00351 { 00352 for (Parameters::const_iterator it = source._values.begin(); 00353 it != source._values.end(); ++it) 00354 { 00355 if (_values.find(it->first) != _values.end()) 00356 delete _values[it->first]; 00357 _values[it->first] = it->second->clone(); 00358 } 00359 00360 return *this; 00361 } 00362 00363 inline 00364 Parameters::Parameters (const Parameters& p) 00365 { 00366 *this = p; 00367 } 00368 00369 00370 00371 inline 00372 Parameters::~Parameters () 00373 { 00374 this->clear (); 00375 } 00376 00377 00378 00379 inline 00380 void Parameters::print (std::ostream& os) const 00381 { 00382 Parameters::const_iterator it = _values.begin(); 00383 00384 os << "Name\t Type\t Value\n" 00385 << "---------------------\n"; 00386 while (it != _values.end()) 00387 { 00388 os << " " << it->first 00389 #ifdef LIBMESH_HAVE_RTTI 00390 << "\t " << it->second->type() 00391 #endif // LIBMESH_HAVE_RTTI 00392 << "\t "; it->second->print(os); 00393 os << '\n'; 00394 00395 ++it; 00396 } 00397 } 00398 00399 00400 00401 // Declare this now that Paramers::print() is defined. 00402 // By declaring this early we can use it in subsequent 00403 // methods. Required for gcc-4.0.2 -- 11/30/2005, BSK 00404 inline 00405 std::ostream& operator << (std::ostream& os, const Parameters& p) 00406 { 00407 p.print(os); 00408 return os; 00409 } 00410 00411 00412 00413 template <typename T> 00414 inline 00415 bool Parameters::have_parameter (const std::string& name) const 00416 { 00417 Parameters::const_iterator it = _values.find(name); 00418 00419 if (it != _values.end()) 00420 #ifdef LIBMESH_HAVE_RTTI 00421 if (dynamic_cast<const Parameter<T>*>(it->second) != NULL) 00422 #else // LIBMESH_HAVE_RTTI 00423 if (cast_ptr<const Parameter<T>*>(it->second) != NULL) 00424 #endif // LIBMESH_HAVE_RTTI 00425 return true; 00426 00427 return false; 00428 } 00429 00430 00431 00432 template <typename T> 00433 inline 00434 const T& Parameters::get (const std::string& name) const 00435 { 00436 if (!this->have_parameter<T>(name)) 00437 { 00438 std::ostringstream oss; 00439 00440 oss << "ERROR: no"; 00441 #ifdef LIBMESH_HAVE_RTTI 00442 oss << ' ' << demangle(typeid(T).name()); 00443 #endif 00444 oss << " parameter named \"" 00445 << name << "\":\n" 00446 << *this; 00447 00448 libmesh_error_msg(oss.str()); 00449 } 00450 00451 Parameters::const_iterator it = _values.find(name); 00452 00453 libmesh_assert(it != _values.end()); 00454 libmesh_assert(it->second); 00455 00456 return cast_ptr<Parameter<T>*>(it->second)->get(); 00457 } 00458 00459 template <typename T> 00460 inline 00461 void Parameters::insert (const std::string &name) 00462 { 00463 if (!this->have_parameter<T>(name)) 00464 _values[name] = new Parameter<T>; 00465 00466 set_attributes(name, true); 00467 } 00468 00469 00470 template <typename T> 00471 inline 00472 T& Parameters::set (const std::string& name) 00473 { 00474 if (!this->have_parameter<T>(name)) 00475 _values[name] = new Parameter<T>; 00476 00477 set_attributes(name, false); 00478 00479 return cast_ptr<Parameter<T>*>(_values[name])->set(); 00480 } 00481 00482 inline 00483 void Parameters::remove (const std::string& name) 00484 { 00485 Parameters::iterator it = _values.find(name); 00486 00487 if (it != _values.end()) 00488 { 00489 delete it->second; 00490 it->second = NULL; 00491 00492 _values.erase(it); 00493 } 00494 } 00495 00496 00497 00498 #ifdef LIBMESH_HAVE_RTTI 00499 template <typename T> 00500 inline 00501 unsigned int Parameters::n_parameters () const 00502 { 00503 unsigned int cnt = 0; 00504 00505 Parameters::const_iterator it = _values.begin(); 00506 const Parameters::const_iterator vals_end = _values.end(); 00507 00508 for (; it != vals_end; ++it) 00509 if (dynamic_cast<Parameter<T>*>(it->second) != NULL) 00510 cnt++; 00511 00512 return cnt; 00513 } 00514 #endif 00515 00516 inline 00517 Parameters::iterator Parameters::begin() 00518 { 00519 return _values.begin(); 00520 } 00521 00522 inline 00523 Parameters::const_iterator Parameters::begin() const 00524 { 00525 return _values.begin(); 00526 } 00527 00528 inline 00529 Parameters::iterator Parameters::end() 00530 { 00531 return _values.end(); 00532 } 00533 00534 inline 00535 Parameters::const_iterator Parameters::end() const 00536 { 00537 return _values.end(); 00538 } 00539 00540 //non-member scalar print function 00541 template<typename P> 00542 void print_helper(std::ostream& os, const P* param) 00543 { 00544 os << *param; 00545 } 00546 00547 //non-member vector print function 00548 template<typename P> 00549 void print_helper(std::ostream& os, const std::vector<P>* param) 00550 { 00551 for (unsigned int i=0; i<param->size(); ++i) 00552 os << (*param)[i] << " "; 00553 } 00554 00555 } // namespace libMesh 00556 00557 #endif // LIBMESH_PARAMETERS_H