Reference documentation for deal.II version Git cb0bd54b52 2019-09-21 16:31:22 -0400
\(\newcommand{\dealcoloneq}{\mathrel{\vcenter{:}}=}\)
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  const Patterns::PatternBase *,
1415  << "The string " << arg1 << " does not match the pattern \""
1416  << arg2->description() << "\"");
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()), ExcNoMatch(str.str(), p.get()));
1548  return str.str();
1549  }
1550 
1551  static T
1552  to_value(const std::string & s,
1553  const std::unique_ptr<Patterns::PatternBase> &p =
1555  {
1556  AssertThrow(p->match(s), ExcNoMatch(s, p.get()));
1557  T value;
1558  if (std::is_same<T, bool>::value)
1559  value = (s == "true");
1560  else
1561  {
1562  std::istringstream is(s);
1563  if (std::is_same<T, unsigned char>::value ||
1564  std::is_same<T, signed char>::value ||
1565  std::is_same<T, char>::value)
1566  {
1567  int i;
1568  is >> i;
1569  value = i;
1570  }
1571  else
1572  is >> value;
1573 
1574  // If someone passes "123 abc" to the function, the method yields an
1575  // integer 123 alright, but the space terminates the read from the
1576  // string although there is more to come. This case, however, is
1577  // checked for in the call p->match(s) at the beginning of this
1578  // function, and would throw earlier. Here it is safe to assume that
1579  // if we didn't fail the conversion with the operator >>, then we
1580  // are good to go.
1581  AssertThrow(
1582  !is.fail(),
1583  ExcMessage("Failed to convert from \"" + s + "\" to the type \"" +
1584  boost::core::demangle(typeid(T).name()) + "\""));
1585  }
1586  return value;
1587  }
1588  };
1589 
1590  namespace internal
1591  {
1592  constexpr std::array<const char *, 4> default_list_separator{
1593  {",", ";", "|", "%"}};
1594  constexpr std::array<const char *, 4> default_map_separator{
1595  {":", "=", "@", "#"}};
1596 
1597  // specialize a type for all of the STL containers and maps
1598  template <typename T>
1599  struct is_list_compatible : std::false_type
1600  {};
1601  template <typename T, std::size_t N>
1602  struct is_list_compatible<std::array<T, N>> : std::true_type
1603  {};
1604  template <typename... Args>
1605  struct is_list_compatible<std::vector<Args...>> : std::true_type
1606  {};
1607  template <typename... Args>
1608  struct is_list_compatible<std::deque<Args...>> : std::true_type
1609  {};
1610  template <typename... Args>
1611  struct is_list_compatible<std::list<Args...>> : std::true_type
1612  {};
1613  template <typename... Args>
1614  struct is_list_compatible<std::set<Args...>> : std::true_type
1615  {};
1616  template <typename... Args>
1617  struct is_list_compatible<std::multiset<Args...>> : std::true_type
1618  {};
1619  template <typename... Args>
1620  struct is_list_compatible<std::unordered_set<Args...>> : std::true_type
1621  {};
1622  template <typename... Args>
1623  struct is_list_compatible<std::unordered_multiset<Args...>>
1624  : std::true_type
1625  {};
1626 
1627  template <typename T>
1628  struct is_map_compatible : std::false_type
1629  {};
1630  template <class Key, class T, class Compare, class Allocator>
1631  struct is_map_compatible<std::map<Key, T, Compare, Allocator>>
1632  : std::true_type
1633  {};
1634  template <class Key, class T, class Compare, class Allocator>
1635  struct is_map_compatible<std::multimap<Key, T, Compare, Allocator>>
1636  : std::true_type
1637  {};
1638  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1639  struct is_map_compatible<
1640  std::unordered_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type
1641  {};
1642  template <class Key, class T, class Hash, class KeyEqual, class Allocator>
1643  struct is_map_compatible<
1644  std::unordered_multimap<Key, T, Hash, KeyEqual, Allocator>>
1645  : std::true_type
1646  {};
1647  } // namespace internal
1648 
1649  // type trait to use the implementation type traits as well as decay the
1650  // type
1651  template <typename T>
1652  struct is_list_compatible
1653  {
1654  static constexpr bool const value =
1655  internal::is_list_compatible<typename std::decay<T>::type>::value;
1656  };
1657 
1658  template <typename T>
1659  struct is_map_compatible
1660  {
1661  static constexpr bool const value =
1662  internal::is_map_compatible<typename std::decay<T>::type>::value;
1663  };
1664 
1665  namespace internal
1666  {
1667  // Helper function for list_rank
1668  template <class T>
1669  constexpr int
1670  max_list_rank()
1671  {
1672  return RankInfo<T>::list_rank;
1673  }
1674 
1675  template <class T1, class T2, class... Types>
1676  constexpr int
1677  max_list_rank()
1678  {
1679  return std_cxx14::max(RankInfo<T1>::list_rank,
1680  max_list_rank<T2, Types...>());
1681  }
1682 
1683  // Helper function for map_rank
1684  template <class T>
1685  constexpr int
1686  max_map_rank()
1687  {
1688  return RankInfo<T>::map_rank;
1689  }
1690 
1691  template <class T1, class T2, class... Types>
1692  constexpr int
1693  max_map_rank()
1694  {
1695  return std_cxx14::max(RankInfo<T1>::map_rank,
1696  max_map_rank<T2, Types...>());
1697  }
1698 
1699  // Rank of vector types
1700  template <class T>
1701  struct RankInfo<
1702  T,
1703  typename std::enable_if<is_list_compatible<T>::value>::type>
1704  {
1705  static constexpr int list_rank =
1707  static constexpr int map_rank =
1709  };
1710 
1711  // Rank of map types
1712  template <class T>
1713  struct RankInfo<
1714  T,
1715  typename std::enable_if<is_map_compatible<T>::value>::type>
1716  {
1717  static constexpr int list_rank =
1718  max_list_rank<typename T::key_type, typename T::mapped_type>() + 1;
1719  static constexpr int map_rank =
1720  max_map_rank<typename T::key_type, typename T::mapped_type>() + 1;
1721  };
1722 
1723  // Rank of Tensor types
1724  template <int rank, int dim, class Number>
1725  struct RankInfo<Tensor<rank, dim, Number>>
1726  {
1727  static constexpr int list_rank = rank + RankInfo<Number>::list_rank;
1728  static constexpr int map_rank = RankInfo<Number>::map_rank;
1729  };
1730 
1731  template <int dim, class Number>
1732  struct RankInfo<Point<dim, Number>> : RankInfo<Tensor<1, dim, Number>>
1733  {};
1734 
1735  // Rank of complex types
1736  template <class Number>
1737  struct RankInfo<std::complex<Number>>
1738  {
1739  static constexpr int list_rank = RankInfo<Number>::list_rank + 1;
1740  static constexpr int map_rank = RankInfo<Number>::map_rank;
1741  };
1742 
1743  // Rank of FunctionParser
1744  template <int dim>
1745  struct RankInfo<std::unique_ptr<FunctionParser<dim>>>
1746  {
1747  static constexpr int list_rank = 1;
1748  static constexpr int map_rank = 0;
1749  };
1750 
1751  // Rank of ComponentMask
1752  template <>
1753  struct RankInfo<ComponentMask>
1754  {
1755  static constexpr int list_rank = 1;
1756  static constexpr int map_rank = 0;
1757  };
1758 
1759  // Rank of std::pair
1760  template <class Key, class Value>
1761  struct RankInfo<std::pair<Key, Value>>
1762  {
1763  static constexpr int list_rank =
1765  static constexpr int map_rank =
1767  1;
1768  };
1769 
1770 
1771  template <class... Types>
1772  struct RankInfo<std::tuple<Types...>>
1773  {
1774  static constexpr int list_rank = max_list_rank<Types...>();
1775  static constexpr int map_rank = max_map_rank<Types...>() + 1;
1776  };
1777  } // namespace internal
1778 
1779  // stl containers
1780  template <class T>
1781  struct Convert<T,
1782  typename std::enable_if<is_list_compatible<T>::value>::type>
1783  {
1784  static std::unique_ptr<Patterns::PatternBase>
1785  to_pattern()
1786  {
1787  static_assert(internal::RankInfo<T>::list_rank > 0,
1788  "Cannot use this class for non List-compatible types.");
1789  return std_cxx14::make_unique<Patterns::List>(
1791  0,
1792  std::numeric_limits<unsigned int>::max(),
1793  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1794  1]);
1795  }
1796 
1797  static std::string
1798  to_string(const T & t,
1799  const std::unique_ptr<Patterns::PatternBase> &pattern =
1801  {
1802  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1803  AssertThrow(p,
1804  ExcMessage("I need a List pattern to convert a "
1805  "string to a List type."));
1806  auto base_p = p->get_base_pattern().clone();
1807  std::vector<std::string> vec(t.size());
1808 
1809  unsigned int i = 0;
1810  for (const auto &entry : t)
1811  vec[i++] = Convert<typename T::value_type>::to_string(entry, base_p);
1812 
1813  std::string s;
1814  if (vec.size() > 0)
1815  s = vec[0];
1816  for (unsigned int i = 1; i < vec.size(); ++i)
1817  s += p->get_separator() + " " + vec[i];
1818 
1819  AssertThrow(pattern->match(s), ExcNoMatch(s, p));
1820  return s;
1821  }
1822 
1823  static T
1824  to_value(const std::string & s,
1825  const std::unique_ptr<Patterns::PatternBase> &pattern =
1827  {
1828  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1829 
1830  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1831  AssertThrow(p,
1832  ExcMessage("I need a List pattern to convert a string "
1833  "to a List type."));
1834 
1835  auto base_p = p->get_base_pattern().clone();
1836  T t;
1837 
1838  auto v = Utilities::split_string_list(s, p->get_separator());
1839  for (const auto &str : v)
1840  t.insert(t.end(),
1842 
1843  return t;
1844  }
1845  };
1846 
1847  // stl maps
1848  template <class T>
1849  struct Convert<T,
1850  typename std::enable_if<is_map_compatible<T>::value>::type>
1851  {
1852  static std::unique_ptr<Patterns::PatternBase>
1853  to_pattern()
1854  {
1855  static_assert(internal::RankInfo<T>::list_rank > 0,
1856  "Cannot use this class for non List-compatible types.");
1857  static_assert(internal::RankInfo<T>::map_rank > 0,
1858  "Cannot use this class for non Map-compatible types.");
1859  return std_cxx14::make_unique<Patterns::Map>(
1862  0,
1863  std::numeric_limits<unsigned int>::max(),
1864  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1865  1],
1866  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
1867  }
1868 
1869  static std::string
1870  to_string(const T & t,
1871  const std::unique_ptr<Patterns::PatternBase> &pattern =
1873  {
1874  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1875  AssertThrow(p,
1876  ExcMessage("I need a Map pattern to convert a string to "
1877  "a Map compatible type."));
1878  auto key_p = p->get_key_pattern().clone();
1879  auto val_p = p->get_value_pattern().clone();
1880  std::vector<std::string> vec(t.size());
1881 
1882  unsigned int i = 0;
1883  for (const auto &ti : t)
1884  vec[i++] =
1885  Convert<typename T::key_type>::to_string(ti.first, key_p) +
1886  p->get_key_value_separator() +
1888 
1889  std::string s;
1890  if (vec.size() > 0)
1891  s = vec[0];
1892  for (unsigned int i = 1; i < vec.size(); ++i)
1893  s += p->get_separator() + " " + vec[i];
1894 
1895  AssertThrow(p->match(s), ExcNoMatch(s, p));
1896  return s;
1897  }
1898 
1899  static T
1900  to_value(const std::string & s,
1901  const std::unique_ptr<Patterns::PatternBase> &pattern =
1903  {
1904  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1905 
1906  auto p = dynamic_cast<const Patterns::Map *>(pattern.get());
1907  AssertThrow(p,
1908  ExcMessage("I need a Map pattern to convert a "
1909  "string to a Map compatible type."));
1910 
1911  auto key_p = p->get_key_pattern().clone();
1912  auto val_p = p->get_value_pattern().clone();
1913  T t;
1914 
1915  auto v = Utilities::split_string_list(s, p->get_separator());
1916  for (const auto &str : v)
1917  {
1918  auto key_val =
1919  Utilities::split_string_list(str, p->get_key_value_separator());
1920  AssertDimension(key_val.size(), 2);
1921  t.insert(std::make_pair(
1922  Convert<typename T::key_type>::to_value(key_val[0], key_p),
1924  }
1925 
1926  return t;
1927  }
1928  };
1929 
1930  // Tensors
1931  template <int rank, int dim, class Number>
1932  struct Convert<Tensor<rank, dim, Number>>
1933  {
1934  using T = Tensor<rank, dim, Number>;
1935  static std::unique_ptr<Patterns::PatternBase>
1936  to_pattern()
1937  {
1938  static_assert(internal::RankInfo<T>::list_rank > 0,
1939  "Cannot use this class for non List-compatible types.");
1940  return std_cxx14::make_unique<Patterns::List>(
1942  dim,
1943  dim,
1944  internal::default_list_separator[internal::RankInfo<T>::list_rank -
1945  1]);
1946  }
1947 
1948  static std::string
1949  to_string(const T & t,
1950  const std::unique_ptr<Patterns::PatternBase> &pattern =
1952  {
1953  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1954  AssertThrow(p,
1955  ExcMessage("I need a List pattern to convert a string "
1956  "to a List compatible type."));
1957  auto base_p = p->get_base_pattern().clone();
1958  std::vector<std::string> vec(dim);
1959 
1960  for (unsigned int i = 0; i < dim; ++i)
1961  vec[i] = Convert<typename T::value_type>::to_string(t[i], base_p);
1962 
1963  std::string s;
1964  if (vec.size() > 0)
1965  s = vec[0];
1966  for (unsigned int i = 1; i < vec.size(); ++i)
1967  s += p->get_separator() + " " + vec[i];
1968 
1969  AssertThrow(p->match(s), ExcNoMatch(s, p));
1970  return s;
1971  }
1972 
1973  static T
1974  to_value(const std::string & s,
1975  const std::unique_ptr<Patterns::PatternBase> &pattern =
1977  {
1978  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
1979 
1980  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
1981  AssertThrow(p,
1982  ExcMessage("I need a List pattern to convert a string "
1983  "to a List compatible type."));
1984 
1985  auto base_p = p->get_base_pattern().clone();
1986  T t;
1987 
1988  auto v = Utilities::split_string_list(s, p->get_separator());
1989  unsigned int i = 0;
1990  for (const auto &str : v)
1991  t[i++] = Convert<typename T::value_type>::to_value(str, base_p);
1992 
1993  return t;
1994  }
1995  };
1996 
1997  // Points
1998  template <int dim, class Number>
1999  struct Convert<Point<dim, Number>>
2000  {
2001  using T = Point<dim, Number>;
2002 
2003  static std::unique_ptr<Patterns::PatternBase>
2004  to_pattern()
2005  {
2006  return Convert<Tensor<1, dim, Number>>::to_pattern();
2007  }
2008 
2009  static std::string
2010  to_string(const T & t,
2011  const std::unique_ptr<Patterns::PatternBase> &pattern =
2013  {
2014  return Convert<Tensor<1, dim, Number>>::to_string(
2015  Tensor<1, dim, Number>(t), pattern);
2016  }
2017 
2018  static T
2019  to_value(const std::string & s,
2020  const std::unique_ptr<Patterns::PatternBase> &pattern =
2022  {
2023  return T(Convert<Tensor<1, dim, Number>>::to_value(s, pattern));
2024  }
2025  };
2026 
2027  // Functions::FunctionParser
2028  template <int dim>
2029  struct Convert<std::unique_ptr<FunctionParser<dim>>>
2030  {
2031  using T = std::unique_ptr<FunctionParser<dim>>;
2032 
2033  static std::unique_ptr<Patterns::PatternBase>
2034  to_pattern()
2035  {
2036  static_assert(internal::RankInfo<T>::list_rank > 0,
2037  "Cannot use this class for non List-compatible types.");
2038 
2039  return std_cxx14::make_unique<Patterns::List>(
2041  1,
2043  internal::default_list_separator[internal::RankInfo<T>::list_rank -
2044  1]);
2045  }
2046 
2047  static std::string
2048  to_string(const T & t,
2049  const std::unique_ptr<Patterns::PatternBase> &pattern =
2051  {
2052  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2053  AssertThrow(p,
2054  ExcMessage("I need a List pattern to convert a string "
2055  "to a List compatible type."));
2056 
2057  const auto &expressions = t->get_expressions();
2058  if (expressions.size() == 0)
2059  return std::string();
2060 
2061  std::string s = expressions[0];
2062  for (unsigned int i = 1; i < expressions.size(); ++i)
2063  s = s + p->get_separator() + expressions[i];
2064 
2065  AssertThrow(pattern->match(s), ExcNoMatch(s, p));
2066  return s;
2067  }
2068 
2069  static T
2070  to_value(const std::string & s,
2071  const std::unique_ptr<Patterns::PatternBase> &pattern =
2073  {
2074  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2075 
2076  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2077  AssertThrow(p,
2078  ExcMessage("I need a List pattern to convert a string "
2079  "to a List compatible type."));
2080 
2081  const auto expressions =
2082  Utilities::split_string_list(s, p->get_separator());
2083 
2084  T t = std_cxx14::make_unique<FunctionParser<dim>>(expressions.size());
2085  const std::string var =
2087  const typename FunctionParser<dim>::ConstMap constants;
2088  t->initialize(var, expressions, constants, true);
2089  return t;
2090  }
2091  };
2092 
2093  // ComponentMask
2094  template <>
2095  struct Convert<ComponentMask>
2096  {
2097  using T = ComponentMask;
2098 
2099  static std::unique_ptr<Patterns::PatternBase>
2100  to_pattern()
2101  {
2102  return Convert<std::vector<bool>>::to_pattern();
2103  }
2104 
2105  static std::string
2106  to_string(const T & t,
2107  const std::unique_ptr<Patterns::PatternBase> &pattern =
2109  {
2110  std::vector<bool> mask(t.size());
2111  for (unsigned int i = 0; i < t.size(); ++i)
2112  mask[i] = t[i];
2113 
2114  return Convert<std::vector<bool>>::to_string(mask, pattern);
2115  }
2116 
2117  static T
2118  to_value(const std::string & s,
2119  const std::unique_ptr<Patterns::PatternBase> &pattern =
2121  {
2122  const auto mask = Convert<std::vector<bool>>::to_value(s, pattern);
2123  return ComponentMask(mask);
2124  }
2125  };
2126 
2127  // Complex numbers
2128  template <class Number>
2129  struct Convert<std::complex<Number>>
2130  {
2131  using T = std::complex<Number>;
2132 
2133  static std::unique_ptr<Patterns::PatternBase>
2134  to_pattern()
2135  {
2136  static_assert(internal::RankInfo<T>::list_rank > 0,
2137  "Cannot use this class for non List-compatible types.");
2138  return std_cxx14::make_unique<Patterns::List>(
2140  2,
2141  2,
2142  internal::default_list_separator[internal::RankInfo<T>::list_rank -
2143  1]);
2144  }
2145 
2146  static std::string
2147  to_string(const T & t,
2148  const std::unique_ptr<Patterns::PatternBase> &pattern =
2150  {
2151  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2152  AssertThrow(p,
2153  ExcMessage("I need a List pattern to convert a string "
2154  "to a List compatible type."));
2155 
2156  auto base_p = p->get_base_pattern().clone();
2157  std::string s =
2158  Convert<typename T::value_type>::to_string(t.real(), base_p) +
2159  p->get_separator() + " " +
2161 
2162  AssertThrow(pattern->match(s), ExcNoMatch(s, p));
2163  return s;
2164  }
2165 
2169  static T
2170  to_value(const std::string & s,
2171  const std::unique_ptr<Patterns::PatternBase> &pattern =
2173  {
2174  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2175 
2176  auto p = dynamic_cast<const Patterns::List *>(pattern.get());
2177  AssertThrow(p,
2178  ExcMessage("I need a List pattern to convert a string "
2179  "to a List compatible type."));
2180 
2181  auto base_p = p->get_base_pattern().clone();
2182 
2183  auto v = Utilities::split_string_list(s, p->get_separator());
2184  AssertDimension(v.size(), 2);
2187  return t;
2188  }
2189  };
2190 
2191  // Strings
2192  template <>
2193  struct Convert<std::string>
2194  {
2195  using T = std::string;
2196 
2197  static std::unique_ptr<Patterns::PatternBase>
2198  to_pattern()
2199  {
2200  return std_cxx14::make_unique<Patterns::Anything>();
2201  }
2202 
2203  static std::string
2204  to_string(const T & t,
2205  const std::unique_ptr<Patterns::PatternBase> &pattern =
2207  {
2208  AssertThrow(pattern->match(t), ExcNoMatch(t, pattern.get()));
2209  return t;
2210  }
2211 
2212  static T
2213  to_value(const std::string & s,
2214  const std::unique_ptr<Patterns::PatternBase> &pattern =
2216  {
2217  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2218  return s;
2219  }
2220  };
2221 
2222  // Pairs
2223  template <class Key, class Value>
2224  struct Convert<std::pair<Key, Value>>
2225  {
2226  using T = std::pair<Key, Value>;
2227 
2228  static std::unique_ptr<Patterns::PatternBase>
2229  to_pattern()
2230  {
2231  static_assert(internal::RankInfo<T>::map_rank > 0,
2232  "Cannot use this class for non Map-compatible types.");
2233  return std_cxx14::make_unique<Patterns::Map>(
2236  1,
2237  1,
2238  // We keep the same list separator of the previous level, as this is
2239  // a map with only 1 possible entry
2240  internal::default_list_separator[internal::RankInfo<T>::list_rank],
2241  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1]);
2242  }
2243 
2244  static std::string
2245  to_string(const T & t,
2246  const std::unique_ptr<Patterns::PatternBase> &pattern =
2248  {
2249  std::unordered_map<Key, Value> m;
2250  m.insert(t);
2251  std::string s = Convert<decltype(m)>::to_string(m, pattern);
2252  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2253  return s;
2254  }
2255 
2256  static T
2257  to_value(const std::string & s,
2258  const std::unique_ptr<Patterns::PatternBase> &pattern =
2260  {
2261  std::unordered_map<Key, Value> m;
2262  m = Convert<decltype(m)>::to_value(s, pattern);
2263  return *m.begin();
2264  }
2265  };
2266 
2267  // Tuples
2268  template <class... Args>
2269  struct Convert<std::tuple<Args...>>
2270  {
2271  using T = std::tuple<Args...>;
2272 
2273  static std::unique_ptr<Patterns::PatternBase>
2274  to_pattern()
2275  {
2276  static_assert(internal::RankInfo<T>::map_rank > 0,
2277  "Cannot use this class for non tuple-compatible types.");
2278  return std_cxx14::make_unique<Patterns::Tuple>(
2279  internal::default_map_separator[internal::RankInfo<T>::map_rank - 1],
2281  }
2282 
2283  static std::string
2284  to_string(const T & t,
2285  const std::unique_ptr<Patterns::PatternBase> &pattern =
2287  {
2288  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2289  AssertThrow(p,
2290  ExcMessage("I need a Tuple pattern to convert a tuple "
2291  "to a string."));
2292 
2293  const auto string_array = Convert<T>::to_string_internal_2(t, *p);
2294  std::string str;
2295  for (unsigned int i = 0; i < string_array.size(); ++i)
2296  str += (i ? " " + p->get_separator() + " " : "") + string_array[i];
2297  AssertThrow(p->match(str), ExcNoMatch(str, p));
2298  return str;
2299  }
2300 
2301  static T
2302  to_value(const std::string & s,
2303  const std::unique_ptr<Patterns::PatternBase> &pattern =
2305  {
2306  AssertThrow(pattern->match(s), ExcNoMatch(s, pattern.get()));
2307 
2308  auto p = dynamic_cast<const Patterns::Tuple *>(pattern.get());
2309  AssertThrow(p,
2310  ExcMessage("I need a Tuple pattern to convert a string "
2311  "to a tuple type."));
2312 
2313  auto v = Utilities::split_string_list(s, p->get_separator());
2314 
2315  return Convert<T>::to_value_internal_2(v, *p);
2316  }
2317 
2318  private:
2319  template <std::size_t... U>
2320  static std::array<std::string, std::tuple_size<T>::value>
2321  to_string_internal_1(const T & t,
2322  const Patterns::Tuple &pattern,
2323  std_cxx14::index_sequence<U...>)
2324  {
2325  std::array<std::string, std::tuple_size<T>::value> a = {
2327  std::get<U>(t), pattern.get_pattern(U).clone())...}};
2328  return a;
2329  }
2330 
2331  static std::array<std::string, std::tuple_size<T>::value>
2332  to_string_internal_2(const T &t, const Patterns::Tuple &pattern)
2333  {
2335  t,
2336  pattern,
2337  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2338  }
2339 
2340  template <std::size_t... U>
2341  static T
2342  to_value_internal_1(const std::vector<std::string> &s,
2343  const Patterns::Tuple & pattern,
2344  std_cxx14::index_sequence<U...>)
2345  {
2346  return std::make_tuple(
2347  Convert<typename std::tuple_element<U, T>::type>::to_value(
2348  s[U], pattern.get_pattern(U).clone())...);
2349  }
2350 
2351  static T
2352  to_value_internal_2(const std::vector<std::string> &s,
2353  const Patterns::Tuple & pattern)
2354  {
2356  s,
2357  pattern,
2358  std_cxx14::make_index_sequence<std::tuple_size<T>::value>{});
2359  }
2360  };
2361 
2362  // Utility function with default Pattern
2363  template <typename T>
2364  std::string
2365  to_string(const T &t)
2366  {
2367  return Convert<T>::to_string(t);
2368  }
2369 
2370  // Utility function with default Pattern
2371  template <typename T>
2372  void
2373  to_value(const std::string &s, T &t)
2374  {
2375  t = Convert<T>::to_value(s);
2376  }
2377  } // namespace Tools
2378 } // namespace Patterns
2379 
2380 
2381 DEAL_II_NAMESPACE_CLOSE
2382 
2383 #endif
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
Definition: utilities.cc:584
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:541
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1567
void to_value(const std::string &s, T &t)
Definition: patterns.h:2373
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:1519
const unsigned int max_elements
Definition: patterns.h:706
static const char * description_init
Definition: patterns.h:977
Definition: point.h:110
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:2365
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
static ::ExceptionBase & ExcNoMatch(std::string arg1, const Patterns::PatternBase *arg2)
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