From: Luca Heltai Date: Wed, 20 Sep 2017 15:04:15 +0000 (+0200) Subject: Added default prm to add_parameter(). X-Git-Tag: v9.0.0-rc1~1033^2~1 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d1529b0fb0e34a987d2ef1bd31ba336ee89a3a0;p=dealii.git Added default prm to add_parameter(). --- diff --git a/include/deal.II/base/parameter_acceptor.h b/include/deal.II/base/parameter_acceptor.h index 78b5814df1..334cfb5b48 100644 --- a/include/deal.II/base/parameter_acceptor.h +++ b/include/deal.II/base/parameter_acceptor.h @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2014 - 2016 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // @@ -36,11 +36,12 @@ DEAL_II_NAMESPACE_OPEN * The basic interface provides two subscription mechanisms: a **global * subscription mechanism** and a **local subscription mechanism**. * - * The global subscription mechanism is such that whenever a class that was - * derived by ParameterAcceptor is constructed, a static registry - * (ParameterAcceptor::class_list) in the base class is updated with a pointer - * to the derived class, and a path in the parameter file. Such registry is - * traversed upon invocation of the single function + * The global subscription mechanism is such that whenever an object of a class + * derived from ParameterAcceptor is created, then a pointer to that + * object-of-derived-type is registered, together with a path in the parameter + * file. + * + * Such registry is traversed upon invocation of the single function * ParameterAcceptor::initialize(file.prm) which in turn calls the method * ParameterAcceptor::declare_parameters() for each of the registered classes, * reads the file `file.prm` and subsequently calls the method @@ -60,9 +61,10 @@ DEAL_II_NAMESPACE_OPEN * any of the virtual methods of this class. * * If some post processing is required on the parsed values, the user can - * attach a signal to ParameterAcceptor::parse_parameters_call_back can be - * overridden, which is called just after the parse_parameters() function of - * each class. + * attach a signal to ParameterAcceptor::declare_parameters_call_back and + * ParameterAcceptor::parse_parameters_call_back, that are called just after + * the declare_parameters() and parse_parameters() functions of each derived + * class. * * A typical usage of this class is the following: * @@ -74,8 +76,8 @@ DEAL_II_NAMESPACE_OPEN * // which defines the section name where the parameters of MyClass * // will be stored. * - * MyClass(std::string name) : - * ParameterAcceptor(name) + * MyClass() : + * ParameterAcceptor("Some class name") * { * add_parameter("A param", member_var); * } @@ -86,7 +88,7 @@ DEAL_II_NAMESPACE_OPEN * }; * * int main() { - * // Make sure you build your class BEFORE calling + * // Make sure you create your object BEFORE calling * // ParameterAcceptor::initialize() * MyClass class; * @@ -101,12 +103,12 @@ DEAL_II_NAMESPACE_OPEN * * @code * // Again your own class, derived from ParameterAcceptor + * // + * // If you don't pass anything to the constructor of + * // ParameterAcceptor, then the class name is used, "MyClass" + * // in this case * class MyClass : public ParameterAcceptor { * - * MyClass(std::string name) : - * ParameterAcceptor(name) - * {} - * * virtual void declare_parameters(ParameterHandler &prm) { * ... * } @@ -117,7 +119,7 @@ DEAL_II_NAMESPACE_OPEN * }; * * int main() { - * // Make sure you build your class BEFORE calling + * // Make sure you create your object BEFORE calling * // ParameterAcceptor::initialize() * MyClass class; * ParameterAcceptor::initialize("file.prm"); @@ -144,7 +146,7 @@ DEAL_II_NAMESPACE_OPEN * end * @endcode * - * In the following examles, we propose some use cases with increasing + * In the following examples, we propose some use cases with increasing * complexities. * * MyClass is derived from ParameterAcceptor and has a @@ -152,11 +154,11 @@ DEAL_II_NAMESPACE_OPEN * @code * class MyClass : public ParameterAcceptor * { - * MyClass (std::string name); - * virtual void declare_parameters(ParameterHandler &prm); - * private: - * SomeParsedClass my_subclass; - * ... + * MyClass (std::string name); + * virtual void declare_parameters(ParameterHandler &prm); + * private: + * SomeParsedClass my_subclass; + * ... * }; * * MyClass::MyClass(std::string name) @@ -167,16 +169,15 @@ DEAL_II_NAMESPACE_OPEN * * void MyClass::declare_parmeters(ParameterHandler &prm) * { - * // many add_parameter(...); + * // many add_parameter(...); * } * * ... * * int main() * { - * MyClass mc("My Class"); - * - * ParameterAcceptor::initialize("file.prm"); + * MyClass mc("My Class"); + * ParameterAcceptor::initialize("file.prm"); * } * @endcode * @@ -189,15 +190,14 @@ DEAL_II_NAMESPACE_OPEN * ... #all the parameters of MyClass defined in declare_parameters * end * @endcode - * Note that the sections are alphabetically sorted. * * Now suppose that in the main file we need two or more objects of MyClass * @code * int main() * { - * MyClass ca("Class A"); - * MyClass cb("Class B"); - * ParameterAcceptor::initialize("file.prm"); + * MyClass ca("Class A"); + * MyClass cb("Class B"); + * ParameterAcceptor::initialize("file.prm"); * } * @endcode * @@ -215,7 +215,7 @@ DEAL_II_NAMESPACE_OPEN * @endcode * Note that there is only one section "Forcing term", this is because * both objects have defined the same name for the section of their - * SomeParsedClass. There are two strategies to manage this issue. The + * SomeParsedClass. There are two strategies to change this behaviour. The * first one (not recommended) would be to change the name of the section * of SomeParsedClass such that it contains also the string passed to * the constructor of MyClass: @@ -232,9 +232,9 @@ DEAL_II_NAMESPACE_OPEN * @code * int main() * { - * MyClass ca("/Class A/Class"); - * MyClass cb("/Class B/Class"); - * ParameterAcceptor::initialize("file.prm"); + * MyClass ca("/Class A/Class"); + * MyClass cb("/Class B/Class"); + * ParameterAcceptor::initialize("file.prm"); * } * @endcode * Now, in the parameter file we can find @@ -256,21 +256,22 @@ DEAL_II_NAMESPACE_OPEN * end * end * @endcode + * * Note the "/" at the begin of the string name. This is interpreted by - * ParameterAcceptor like the root folder in Unix systems. This means - * that the sections "Class A" and "Class B" will not be nested under any - * section. On the other hand, if the string does not begin with a "/" - * as in the previous cases (and for the ParsedFunction also in this last - * example) the section will be created **under the current path**, which - * depends on the previously defined sections/subsections/subsubsections. - * Indeed, the section "Forcing term" is nested under "Class A" or "Class B". - * To make things more clear. let's consider the following two examples + * ParameterAcceptor like the root folder in Unix systems. The sections "Class + * A" and "Class B" will not be nested under any section. On the other hand, if + * the string does not begin with a "/" as in the previous cases the section + * will be created **under the current path**, which depends on the previously + * defined sections/subsections/subsubsections. Indeed, the section "Forcing + * term" is nested under "Class A" or "Class B". To make things more clear. + * let's consider the following two examples + * * @code * int main() * { - * MyClass ca("/Class A/Class"); - * MyClass cb("Class B/Class"); - * ParameterAcceptor::initialize("file.prm"); + * MyClass ca("/Class A/Class"); + * MyClass cb("Class B/Class"); + * ParameterAcceptor::initialize("file.prm"); * } * @endcode * The parameter file will have the following structure @@ -294,15 +295,14 @@ DEAL_II_NAMESPACE_OPEN * @endcode * * If instead one of the paths ends with "/" instead of just - * a name of the class, subsequent classes will be declared - * under the full path, as if the class name should be interpreted - * as a directory: + * a name of the class, subsequent classes will interpret this as + * a full path, interpreting the class name as a directory name: * @code * int main() * { - * MyClass ca("/Class A/Class/"); - * MyClass cb("Class B/Class"); - * ParameterAcceptor::initialize("file.prm"); + * MyClass ca("/Class A/Class/"); + * MyClass cb("Class B/Class"); + * ParameterAcceptor::initialize("file.prm"); * } * @endcode * The parameter file will have the following structure @@ -327,7 +327,8 @@ DEAL_II_NAMESPACE_OPEN * * As a final remark, in order to allow a proper management of all the * sections/subsections, the instantiation of objects and the call to - * ParameterAcceptor::initialize() **cannot be done in multithread**. + * ParameterAcceptor::initialize() cannot be done on multiple, concurrently + * running threads. * * If you pass an empty name, the boost::core::demangle() function is used to * fill the section name with a human readable version of the class name @@ -344,23 +345,30 @@ public: * parameters in the given section, otherwise a pretty printed * version of the derived class is used. */ - ParameterAcceptor(const std::string section_name=""); + ParameterAcceptor(const std::string §ion_name=""); /** - * The destructor sets to zero the pointer relative to this index, - * so that it is safe to destroy the mother class. + * Destructor. */ virtual ~ParameterAcceptor(); /** - * Call declare_all_parameters(), read filename (if it is present as input - * parameter) and parse_all_parameters() on the static member prm. If - * outfilename is not the emtpy string, then write the content that was read - * in to the outfilename. The format of both input and output files are + * Call declare_all_parameters(), read the parameters from `filename` (only + * if `filename` is a non-empty string), and then call + * parse_all_parameters(). + * + * If the parameter `filename` is the empty string, then no attempt to read a + * parameter file is done. This may be useful if you are ok with using + * default values, and don't want to read external files to use a class + * derived from ParameterAcceptor. + * + * If outfilename is not the emtpy string, then write the content that was + * read in to the outfilename. The format of both input and output files are * selected using the extensions of the files themselves. This can be either - * `prm` or `xml`. If the output format is `prm`, then the - * `output_style_for_prm_format` is used to decide wether we write the full - * documentation as well, or only the parameters. + * `prm` or `xml` for input, and `prm`, `xml`, or `tex/latex` for output. If + * the output format is `prm`, then `output_style_for_prm_format` is used to + * decide wether we write the full documentation as well, or only the + * parameters. * * If the input file does not exist, a default one with the same name is created * for you, and an exception is thrown. @@ -369,8 +377,8 @@ public: * @param output_filename Output file name * @param output_style_for_prm_format How to write the output file if format is `prm` */ - static void initialize(const std::string filename, - const std::string output_filename="", + static void initialize(const std::string &filename="", + const std::string &output_filename="", const ParameterHandler::OutputStyle output_style_for_prm_format=ParameterHandler::ShortText); /** @@ -379,34 +387,35 @@ public: static void clear(); /** - * Declare parameter entries of the derived class. + * Derived classes can use this method to declare their parameters. + * ParameterAcceptor::initialize() calls it for each derived class. The + * default implementation is empty. */ virtual void declare_parameters(ParameterHandler &prm); /** - * Declare parameter call back. This function is called at the end of - * declare_all_parameters, to allow users to process their parameters right - * after they have been parsed. The default implementation is empty. - * - * You can use this function, for example, to create a quadrature - * rule after you have read how many quadrature points you wanted - * to use from the parameter file. + * Declare parameter call back. This signal is triggered right after + * declare_parameters() has been called, to allow users to prepare their + * variables right after parameters have been decalred. The default + * implementation is empty. */ boost::signals2::signal declare_parameters_call_back; /** - * Parse the (derived class) parameters. + * Derived classes can use this method to parse their parameters. + * ParameterAcceptor::initialize() calls it for each derived class. The + * default implementation is empty. */ virtual void parse_parameters(ParameterHandler &prm); /** * Parse parameter call back. This function is called at the end of - * parse_all_parameters, to allow users to process their parameters right - * after they have been parsed. The default implementation is empty. + * parse_parameters(), to allow users to process their parameters right after + * they have been parsed. The default implementation is empty. * - * You can use this function, for example, to create a quadrature - * rule after you have read how many quadrature points you wanted - * to use from the parameter file. + * You can use this function, for example, to create a quadrature rule after + * you have read how many quadrature points you wanted to use from the + * parameter file. */ boost::signals2::signal parse_parameters_call_back; @@ -417,13 +426,6 @@ public: */ static void parse_all_parameters(ParameterHandler &prm=ParameterAcceptor::prm); - - /** - * Print information to deallog about all stored classes. - */ - static void log_info(); - - /** * Initialize the global ParameterHandler with all derived classes * parameters.This function enters the subsection returned by @@ -432,24 +434,24 @@ public: */ static void declare_all_parameters(ParameterHandler &prm=ParameterAcceptor::prm); - /** * Return the section name of this class. If a name was provided * at construction time, then that name is returned, otherwise it - * returns the name of this class, pretty printed. + * returns the demangled name of this class. */ std::string get_section_name() const; /** - * Travers all registered classes, and figure out what - * subsections we need to enter. + * Traverse all registered classes, and figure out what subsections we need to + * enter. */ std::vector get_section_path() const; /** * Add a parameter in the correct path. This method forwards all arguments to - * the ParameterHandler::add_parameter() method, after entering the correct - * section path. + * the prm.add_parameter() method, after entering the correct section path. + * By default it uses the ParameterAcceptor::prm variable as + * ParameterHandler. * * See the documentation of ParameterHandler::add_parameter() for more * information. @@ -458,6 +460,7 @@ public: void add_parameter(const std::string &entry, ParameterType ¶meter, const std::string &documentation = std::string(), + ParameterHandler &prm = ParameterAcceptor::prm, const Patterns::PatternBase &pattern = *Patterns::Tools::Convert::to_pattern()); @@ -468,13 +471,13 @@ public: private: /** - * Make sure we enter the right subsection of the global parameter file. + * Make sure we enter the right subsection of the given parameter. */ void enter_my_subsection(ParameterHandler &prm); /** * This function undoes what the enter_my_subsection() function did. It only - * makes sense if enter_my_subsection() is called before this one. + * makes sense if enter_my_subsection() was called on `prm` before this one. */ void leave_my_subsection(ParameterHandler &prm); @@ -488,7 +491,7 @@ private: const unsigned int acceptor_id; /** - * Separator between section and subsection. + * Separator between sections. */ static const char sep = '/'; @@ -498,11 +501,13 @@ protected: }; + // Inline and template functions template void ParameterAcceptor::add_parameter(const std::string &entry, ParameterType ¶meter, const std::string &documentation, + ParameterHandler &prm, const Patterns::PatternBase &pattern) { enter_my_subsection(prm); @@ -511,6 +516,7 @@ void ParameterAcceptor::add_parameter(const std::string &entry, } + DEAL_II_NAMESPACE_CLOSE #endif diff --git a/source/base/parameter_acceptor.cc b/source/base/parameter_acceptor.cc index 9e28e7474c..105ef2fa86 100644 --- a/source/base/parameter_acceptor.cc +++ b/source/base/parameter_acceptor.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 - 2016 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // @@ -28,7 +28,7 @@ std::vector > ParameterAcceptor::class_list; // Static parameter handler ParameterHandler ParameterAcceptor::prm; -ParameterAcceptor::ParameterAcceptor(const std::string name) : +ParameterAcceptor::ParameterAcceptor(const std::string &name) : acceptor_id(class_list.size()), section_name(name) { @@ -49,49 +49,50 @@ std::string ParameterAcceptor::get_section_name() const void -ParameterAcceptor::initialize(const std::string filename, - const std::string output_filename, +ParameterAcceptor::initialize(const std::string &filename, + const std::string &output_filename, const ParameterHandler::OutputStyle output_style_for_prm_format) { declare_all_parameters(); - // check the extension of input file - if (filename.substr(filename.find_last_of(".") + 1) == "prm") + if (filename != "") { - try + // check the extension of input file + if (filename.substr(filename.find_last_of(".") + 1) == "prm") { - prm.parse_input(filename); + try + { + prm.parse_input(filename); + } + catch (dealii::PathSearch::ExcFileNotFound) + { + std::ofstream out(filename); + Assert(out, ExcIO()); + prm.print_parameters(out, ParameterHandler::Text); + out.close(); + AssertThrow(false, ExcMessage("You specified <"+filename+"> as input "+ + "parameter file, but it does not exist. " + + "We created it for you.")); + } } - catch (dealii::PathSearch::ExcFileNotFound) + else if (filename.substr(filename.find_last_of(".") + 1) == "xml") { - std::ofstream out(filename); - Assert(out, ExcIO()); - prm.print_parameters(out, ParameterHandler::Text); - out.close(); - AssertThrow(false, ExcMessage("You specified "+filename+" as input "+ - "parameter file, but it does not exist. " + - "We created one for you.")); + std::ifstream is(filename); + if (!is) + { + std::ofstream out(filename); + Assert(out, ExcIO()); + prm.print_parameters(out, ParameterHandler::XML); + out.close(); + AssertThrow(false, ExcMessage("You specified <"+filename+"> as input "+ + "parameter file, but it does not exist. " + + "We created it for you.")); + } + prm.parse_input_from_xml(is); } + else + AssertThrow(false, ExcMessage("Invalid extension of parameter file. Please use .prm or .xml")); } - else if (filename.substr(filename.find_last_of(".") + 1) == "xml") - { - std::ifstream is(filename); - if (!is) - { - std::ofstream out(filename); - Assert(out, ExcIO()); - prm.print_parameters(out, ParameterHandler::XML); - out.close(); - is.clear(); - AssertThrow(false, ExcMessage("You specified "+filename+" as input "+ - "parameter file, but it does not exist. " + - "We created one for you.")); - } - prm.parse_input_from_xml(is); - } - else - AssertThrow(false, ExcMessage("Invalid extension of parameter file. Please use .prm or .xml")); - parse_all_parameters(); if (output_filename != "") { std::ofstream outfile(output_filename.c_str()); @@ -115,6 +116,9 @@ ParameterAcceptor::initialize(const std::string filename, else AssertThrow(false,ExcNotImplemented()); } + + // Finally do the parsing. + parse_all_parameters(); } void @@ -136,21 +140,6 @@ void ParameterAcceptor::parse_parameters(ParameterHandler &prm) -void -ParameterAcceptor::log_info() -{ - deallog.push("ParameterAcceptor"); - for (unsigned int i=0; iget_section_name() << std::endl; - else - deallog << " NULL" << std::endl; - } - deallog.pop(); -} - void ParameterAcceptor::parse_all_parameters(ParameterHandler &prm) { for (unsigned int i=0; i< class_list.size(); ++i) @@ -180,17 +169,20 @@ std::vector ParameterAcceptor::get_section_path() const { Assert(acceptor_id < class_list.size(), ExcInternalError()); - auto my_section_name = get_section_name(); - bool is_absolute = my_section_name.front() == sep; + const auto my_section_name = get_section_name(); + const bool is_absolute = (my_section_name.front() == sep); std::vector sections = Utilities::split_string_list(my_section_name, sep); + // Split string list removes trailing empty strings, but not + // preceeding ones. Make sure that if we had an absolute path, + // we don't store as first section the empty string. if (is_absolute) sections.erase(sections.begin()); else { - // If we want a relative path, we prepend the path of the previous class + // If we have a relative path, we prepend the path of the previous class // to ours. This is tricky. If the previous class has a path with a // trailing /, then the full path is used, else only the path except the // last one @@ -201,7 +193,7 @@ ParameterAcceptor::get_section_path() const auto previous_path = class_list[i]->get_section_path(); // See if we need to remove last piece of the path - if (previous_path.size() >= 1 && has_trailing == false) + if ( (previous_path.size() > 0) && has_trailing == false) previous_path.resize(previous_path.size()-1); sections.insert(sections.begin(), previous_path.begin(), previous_path.end()); @@ -214,7 +206,7 @@ ParameterAcceptor::get_section_path() const void ParameterAcceptor::enter_my_subsection(ParameterHandler &prm=ParameterAcceptor::prm) { - std::vector sections = get_section_path(); + const auto sections = get_section_path(); for (auto sec : sections) { prm.enter_subsection(sec); @@ -223,7 +215,7 @@ void ParameterAcceptor::enter_my_subsection(ParameterHandler &prm=ParameterAccep void ParameterAcceptor::leave_my_subsection(ParameterHandler &prm=ParameterAcceptor::prm) { - std::vector sections = get_section_path(); + const auto sections = get_section_path(); for (auto sec : sections) { prm.leave_subsection(); diff --git a/tests/parameter_handler/parameter_acceptor_01.cc b/tests/parameter_handler/parameter_acceptor_01.cc index 2abeb978be..bef25c877b 100644 --- a/tests/parameter_handler/parameter_acceptor_01.cc +++ b/tests/parameter_handler/parameter_acceptor_01.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_02.cc b/tests/parameter_handler/parameter_acceptor_02.cc index 7f3ecbe2cd..c7e8a3a5af 100644 --- a/tests/parameter_handler/parameter_acceptor_02.cc +++ b/tests/parameter_handler/parameter_acceptor_02.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_03.cc b/tests/parameter_handler/parameter_acceptor_03.cc index 92a4348852..4e4dd8c6c2 100644 --- a/tests/parameter_handler/parameter_acceptor_03.cc +++ b/tests/parameter_handler/parameter_acceptor_03.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_04.cc b/tests/parameter_handler/parameter_acceptor_04.cc index 03438c0d06..8dd629dca9 100644 --- a/tests/parameter_handler/parameter_acceptor_04.cc +++ b/tests/parameter_handler/parameter_acceptor_04.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_05.cc b/tests/parameter_handler/parameter_acceptor_05.cc index ae91c331ab..b8c023e654 100644 --- a/tests/parameter_handler/parameter_acceptor_05.cc +++ b/tests/parameter_handler/parameter_acceptor_05.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_06.cc b/tests/parameter_handler/parameter_acceptor_06.cc index 5353ae0b04..6b348ef63a 100644 --- a/tests/parameter_handler/parameter_acceptor_06.cc +++ b/tests/parameter_handler/parameter_acceptor_06.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_07.cc b/tests/parameter_handler/parameter_acceptor_07.cc index acda6cd341..a9e5d1689d 100644 --- a/tests/parameter_handler/parameter_acceptor_07.cc +++ b/tests/parameter_handler/parameter_acceptor_07.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. // diff --git a/tests/parameter_handler/parameter_acceptor_08.cc b/tests/parameter_handler/parameter_acceptor_08.cc index bf869581cc..4dc7f3bb5f 100644 --- a/tests/parameter_handler/parameter_acceptor_08.cc +++ b/tests/parameter_handler/parameter_acceptor_08.cc @@ -1,6 +1,6 @@ //----------------------------------------------------------- // -// Copyright (C) 2015 by the deal.II authors +// Copyright (C) 2017 by the deal.II authors // // This file is part of the deal.II library. //