]> https://gitweb.dealii.org/ - dealii.git/commitdiff
extend function parse_input() for file-type-independent parsing 9741/head
authorNiklas Fehn <fehn@lnm.mw.tum.de>
Thu, 26 Mar 2020 15:44:24 +0000 (16:44 +0100)
committerNiklas Fehn <fehn@lnm.mw.tum.de>
Mon, 13 Apr 2020 08:24:47 +0000 (10:24 +0200)
17 files changed:
doc/news/changes/minor/20200326NiklasFehn [new file with mode: 0644]
include/deal.II/base/parameter_handler.h
source/base/parameter_handler.cc
tests/parameter_handler/parameter_handler_26.cc [new file with mode: 0644]
tests/parameter_handler/parameter_handler_26.output [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_json_02.cc
tests/parameter_handler/parameter_handler_read_json_03.cc [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_json_03.output [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_prm_01.cc [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_prm_01.output [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_xml_01.cc [new file with mode: 0644]
tests/parameter_handler/parameter_handler_read_xml_01.output [new file with mode: 0644]
tests/parameter_handler/prm/parameter_handler_26_fail.json [new file with mode: 0644]
tests/parameter_handler/prm/parameter_handler_26_success.json [new file with mode: 0644]
tests/parameter_handler/prm/parameter_handler_read_json_03.json [new file with mode: 0644]
tests/parameter_handler/prm/parameter_handler_read_prm_01.prm [new file with mode: 0644]
tests/parameter_handler/prm/parameter_handler_read_xml_01.xml [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20200326NiklasFehn b/doc/news/changes/minor/20200326NiklasFehn
new file mode 100644 (file)
index 0000000..6a97e7e
--- /dev/null
@@ -0,0 +1,6 @@
+Extension: The function ParameterHandler::parse_input() has been extended so that
+the same parse_input function can be called independently of the type of input
+file (prm, xml, json). An additional parameter assert_mandatory_entries_are_found
+is introduced to avoid errors, e.g., due to typos in the input file.
+<br>
+(Niklas Fehn, 2020/03/26)
index ebc1bdf2618b92e2eee4c9a42126b8ccb1899e93..a9eb31d0af466a5ebc303b05a9a564f4ec460d22 100644 (file)
@@ -965,52 +965,31 @@ public:
               const bool         skip_undefined = false);
 
   /**
-   * Parse the given file to provide values for known parameter fields. The
-   * PathSearch class "PARAMETERS" is used to find the file.
+   * Parse input from a specified parameter file @param filename independently
+   * of the type of input file (prm, xml, json) being used. The code path
+   * selected by this function is extracted from the ending of the filename,
+   * so the user has to make sure that the content of the input file is
+   * consistent with its name.
    *
-   * The function in essence reads the entire file into a stream and
-   * then calls the other parse_input() function with that stream. See
-   * there for more information.
+   * The parameter @p last_line will only be used for parameter files of .prm type.
+   * See the other parse_input function for documentation.
    *
-   * Previous versions of deal.II included a similar function named
-   * <code>read_input</code> which, if the parameter file could not be found
-   * by PathSearch::find, would not modify the calling ParameterHandler (i.e.,
-   * the parameters would all be set to their default values) and would
-   * (optionally) create a parameter file with default values. In order to
-   * obtain that behavior one should catch the PathSearch::ExcFileNotFound
-   * exception and then optionally call ParameterHandler::print_parameters,
-   * e.g.,
+   * The user can specify whether parameters in the input file not added to the
+   * parameter handler will be skipped by @p skip_undefined (enables partial
+   * parsing), and whether the code will assert that all parameters of the
+   * parameter handler declared with flag `has_to_be_set=true` are indeed found
+   * in the input file.
    *
-   * @code
-   * const std::string filename = "parameters.prm";
-   * const bool print_default_prm_file = true;
-   * try
-   *   {
-   *     parameter_handler.parse_input (filename);
-   *   }
-   * catch (const PathSearch::ExcFileNotFound &)
-   *   {
-   *     std::cerr << "ParameterHandler::parse_input: could not open file <"
-   *               << filename
-   *               << "> for reading."
-   *               << std::endl;
-   *     if (print_default_prm_file)
-   *       {
-   *         std::cerr << "Trying to make file <"
-   *                   << filename
-   *                   << "> with default values for you."
-   *                   << std::endl;
-   *         std::ofstream output (filename);
-   *         parameter_handler.print_parameters(
-   *           output, ParameterHandler::OutputStyle::Text);
-   *       }
-   *   }
-   * @endcode
+   * If the function is called with `skip_undefined=true`, it is recommended to
+   * also set `assert_mandatory_entries_are_found=true`. For example, this
+   * ensures that parameters with typos in the input file will not be skipped,
+   * while such mistakes would otherwise remain unrecognized.
    */
   virtual void
   parse_input(const std::string &filename,
-              const std::string &last_line      = "",
-              const bool         skip_undefined = false);
+              const std::string &last_line                          = "",
+              const bool         skip_undefined                     = false,
+              const bool         assert_mandatory_entries_are_found = false);
 
   /**
    * Parse input from a string to populate known parameter fields. The lines
index 82167e8a61bbd8c176e1dfc276e0b6f55ef5e9aa..d25e89022079ae134f0d2787c66b4acae793940a 100644 (file)
@@ -20,6 +20,7 @@
 #include <deal.II/base/path_search.h>
 #include <deal.II/base/utilities.h>
 
+#include <boost/algorithm/string.hpp>
 #include <boost/io/ios_state.hpp>
 #include <boost/property_tree/json_parser.hpp>
 #include <boost/property_tree/ptree.hpp>
@@ -509,13 +510,38 @@ ParameterHandler::parse_input(std::istream &     input,
 void
 ParameterHandler::parse_input(const std::string &filename,
                               const std::string &last_line,
-                              const bool         skip_undefined)
+                              const bool         skip_undefined,
+                              const bool assert_mandatory_entries_are_found)
 {
-  PathSearch search("PARAMETERS");
+  std::filebuf fb;
+  if (fb.open(filename, std::ios::in))
+    {
+      std::istream is(&fb);
+      std::string file_ending = filename.substr(filename.find_last_of('.') + 1);
+      boost::algorithm::to_lower(file_ending);
+      if (file_ending == "prm")
+        parse_input(is, filename, last_line, skip_undefined);
+      else if (file_ending == "xml")
+        parse_input_from_xml(is, skip_undefined);
+      else if (file_ending == "json")
+        parse_input_from_json(is, skip_undefined);
+      else
+        AssertThrow(
+          false,
+          ExcMessage(
+            "Unknown input file. Supported types are .prm, .xml, and .json."));
+
+      fb.close();
+    }
+  else
+    {
+      AssertThrow(false,
+                  ExcMessage("Invalid filename " + filename +
+                             " provided. File does not exist."));
+    }
 
-  std::string   openname = search.find(filename);
-  std::ifstream file_stream(openname.c_str());
-  parse_input(file_stream, filename, last_line, skip_undefined);
+  if (assert_mandatory_entries_are_found)
+    assert_that_entries_have_been_set();
 }
 
 
diff --git a/tests/parameter_handler/parameter_handler_26.cc b/tests/parameter_handler/parameter_handler_26.cc
new file mode 100644 (file)
index 0000000..7d62d24
--- /dev/null
@@ -0,0 +1,103 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2019 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.
+//
+// ---------------------------------------------------------------------
+
+#include <deal.II/base/parameter_handler.h>
+
+#include <map>
+
+#include "../tests.h"
+
+void
+success()
+{
+  unsigned int dim       = 2;
+  std::string  precision = "double";
+
+  ParameterHandler prm;
+  prm.enter_subsection("General");
+  // this one does not have to be set
+  prm.add_parameter("dim",
+                    dim,
+                    "Number of space dimensions",
+                    Patterns::Integer(2, 3));
+  // this one has to be set
+  prm.declare_entry("Precision",
+                    precision,
+                    Patterns::Selection("float|double"),
+                    "Floating point precision",
+                    true);
+  prm.leave_subsection();
+
+  try
+    {
+      std::string source   = SOURCE_DIR;
+      std::string filename = source + "/prm/parameter_handler_26_success.json";
+      prm.parse_input(filename, "", true, true);
+    }
+  catch (std::exception &exc)
+    {
+      deallog << exc.what() << std::endl;
+    }
+
+  deallog << std::endl << "successful" << std::endl;
+}
+
+void
+fail()
+{
+  unsigned int dim       = 2;
+  std::string  precision = "double";
+
+  ParameterHandler prm;
+  prm.enter_subsection("General");
+  // both parameters have to be set
+  prm.add_parameter(
+    "dim", dim, "Number of space dimensions", Patterns::Integer(2, 3), true);
+  prm.add_parameter("Precision",
+                    precision,
+                    "Floating point precision",
+                    Patterns::Selection("float|double"),
+                    true);
+  prm.leave_subsection();
+
+  try
+    {
+      std::string source   = SOURCE_DIR;
+      std::string filename = source + "/prm/parameter_handler_26_fail.json";
+      prm.parse_input(filename, "", true, true);
+    }
+  catch (std::exception &exc)
+    {
+      deallog << exc.what() << std::endl;
+    }
+}
+
+
+int
+main()
+{
+  initlog();
+  deallog.get_file_stream().precision(3);
+
+  try
+    {
+      success();
+      fail();
+    }
+  catch (std::exception &exc)
+    {
+      deallog << exc.what() << std::endl;
+    }
+}
diff --git a/tests/parameter_handler/parameter_handler_26.output b/tests/parameter_handler/parameter_handler_26.output
new file mode 100644 (file)
index 0000000..e9c2284
--- /dev/null
@@ -0,0 +1,18 @@
+
+DEAL::
+DEAL::successful
+DEAL::
+--------------------------------------------------------
+An error occurred in file <parameter_handler.cc> in function
+    void dealii::ParameterHandler::assert_that_entries_have_been_set() const
+The violated condition was:
+    entries_wrongly_not_set.size() == 0
+Additional information:
+    Not all entries of the parameter handler that were declared with `has_to_be_set = true` have been set. The following parameters
+
+  General.Precision
+  General.dim
+
+ have not been set. A possible reason might be that you did not add these parameter to the input file or that their spelling is not correct.
+--------------------------------------------------------
+
index b1f7e0f6e6a5872b133eee07dc701d31fc82e157..fafe3c7f35a72e330effa54d8b6e0f000487452d 100644 (file)
@@ -15,7 +15,7 @@
 
 
 
-// check ParameterHandler::parse_input_from_xml
+// check ParameterHandler::parse_input_from_json
 
 #include <deal.II/base/parameter_handler.h>
 
diff --git a/tests/parameter_handler/parameter_handler_read_json_03.cc b/tests/parameter_handler/parameter_handler_read_json_03.cc
new file mode 100644 (file)
index 0000000..b411a87
--- /dev/null
@@ -0,0 +1,55 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2020 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 ParameterHandler::parse_input() for json file
+
+#include <deal.II/base/parameter_handler.h>
+
+#include "../tests.h"
+
+
+int
+main()
+{
+  initlog();
+
+  // default values
+  int int1 = 0;
+  int int2 = 0;
+  int int3 = 0;
+  int int4 = 0;
+
+  ParameterHandler prm;
+  prm.add_parameter("int1", int1);
+  prm.add_parameter("int2", int2);
+
+  prm.enter_subsection("dummy");
+  prm.add_parameter("int3", int3);
+  prm.add_parameter("int4", int4);
+  prm.leave_subsection();
+
+  std::string source   = SOURCE_DIR;
+  std::string filename = source + "/prm/parameter_handler_read_json_03.json";
+  prm.parse_input(filename, "", true, true);
+
+  AssertDimension(int1, 1);
+  AssertDimension(int2, 2);
+  AssertDimension(int3, 3);
+  AssertDimension(int4, 4);
+
+  return 0;
+}
diff --git a/tests/parameter_handler/parameter_handler_read_json_03.output b/tests/parameter_handler/parameter_handler_read_json_03.output
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/tests/parameter_handler/parameter_handler_read_prm_01.cc b/tests/parameter_handler/parameter_handler_read_prm_01.cc
new file mode 100644 (file)
index 0000000..f1b4942
--- /dev/null
@@ -0,0 +1,56 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2020 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 ParameterHandler::parse_input for prm file
+
+#include <deal.II/base/parameter_handler.h>
+
+#include "../tests.h"
+
+
+int
+main()
+{
+  initlog();
+
+  // default values
+  int int1 = 0;
+  int int2 = 0;
+  int int3 = 0;
+  int int4 = 0;
+
+  ParameterHandler prm;
+  prm.add_parameter("int1", int1);
+  prm.add_parameter("int2", int2);
+
+  prm.enter_subsection("dummy");
+  prm.add_parameter("int3", int3);
+  prm.add_parameter("int4", int4);
+  prm.leave_subsection();
+
+  // read from json
+  std::string source   = SOURCE_DIR;
+  std::string filename = source + "/prm/parameter_handler_read_prm_01.prm";
+  prm.parse_input(filename, "", true, true);
+
+  AssertDimension(int1, 1);
+  AssertDimension(int2, 2);
+  AssertDimension(int3, 3);
+  AssertDimension(int4, 4);
+
+  return 0;
+}
diff --git a/tests/parameter_handler/parameter_handler_read_prm_01.output b/tests/parameter_handler/parameter_handler_read_prm_01.output
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/tests/parameter_handler/parameter_handler_read_xml_01.cc b/tests/parameter_handler/parameter_handler_read_xml_01.cc
new file mode 100644 (file)
index 0000000..6e8db1a
--- /dev/null
@@ -0,0 +1,55 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2020 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 ParameterHandler::parse_input for xml file
+
+#include <deal.II/base/parameter_handler.h>
+
+#include "../tests.h"
+
+
+int
+main()
+{
+  initlog();
+
+  // default values
+  int int1 = 0;
+  int int2 = 0;
+  int int3 = 0;
+  int int4 = 0;
+
+  ParameterHandler prm;
+  prm.add_parameter("int1", int1);
+  prm.add_parameter("int2", int2);
+
+  prm.enter_subsection("dummy");
+  prm.add_parameter("int3", int3);
+  prm.add_parameter("int4", int4);
+  prm.leave_subsection();
+
+  std::string source   = SOURCE_DIR;
+  std::string filename = source + "/prm/parameter_handler_read_xml_01.xml";
+  prm.parse_input(filename, "", true, true);
+
+  AssertDimension(int1, 1);
+  AssertDimension(int2, 2);
+  AssertDimension(int3, 3);
+  AssertDimension(int4, 4);
+
+  return 0;
+}
diff --git a/tests/parameter_handler/parameter_handler_read_xml_01.output b/tests/parameter_handler/parameter_handler_read_xml_01.output
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/tests/parameter_handler/prm/parameter_handler_26_fail.json b/tests/parameter_handler/prm/parameter_handler_26_fail.json
new file mode 100644 (file)
index 0000000..bb26073
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "General": {
+  "Precison": "float"
+  }
+}
diff --git a/tests/parameter_handler/prm/parameter_handler_26_success.json b/tests/parameter_handler/prm/parameter_handler_26_success.json
new file mode 100644 (file)
index 0000000..2df3ba6
--- /dev/null
@@ -0,0 +1,5 @@
+{
+  "General": {
+  "Precision": "float"
+  }
+}
diff --git a/tests/parameter_handler/prm/parameter_handler_read_json_03.json b/tests/parameter_handler/prm/parameter_handler_read_json_03.json
new file mode 100644 (file)
index 0000000..0ed12e1
--- /dev/null
@@ -0,0 +1,8 @@
+{
+    "int1": {"value": 1},
+    "int2": 2,
+    "dummy" : {"int3" : 3, "int4" : 4},
+    "int5": {"value": 5},
+    "int6": 6,
+    "dummy2" : {"int7" : 7, "int8" : 8}
+}
\ No newline at end of file
diff --git a/tests/parameter_handler/prm/parameter_handler_read_prm_01.prm b/tests/parameter_handler/prm/parameter_handler_read_prm_01.prm
new file mode 100644 (file)
index 0000000..d8f2b89
--- /dev/null
@@ -0,0 +1,12 @@
+set int1 = 1
+set int2 = 2
+subsection dummy
+ set int3 = 3
+ set int4 = 4
+end
+set int5 = 5
+set int6 = 6
+subsection dummy2
+  set int7 = 7
+  set int8 = 8
+end
diff --git a/tests/parameter_handler/prm/parameter_handler_read_xml_01.xml b/tests/parameter_handler/prm/parameter_handler_read_xml_01.xml
new file mode 100644 (file)
index 0000000..79d929f
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ParameterHandler>
+<int1><value>1</value></int1>
+<int2><value>2</value></int2>
+  <dummy>
+    <int3><value>3</value></int3>
+    <int4><value>4</value></int4>
+  </dummy>
+<int5><value>5</value></int5>
+<int6><value>6</value></int6>
+  <dummy2>
+    <int7><value>7</value></int7>
+    <int8><value>8</value></int8>
+  </dummy2>
+</ParameterHandler>

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.