]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Added overloads for ParameterHandler getters to accept a subsection path so that... 7090/head
authorAlexanderBlank <alexanderblank@hotmail.com>
Tue, 21 Aug 2018 05:54:59 +0000 (22:54 -0700)
committerAlexanderBlank <alexanderblank@hotmail.com>
Tue, 21 Aug 2018 05:54:59 +0000 (22:54 -0700)
include/deal.II/base/parameter_handler.h
source/base/parameter_handler.cc
tests/parameter_handler/parameter_handler_23.cc [new file with mode: 0644]
tests/parameter_handler/parameter_handler_23.output [new file with mode: 0644]

index b7ea141f88a23c71d53d5a0b853557d867187557..6e71821ace8df3c811a5ae81c8fe51f0b99dc6b4 100644 (file)
@@ -270,8 +270,34 @@ class MultipleParameterLoop;
  *   @endcode
  * get() returns the value of the given entry. If the entry was not specified
  * in the input source(s), the default value is returned. You have to enter
- * and leave subsections exactly as you did when declaring subsection. You may
- * chose the order in which to transverse the subsection tree.
+ * and leave subsections exactly as you did when declaring subsections. You may
+ * choose the order in which to traverse the subsection tree.
+ *
+ * It is possible to avoid calls to enter_subsection() and leave_subsection()
+ * by supplying get() with a vector of strings representing the path from
+ * which to get a value. For example, the following two versions of
+ * get_parameters() will produce the same result:
+ *   @code
+ *     void NonLinEq::get_parameters (ParameterHandler &prm)
+ *     {
+ *       prm.enter_subsection ("Equation 1 Settings");
+ *       prm.enter_subsection ("Linear solver");
+ *       solver_ = prm.get ("Solver");
+ *       prm.leave_subsection ();
+ *       prm.leave_subsection ();
+ *     }
+ *   @endcode
+ *
+ *   @code
+ *     void NonLinEq::get_parameters (const ParameterHandler &prm)
+ *     {
+ *       std::vector<std::string> path =
+ *         {"Equation 1 Settings", "Linear solver"};
+ *       solver_ = prm.get (path, "Solver");
+ *     }
+ *   @endcode
+ *
+ * The latter method allows the ParameterHandler reference to be @p const.
  *
  * It is guaranteed that only entries matching the given regular expression
  * are returned, i.e. an input entry value which does not match the regular
@@ -1152,15 +1178,29 @@ public:
   leave_subsection();
 
   /**
-   * Return value of entry <tt>entry_string</tt>.  If the entry was changed,
+   * Return value of entry @p entry_string.  If the entry was changed,
    * then the changed value is returned, otherwise the default value. If the
-   * value of an undeclared entry is required, an exception will be thrown.
+   * value of an undeclared entry is required, an @p Assert will fail.
    */
   std::string
   get(const std::string &entry_string) const;
 
   /**
-   * Return value of entry <tt>entry_string</tt> as <tt>long int</tt>. (A long
+   * Return value of entry @p entry_string.  If the entry was changed,
+   * then the changed value is returned, otherwise the default value. If the
+   * value of an undeclared entry is required, an @p Assert will fail.
+   * If @p entry_subsection_path is non-empty, the value will be gotten
+   * from the subsection represented by that path instead of the current
+   * subsection. The first string in @p entry_subsection_path must be the name
+   * of a subsection of the current section, and each next string must be the
+   * name of a subsection of the one before it.
+   */
+  std::string
+  get(const std::vector<std::string> &entry_subsection_path,
+      const std::string &             entry_string) const;
+
+  /**
+   * Return value of entry @p entry_string as <code>long int</code>. (A long
    * int is chosen so that even very large unsigned values can be returned by
    * this function).
    */
