deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
parameter_handler.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 1998 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_parameter_handler_h
14#define dealii_parameter_handler_h
15
16
17#include <deal.II/base/config.h>
18
22
23#include <boost/archive/basic_archive.hpp>
24#include <boost/property_tree/ptree_fwd.hpp>
25#include <boost/property_tree/ptree_serialization.hpp>
26#include <boost/serialization/split_member.hpp>
27
28#include <map>
29#include <memory>
30#include <set>
31#include <string>
32#include <vector>
33
35
36// forward declarations for interfaces and friendship
37#ifndef DOXYGEN
38class LogStream;
40#endif
41
854{
855public:
872 {
877 DefaultStyle = 0x0000,
878
883 Short = 0x0001,
884
889
894 PRM = 0x0010,
895
899 LaTeX = 0x0020,
900
906 Description = 0x0040,
907
915 XML = 0x0080,
916
922 JSON = 0x0100,
923
929
935
941
947
952 };
953
954
955
960
966 virtual ~ParameterHandler() override = default;
967
972
977 operator=(const ParameterHandler &) = delete;
978
1013 virtual void
1014 parse_input(std::istream &input,
1015 const std::string &filename = "input file",
1016 const std::string &last_line = "",
1017 const bool skip_undefined = false);
1018
1040 virtual void
1041 parse_input(const std::string &filename,
1042 const std::string &last_line = "",
1043 const bool skip_undefined = false,
1044 const bool assert_mandatory_entries_are_found = false);
1045
1054 virtual void
1055 parse_input_from_string(const std::string &s,
1056 const std::string &last_line = "",
1057 const bool skip_undefined = false);
1058
1066 virtual void
1067 parse_input_from_xml(std::istream &input, const bool skip_undefined = false);
1068
1076 virtual void
1077 parse_input_from_json(std::istream &input, const bool skip_undefined = false);
1078
1082 void
1083 clear();
1084
1085
1111 void
1112 declare_entry(const std::string &entry,
1113 const std::string &default_value,
1114 const Patterns::PatternBase &pattern = Patterns::Anything(),
1115 const std::string &documentation = "",
1116 const bool has_to_be_set = false);
1117
1135 void
1136 mark_as_deprecated(const std::string &entry, const bool is_deprecated = true);
1137
1185 void
1186 add_action(const std::string &entry,
1187 const std::function<void(const std::string &value)> &action,
1188 const bool execute_action = true);
1189
1205 template <typename ParameterType>
1206 void
1207 add_parameter(const std::string &entry,
1208 ParameterType &parameter,
1209 const std::string &documentation = "",
1210 const Patterns::PatternBase &pattern =
1212 const bool has_to_be_set = false);
1213
1257 void
1258 declare_alias(const std::string &existing_entry_name,
1259 const std::string &alias_name,
1260 const bool alias_is_deprecated = false);
1261
1265 void
1266 enter_subsection(const std::string &subsection,
1267 const bool create_path_if_needed = true);
1268
1272 void
1274
1280 bool
1281 subsection_path_exists(const std::vector<std::string> &sub_path) const;
1282
1292 std::string
1293 get_current_path() const;
1294
1300 std::string
1301 get_current_full_path(const std::string &name) const;
1302
1308 std::string
1309 get_current_full_path(const std::vector<std::string> &sub_path,
1310 const std::string &name) const;
1311
1317 std::string
1318 get(const std::string &entry_string) const;
1319
1330 std::string
1331 get(const std::vector<std::string> &entry_subsection_path,
1332 const std::string &entry_string) const;
1333
1339 long int
1340 get_integer(const std::string &entry_string) const;
1341
1350 long int
1351 get_integer(const std::vector<std::string> &entry_subsection_path,
1352 const std::string &entry_string) const;
1353
1357 double
1358 get_double(const std::string &entry_name) const;
1359
1366 double
1367 get_double(const std::vector<std::string> &entry_subsection_path,
1368 const std::string &entry_string) const;
1374 bool
1375 get_bool(const std::string &entry_name) const;
1376
1385 bool
1386 get_bool(const std::vector<std::string> &entry_subsection_path,
1387 const std::string &entry_string) const;
1388
1398 void
1399 set(const std::string &entry_name, const std::string &new_value);
1400
1411 void
1412 set(const std::string &entry_name, const char *new_value);
1413
1423 void
1424 set(const std::string &entry_name, const long int new_value);
1425
1439 void
1440 set(const std::string &entry_name, const double new_value);
1441
1451 void
1452 set(const std::string &entry_name, const bool new_value);
1453
1526 std::ostream &
1527 print_parameters(std::ostream &out, const OutputStyle style) const;
1528
1529
1530
1551 void
1552 print_parameters(const std::string &filename,
1553 const OutputStyle style = DefaultStyle) const;
1554
1569 void
1570 log_parameters(LogStream &out, const OutputStyle style = DefaultStyle);
1571
1590 void
1592 const OutputStyle style = DefaultStyle);
1593
1598 std::size_t
1599 memory_consumption() const;
1600
1606 template <class Archive>
1607 void
1608 save(Archive &ar, const unsigned int version) const;
1609
1615 template <class Archive>
1616 void
1617 load(Archive &ar, const unsigned int version);
1618
1619#ifdef DOXYGEN
1625 template <class Archive>
1626 void
1627 serialize(Archive &archive, const unsigned int version);
1628#else
1629 // This macro defines the serialize() method that is compatible with
1630 // the templated save() and load() method that have been implemented.
1631 BOOST_SERIALIZATION_SPLIT_MEMBER()
1632#endif
1633
1637 bool
1638 operator==(const ParameterHandler &prm2) const;
1639
1648 std::set<std::string>
1650
1656 void
1658
1668 std::string,
1669 << "The following entry already exists: " << arg1 << '.');
1670
1675 int,
1676 std::string,
1677 std::string,
1678 << "Line <" << arg1 << "> of file <" << arg2 << ">: "
1679 << "Entry <" << arg3 << "> is deprecated.");
1680
1685 std::string,
1686 << "The following deprecated entries were encountered:\n\n"
1687 << arg1);
1688
1693 std::string,
1694 std::string,
1695 << "The string <" << arg1
1696 << "> does not match the given pattern <" << arg2 << ">.");
1702 "You can't leave a subsection if you are already at the top level "
1703 "of the subsection hierarchy.");
1704
1709 std::string,
1710 << "You can't ask for entry <" << arg1
1711 << "> you have not yet declared.");
1712
1720 std::string,
1721 std::string,
1722 << "There are unequal numbers of 'subsection' and 'end' "
1723 "statements in the parameter file"
1724 << (arg1.empty() ? "" : (" <" + arg1 + ">")) << "."
1725 << (arg2.empty() ? "" : ("\n" + arg2)));
1726
1732 int,
1733 std::string,
1734 std::string,
1735 << "Line <" << arg1 << ">"
1736 << (arg2.empty() ? "" : (" of file <" + arg2 + ">"))
1737 << ": You are trying to enter a subsection '" << arg3
1738 << "', but the ParameterHandler object does "
1739 << "not know of any such subsection.");
1740
1747 int,
1748 std::string,
1749 std::string,
1750 << "Line <" << arg1 << ">"
1751 << (arg2.empty() ? "" : (" of file <" + arg2 + ">")) << ": "
1752 << arg3);
1753
1761 int,
1762 std::string,
1763 std::string,
1764 std::string,
1765 std::string,
1766 << "In line <" << arg1 << ">"
1767 << (arg2.empty() ? "" : (" of file <" + arg2 + ">")) << ": The value <"
1768 << arg3 << "> for the parameter entry named <" << arg4
1769 << "> does not match the pattern expected for this parameter.\n"
1770 "The expected pattern for this parameter is:\n"
1771 << arg5);
1772
1779 "The provided file could not be parsed as a "
1780 "ParameterHandler description.");
1781
1790 int,
1791 std::string,
1792 std::string,
1793 << "Line <" << arg1 << ">"
1794 << (arg2.empty() ? "" : (" of file <" + arg2 + ">"))
1795 << ": This line "
1796 "contains an 'include' or 'INCLUDE' statement, but the given "
1797 "file to include <"
1798 << arg3 << "> cannot be opened.");
1799
1802private:
1807 static const char path_separator = '.';
1808
1812 std::vector<std::string> subsection_path;
1813
1822 std::unique_ptr<boost::property_tree::ptree> entries;
1823
1832 std::map<std::string, std::pair<bool, bool>> entries_set_status;
1833
1839 std::vector<std::unique_ptr<const Patterns::PatternBase>> patterns;
1840
1847 std::vector<std::function<void(const std::string &)>> actions;
1848
1867 void
1868 scan_line(std::string line,
1869 const std::string &input_filename,
1870 const unsigned int current_line_n,
1871 const bool skip_undefined);
1872
1884 void
1886 const boost::property_tree::ptree &tree,
1887 const std::vector<std::string> &target_subsection_path,
1889 const unsigned int indent_level,
1890 std::ostream &out) const;
1891
1893};
1894
1905{
1906 return static_cast<ParameterHandler::OutputStyle>(
1907 static_cast<unsigned int>(f1) | static_cast<unsigned int>(f2));
1908}
1909
2126{
2127public:
2133 {
2134 public:
2139 virtual ~UserClass() = default;
2140
2145 virtual void
2146 create_new(const unsigned int run_no) = 0;
2147
2151 virtual void
2153 };
2154
2159
2164 virtual ~MultipleParameterLoop() override = default;
2165
2187 virtual void
2188 parse_input(std::istream &input,
2189 const std::string &filename = "input file",
2190 const std::string &last_line = "",
2191 const bool skip_undefined = false) override;
2192
2201
2205 void
2206 loop(UserClass &uc);
2207
2212 std::size_t
2213 memory_consumption() const;
2214
2215private:
2219 class Entry
2220 {
2221 public:
2238
2243 : type(array)
2244 {}
2245
2251 Entry(const std::vector<std::string> &Path,
2252 const std::string &Name,
2253 const std::string &Value);
2254
2258 void
2260
2264 std::vector<std::string> subsection_path;
2265
2269 std::string entry_name;
2270
2274 std::string entry_value;
2275
2280 std::vector<std::string> different_values;
2281
2286
2291 std::size_t
2292 memory_consumption() const;
2293 };
2294
2298 std::vector<Entry> multiple_choices;
2299
2304 unsigned int n_branches;
2305
2309 void
2310 init_branches();
2311
2318 void
2320
2324 void
2325 fill_entry_values(const unsigned int run_no);
2326};
2327
2328
2329// ---------------------- inline and template functions --------------------
2330template <class Archive>
2331inline void
2332ParameterHandler::save(Archive &ar, const unsigned int) const
2333{
2334 // Forward to serialization
2335 // function in the base class.
2336 ar &static_cast<const EnableObserverPointer &>(*this);
2337
2338 ar &*entries.get();
2339
2340 std::vector<std::string> descriptions;
2341
2342 descriptions.reserve(patterns.size());
2343 for (const auto &pattern : patterns)
2344 descriptions.push_back(pattern->description());
2345
2346 ar &descriptions;
2347}
2348
2349
2350template <class Archive>
2351inline void
2352ParameterHandler::load(Archive &ar, const unsigned int)
2353{
2354 // Forward to serialization
2355 // function in the base class.
2356 ar &static_cast<EnableObserverPointer &>(*this);
2357
2358 ar &*entries.get();
2359
2360 std::vector<std::string> descriptions;
2361 ar &descriptions;
2362
2363 patterns.clear();
2364 for (const auto &description : descriptions)
2365 patterns.push_back(Patterns::pattern_factory(description));
2366}
2367
2368
2369template <typename ParameterType>
2370void
2371ParameterHandler::add_parameter(const std::string &entry,
2372 ParameterType &parameter,
2373 const std::string &documentation,
2374 const Patterns::PatternBase &pattern,
2375 const bool has_to_be_set)
2376{
2377 static_assert(std::is_const_v<ParameterType> == false,
2378 "You tried to add a parameter using a type "
2379 "that is const. Use a non-const type.");
2380
2381 declare_entry(entry,
2383 pattern),
2384 pattern,
2385 documentation,
2386 has_to_be_set);
2387
2388 std::string path = get_current_full_path(entry);
2389 const unsigned int pattern_index =
2390 entries->get<unsigned int>(path + path_separator + "pattern");
2391
2392 auto action = [&, pattern_index](const std::string &val) {
2394 val, *patterns[pattern_index]);
2395 };
2396 add_action(entry, action, false);
2397}
2398
2400
2401#endif
std::vector< std::string > subsection_path
std::vector< std::string > different_values
std::size_t memory_consumption() const
virtual void create_new(const unsigned int run_no)=0
virtual void run(ParameterHandler &prm)=0
void fill_entry_values(const unsigned int run_no)
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="", const bool skip_undefined=false) override
std::size_t memory_consumption() const
virtual ~MultipleParameterLoop() override=default
void loop(UserClass &uc)
std::vector< Entry > multiple_choices
static const char path_separator
std::size_t memory_consumption() const
void add_parameter(const std::string &entry, ParameterType &parameter, const std::string &documentation="", const Patterns::PatternBase &pattern= *Patterns::Tools::Convert< ParameterType >::to_pattern(), const bool has_to_be_set=false)
void load(Archive &ar, const unsigned int version)
virtual void parse_input(std::istream &input, const std::string &filename="input file", const std::string &last_line="", const bool skip_undefined=false)
virtual void parse_input_from_xml(std::istream &input, const bool skip_undefined=false)
std::string get_current_path() const
ParameterHandler(const ParameterHandler &)=delete
std::vector< std::unique_ptr< const Patterns::PatternBase > > patterns
void enter_subsection(const std::string &subsection, const bool create_path_if_needed=true)
std::ostream & print_parameters(std::ostream &out, const OutputStyle style) const
void recursively_print_parameters(const boost::property_tree::ptree &tree, const std::vector< std::string > &target_subsection_path, const ParameterHandler::OutputStyle style, const unsigned int indent_level, std::ostream &out) const
void add_action(const std::string &entry, const std::function< void(const std::string &value)> &action, const bool execute_action=true)
void save(Archive &ar, const unsigned int version) const
long int get_integer(const std::string &entry_string) const
bool get_bool(const std::string &entry_name) const
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation="", const bool has_to_be_set=false)
virtual void parse_input_from_string(const std::string &s, const std::string &last_line="", const bool skip_undefined=false)
std::string get(const std::string &entry_string) const
std::set< std::string > get_entries_wrongly_not_set() const
void set(const std::string &entry_name, const std::string &new_value)
void log_parameters(LogStream &out, const OutputStyle style=DefaultStyle)
void serialize(Archive &archive, const unsigned int version)
std::map< std::string, std::pair< bool, bool > > entries_set_status
std::string get_current_full_path(const std::string &name) const
ParameterHandler & operator=(const ParameterHandler &)=delete
void mark_as_deprecated(const std::string &entry, const bool is_deprecated=true)
std::vector< std::function< void(const std::string &)> > actions
void log_parameters_section(LogStream &out, const OutputStyle style=DefaultStyle)
std::unique_ptr< boost::property_tree::ptree > entries
bool subsection_path_exists(const std::vector< std::string > &sub_path) const
virtual ~ParameterHandler() override=default
void scan_line(std::string line, const std::string &input_filename, const unsigned int current_line_n, const bool skip_undefined)
double get_double(const std::string &entry_name) const
void declare_alias(const std::string &existing_entry_name, const std::string &alias_name, const bool alias_is_deprecated=false)
bool operator==(const ParameterHandler &prm2) const
std::vector< std::string > subsection_path
void assert_that_entries_have_been_set() const
virtual void parse_input_from_json(std::istream &input, const bool skip_undefined=false)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
static ::ExceptionBase & ExcNoSubsection(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcCannotOpenIncludeStatementFile(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcEntryAlreadyExists(std::string arg1)
static ::ExceptionBase & ExcEntryIsDeprecated(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcEncounteredDeprecatedEntries(std::string arg1)
static ::ExceptionBase & ExcAlreadyAtTopLevel()
#define DeclException2(Exception2, type1, type2, outsequence)
static ::ExceptionBase & ExcInvalidEntryForPattern(int arg1, std::string arg2, std::string arg3, std::string arg4, std::string arg5)
static ::ExceptionBase & ExcEntryUndeclared(std::string arg1)
#define DeclExceptionMsg(Exception, defaulttext)
static ::ExceptionBase & ExcValueDoesNotMatchPattern(std::string arg1, std::string arg2)
static ::ExceptionBase & ExcUnbalancedSubsections(std::string arg1, std::string arg2)
#define DeclException3(Exception3, type1, type2, type3, outsequence)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcCannotParseLine(int arg1, std::string arg2, std::string arg3)
static ::ExceptionBase & ExcInvalidXMLParameterFile()
#define DeclException5( Exception5, type1, type2, type3, type4, type5, outsequence)
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
Definition patterns.cc:134
ParameterHandler::OutputStyle operator|(const ParameterHandler::OutputStyle f1, const ParameterHandler::OutputStyle f2)
static T to_value(const std::string &s, const Patterns::PatternBase &p= *Convert< T >::to_pattern())=delete