dune-fem 2.12-git
Loading...
Searching...
No Matches
container.hh
Go to the documentation of this file.
1#ifndef DUNE_FEM_IO_PARAMETER_CONTAINER_HH
2#define DUNE_FEM_IO_PARAMETER_CONTAINER_HH
3
4#include <cassert>
5#include <cstddef>
6
7#include <fstream>
8#include <iostream>
9#include <map>
10#include <queue>
11#include <set>
12#include <string>
13#include <utility>
14
15#include <dune/grid/io/file/dgfparser/dgfparser.hh>
16
17#include <dune/fem/io/io.hh>
21
22namespace Dune
23{
24
25 namespace Fem
26 {
27
28 // ParameterContainerData
29 // ----------------------
30
32 {
34 static const int solverStatistics = 1; // this is the new default level
36 static const int extendedStatistics = 2;
38 static const int parameterOutput = 3;
40 static const int diagnosticsOutput = 4;
42 static const int debugOutput = 5;
43
44 // default verbosity level used when verbose()
45 // without specifying a level is called (old behavior)
47
48 struct Value
49 {
51
52 Value () = default;
53
54 Value ( std::string v, std::string fn ) : value( std::move( v ) ), fileName( std::move( fn ) ) {}
55
57 bool used = false, hasDefault = false;
59 };
60
61 const std::string *operator() ( const std::string &key, const std::string *defaultValue ) const;
62
63 static std::string trim ( const std::string &s )
64 {
65 const std::size_t first = s.find_first_not_of( " \t\n" );
66 return (first != s.npos ? s.substr( first, s.find_last_not_of( " \t\n" ) + 1 - first ) : std::string());
67 }
68
69 std::string resolveEscape ( const std::string &key, std::string &value ) const;
70 void resolveShadows ( const std::string &key, Value &val ) const;
71 std::string getShadowKey ( const std::string key, const char delimter, std::string &value ) const;
72
73 bool verbose ( const int level = defaultVerbosityLevel ) const
74 {
75 // return true if verboserank is the current rank and if
76 // the activated verbosity level is higher or equal to the given level
77 return (verboseRank == MPIManager::rank() && level <= verbosityLevel);
78 }
79
82 int verboseRank = 0; // default is to output on rank 0
83 int verbosityLevel = 1; // default verbosity level is 1
84 bool verbosityLevelPresent = false; // this is parameter was provided
85 bool verbosityChangedByVerboseRank = false; // this is true if verboserank was provided, but not verbositylevel
86 };
87
88
89
90 // ParameterContainer
91 // ------------------
92
94 : public BasicParameterReader< ParameterContainerData >
95 {
97
98 struct DGFBlock;
99
100 static std::string stripComment ( const std::string &line );
101
102 const std::string &insert ( const std::string &key, const std::string &value, bool force );
103 bool insert ( const std::string &s, std::queue< std::string > &includes );
104
105 void processFile ( const std::string &filename );
106 void processIncludes( std::queue< std::string > &includes );
107
108 public:
109
111 operator ParameterReader () const { return ParameterReader( std::ref( parameter_ ) ); }
112
123 void append ( int &argc, char **argv );
124
130 void append ( const std::string &filename )
131 {
132 processFile( filename );
133 }
134
142 void append ( const std::string &key, const std::string &value, bool force = false )
143 {
144 if( key != "paramfile" )
145 {
146 curFileName_ = "program code";
147 insert( key, value, force );
148 }
149 else
150 append( value );
151 }
152
153
159 template <class T>
160 std::string toString( const T& value )
161 {
163 str << std::scientific;
164 str << value;
165 return str.str();
166 }
167
175 template<class NumberType, std::enable_if_t< std::is_floating_point< NumberType >::value || std::is_integral< NumberType >::value, int> = 0 >
176 void append ( const std::string &key, NumberType value, bool force = false )
177 {
178 assert( key != "paramfile" );
179 curFileName_ = "program code";
180 std::string valueString = toString( value );
181 insert( key, valueString, force );
182 }
183
192 void appendDGF ( const std::string &filename );
193
195 void clear () { parameter_.map.clear(); }
196
199 {
200 return parameter_.verbose( level );
201 }
202
204 {
205 return getValue( "fem.prefix.input", std::string( "." ) );
206 }
207
209 {
210 return getValue( "fem.prefix", std::string( "." ) );
211 }
212
227 void write ( std::ostream &out, bool writeAll = true ) const;
228 auto write ( ) const;
229
231
232 private:
233 std::string curFileName_;
234 int curLineNumber_;
235 };
236
237
238
239 // ParameterContainer::DGFBlock
240 // ----------------------------
241
244 {
245 explicit DGFBlock ( std::istream &in ) : BasicBlock( in, "FemParameter" ) {}
246
247 bool advance () { return getnextline(); }
248 std::string getLine () const { return line.str(); }
249 };
250
251
252
253 // Implementation of ParameterContainerData
254 // ----------------------------------------
255
256 inline const std::string *ParameterContainerData::operator() ( const std::string &key, const std::string *defaultValue ) const
257 {
258 if( deprecated.find( key ) != deprecated.end() )
259 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' deprecated" );
260
262 if( defaultValue )
263 {
264 const std::string& defaultValueStr = *defaultValue;
265 // only check existence, do not check default values and the like
266 // when the default string has the value of checkParameterExistsString
267 // this is to avoid problems with default and non-default parameters
268 if( defaultValueStr == checkParameterExistsString() )
269 {
270 pos = map.find( key );
271 if( pos == map.end() )
272 return nullptr;
273 else
274 {
275 Value &val = pos->second;
276 return &val.value ;
277 }
278 }
279
280 auto info = map.insert( std::make_pair( key, Value( *defaultValue, "default" ) ) );
281 if( info.second && verbose() )
282 std::cout << "Adding default: " << key << ": " << *defaultValue << std::endl;
283 pos = info.first;
284 }
285 else
286 pos = map.find( key );
287
288 if( pos == map.end() )
289 return nullptr;
290 Value &val = pos->second;
291
292 if( val.used )
293 {
294 if( val.hasDefault != static_cast< bool >( defaultValue ) )
295 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' used with and without default" );
296 if( defaultValue && (val.defaultValue != *defaultValue) )
297 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' used with different default values" );
298 }
299 else
300 {
301 val.used = true;
302 val.hasDefault = static_cast< bool >( defaultValue );
303 if( defaultValue )
304 val.defaultValue = *defaultValue;
305 }
306
307 resolveShadows( key, val );
308 return &val.value;
309 }
310
311
313 {
314 if( value.empty() )
315 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' contains trailing '$'." );
316
317 const char escapedChar = value[ 0 ];
318 value.replace( 0, 1, "" );
319
320 switch( escapedChar )
321 {
322 case '$':
323 case '%':
324 case '#':
325 return std::string( "" ) + escapedChar;
326
327 case '(':
328 {
329 auto pos = map.find( getShadowKey( key, ')', value ) );
330 if( pos == map.end() )
331 DUNE_THROW( ParameterNotFound, "Parameter '" << key << "' not found" );
332 resolveShadows( pos->first, pos->second );
333 return pos->second.value;
334 }
335
336 case '[':
337 return trim( executeCommand( getShadowKey( key, ']', value ) ) );
338
339 default:
340 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' invalid." );
341 }
342 }
343
344
345 inline void ParameterContainerData::resolveShadows ( const std::string &key, Value &val ) const
346 {
347 std::string &realValue = val.value;
348 if( val.shadowStatus == Value::resolved )
349 return;
350
351 if ( val.shadowStatus == Value::resolving )
352 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' invalid, contains infinite loop" );
353
355 std::string realValueHelper;
356 realValue.swap( realValueHelper );
357
358 while( !realValueHelper.empty() )
359 {
360 std::size_t startPoint = realValueHelper.find_first_of( '$' );
361 realValue += realValueHelper.substr( 0, startPoint );
362
363 if( startPoint == std::string::npos )
364 break;
365
366 realValueHelper.replace( 0, startPoint+1, "" );
367
368 realValue += resolveEscape( key, realValueHelper );
369 }
371 }
372
373
374 inline std::string ParameterContainerData::getShadowKey ( const std::string key, const char delimiter, std::string &value ) const
375 {
376 std::string shadowKey;
377
378 while( true )
379 {
380 std::size_t startPoint = value.find_first_of( std::string( "$" ) + delimiter );
381
382 if( startPoint == std::string::npos )
383 DUNE_THROW( ParameterInvalid, "Parameter '" << key << "' invalid." );
384
385 shadowKey += value.substr( 0, startPoint );
386 const char startChar = value[ startPoint ];
387
388 value.replace( 0, startPoint+1, "" );
389
390 if( startChar == delimiter )
391 return shadowKey;
392 assert( startChar == '$' );
393
394 shadowKey += resolveEscape( key, value );
395 }
396 }
397
398
399
400 // Implementation of ParameterContainer
401 // ------------------------------------
402
403 inline const std::string &ParameterContainer::insert ( const std::string &key, const std::string &value, bool force = false)
404 {
405 auto pos = parameter_.map.find( key );
406 bool paramExists = ( pos != parameter_.map.end() );
407 std::string paramValue;
408 if( force && paramExists )
409 {
410 paramValue = pos->second.value;
411 if( paramValue == value )
412 return value;
413 parameter_.map.erase( key );
414 }
415 auto info = parameter_.map.insert( std::make_pair( key, Value( value, curFileName_ ) ) );
416 Value &val = info.first->second;
417 if( key == "fem.verboserank" )
418 {
421 std::cout << "Warning: Parameter 'fem.verboserank' is neither a " << "valid rank nor -1." << std::endl;
422
423 // Restore default behavior:
424 // If fem.verboserank is provided, then we set the verbosityLevel to 3
425 // to restore the old behavior. Otherwise the level is 1.
428 {
431 }
432 }
433
434 if( key == "fem.verbositylevel" )
435 {
436 // if verbositylevel is provided undo the changed by verboserank
439
441
443 if( (parameter_.verbosityLevel < 0) || (parameter_.verbosityLevel >= 10 ) )
444 std::cout << "Warning: Parameter 'fem.verbositylevel' is neither a " << "valid level nor 0." << std::endl;
445 }
446
447 if( verbose() )
448 {
449 std::cout << curFileName_ << "[" << curLineNumber_ << "]: ";
450 if( !paramExists )
451 std::cout << "Adding " << key << " = " << value << std::endl;
452 else if ( !force )
453 std::cout << "Ignored " << key << " = " << value << ", using " << val.value << std::endl;
454 else
455 std::cout << "Replacing " << key << " = " << paramValue << " by " << value << std::endl;
456 }
457
458 return force ? value : val.value;
459 }
460
461
462 inline std::string ParameterContainer::stripComment ( const std::string &line )
463 {
464 std::size_t size = line.size();
465 std::size_t end = line.find_first_of ( "%#$" );
466
467 while( (end != std::string::npos) && (line[end] =='$') )
468 {
469 if( end+2 < size )
470 end = line.find_first_of ( "%#$", end+2 );
471 else
472 end = std::string::npos;
473 }
474
475 return ParameterContainerData::trim( line.substr( 0, end ) );
476 }
477
478
479 inline bool ParameterContainer::insert ( const std::string &s, std::queue< std::string > &includes )
480 {
481 const std::size_t size = s.size();
482
483 std::size_t key_start = 0;
484 for( ; key_start < size; ++key_start )
485 {
486 if( (s[ key_start ] != ' ') && (s[ key_start ] != '\t') )
487 break;
488 }
489
490 std::size_t key_end = key_start;
491 for( ; key_end < size; ++key_end )
492 {
493 const char &c = s[ key_end ];
494 if( (c == ' ') || (c == '\t') || (c == ':') )
495 break;
496 }
497
498 std::size_t value_start = key_end;
499 for( ; value_start < size ; ++value_start )
500 {
501 if( s[ value_start ] == ':' )
502 break;
503 }
504 ++value_start;
505
506 for( ; value_start < size; ++value_start )
507 {
508 if( (s[ value_start ] != ' ') && (s[ value_start ] != '\t') )
509 break;
510 }
511
512 std::size_t value_end = value_start;
513 for( std::size_t i = 0; i < size; ++i )
514 {
515 if( (s[ i ] != ' ') && (s[ i ] != '\t') )
516 value_end = i+1;
517 }
518
519 if( value_start >= size )
520 return false;
521
522 std::string key = s.substr( key_start, key_end - key_start );
523 std::string value = s.substr( value_start, value_end - value_start );
524
525 if( key == "paramfile" )
526 includes.push( commonInputPath() + "/" + value );
527 else if( key == "deprecated" )
529 else
530 insert( key, value );
531 return true;
532 }
533
534
535 inline void ParameterContainer::processFile ( const std::string &filename )
536 {
537 if( verbose() )
538 std::cout << "Parameter: Processing '" << filename << "'..." << std::endl;
539
540 std::ifstream file( filename );
541 if( !file.is_open() )
542 {
543 std::cerr << "Warning: Unable to read parameter file '" << filename << "'" << std::endl;
544 return;
545 }
546
547 curFileName_ = filename;
548 curLineNumber_ = 0;
550
551 while( !file.eof() )
552 {
554 std::getline( file, line );
555 curLineNumber_++;
556 line = stripComment( line );
557 if( !line.empty() )
558 insert( line, includes );
559 }
560 file.close();
561
562 processIncludes( includes );
563 }
564
565
566 inline void ParameterContainer::processIncludes( std::queue< std::string > &includes )
567 {
568 while( !includes.empty() )
569 {
570 Value val;
571 val.value = includes.front();
572 includes.pop();
573 parameter_.resolveShadows( "paramfile", val );
574 processFile( val.value );
575 }
576 }
577
578
579 inline void ParameterContainer::append ( int &argc, char **argv )
580 {
582 curFileName_ = "program arguments";
583 curLineNumber_ = 0;
584 for( int i = 1 ; i < argc; ++i )
585 {
586 ++curLineNumber_;
587 if( !insert( std::string( argv[ i ] ), includes ) )
588 continue;
589
590 std::copy( argv + (i+1), argv + argc, argv + i );
591 --i;
592 --argc;
593 }
594
595 processIncludes( includes );
596 }
597
598
599 inline void ParameterContainer::appendDGF ( const std::string &filename )
600 {
601 if( verbose() )
602 std::cout << "Parameter: Processing DGF '" << filename << "'..." << std::endl;
603
604 std::ifstream file( filename );
605 if( !file.is_open() )
606 {
607 std::cerr << "Warning: Unable to read DGF file '" << filename << "'" << std::endl;
608 return;
609 }
610
612 return;
613
614 DGFBlock block( file );
615 if( !block.isactive() )
616 return;
617
618 curFileName_ = filename;
619 curLineNumber_ = 0;
621
622 while( block.advance() )
623 {
624 ++curLineNumber_;
625 const std::string line = stripComment( block.getLine() );
626 if( !line.empty() )
627 insert( line, includes );
628 }
629
630 processIncludes( includes );
631 }
632
633
634 inline void ParameterContainer::write ( std::ostream &out, bool writeAll ) const
635 {
637 for( const auto &param : parameter_.map )
638 {
639 const Value &val = param.second;
640 if( writeAll || !val.hasDefault || (val.used && (val.value != val.defaultValue)) )
641 writeMap[ val.fileName ][ (val.used ? "": "# " ) + param.first ] = val.value;
642 }
643
644 for( const auto &source : writeMap )
645 {
646 out << "# from " << source.first << std::endl;
647 for( const auto &param : source.second )
648 out << param.first << ": " << param.second << std::endl;
649 out << std::endl;
650 }
651 }
652 inline auto ParameterContainer::write () const
653 {
655 for( const auto &param : parameter_.map )
656 {
657 const Value &val = param.second;
658 writeMap[ val.fileName ].insert( {param.first,val.value} );
659 }
660 return writeMap;
661 }
662
663 } // namespace Fem
664
665} // namespace Dune
666
667#endif // #ifndef DUNE_FEM_IO_PARAMETER_CONTAINER_HH
int size() const
iterator end()
void insert(const T &v)
virtual void operator()()=0
#define DUNE_THROW(E,...)
STL namespace.
static const std::string & checkParameterExistsString()
Definition reader.hh:22
std::string executeCommand(const std::string &command)
executes a command and return the output
Definition io.cc:70
BasicParameterReader< std::function< const std::string *(const std::string &, const std::string *) > > ParameterReader
Definition reader.hh:316
BasicBlock(std::istream &in, const char *id)
std::stringstream line
static bool isDuneGridFormat(std::istream &input)
Definition container.hh:32
bool verbosityLevelPresent
Definition container.hh:84
void resolveShadows(const std::string &key, Value &val) const
Definition container.hh:345
static const int solverStatistics
print iteration count and residual information
Definition container.hh:34
std::string getShadowKey(const std::string key, const char delimter, std::string &value) const
Definition container.hh:374
bool verbosityChangedByVerboseRank
Definition container.hh:85
static const int defaultVerbosityLevel
Definition container.hh:46
static std::string trim(const std::string &s)
Definition container.hh:63
static const int parameterOutput
print which parameters have been read, i.e. fem.dofmanager.memoryfactor
Definition container.hh:38
bool verbose(const int level=defaultVerbosityLevel) const
Definition container.hh:73
static const int debugOutput
print debug output at this level
Definition container.hh:42
int verboseRank
Definition container.hh:82
static const int extendedStatistics
some solver packages offer extended output, use this level for this
Definition container.hh:36
const std::string * operator()(const std::string &key, const std::string *defaultValue) const
Definition container.hh:256
std::string resolveEscape(const std::string &key, std::string &value) const
Definition container.hh:312
std::map< std::string, Value > map
Definition container.hh:80
std::set< std::string > deprecated
Definition container.hh:81
static const int diagnosticsOutput
more diagnostics, i.e. about timing and other things
Definition container.hh:40
int verbosityLevel
Definition container.hh:83
std::string value
Definition container.hh:56
ShadowStatus
Definition container.hh:50
@ resolved
Definition container.hh:50
@ resolving
Definition container.hh:50
@ unresolved
Definition container.hh:50
bool hasDefault
Definition container.hh:57
Value(std::string v, std::string fn)
Definition container.hh:54
std::string defaultValue
Definition container.hh:56
ShadowStatus shadowStatus
Definition container.hh:58
bool used
Definition container.hh:57
std::string fileName
Definition container.hh:56
Definition container.hh:95
std::string commonInputPath() const
Definition container.hh:203
void clear()
clear all parameters
Definition container.hh:195
void append(const std::string &filename)
add parameters from a file
Definition container.hh:130
std::map< std::string, std::set< std::pair< std::string, std::string > > > localParameterLog_
Definition container.hh:230
std::string toString(const T &value)
A helper function to convert numbers to scientific strings.
Definition container.hh:160
auto write() const
Definition container.hh:652
bool verbose(const int level=ParameterContainerData::defaultVerbosityLevel) const
obtain the cached value for fem.verbose
Definition container.hh:198
void append(const std::string &key, const std::string &value, bool force=false)
add a single parameter to the container
Definition container.hh:142
void append(const std::string &key, NumberType value, bool force=false)
add a single Floating number parameter to the container
Definition container.hh:176
void append(int &argc, char **argv)
add parameters from the command line
Definition container.hh:579
void appendDGF(const std::string &filename)
add parameters from a DGF file
Definition container.hh:599
std::string commonOutputPath() const
Definition container.hh:208
Definition container.hh:244
bool advance()
Definition container.hh:247
DGFBlock(std::istream &in)
Definition container.hh:245
std::string getLine() const
Definition container.hh:248
Definition io/parameter/exceptions.hh:17
Definition io/parameter/exceptions.hh:26
static bool parse(const std::string &s, T &value)
Definition parser.hh:22
Definition reader.hh:33
T getValue(const std::string &key) const
get mandatory parameter
Definition reader.hh:161
ParameterContainerData parameter_
Definition reader.hh:308
Definition grcommon.hh:31
static int size()
Definition mpimanager.hh:424
static int rank()
Definition mpimanager.hh:419
T copy(T... args)
T empty(T... args)
T end(T... args)
T endl(T... args)
T find_first_not_of(T... args)
T find_first_of(T... args)
T find(T... args)
T find_last_not_of(T... args)
T scientific(T... args)
T getline(T... args)
T includes(T... args)
T insert(T... args)
T is_open(T... args)
T make_pair(T... args)
T ref(T... args)
T replace(T... args)
T size(T... args)
T str(T... args)
T substr(T... args)
T swap(T... args)