@@ -1168,19 +1208,52 @@ public:
   get_integer(const std::string &entry_string) const;
 
   /**
-   * Return value of entry <tt>entry_name</tt> as <tt>double</tt>.
+   * Return value of entry @p entry_string as <code>long int</code>. (A long
+   * int is chosen so that even very large unsigned values can be returned by
+   * this function).
+   * If @p entry_subsection_path is non-empty, the value will be gotten
+   * from the subsection represented by that path instead of the current
+   * subsection.
+   */
+  long int
+  get_integer(const std::vector<std::string> &entry_subsection_path,
+              const std::string &             entry_string) const;
+
+  /**
+   * Return value of entry @p entry_name as @p double.
    */
   double
   get_double(const std::string &entry_name) const;
 
   /**
-   * Return value of entry <tt>entry_name</tt> as <tt>bool</tt>. The entry may
-   * be "true" or "yes" for <tt>true</tt>, "false" or "no" for <tt>false</tt>
+   * Return value of entry @p entry_name as @p double.
+   * If @p entry_subsection_path is non-empty, the value will be gotten
+   * from the subsection represented by that path instead of the current
+   * subsection.
+   */
+  double
+  get_double(const std::vector<std::string> &entry_subsection_path,
+             const std::string &             entry_string) const;
+  /**
+   * Return value of entry @p entry_name as @p bool. The entry may
+   * be "true" or "yes" for @p true, "false" or "no" for @p false
    * respectively.
    */
   bool
   get_bool(const std::string &entry_name) const;
 
