]> https://gitweb.dealii.org/ - dealii.git/commitdiff
ParameterAcceptor::enter/leave_subsection()
authorLuca Heltai <luca.heltai@sissa.it>
Tue, 12 Jan 2021 22:44:50 +0000 (23:44 +0100)
committerLuca Heltai <luca.heltai@sissa.it>
Tue, 12 Jan 2021 22:44:50 +0000 (23:44 +0100)
doc/news/changes/minor/20210112LucaHeltai [new file with mode: 0644]
include/deal.II/base/parameter_acceptor.h
source/base/parameter_acceptor.cc
tests/parameter_handler/parameter_acceptor_10.cc [new file with mode: 0644]
tests/parameter_handler/parameter_acceptor_10.output [new file with mode: 0644]

diff --git a/doc/news/changes/minor/20210112LucaHeltai b/doc/news/changes/minor/20210112LucaHeltai
new file mode 100644 (file)
index 0000000..64ab70b
--- /dev/null
@@ -0,0 +1,5 @@
+New: Created two new methods ParameterAcceptor::enter_subsection() and
+ParameterAcceptor::leave_subsection() that allow more intricated parameter 
+paths within ParameterAcceptor classes.
+<br>
+(Luca Heltai, 2021/01/12)
index 79693c1f9b47f3536b4de8d281b35873651faf91..51653b9f3aa68dd1f16518a3dc3b81b5ee42b897 100644 (file)
@@ -516,6 +516,67 @@ public:
    */
   static ParameterHandler prm;
 
+  /**
+   * Add the given @p subsection to the global path stored in this class.
+   *
+   * This function changes the behaviour of enter_my_subsection(), by
+   * appending a new subsection to the path stored in this class.
+   *
+   * This method can be used to split the parameters of this class into
+   * subsections, while still maintaining the general behaviour of this
+   * class.
+   *
+   * An example usage is given by the following snippet:
+   * @code
+   * class MyClass : public ParameterAcceptor
+   * {
+   *   MyClass()
+   *     : ParameterAcceptor("Main section")
+   *   {
+   *     add_parameter("A param", member_var);
+   *     enter_subsection("New section");
+   *     add_parameter("Another param", another_member_var);
+   *     leave_subsection();
+   *   }
+   *
+   * private:
+   *   std::vector<unsigned int> member_var = {1,2};
+   *   std::map<types::boundary_id, std::string> another_member_var;
+   *   ...
+   * };
+   *
+   * int main()
+   * {
+   *   // ParameterAcceptor::initialize()
+   *   MyClass class;
+   *
+   *   // With this call, all derived classes will have their
+   *   // parameters initialized
+   *   ParameterAcceptor::initialize("file.prm");
+   * }
+   * @endcode
+   *
+   * which will produce a parameter file organized as
+   *
+   * @code
+   * subsection Main section
+   *   set A param = 1, 2
+   *   subsection New section
+   *     set Another param =
+   *   end
+   * end
+   * @endcode
+   */
+  void
+  enter_subsection(const std::string &subsection);
+
+  /**
+   * Leave the subsection that was entered by calling the enter_subsection()
+   * function.
+   */
+  void
+  leave_subsection();
+
   /**
    * Make sure we enter the right subsection of the given parameter.
    */
@@ -547,6 +608,9 @@ private:
 protected:
   /** The subsection name for this class. */
   const std::string section_name;
+
+  /** The subsubsections that are currently active. */
+  std::vector<std::string> subsections;
 };
 
 
index 063849be274e681b978546800e4560dfd48ac7f9..1dfbcfb8a9727d1a386a8bae6380158faeb85c78 100644 (file)
@@ -39,11 +39,14 @@ ParameterAcceptor::ParameterAcceptor(const std::string &name)
 }
 
 
+
 ParameterAcceptor::~ParameterAcceptor()
 {
   class_list[acceptor_id] = nullptr;
 }
 
+
+
 std::string
 ParameterAcceptor::get_section_name() const
 {
@@ -52,6 +55,7 @@ ParameterAcceptor::get_section_name() const
 }
 
 
+
 void
 ParameterAcceptor::initialize(
   const std::string &                 filename,
@@ -96,6 +100,8 @@ ParameterAcceptor::initialize(std::istream &input_stream, ParameterHandler &prm)
   parse_all_parameters(prm);
 }
 
+
+
 void
 ParameterAcceptor::clear()
 {
@@ -130,6 +136,8 @@ ParameterAcceptor::parse_all_parameters(ParameterHandler &prm)
       }
 }
 
+
+
 void
 ParameterAcceptor::declare_all_parameters(ParameterHandler &prm)
 {
@@ -144,6 +152,7 @@ ParameterAcceptor::declare_all_parameters(ParameterHandler &prm)
 }
 
 
+
 std::vector<std::string>
 ParameterAcceptor::get_section_path() const
 {
@@ -182,9 +191,37 @@ ParameterAcceptor::get_section_path() const
             break;
           }
     }
+  // Finally, insert the remaining subsections
+  sections.insert(sections.end(), subsections.begin(), subsections.end());
   return sections;
 }
 
