Reference documentation for deal.II version Git a2518c4284 2020-04-02 19:23:00 +0200
\(\newcommand{\vcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\vcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
patterns.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2019 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_patterns_h
17 #define dealii_patterns_h
18 
19 
20 #include <deal.II/base/config.h>
21 
22 #include <deal.II/base/exceptions.h>
23 #include <deal.II/base/point.h>
24 #include <deal.II/base/std_cxx14/algorithm.h>
25 #include <deal.II/base/std_cxx14/memory.h>
26 #include <deal.II/base/std_cxx14/utility.h>
27 #include <deal.II/base/subscriptor.h>
28 #include <deal.II/base/template_constraints.h>
29 #include <deal.II/base/utilities.h>
30 
31 #include <deal.II/fe/component_mask.h>
32 
33 DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
34 #include <boost/archive/basic_archive.hpp>
35 #include <boost/core/demangle.hpp>
36 #include <boost/property_tree/ptree_fwd.hpp>
37 #include <boost/property_tree/ptree_serialization.hpp>
38 #include <boost/serialization/split_member.hpp>
39 DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
40 
41 #include <array>
42 #include <deque>
43 #include <list>
44 #include <map>
45 #include <set>
46 #include <sstream>
47 #include <string>
48 #include <type_traits>
49 #include <unordered_map>
50 #include <unordered_set>
51 #include <utility>
52 #include <vector>
53 
54 DEAL_II_NAMESPACE_OPEN
55 
56 // forward declarations for interfaces and friendship
57 #ifndef DOXYGEN
58 class LogStream;
60 template <int dim>
61 class FunctionParser;
62 #endif
63 
72 namespace Patterns
73 {
81  {
82  public:
86  virtual ~PatternBase() = default;
87 
91  virtual bool
92  match(const std::string &test_string) const = 0;
93 
100  {
117  };
118 
122  virtual std::string
123  description(const OutputStyle style = Machine) const = 0;
124 
134  virtual std::unique_ptr<PatternBase>
135  clone() const = 0;
136 
152  virtual std::size_t
153  memory_consumption() const;
154  };
155 
159  std::unique_ptr<PatternBase>
160  pattern_factory(const std::string &description);
161 
162  namespace internal
163  {
169  std::string
170  escape(const std::string &input, const PatternBase::OutputStyle style);
171 
172  } // namespace internal
173 
190  class Integer : public PatternBase
191  {
192  public:
198  static const int min_int_value;
199 
205  static const int max_int_value;
206 
219  Integer(const int lower_bound = min_int_value,
220  const int upper_bound = max_int_value);
221 
226  virtual bool
227  match(const std::string &test_string) const override;
228 
234  virtual std::string
235  description(const OutputStyle style = Machine) const override;
236 
242  virtual std::unique_ptr<PatternBase>
243  clone() const override;
244 
250  static std::unique_ptr<Integer>
251  create(const std::string &description);
252 
253  private:
260  const int lower_bound;
261 
268  const int upper_bound;
269 
273  static const char *description_init;
274  };
275 
293  class Double : public PatternBase
294  {
295  public:
300  static const double min_double_value;
301 
306  static const double max_double_value;
307 
315  Double(const double lower_bound = min_double_value,
316  const double upper_bound = max_double_value);
317 
322  virtual bool
323  match(const std::string &test_string) const override;
324 
330  virtual std::string
331  description(const OutputStyle style = Machine) const override;
332 
338  virtual std::unique_ptr<PatternBase>
339  clone() const override;
340 
348  static std::unique_ptr<Double>
349  create(const std::string &description);
350 
351  private:
358  const double lower_bound;
359 
366  const double upper_bound;
367 
371  static const char *description_init;
372  };
373 
383  class Selection : public PatternBase
384  {
385  public:
390  Selection(const std::string &seq);
391 
396  virtual bool
397  match(const std::string &test_string) const override;
398 
404  virtual std::string
405  description(const OutputStyle style = Machine) const override;
406 
412  virtual std::unique_ptr<PatternBase>
413  clone() const override;
414 
419  std::size_t
420  memory_consumption() const override;
421 
427  static std::unique_ptr<Selection>
428  create(const std::string &description);
429 
430  private:
435  std::string sequence;
436 
440  static const char *description_init;
441  };
442 
443 
451  class List : public PatternBase
452  {
453  public:
459  static const unsigned int max_int_value;
460 
469  List(const PatternBase &base_pattern,
470  const unsigned int min_elements = 0,
471  const unsigned int max_elements = max_int_value,
472  const std::string &separator = ",");
473 
474 
478  const std::string &
479  get_separator() const;
480 
484  const PatternBase &
485  get_base_pattern() const;
486 
490  List(const List &other);
491 
496  virtual bool
497  match(const std::string &test_string) const override;
498 
503  virtual std::string
504  description(const OutputStyle style = Machine) const override;
505 
511  virtual std::unique_ptr<PatternBase>
512  clone() const override;
513 
519  static std::unique_ptr<List>
520  create(const std::string &description);
521 
526  std::size_t
527  memory_consumption() const override;
528 
537  DeclException2(ExcInvalidRange,
538  int,
539  int,
540  << "The values " << arg1 << " and " << arg2
541  << " do not form a valid range.");
543  private:
547  std::unique_ptr<PatternBase> pattern;
548 
552  const unsigned int min_elements;
553 
557  const unsigned int max_elements;
558 
562  const std::string separator;
563 
567  static const char *description_init;
568  };
569 
570 
585  class Map : public PatternBase
586  {
587  public:
593  static const unsigned int max_int_value;
594 
603  Map(const PatternBase &key_pattern,
604  const PatternBase &value_pattern,
605  const unsigned int min_elements = 0,
606  const unsigned int max_elements = max_int_value,
607  const std::string &separator = ",",
608  const std::string &key_value_separator = ":");
609 
613  Map(const Map &other);
614 
619  virtual bool
620  match(const std::string &test_string) const override;
621 
626  virtual std::string
627  description(const OutputStyle style = Machine) const override;
628 
634  virtual std::unique_ptr<PatternBase>
635  clone() const override;
636 
642  static std::unique_ptr<Map>
643  create(const std::string &description);
644 
649  std::size_t
650  memory_consumption() const override;
651 
655  const PatternBase &
656  get_key_pattern() const;
657 
661  const PatternBase &
662  get_value_pattern() const;
663 
667  const std::string &
668  get_separator() const;
669 
673  const std::string &
674  get_key_value_separator() const;
675 
684  DeclException2(ExcInvalidRange,
685  int,
686  int,
687  << "The values " << arg1 << " and " << arg2
688  << " do not form a valid range.");
690  private:
695  std::unique_ptr<PatternBase> key_pattern;
696  std::unique_ptr<PatternBase> value_pattern;
697 
701  const unsigned int min_elements;
702 
706  const unsigned int max_elements;
707 
711  const std::string separator;
712 
713 
717  const std::string key_value_separator;
718 
722  static const char *description_init;
723  };
724 
725 
726 
774  class Tuple : public PatternBase
775  {
776  public:
785  Tuple(const std::vector<std::unique_ptr<PatternBase>> &patterns,
786  const std::string & separator = ":");
787 
793  Tuple(const std::vector<std::unique_ptr<PatternBase>> &patterns,
794  const char * separator);
795 
796 
804  template <class... PatternTypes>
805  Tuple(const std::string &separator, const PatternTypes &... patterns);
806 
814  template <class... PatternTypes>
815  Tuple(const char *separator, const PatternTypes &... patterns);
816 
822  template <typename... Patterns>
823  Tuple(const Patterns &... patterns);
824 
828  Tuple(const Tuple &other);
829 
834  virtual bool
835  match(const std::string &test_string) const override;
836 
841  virtual std::string
842  description(const OutputStyle style = Machine) const override;
843 
849  virtual std::unique_ptr<PatternBase>
850  clone() const override;
851 
857  static std::unique_ptr<Tuple>
858  create(const std::string &description);
859 
864  std::size_t
865  memory_consumption() const override;
866 
870  const PatternBase &
871  get_pattern(const unsigned int i) const;
872 
876  const std::string &
877  get_separator() const;
878 
879  private:
883  std::vector<std::unique_ptr<PatternBase>> patterns;
884 
888  const std::string separator;
889 
893  static const char *description_init;
894  };
895 
896 
908  {
909  public:
913  MultipleSelection(const std::string &seq);
914 
919  virtual bool
920  match(const std::string &test_string) const override;
921 
927  virtual std::string
928  description(const OutputStyle style = Machine) const override;
929 
935  virtual std::unique_ptr<PatternBase>
936  clone() const override;
937 
943  static std::unique_ptr<MultipleSelection>
944  create(const std::string &description);
945 
950  std::size_t
951  memory_consumption() const override;
952 
962  ExcCommasNotAllowed,
963  int,
964  << "A comma was found at position " << arg1
965  << " of your input string, but commas are not allowed here.");
967  private:
972  std::string sequence;
973 
977  static const char *description_init;
978  };
979 
984  class Bool : public Selection
985  {
986  public:
990  Bool();
991 
996  virtual std::string
997  description(const OutputStyle style = Machine) const override;
998 
1004  virtual std::unique_ptr<PatternBase>
1005  clone() const override;
1006 
1012  static std::unique_ptr<Bool>
1013  create(const std::string &description);
1014 
1015  private:
1019  static const char *description_init;
1020  };
1021 
1025  class Anything : public PatternBase
1026  {
1027  public:
1032  Anything() = default;
1033 
1038  virtual bool
1039  match(const std::string &test_string) const override;
1040 
1045  virtual std::string
1046  description(const OutputStyle style = Machine) const override;
1047 
1053  virtual std::unique_ptr<PatternBase>
1054  clone() const override;
1055 
1061  static std::unique_ptr<Anything>
1062  create(const std::string &description);
1063 
1064  private:
1068  static const char *description_init;
1069  };
1070 
1071 
1086  class FileName : public PatternBase
1087  {
1088  public:
1094  {
1098  input = 0,
1102  output = 1
1103  };
1104 
1109  FileName(const FileType type = input);
1110 
1115  virtual bool
1116  match(const std::string &test_string) const override;
1117 
1122  virtual std::string
1123  description(const OutputStyle style = Machine) const override;
1124 
1130  virtual std::unique_ptr<PatternBase>
1131  clone() const override;
1132 
1137 
1143  static std::unique_ptr<FileName>
1144  create(const std::string &description);
1145 
1146  private:
1150  static const char *description_init;
1151  };
1152 
1153 
1167  {
1168  public:
1172  DirectoryName() = default;
1173 
1178  virtual bool
1179  match(const std::string &test_string) const override;
1180 
1185  virtual std::string
1186  description(const OutputStyle style = Machine) const override;
1187 
1193  virtual std::unique_ptr<PatternBase>
1194  clone() const override;
1195 
1201  static std::unique_ptr<DirectoryName>
1202  create(const std::string &description);
1203 
1204  private:
1208  static const char *description_init;
1209  };
1210 
1211 
1291  namespace Tools
1292  {
1304  template <class T, class Enable = void>
1305  struct Convert
1306  {
1316  static std::unique_ptr<Patterns::PatternBase>
1317  to_pattern() = delete;
1318 
1329  static std::string
1330  to_string(const T & s,
1331  const std::unique_ptr<Patterns::PatternBase> &p =
1332  Convert<T>::to_pattern()) = delete;
1333 
1343  static T
1344  to_value(const std::string & s,
1345  const std::unique_ptr<Patterns::PatternBase> &p =
1346  Convert<T>::to_pattern()) = delete;
1347  };
1348 
1369  template <typename T>
1370  std::string
1371  to_string(const T &t);
1372 
1400  template <typename T>
1401  void
1402  to_value(const std::string &s, T &t);
1403 
1413  std::string,
1414  std::string,
1415  << "The string " << arg1 << " does not match the pattern \""
1416  << arg2 << "\"");
1418  } // namespace Tools
1419 } // namespace Patterns
1420 
1421 
1422 // ---------------------- inline and template functions --------------------
1423 namespace Patterns
1424 {
1425  template <class... PatternTypes>
1426  Tuple::Tuple(const char *separator, const PatternTypes &... ps)
1427  : // forward to the version with std::string argument
1428  Tuple(std::string(separator), ps...)
1429  {}
1430 
1431 
1432 
1433  template <class... PatternTypes>
1434  Tuple::Tuple(const std::string &separator, const PatternTypes &... ps)
1435  : separator(separator)
1436  {
1438  "Not all of the input arguments of this function "
1439  "are derived from PatternBase");
1440  static_assert(sizeof...(ps) > 0,
1441  "The number of PatternTypes must be greater than zero!");
1442  const auto pattern_pointers = {(static_cast<const PatternBase *>(&ps))...};
1443  for (const auto p : pattern_pointers)
1444  patterns.push_back(p->clone());
1445  }
1446 
1447 
1448 
1449  template <class... PatternTypes>
1450  Tuple::Tuple(const PatternTypes &... ps)
1451  : // forward to the version with the separator argument
1452  Tuple(std::string(":"), ps...)
1453  {}
1454 
1455 
1456 
1457  namespace Tools
1458  {
1459  namespace internal
1460  {
1487  template <class T, class Enable = void>
1488  struct RankInfo
1489  {
1490  static constexpr int list_rank = 0;
1491  static constexpr int map_rank = 0;
1492  };
1493  } // namespace internal
1494 
1495  // Arithmetic types
1496  template <class T>
1497  struct Convert<T,
1498  typename std::enable_if<std::is_arithmetic<T>::value>::type>
1499  {
1500  template <typename Dummy = T>
1501  static
1502  typename std::enable_if<std::is_same<Dummy, T>::value &&
1503  std::is_same<T, bool>::value,
1504  std::unique_ptr<Patterns::PatternBase>>::type
1505  to_pattern()
1506  {
1507  return std_cxx14::make_unique<Patterns::Bool>();
1508  }
1509 
1510  template <typename Dummy = T>
1511  static
1512  typename std::enable_if<std::is_same<Dummy, T>::value &&
1513  !std::is_same<T, bool>::value &&
1514  std::is_integral<T>::value,
1515  std::unique_ptr<Patterns::PatternBase>>::type
1516  to_pattern()
1517  {
1518  return std_cxx14::make_unique<Patterns::Integer>(
1519  std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
1520  }
1521 
1522  template <typename Dummy = T>
1523  static
1524  typename std::enable_if<std::is_same<Dummy, T>::value &&
1525  !std::is_same<T, bool>::value &&
1526  std::is_floating_point<T>::value,
1527  std::unique_ptr<Patterns::PatternBase>>::type
1528  to_pattern()
1529  {
1530  return std_cxx14::make_unique<Patterns::Double>(
1531  std::numeric_limits<T>::lowest(), std::numeric_limits<T>::max());
1532  }
1533 
1534  static std::string
1535  to_string(const T & value,
1536  const std::unique_ptr<Patterns::PatternBase> &p =
1538  {
1539  std::stringstream str;
1540  if (std::is_same<T, unsigned char>::value ||
1541  std::is_same<T, signed char>::value || std::is_same<T, char>::value)
1542  str << static_cast<int>(value);
1543  else if (std::is_same<T, bool>::value)
1544  str << (static_cast<bool>(value) ? "true" : "false");
1545  else
1546  str << value;
1547  AssertThrow(p->match(str.str()),
1548  ExcNoMatch(str.str(), p->description()));
1549  return str.str();
1550  }
1551 
1552  static T
1553  to_value(const std::string & s,
1554  const std::unique_ptr<Patterns::PatternBase> &p =
1556  {
1557  AssertThrow(p->match(s), ExcNoMatch(s, p->description()));
1558  T value;
1559  if (std::is_same<T, bool>::value)
1560  value = (s == "true");
1561  else
1562  {
1563  std::istringstream is(s);
1564  if (std::is_same<T, unsigned char>::value ||
1565  std::is_same<T, signed char>::value ||
1566  std::is_same<T, char>::value)
1567  {
1568  int i;
1569  is >> i;
1570  value = i;
1571  }
1572  else
1573  is >> value;
1574 
1575  // If someone passes "123 abc" to the function, the method yields an
1576  // integer 123 alright, but the space terminates the read from the
1577  // string although there is more to come. This case, however, is
1578  // checked for in the call p->match(s) at the beginning of this
1579  // function, and would throw earlier. Here it is safe to assume that
1580  // if we didn't fail the conversion with the operator >>, then we
1581  // are good to go.
1582  AssertThrow(
1583  !is.fail(),
1584  ExcMessage("Failed to convert from \"" + s + "\" to the type \"" +
1585  boost::core::demangle(typeid(T).name()) + "\""));
1586  }
1587  return value;
1588  }
1589  };
1590 
1591  namespace internal
1592  {
1593  constexpr std::array<const char *, 4> default_list_separator{
1594  {",", ";", "|", "%"}};
1595  constexpr std::array<const char *, 4> default_map_separator{
1596  {":", "=", "@", "#"}};
1597 
1598  // specialize a type for all of the STL containers and maps
1599  template <typename T>
1600  struct is_list_compatible : std::false_type
1601  {};
1602  template <typename T, std::size_t N>
1603  struct is_list_compatible<std::array<T, N>> : std::true_type
1604  {};
1605  template <typename... Args>
1606  struct is_list_compatible<std::vector<Args...>> : std::true_type
1607  {};
1608  template <typename... Args>
1609  struct is_list_compatible<std::deque<Args...>> : std::true_type
1610  {};
1611  template <typename... Args>
1612  struct is_list_compatible<std::list<Args...>> : std::true_type
1613  {};
1614  template <typename... Args>
1615  struct is_list_compatible<std::set<Args...>> : std::true_type
1616  {};
1617  template <typename... Args>
1618  struct is_list_compatible<std::multiset<Args...>> : std::true_type
1619  {};
1620  template <typename... Args>
1621  struct is_list_compatible<std::unordered_set<Args...>> : std::true_type
1622  {};
1623  template <typename... Args>
1624  struct is_list_compatible<std::unordered_multiset<Args...>>
1625  : std::true_type
1626  {};
1627 
1628  template <typename T>
1629  struct is_map_compatible : std::false_type
1630  {};
1631  template <class Key, class T, class Compare, class Allocator>
1632  struct is_map_compatible<std::map<Key, T, Compare, Allocator>>
1633  : std::true_type
1634  {};
1635  template <class Key, class T, class Compare, class Allocator>
1636  struct is_map_compatible<std::multimap<Key, T, Compare, Allocator>>
1637  : std::true_type
1638  {};
1639  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1640  struct is_map_compatible<
1641  std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type
1642  {};
1643  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1644  struct is_map_compatible<
1645  std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
1646  : std::true_type
1647  {};
1648  } // namespace internal
1649 
1650  // type trait to use the implementation type traits as well as decay the
1651  // type
1652  template <typename T>
1653  struct is_list_compatible
1654  {
1655  static constexpr bool const value =
1656  internal::is_list_compatible<typename std::decay<T>::type>::value;
1657  };
1658 
1659  template <typename T>
1660  struct is_map_compatible
1661  {
1662  static constexpr bool const value =
1663  internal::is_map_compatible<typename std::decay<T>::type>::value;
1664  };
1665 
1666  namespace internal
1667  {
1668  // Helper function for list_rank
1669  template <class T>
1670  constexpr int
1671  max_list_rank()
1672  {
1673  return RankInfo<T>::list_rank;
1674  }
1675 
1676  template <class T1, class T2, class... Types>
1677  constexpr int
1678  max_list_rank()
1679  {
1680  return std_cxx14::max(RankInfo<T1>::list_rank,
1681  max_list_rank<T2, Types...>());
1682  }
1683 
1684  // Helper function for map_rank
1685  template <class T>
1686  constexpr int
1687  max_map_rank()
1688  {
1689  return RankInfo<T>::map_rank;
1690  }
1691 
1692  template <class T1, class T2, class... Types>
1693  constexpr int
1694  max_map_rank()
1695  {
1696  return std_cxx14::max(RankInfo<T1>::map_rank,
1697  max_map_rank<T2, Types...>());
1698  }
1699 
1700  // Rank of vector types
1701  template <class T>
1702  struct RankInfo<
1703  T,
1704  typename std::enable_if<is_list_compatible<T>::value>::type>
1705  {
1706  static constexpr int list_rank =
1708  static constexpr int map_rank =
1710  };
1711 
1712  // Rank of map types
1713  template <class T>
1714  struct RankInfo<
1715  T,
1716  typename std::enable_if<is_map_compatible<T>::value>::type>
1717  {
1718  static constexpr int list_rank =
1719  max_list_rank<typename T::key_type, typename T::mapped_type>() + 1;
1720  static constexpr int map_rank =
1721  max_map_rank<typename T::key_type, typename T::mapped_type>() + 1;
1722  };
1723 
1724  // Rank of Tensor types
1725  template <int rank, int dim, class Number>
1726  struct RankInfo<Tensor<rank, dim, Number>>
1727  {
1728  static constexpr int list_rank = rank + RankInfo<Number>::list_rank;
1729  static constexpr int map_rank = RankInfo<Number>::map_rank;
1730  };
1731 
1732  template <int dim, class Number>
1733  struct RankInfo<Point<dim, Number>> : RankInfo<Tensor<1, dim, Number>>
1734  {};
1735 
1736  // Rank of complex types
1737  template <class Number>
1738  struct RankInfo<std::complex<Number>>
1739  {
1740  static constexpr int list_rank = RankInfo<Number>::list_rank + 1;
1741  static constexpr int map_rank = RankInfo<Number>::map_rank;
1742  };
1743 
1744  // Rank of FunctionParser
1745  template <int dim>
1746  struct RankInfo<std::unique_ptr<FunctionParser<dim>>>
1747  {
1748  static constexpr int list_rank = 1;
1749  static constexpr int map_rank = 0;
1750  };
1751 
1752  // Rank of ComponentMask
1753  template <>
1754  struct RankInfo<ComponentMask>
1755  {
1756  static constexpr int list_rank = 1;
1757  static constexpr int map_rank = 0;
1758  };
1759 
1760  // Rank of std::pair
1761  template <class Key, class Value>
1762  struct RankInfo<std::pair<Key, Value>>
1763  {
1764  static constexpr int list_rank =
1766  static constexpr int map_rank =
1768  1;
1769  };
1770 
1771 
1772  template <class... Types>
1773  struct RankInfo<std::tuple<Types...>>
1774  {
1775  static constexpr int list_rank = max_list_rank<Types...>();
1776  static constexpr int map_rank = max_map_rank<Types...>() + 1;
1777  };
1778  } // namespace internal
1779 
1780  // stl containers
1781  template <class T>
1782  struct Convert<T,
1783  typename std::enable_if<is_list_compatible<T>::value>::type>
1784  {
1785  static std::unique_ptr<Patterns::PatternBase>
1786  to_pattern()
1787  {
1788  static_assert(internal::RankInfo<T>::list_rank > 0,
1789  "Cannot use this class for non List-compatible types.");
1790  return std_cxx14::make_unique<Patterns::List>(
1792  0,
1793  std::numeric_limits<unsigned int>::max(),
1794  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1795  1]);
1796  }
1797 
1798  static std::string
1799  to_string(const T & t,
1800  const std::unique_ptr<Patterns::PatternBase> &pattern =
1802  {
1803  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1804  AssertThrow(p,
1805  ExcMessage("I need a List pattern to convert a "
1806  "string to a List type."));
1807  auto base_p = p->get_base_pattern().clone();
1808  std::vector<std::string> vec(t.size());
1809 
1810  unsigned int i = 0;
1811  for (const auto &entry : t)
1812  vec[i++] = Convert<typename T::value_type>::to_string(entry, base_p);
1813 
1814  std::string s;
1815  if (vec.size() > 0)
1816  s = vec[0];
1817  for (unsigned int i = 1; i < vec.size(); ++i)
1818  s += p->get_separator() + " " + vec[i];
1819 
1820  AssertThrow(pattern->match(s), ExcNoMatch(s, p->description()));
1821  return s;
1822  }
1823 
1824  static T
1825  to_value(const std::string & s,
1826  const std::unique_ptr<Patterns::PatternBase> &pattern =
1828  {
1829  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
1830 
1831  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1832  AssertThrow(p,
1833  ExcMessage("I need a List pattern to convert a string "
1834  "to a List type."));
1835 
1836  auto base_p = p->get_base_pattern().clone();
1837  T t;
1838 
1839  auto v = Utilities::split_string_list(s, p->get_separator());
1840  for (const auto &str : v)
1841  t.insert(t.end(),
1843 
1844  return t;
1845  }
1846  };
1847 
1848  // stl maps
1849  template <class T>
1850  struct Convert<T,
1851  typename std::enable_if<is_map_compatible<T>::value>::type>
1852  {
1853  static std::unique_ptr<Patterns::PatternBase>
1854  to_pattern()
1855  {
1856  static_assert(internal::RankInfo<T>::list_rank > 0,
1857  "Cannot use this class for non List-compatible types.");
1858  static_assert(internal::RankInfo<T>::map_rank > 0,
1859  "Cannot use this class for non Map-compatible types.");
1860  return std_cxx14::make_unique<Patterns::Map>(
1863  0,
1864  std::numeric_limits<unsigned int>::max(),
1865  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1866  1],
1867  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
1868  }
1869 
1870  static std::string
1871  to_string(const T & t,
1872  const std::unique_ptr<Patterns::PatternBase> &pattern =
1874  {
1875  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1876  AssertThrow(p,
1877  ExcMessage("I need a Map pattern to convert a string to "
1878  "a Map compatible type."));
1879  auto key_p = p->get_key_pattern().clone();
1880  auto val_p = p->get_value_pattern().clone();
1881  std::vector<std::string> vec(t.size());
1882 
1883  unsigned int i = 0;
1884  for (const auto &ti : t)
1885  vec[i++] =
1886  Convert<typename T::key_type>::to_string(ti.first, key_p) +
1887  p->get_key_value_separator() +
1889 
1890  std::string s;
1891  if (vec.size() > 0)
1892  s = vec[0];
1893  for (unsigned int i = 1; i < vec.size(); ++i)
1894  s += p->get_separator() + " " + vec[i];
1895 
1896  AssertThrow(p->match(s), ExcNoMatch(s, p->description()));
1897  return s;
1898  }
1899 
1900  static T
1901  to_value(const std::string & s,
1902  const std::unique_ptr<Patterns::PatternBase> &pattern =
1904  {
1905  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
1906 
1907  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1908  AssertThrow(p,
1909  ExcMessage("I need a Map pattern to convert a "
1910  "string to a Map compatible type."));
1911 
1912  auto key_p = p->get_key_pattern().clone();
1913  auto val_p = p->get_value_pattern().clone();
1914  T t;
1915 
1916  auto v = Utilities::split_string_list(s, p->get_separator());
1917  for (const auto &str : v)
1918  {
1919  auto key_val =
1920  Utilities::split_string_list(str, p->get_key_value_separator());
1921  AssertDimension(key_val.size(), 2);
1922  t.insert(std::make_pair(
1923  Convert<typename T::key_type>::to_value(key_val[0], key_p),
1925  }
1926 
1927  return t;
1928  }
1929  };
1930 
1931  // Tensors
1932  template <int rank, int dim, class Number>
1933  struct Convert<Tensor<rank, dim, Number>>
1934  {
1935  using T = Tensor<rank, dim, Number>;
1936  static std::unique_ptr<Patterns::PatternBase>
1937  to_pattern()
1938  {
1939  static_assert(internal::RankInfo<T>::list_rank > 0,
1940  "Cannot use this class for non List-compatible types.");
1941  return std_cxx14::make_unique<Patterns::List>(
1943  dim,
1944  dim,
1945  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1946  1]);
1947  }
1948 
1949  static std::string
1950  to_string(const T & t,
1951  const std::unique_ptr<Patterns::PatternBase> &pattern =
1953  {
1954  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1955  AssertThrow(p,
1956  ExcMessage("I need a List pattern to convert a string "
1957  "to a List compatible type."));
1958  auto base_p = p->get_base_pattern().clone();
1959  std::vector<std::string> vec(dim);
1960 
1961  for (unsigned int i = 0; i < dim; ++i)
1962  vec[i] = Convert<typename T::value_type>::to_string(t[i], base_p);
1963 
1964  std::string s;
1965  if (vec.size() > 0)
1966  s = vec[0];
1967  for (unsigned int i = 1; i < vec.size(); ++i)
1968  s += p->get_separator() + " " + vec[i];
1969 
1970  AssertThrow(p->match(s), ExcNoMatch(s, p->description()));
1971  return s;
1972  }
1973 
1974  static T
1975  to_value(const std::string & s,
1976  const std::unique_ptr<Patterns::PatternBase> &pattern =
1978  {
1979  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
1980 
1981  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1982  AssertThrow(p,
1983  ExcMessage("I need a List pattern to convert a string "
1984  "to a List compatible type."));
1985 
1986  auto base_p = p->get_base_pattern().clone();
1987  T t;
1988 
1989  auto v = Utilities::split_string_list(s, p->get_separator());
1990  unsigned int i = 0;
1991  for (const auto &str : v)
1992  t[i++] = Convert<typename T::value_type>::to_value(str, base_p);
1993 
1994  return t;
1995  }
1996  };
1997 
1998  // Points
1999  template <int dim, class Number>
2000  struct Convert<Point<dim, Number>>
2001  {
2002  using T = Point<dim, Number>;
2003 
2004  static std::unique_ptr<Patterns::PatternBase>
2005  to_pattern()
2006  {
2007  return Convert<Tensor<1, dim, Number>>::to_pattern();
2008  }
2009 
2010  static std::string
2011  to_string(const T & t,
2012  const std::unique_ptr<Patterns::PatternBase> &pattern =
2014  {
2015  return Convert<Tensor<1, dim, Number>>::to_string(
2016  Tensor<1, dim, Number>(t), pattern);
2017  }
2018 
2019  static T
2020  to_value(const std::string & s,
2021  const std::unique_ptr<Patterns::PatternBase> &pattern =
2023  {
2024  return T(Convert<Tensor<1, dim, Number>>::to_value(s, pattern));
2025  }
2026  };
2027 
2028  // Functions::FunctionParser
2029  template <int dim>
2030  struct Convert<std::unique_ptr<FunctionParser<dim>>>
2031  {
2032  using T = std::unique_ptr<FunctionParser<dim>>;
2033 
2034  static std::unique_ptr<Patterns::PatternBase>
2035  to_pattern()
2036  {
2037  static_assert(internal::RankInfo<T>::list_rank > 0,
2038  "Cannot use this class for non List-compatible types.");
2039 
2040  return std_cxx14::make_unique<Patterns::List>(
2042  1,
2044  internal::default_list_separator[internal::RankInfo<T>::list_rank -
2045  1]);
2046  }
2047 
2048  static std::string
2049  to_string(const T & t,
2050  const std::unique_ptr<Patterns::PatternBase> &pattern =
2052  {
2053  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2054  AssertThrow(p,
2055  ExcMessage("I need a List pattern to convert a string "
2056  "to a List compatible type."));
2057 
2058  const auto &expressions = t->get_expressions();
2059  if (expressions.size() == 0)
2060  return std::string();
2061 
2062  std::string s = expressions[0];
2063  for (unsigned int i = 1; i < expressions.size(); ++i)
2064  s = s + p->get_separator() + expressions[i];
2065 
2066  AssertThrow(pattern->match(s), ExcNoMatch(s, p->description()));
2067  return s;
2068  }
2069 
2070  static T
2071  to_value(const std::string & s,
2072  const std::unique_ptr<Patterns::PatternBase> &pattern =
2074  {
2075  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
2076 
2077  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2078  AssertThrow(p,
2079  ExcMessage("I need a List pattern to convert a string "
2080  "to a List compatible type."));
2081 
2082  const auto expressions =
2083  Utilities::split_string_list(s, p->get_separator());
2084 
2085  T t = std_cxx14::make_unique<FunctionParser<dim>>(expressions.size());
2086  const std::string var =
2088  const typename FunctionParser<dim>::ConstMap constants;
2089  t->initialize(var, expressions, constants, true);
2090  return t;
2091  }
2092  };
2093 
2094  // ComponentMask
2095  template <>
2096  struct Convert<ComponentMask>
2097  {
2098  using T = ComponentMask;
2099 
2100  static std::unique_ptr<Patterns::PatternBase>
2101  to_pattern()
2102  {
2103  return Convert<std::vector<bool>>::to_pattern();
2104  }
2105 
2106  static std::string
2107  to_string(const T & t,
2108  const std::unique_ptr<Patterns::PatternBase> &pattern =
2110  {
2111  std::vector<bool> mask(t.size());
2112  for (unsigned int i = 0; i < t.size(); ++i)
2113  mask[i] = t[i];
2114 
2115  return Convert<std::vector<bool>>::to_string(mask, pattern);
2116  }
2117 
2118  static T
2119  to_value(const std::string & s,
2120  const std::unique_ptr<Patterns::PatternBase> &pattern =
2122  {
2123  const auto mask = Convert<std::vector<bool>>::to_value(s, pattern);
2124  return ComponentMask(mask);
2125  }
2126  };
2127 
2128  // Complex numbers
2129  template <class Number>
2130  struct Convert<std::complex<Number>>
2131  {
2132  using T = std::complex<Number>;
2133 
2134  static std::unique_ptr<Patterns::PatternBase>
2135  to_pattern()
2136  {
2137  static_assert(internal::RankInfo<T>::list_rank > 0,
2138  "Cannot use this class for non List-compatible types.");
2139  return std_cxx14::make_unique<Patterns::List>(
2141  2,
2142  2,
2143  internal::default_list_separator[internal::RankInfo<T>::list_rank -
2144  1]);
2145  }
2146 
2147  static std::string
2148  to_string(const T & t,
2149  const std::unique_ptr<Patterns::PatternBase> &pattern =
2151  {
2152  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2153  AssertThrow(p,
2154  ExcMessage("I need a List pattern to convert a string "
2155  "to a List compatible type."));
2156 
2157  auto base_p = p->get_base_pattern().clone();
2158  std::string s =
2159  Convert<typename T::value_type>::to_string(t.real(), base_p) +
2160  p->get_separator() + " " +
2162 
2163  AssertThrow(pattern->match(s), ExcNoMatch(s, p->description()));
2164  return s;
2165  }
2166 
2170  static T
2171  to_value(const std::string & s,
2172  const std::unique_ptr<Patterns::PatternBase> &pattern =
2174  {
2175  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
2176 
2177  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2178  AssertThrow(p,
2179  ExcMessage("I need a List pattern to convert a string "
2180  "to a List compatible type."));
2181 
2182  auto base_p = p->get_base_pattern().clone();
2183 
2184  auto v = Utilities::split_string_list(s, p->get_separator());
2185  AssertDimension(v.size(), 2);
2188  return t;
2189  }
2190  };
2191 
2192  // Strings
2193  template <>
2194  struct Convert<std::string>
2195  {
2196  using T = std::string;
2197 
2198  static std::unique_ptr<Patterns::PatternBase>
2199  to_pattern()
2200  {
2201  return std_cxx14::make_unique<Patterns::Anything>();
2202  }
2203 
2204  static std::string
2205  to_string(const T & t,
2206  const std::unique_ptr<Patterns::PatternBase> &pattern =
2208  {
2209  AssertThrow(pattern->match(t), ExcNoMatch(t, pattern->description()));
2210  return t;
2211  }
2212 
2213  static T
2214  to_value(const std::string & s,
2215  const std::unique_ptr<Patterns::PatternBase> &pattern =
2217  {
2218  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
2219  return s;
2220  }
2221  };
2222 
2223  // Pairs
2224  template <class Key, class Value>
2225  struct Convert<std::pair<Key, Value>>
2226  {
2227  using T = std::pair<Key, Value>;
2228 
2229  static std::unique_ptr<Patterns::PatternBase>
2230  to_pattern()
2231  {
2232  static_assert(internal::RankInfo<T>::map_rank > 0,
2233  "Cannot use this class for non Map-compatible types.");
2234  return std_cxx14::make_unique<Patterns::Map>(
2237  1,
2238  1,
2239  // We keep the same list separator of the previous level, as this is
2240  // a map with only 1 possible entry
2241  internal::default_list_separator[internal::RankInfo<T>::list_rank],
2242  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
2243  }
2244 
2245  static std::string
2246  to_string(const T & t,
2247  const std::unique_ptr<Patterns::PatternBase> &pattern =
2249  {
2250  std::unordered_map<Key, Value> m;
2251  m.insert(t);
2252  std::string s = Convert<decltype(m)>::to_string(m, pattern);
2253  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
2254  return s;
2255  }
2256 
2257  static T
2258  to_value(const std::string & s,
2259  const std::unique_ptr<Patterns::PatternBase> &pattern =
2261  {
2262  std::unordered_map<Key, Value> m;
2263  m = Convert<decltype(m)>::to_value(s, pattern);
2264  return *m.begin();
2265  }
2266  };
2267 
2268  // Tuples
2269  template <class... Args>
2270  struct Convert<std::tuple<Args...>>
2271  {
2272  using T = std::tuple<Args...>;
2273 
2274  static std::unique_ptr<Patterns::PatternBase>
2275  to_pattern()
2276  {
2277  static_assert(internal::RankInfo<T>::map_rank > 0,
2278  "Cannot use this class for non tuple-compatible types.");
2279  return std_cxx14::make_unique<Patterns::Tuple>(
2280  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1],
2282  }
2283 
2284  static std::string
2285  to_string(const T & t,
2286  const std::unique_ptr<Patterns::PatternBase> &pattern =
2288  {
2289  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2290  AssertThrow(p,
2291  ExcMessage("I need a Tuple pattern to convert a tuple "
2292  "to a string."));
2293 
2294  const auto string_array = Convert<T>::to_string_internal_2(t, *p);
2295  std::string str;
2296  for (unsigned int i = 0; i < string_array.size(); ++i)
2297  str += (i ? " " + p->get_separator() + " " : "") + string_array[i];
2298  AssertThrow(p->match(str), ExcNoMatch(str, p->description()));
2299  return str;
2300  }
2301 
2302  static T
2303  to_value(const std::string & s,
2304  const std::unique_ptr<Patterns::PatternBase> &pattern =
2306  {
2307  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern->description()));
2308 
2309  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2310  AssertThrow(p,
2311  ExcMessage("I need a Tuple pattern to convert a string "
2312  "to a tuple type."));
2313 
2314  auto v = Utilities::split_string_list(s, p->get_separator());
2315 
2316  return Convert<T>::to_value_internal_2(v, *p);
2317  }
2318 
2319  private:
2320  template <std::size_t... U>
2321  static std::array<std::string, std::tuple_size<T>::value>
2322  to_string_internal_1(const T & t,
2323  const Patterns::Tuple &pattern,
2324  std_cxx14::index_sequence<U...>)
2325  {
2326  std::array<std::string, std::tuple_size<T>::value> a = {
2328  std::get<U>(t), pattern.get_pattern(U).clone())...}};
2329  return a;
2330  }
2331 
2332  static std::array<std::string, std::tuple_size<T>::value>
2333  to_string_internal_2(const T &t, const Patterns::Tuple &pattern)
2334  {
2336  t,
2337  pattern,
2338  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2339  }
2340 
2341  template <std::size_t... U>
2342  static T
2343  to_value_internal_1(const std::vector<std::string> &s,
2344  const Patterns::Tuple & pattern,
2345  std_cxx14::index_sequence<U...>)
2346  {
2347  return std::make_tuple(
2348  Convert<typename std::tuple_element<U, T>::type>::to_value(
2349  s[U], pattern.get_pattern(U).clone())...);
2350  }
2351 
2352  static T
2353  to_value_internal_2(const std::vector<std::string> &s,
2354  const Patterns::Tuple & pattern)
2355  {
2357  s,
2358  pattern,
2359  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2360  }
2361  };
2362 
2363  // Utility function with default Pattern
2364  template <typename T>
2365  std::string
2366  to_string(const T &t)
2367  {
2368  return Convert<T>::to_string(t);
2369  }
2370 
2371  // Utility function with default Pattern
2372  template <typename T>
2373  void
2374  to_value(const std::string &s, T &t)
2375  {
2376  t = Convert<T>::to_value(s);
2377  }
2378  } // namespace Tools
2379 } // namespace Patterns
2380 
2381 
2382 DEAL_II_NAMESPACE_CLOSE
2383 
2384 #endif
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:663
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:541
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1579
void to_value(const std::string &s, T &t)
Definition: patterns.h:2374
std::string sequence
Definition: patterns.h:435
const double upper_bound
Definition: patterns.h:366
static const char * description_init
Definition: patterns.h:371
static const char * description_init
Definition: patterns.h:1150
const PatternBase & get_pattern(const unsigned int i) const
Definition: patterns.cc:1219
const std::string separator
Definition: patterns.h:888
const std::string separator
Definition: patterns.h:711
std::unique_ptr< PatternBase > pattern
Definition: patterns.h:547
static const unsigned int max_int_value
Definition: patterns.h:593
virtual std::unique_ptr< PatternBase > clone() const =0
static const char * description_init
Definition: patterns.h:722
STL namespace.
static const int max_int_value
Definition: patterns.h:205
#define AssertThrow(cond, exc)
Definition: exceptions.h:1531
const unsigned int max_elements
Definition: patterns.h:706
static const char * description_init
Definition: patterns.h:977
static ::ExceptionBase & ExcNoMatch(std::string arg1, std::string arg2)
Definition: point.h:111
FileType file_type
Definition: patterns.h:1136
static const int min_int_value
Definition: patterns.h:198
static std::string default_variable_names()
const double lower_bound
Definition: patterns.h:358
static const char * description_init
Definition: patterns.h:567
static ::ExceptionBase & ExcMessage(std::string arg1)
static const char * description_init
Definition: patterns.h:1019
static const char * description_init
Definition: patterns.h:440
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:518
std::vector< std::unique_ptr< PatternBase > > patterns
Definition: patterns.h:883
virtual std::size_t memory_consumption() const
Definition: patterns.cc:188
static const char * description_init
Definition: patterns.h:273
static const char * description_init
Definition: patterns.h:893
std::unique_ptr< PatternBase > key_pattern
Definition: patterns.h:695
virtual ~PatternBase()=default
std::string to_string(const T &t)
Definition: patterns.h:2366
static const double min_double_value
Definition: patterns.h:300
std::unique_ptr< PatternBase > pattern_factory(const std::string &description)
Definition: patterns.cc:136
static const char * description_init
Definition: patterns.h:1208
virtual bool match(const std::string &test_string) const =0
static const char * description_init
Definition: patterns.h:1068
__global__ void set(Number *val, const Number s, const size_type N)
static const double max_double_value
Definition: patterns.h:306
virtual std::string description(const OutputStyle style=Machine) const =0
std::map< std::string, double > ConstMap
const int upper_bound
Definition: patterns.h:268
Tuple(const std::vector< std::unique_ptr< PatternBase >> &patterns, const std::string &separator=":")
Definition: patterns.cc:1053
const unsigned int min_elements
Definition: patterns.h:701
static const unsigned int max_int_value
Definition: patterns.h:459
const int lower_bound
Definition: patterns.h:260
const std::string separator
Definition: patterns.h:562
const std::string key_value_separator
Definition: patterns.h:717
const unsigned int max_elements
Definition: patterns.h:557
const unsigned int min_elements
Definition: patterns.h:552