+  /**
+   * Return value of entry @p entry_name as @p bool. The entry may
+   * be "true" or "yes" for @p true, "false" or "no" for @p false
+   * respectively.
+   * If @p entry_subsection_path is non-empty, the value will be gotten
+   * from the subsection represented by that path instead of the current
+   * subsection.
+   */
+  bool
+  get_bool(const std::vector<std::string> &entry_subsection_path,
+           const std::string &             entry_string) const;
+
   /**
    * Change the value presently stored for <tt>entry_name</tt> to the one
    * given in the second argument.
@@ -1582,6 +1655,14 @@ private:
   std::string
   get_current_full_path(const std::string &name) const;
 
+  /**
+   * This function computes a full path into the parameter tree given a path
+   * from the current subsection and the name of an entry.
+   */
+  std::string
+  get_current_full_path(const std::vector<std::string> &sub_path,
+                        const std::string &             name) const;
+
   /**
    * Scan one line of input. <tt>input_filename</tt> and
    * <tt>current_line_n</tt> are the name of the input file and the number of
index 03a3cc0ce89444127d9221bc0d1ca0e2b38fc283..742203ec2be052a2195a7bc5e6212f444bf6ad9e 100644 (file)
@@ -294,6 +294,25 @@ ParameterHandler::get_current_full_path(const std::string &name) const
 
 
 
+std::string
+ParameterHandler::get_current_full_path(
+  const std::vector<std::string> &sub_path,
+  const std::string &             name) const
+{
+  std::string path = get_current_path();
+  if (path.empty() == false)
+    path += path_separator;
+
+  if (sub_path.empty() == false)
+    path += collate_path_string(sub_path) + path_separator;
+
+  path += mangle(name);
+
+  return path;
+}
+
+
+
 void
 ParameterHandler::parse_input(std::istream &     input,
                               const std::string &filename,
@@ -783,6 +802,27 @@ ParameterHandler::get(const std::string &entry_string) const
 
 
 
+std::string
+ParameterHandler::get(const std::vector<std::string> &entry_subsection_path,
+                      const std::string &             entry_string) const
+{
+  // assert that the entry is indeed
+  // declared
+  if (boost::optional<std::string> value = entries->get_optional<std::string>(
+        get_current_full_path(entry_subsection_path, entry_string) +
+        path_separator + "value"))
+    return value.get();
+  else
+    {
+      Assert(false,
+             ExcEntryUndeclared(demangle(
+               get_current_full_path(entry_subsection_path, entry_string))));
+      return "";
+    }
+}
+
+
+
 long int
 ParameterHandler::get_integer(const std::string &entry_string) const
 {
@@ -795,7 +835,31 @@ ParameterHandler::get_integer(const std::string &entry_string) const
       AssertThrow(false,
                   ExcMessage("Can't convert the parameter value <" +
                              get(entry_string) + "> for entry <" +
-                             entry_string + " to an integer."));
+                             entry_string + "> to an integer."));
+      return 0;
+    }
+}
+
+
+
+long int
+ParameterHandler::get_integer(
+  const std::vector<std::string> &entry_subsection_path,
+  const std::string &             entry_string) const
+{
+  try
+    {
+      return Utilities::string_to_int(get(entry_subsection_path, entry_string));
+    }
+  catch (...)
+    {
+      AssertThrow(false,
+                  ExcMessage(
+                    "Can't convert the parameter value <" +
+                    get(entry_subsection_path, entry_string) + "> for entry <" +
+                    demangle(get_current_full_path(entry_subsection_path,
+                                                   entry_string)) +
+                    "> to an integer."));
       return 0;
     }
 }
@@ -815,7 +879,32 @@ ParameterHandler::get_double(const std::string &entry_string) const
                   ExcMessage("Can't convert the parameter value <" +
                              get(entry_string) + "> for entry <" +
                              entry_string +
-                             " to a double precision variable."));
+                             "> to a double precision variable."));
+      return 0;
+    }
+}
+
+
+
+double
+ParameterHandler::get_double(
+  const std::vector<std::string> &entry_subsection_path,
+  const std::string &             entry_string) const
+{
+  try
+    {
+      return Utilities::string_to_double(
+        get(entry_subsection_path, entry_string));
+    }
+  catch (...)
+    {
+      AssertThrow(false,
+                  ExcMessage(
+                    "Can't convert the parameter value <" +
+                    get(entry_subsection_path, entry_string) + "> for entry <" +
+                    demangle(get_current_full_path(entry_subsection_path,
+                                                   entry_string)) +
+                    "> to a double precision variable."));
       return 0;
     }
 }
@@ -830,7 +919,29 @@ ParameterHandler::get_bool(const std::string &entry_string) const
   AssertThrow((s == "true") || (s == "false") || (s == "yes") || (s == "no"),
               ExcMessage("Can't convert the parameter value <" +
                          get(entry_string) + "> for entry <" + entry_string +
-                         " to a boolean."));
+                         "> to a boolean."));
+  if (s == "true" || s == "yes")
+    return true;
+  else
+    return false;
+}
+
+
+
+bool
+ParameterHandler::get_bool(
+  const std::vector<std::string> &entry_subsection_path,
+  const std::string &             entry_string) const
+{
+  const std::string s = get(entry_subsection_path, entry_string);
+
+  AssertThrow((s == "true") || (s == "false") || (s == "yes") || (s == "no"),
+              ExcMessage("Can't convert the parameter value <" +
+                         get(entry_subsection_path, entry_string) +
+                         "> for entry <" +
+                         demangle(get_current_full_path(entry_subsection_path,
+                                                        entry_string)) +
+                         "> to a boolean."));
   if (s == "true" || s == "yes")
     return true;
   else
diff --git a/tests/parameter_handler/parameter_handler_23.cc b/tests/parameter_handler/parameter_handler_23.cc
new file mode 100644 (file)
index 0000000..3ae1179
--- /dev/null
@@ -0,0 +1,339 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2018 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+
+// check use of path in ParameterHandler::Get
+
+#include <deal.II/base/parameter_handler.h>
+
+#include <sstream>
+
+#include "../tests.h"
+
+void
+log_entry(const ParameterHandler &       prm,
+          const std::vector<std::string> path,
+          const std::string &            entry)
+{
+  for (unsigned int i = 0; i < path.size(); ++i)
+    {
+      deallog << path[i] << ".";
+    }
+
+  deallog << entry << " = ";
+  deallog << prm.get(path, entry) << std::endl;
+}
+
+void
+log_exception(const StandardExceptions::ExcMessage &exc)
+{
+  std::ostringstream string_stream;
+  exc.print_info(string_stream);
+  std::string exc_info = string_stream.str();
+
+  const std::string whitespace_chars = " \t\r\n\v\f";
+  exc_info.erase(0, exc_info.find_first_not_of(whitespace_chars));
+  exc_info.erase(exc_info.find_last_not_of(whitespace_chars) + 1);
+
+  deallog << exc_info << std::endl;
+}
+
+void
+test_basic()
+{
+  ParameterHandler prm;
+  prm.declare_entry("a", "1");
+  prm.enter_subsection("x");
+  prm.declare_entry("a", "2");
+  prm.enter_subsection("y");
+  prm.declare_entry("a", "3");
+  prm.declare_entry("b", "4");
+  prm.leave_subsection();
+  prm.enter_subsection("v");
+  prm.enter_subsection("v");
+  prm.enter_subsection("v");
+  prm.declare_entry("a", "5");
+  prm.declare_entry("b", "6");
+  prm.leave_subsection();
+  prm.declare_entry("a", "7");
+  prm.leave_subsection();
+  prm.leave_subsection();
+  prm.enter_subsection("z");
+  prm.declare_entry("a", "8");
+  prm.leave_subsection();
+  prm.leave_subsection();
+  prm.declare_entry("b", "9");
+
+  /*
+    prm should now look like this
+
+    # Listing of Parameters
+    # ---------------------
+    set a = 1
+    set b = 9
+
+    subsection x
+      set a = 2
+
+
+      subsection v
+        subsection v
+          set a = 7
+
+
+          subsection v
+            set a = 5
+            set b = 6
+          end
+
+        end
+
+      end
+
+      subsection y
+        set a = 3
+        set b = 4
+      end
+
+      subsection z
+        set a = 8
+      end
+
+    end
+
+  */
+
+  // reading from top level
+  std::vector<std::string> path = {};
+  log_entry(prm, path, "a");
+  path.push_back("x");
+  log_entry(prm, path, "a");
+  path.push_back("y");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  path.push_back("v");
+  path.push_back("v");
+  path.push_back("v");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  log_entry(prm, path, "a");
+  path.pop_back();
+  path.pop_back();
+  path.push_back("z");
+  log_entry(prm, path, "a");
+  path.pop_back();
+  path.pop_back();
+  log_entry(prm, path, "b");
+
+  // reading from other subsections
+  prm.enter_subsection("x");
+  deallog << "in x" << std::endl;
+  log_entry(prm, path, "a");
+  path.push_back("y");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  path.push_back("v");
+  path.push_back("v");
+  path.push_back("v");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  log_entry(prm, path, "a");
+  path.pop_back();
+  path.pop_back();
+  path.push_back("z");
+  log_entry(prm, path, "a");
+  path.pop_back();
+
+  prm.enter_subsection("y");
+  deallog << "in y" << std::endl;
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+
+  prm.leave_subsection();
+  prm.enter_subsection("v");
+  deallog << "in v (first)" << std::endl;
+  path.push_back("v");
+  path.push_back("v");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  log_entry(prm, path, "a");
+  path.pop_back();
+
+  prm.enter_subsection("v");
+  deallog << "in v (second)" << std::endl;
+  path.push_back("v");
+  log_entry(prm, path, "a");
+  log_entry(prm, path, "b");
+  path.pop_back();
+  log_entry(prm, path, "a");
+}
+
+void
+test_getting_types()
+{
+  ParameterHandler prm;
+  prm.enter_subsection("foo");
+  prm.enter_subsection("bar");
+  prm.declare_entry("jik", "1");
+  prm.declare_entry("baz", "77.3");
+  prm.declare_entry("yox", "true");
+  prm.declare_entry("spam", "eggs");
+  prm.leave_subsection();
+  prm.leave_subsection();
+
+  deallog << "in test_getting_types top level" << std::endl;
+
+  if (prm.get_integer({"foo", "bar"}, "jik") != 1)
+    deallog << "unexpected failure to read \"1\" as an integer" << std::endl;
+
+  if (prm.get_double({"foo", "bar"}, "jik") != 1)
+    deallog << "unexpected failure to read \"1\" as a double" << std::endl;
+
+  if (prm.get_double({"foo", "bar"}, "baz") != 77.3)
+    deallog << "unexpected failure to read \"77.3\" as a double" << std::endl;
+
+  if (prm.get_bool({"foo", "bar"}, "yox") != true)
+    deallog << "unexpected failure to read \"true\" as a boolean" << std::endl;
+
+  try
+    {
+      prm.get_integer({"foo", "bar"}, "baz");
+    }
+  catch (StandardExceptions::ExcMessage &e)
+    {
+      log_exception(e);
+    }
+
+  try
+    {
+      prm.get_integer({"foo", "bar"}, "yox");
+    }
+  catch (StandardExceptions::ExcMessage &e)
+    {
+      log_exception(e);
+    }
+
+  try
+    {
+      prm.get_double({"foo", "bar"}, "yox");
+    }
+  catch (StandardExceptions::ExcMessage &e)
+    {
+      log_exception(e);
+    }
+
+  try
+    {
+      prm.get_bool({"foo", "bar"}, "jik");
+    }
+  catch (StandardExceptions::ExcMessage &e)
+    {
+      log_exception(e);
+    }
+
+  try
+    {
+      prm.get_bool({"foo", "bar"}, "spam");
+    }
+  catch (StandardExceptions::ExcMessage &e)
+    {
+      log_exception(e);
+    }
+}
+
+void
+test_weird_strings()
+{
+  const std::vector<std::string> weird_strings = {
+    ".,/<[\"';:=-_)*&~\t`/.\\",
+    "$.7.%...  =   . -",
+    "`/=/a/!",
+    "<<>>>]]]\t\n\n   ",
+    "****&//&%.^$!.$@$%@^*&(*)_/*-`~",
+    ".,/<[\"';:=-_)*&~\t`/.\\",
+    "value",
+    " set value = 5 \n\n."};
+
+  ParameterHandler prm;
+
+  for (int i = 0; i < 6; ++i)
+    {
+      prm.enter_subsection(weird_strings[i]);
+    }
+
+  prm.declare_entry(weird_strings[6], weird_strings[7]);
+
+  for (int i = 0; i < 6; ++i)
+    {
+      prm.leave_subsection();
+    }
+
+  std::vector<std::string> path = {};
+  for (int i = 0; i < 3; ++i)
+    {
+      prm.enter_subsection(weird_strings[i]);
+      path.push_back(weird_strings[3 + i]);
+    }
+
+  deallog << "in <weird_strings[3]>" << std::endl;
+  log_entry(prm, path, weird_strings[6]);
+}
+
+int
+main()
+{
+  initlog();
+
+  try
+    {
+      test_basic();
+      test_getting_types();
+      test_weird_strings();
+    }
+  catch (std::exception &exc)
+    {
+      deallog << std::endl
+              << std::endl
+              << "----------------------------------------------------"
+              << std::endl;
+      deallog << "Exception on processing: " << std::endl
+              << exc.what() << std::endl
+              << "Aborting!" << std::endl
+              << "----------------------------------------------------"
+              << std::endl;
+
+      return 1;
+    }
+  catch (...)
+    {
+      deallog << std::endl
+              << std::endl
+              << "----------------------------------------------------"
+              << std::endl;
+      deallog << "Unknown exception!" << std::endl
+              << "Aborting!" << std::endl
+              << "----------------------------------------------------"
+              << std::endl;
+      return 1;
+    };
+
+  return 0;
+}
diff --git a/tests/parameter_handler/parameter_handler_23.output b/tests/parameter_handler/parameter_handler_23.output
new file mode 100644 (file)
index 0000000..47efbf1
--- /dev/null
@@ -0,0 +1,41 @@
+
+DEAL::a = 1
+DEAL::x.a = 2
+DEAL::x.y.a = 3
+DEAL::x.y.b = 4
+DEAL::x.v.v.v.a = 5
+DEAL::x.v.v.v.b = 6
+DEAL::x.v.v.a = 7
+DEAL::x.z.a = 8
+DEAL::b = 9
+DEAL::in x
+DEAL::a = 2
+DEAL::y.a = 3
+DEAL::y.b = 4
+DEAL::v.v.v.a = 5
+DEAL::v.v.v.b = 6
+DEAL::v.v.a = 7
+DEAL::z.a = 8
+DEAL::in y
+DEAL::a = 3
+DEAL::b = 4
+DEAL::in v (first)
+DEAL::v.v.a = 5
+DEAL::v.v.b = 6
+DEAL::v.a = 7
+DEAL::in v (second)
+DEAL::v.a = 5
+DEAL::v.b = 6
+DEAL::a = 7
+DEAL::in test_getting_types top level
+DEAL::Can't convert the parameter value <77.3> for entry <foo.bar.baz> to an integer.
+DEAL::Can't convert the parameter value <true> for entry <foo.bar.yox> to an integer.
+DEAL::Can't convert the parameter value <true> for entry <foo.bar.yox> to a double precision variable.
+DEAL::Can't convert the parameter value <1> for entry <foo.bar.jik> to a boolean.
+DEAL::Can't convert the parameter value <eggs> for entry <foo.bar.spam> to a boolean.
+DEAL::in <weird_strings[3]>
+DEAL::<<>>>]]] 
+
+   .****&//&%.^$!.$@$%@^*&(*)_/*-`~..,/<["';:=-_)*&~   `/.\.value =  set value = 5 
+
+.

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.