+
+
+void
+ParameterAcceptor::enter_subsection(const std::string &subsection)
+{
+  AssertThrow(subsection.find(sep) == std::string::npos,
+              ExcMessage(
+                "A subsection name cannot contain the special character '/'"));
+  // First the easy case.
+  if (subsection == "")
+    return;
+  subsections.push_back(subsection);
+}
+
+
+
+void
+ParameterAcceptor::leave_subsection()
+{
+  AssertThrow(subsections.size() > 0,
+              ExcMessage("There is no subsection to leave here."));
+  subsections.pop_back();
+}
+
+
+
 void
 ParameterAcceptor::enter_my_subsection(
   ParameterHandler &prm = ParameterAcceptor::prm)
@@ -196,6 +233,8 @@ ParameterAcceptor::enter_my_subsection(
     }
 }
 
+
+
 void
 ParameterAcceptor::leave_my_subsection(
   ParameterHandler &prm = ParameterAcceptor::prm)
@@ -207,6 +246,4 @@ ParameterAcceptor::leave_my_subsection(
     }
 }
 
-
-
 DEAL_II_NAMESPACE_CLOSE
diff --git a/tests/parameter_handler/parameter_acceptor_10.cc b/tests/parameter_handler/parameter_acceptor_10.cc
new file mode 100644 (file)
index 0000000..e1a9aa1
--- /dev/null
@@ -0,0 +1,81 @@
+//-----------------------------------------------------------
+//
+//    Copyright (C) 2017 - 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.
+//
+//-----------------------------------------------------------
+
+
+// Test subsectioning within parameter acceptor itself
+
+#include <deal.II/base/parameter_acceptor.h>
+#include <deal.II/base/path_search.h>
+
+#include "../tests.h"
+
+class Test : public ParameterAcceptor
+{
+public:
+  Test(const std::string &sec_name        = "First Class",
+       const std::string &par_name        = "Parameter name",
+       const std::string &par_value       = "Parameter value",
+       const std::string &subsection_name = "")
+    : ParameterAcceptor(sec_name)
+    , par_name(par_name)
+    , par_value(par_value)
+  {
+    if (subsection_name != "")
+      enter_subsection(subsection_name);
+    add_parameter(par_name, this->par_value);
+    if (subsection_name != "")
+      leave_subsection();
+
+    deallog << "Section Name    : " << sec_name << std::endl;
+    deallog << "N sections      : " << get_section_path().size() << std::endl;
+    deallog << "Sections        : ";
+    for (auto s : get_section_path())
+      deallog << "\"" << s << "\"    ";
+    deallog << std::endl << std::endl;
+  };
+
+private:
+  std::string par_name;
+  std::string par_value;
+  std::string subsection_name;
+};
+
+int
+main()
+{
+  initlog();
+  auto &prm = ParameterAcceptor::prm;
+
+  // Relative, no subsections
+  Test a("Class A", "Parameter A", "a");
+
+  // Relative, with subsection
+  Test c("Class B", "Parameter C", "c", "Subsection B");
+
+  // Explicit, with absolute path
+  Test d1("/Class D/Class D1", "Parameter D1", "d");
+
+  // Relative to previous, with trailing
+  Test d2("Class D2/", "Parameter D2", "d");
+
+  // Relative to previous
+  Test d3("Class D2D3", "Parameter D2D3", "e");
+
+  // Relative to previous, with subsection
+  Test d4("Class D2D3", "Parameter D2D3", "e", "Subsection D2D3");
+
+  ParameterAcceptor::declare_all_parameters();
+  prm.log_parameters(deallog);
+}
diff --git a/tests/parameter_handler/parameter_acceptor_10.output b/tests/parameter_handler/parameter_acceptor_10.output
new file mode 100644 (file)
index 0000000..5d9711e
--- /dev/null
@@ -0,0 +1,31 @@
+
+DEAL::Section Name    : Class A
+DEAL::N sections      : 1
+DEAL::Sections        : "Class A"    
+DEAL::
+DEAL::Section Name    : Class B
+DEAL::N sections      : 1
+DEAL::Sections        : "Class B"    
+DEAL::
+DEAL::Section Name    : /Class D/Class D1
+DEAL::N sections      : 2
+DEAL::Sections        : "Class D"    "Class D1"    
+DEAL::
+DEAL::Section Name    : Class D2/
+DEAL::N sections      : 2
+DEAL::Sections        : "Class D"    "Class D2"    
+DEAL::
+DEAL::Section Name    : Class D2D3
+DEAL::N sections      : 3
+DEAL::Sections        : "Class D"    "Class D2"    "Class D2D3"    
+DEAL::
+DEAL::Section Name    : Class D2D3
+DEAL::N sections      : 3
+DEAL::Sections        : "Class D"    "Class D2"    "Class D2D3"    
+DEAL::
+DEAL:parameters:Class A::Parameter A: a
+DEAL:parameters:Class B:Subsection B::Parameter C: c
+DEAL:parameters:Class D:Class D1::Parameter D1: d
+DEAL:parameters:Class D:Class D2::Parameter D2: d
+DEAL:parameters:Class D:Class D2:Class D2D3::Parameter D2D3: e
+DEAL:parameters:Class D:Class D2:Class D2D3:Subsection D2D3::Parameter D2D3: e

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.