--- /dev/null
+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)
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
#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>
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();
}
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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;
+ }
+}
--- /dev/null
+
+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.
+--------------------------------------------------------
+
-// check ParameterHandler::parse_input_from_xml
+// check ParameterHandler::parse_input_from_json
#include <deal.II/base/parameter_handler.h>
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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;
+}
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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;
+}
--- /dev/null
+// ---------------------------------------------------------------------
+//
+// 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;
+}
--- /dev/null
+{
+ "General": {
+ "Precison": "float"
+ }
+}
--- /dev/null
+{
+ "General": {
+ "Precision": "float"
+ }
+}
--- /dev/null
+{
+ "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
--- /dev/null
+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
--- /dev/null
+<?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>