-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
"http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<p>
When writing a numerical program you will usually wish to keep it flexible
with regard to parameter settings and the like. Rewriting a program
-everytime a parameter changes is ever so annoying.
+every time a parameter changes is ever so annoying.
For this reason <acronym>deal.II</acronym> provides a class
called <code>ParameterHandler</code>. This class enables you to easily
parse a parameter file and extract the values of the parameters.
The names and allowed values of the parameters can be defined by you.
</p>
+<h2>Introducing parameters into your code</h2>
+
+<h3>Introduction - the most simple case</h3>
<p>
-The way to using runtime parameters in your program is the following:
+The most simple way to using runtime parameters in your program is the following:
</p>
<table>
<td><code>ParameterHandler prm;</code>
</td>
</tr>
+<tr>
+ <td>3.</td>
+ <td>Tell the parameter handler about the parameters, their types and their
+ default values. Here we get one parameter called
+ "My favourite booze", its default value is
+ "Stout" and we allow anything as its value. Note that
+ the parameter name may contain whitespace.
+ </td>
+ <td><code>prm.declare_entry("My favourite booze",
+ "Stout",Patterns::Anything());
+ </code>
+ </td>
+</tr>
+<tr>
+ <td>4.</td>
+ <td>Generate a parameter file. Following the example above, we
+ set "My favourite booze" to "Ale". This
+ file will be called "parameters.in".
+ </td>
+ <td><code>set My favourite booze = Ale</code>
+ </td>
+</tr>
+<tr>
+ <td>5.</td>
+ <td>Read the parameters from the file.
+ </td>
+ <td><code>prm.read_input("parameters.in");</code>
+ </td>
+</tr>
+<tr>
+ <td>6.</td>
+ <td>Find the values of your parameters.
+ </td>
+ <td><code>string booze = prm.get("My favourite booze");</code>
+ </td>
+</tr>
</table>
+<p>
+The few steps outlined above are indeed the most simple case. What, now, if
+you have a more complex set of parameters, grouped by purpose ? You could,
+for example, wish to solve different equations and set parameters for each
+of them. For this purpose you can introduce <em>subsections</em> into
+your parameter set.
+</p>
+
+<h3>Subsections</h3>
+
+<p>
+Parameters declared in different subsections are distinct, although they
+may share the same name. Let us stay with the example of two equations
+for which you wish to set parameters: <code>Zeldovich-equation</code> and
+<code>Sunyaev-equation</code>. You want to be able to use different solvers,
+and thus both take a parameter called <code>Solver</code>.
+The way to go is to declare two subsections called (preferably)
+<code>Zeldovich-equation</code> and <code>Sunyaev-equation</code>. Each of the two
+subsections contains a parameter called <code>Solver</code>.
+</p>
+
<p class=example>
<span class=example>Example:</span>
-We enable a program, that is, the class TestCases that really handles
-everything to read parameters from a file given on the command line.
-Everything that is not strictly relevant to parameter input has been cut out.
+We declare subsections for two equations called
+Zeldovich-equation and Sunyaev-equation
+within a parameter handler.
+The allowed values for the parameter <code>Solver</code> are
+<code>CG</code> (default) and <code>GMRES</code>. Afterwards
+we read the settings from a file called "parameters.in"
+and retrieve their values. The values are stored in the strings
+<code>zeldovich_solver</code> and <code>sunyaev_solver</code>.
+Please note that in order to stick to the essentials this example
+violates the
+<a href="http://gaia.iwr.uni-heidelberg.de/~deal/doc/auto/kdoc/base/ParameterHandler.html">
+recommended style for parameter declaration</a>.
</p>
-<pre class=example>
+<pre class="example">
<code>
-#include <base/parameter_handler.h>
+// We declare a parameter handler
+ParameterHandler prm;
-#include <fstream>
-#include <cmath>
-#include <cstdlib>
+// We declare the first subsection and its entry
+prm.enter_subsection("Zeldovich-equation")
+prm.declare_entry("Solver","CG",Patterns::Sequence("CG|GMRES"));
+prm.leave_subsection();
+// We declare the second subsection and its entry
-template <int dim>
-class TestCases : public MultipleParameterLoop::UserClass{
- public:
- TestCases ();
-
- virtual void declare_parameters (ParameterHandler &prm);
- virtual void run (ParameterHandler &prm);
+prm.enter_subsection("Sunyaev-equation")
+prm.declare_entry("Solver","CG",Patterns::Sequence("CG|GMRES"));
+prm.leave_subsection();
-};
+// The input file is read
+prm.read_input("parameters.in"
+// We retrieve the parameters from the first subsection
-template <int dim>
-TestCases<dim>::TestCases () :
- {};
+prm.enter_subsection("Zeldovich-equation")
+string zeldovich_solver = prm.get("Solver");
+prm.leave_subsection();
+// We retrieve the parameters from the second subsection
+prm.enter_subsection("Sunyaev-equation")
+string sunyaev_solver = prm.get("Solver");
+prm.leave_subsection();
+</code>
+</pre>
-template <int dim>
-void TestCases<dim>::declare_parameters (ParameterHandler &prm) {
- if (dim>=2)
- prm.declare_entry ("Test run", "zoom in",
- Patterns::Sequence("zoom in|ball|curved line|random"));
- else
- prm.declare_entry ("Test run", "zoom in",
- Patterns::Sequence("zoom in|random"));
- prm.declare_entry ("Grid file", "grid.1");
- prm.declare_entry ("Sparsity file", "sparsity.1");
- prm.declare_entry ("Condensed sparsity file", "sparsity.c.1");
-};
+<p class="example">We continue this example with a sample parameter
+file that tells the code to solve the Zeldovich equation using GMRES
+and the Sunyaev equation using CG.
+</p>
+<pre class="example">
+<code>
+subsection Zeldovich-equation
+ set Solver = GMRES
+end
+subsection Sunyaev-equation
+ set Solver = CG
+end
+</code>
+</pre>
-template <int dim>
-void TestCases<dim>::run (ParameterHandler &prm) {
- cout << "Test case = " << prm.get ("Test run") << endl
- << endl;
-
- cout << " Making grid..." << endl;
+<p>
+There are, as we have seen, two methods within the
+<code>ParameterHandler</code> class handling subsections:<br>
+<code>
+void ParameterHandler::enter_subsection(const string &subsection)
+</code><br>
+and<br>
+<code>
+bool ParameterHandler::leave_subsection()
+</code><br>
+Their names are telling. First you enter a subsection, then you declare
+(or retrieve)
+all the parameters for this subsection and finally you leave it.
+Subsections may be nested, i.e. you are at liberty to declare
+subsections within subsections within subsections...
+</p>
- string test = prm.get ("Test run");
- unsigned int test_case;
- if (test=="zoom in") test_case = 1;
- else
- if (test=="ball") test_case = 2;
- else
- if (test=="curved line") test_case = 3;
- else
- if (test=="random") test_case = 4;
- else
- cerr << "This test seems not to be implemented!" << endl;
-
-
- switch (test_case)
- {
- case 1: // code for case 1: zoom in
- case 2: // code for case 2: ball
- case 3: // code for case 3: curved line
- case 4: // code for case 4: random
- };
+<h3>Parameter types and pattern matching</h3>
- cout << " Writing grid..." << endl;
- ofstream out(prm.get("Grid file").c_str());
- // code for output
+<p>
+The parameter handler allows you to specify that any parameter
+be of a distinct type.
+Upon reading a file the value of this
+parameter is checked against the type and an exception is thrown
+if they do not match. An exception is also thrown if the default
+parameter if the default parameter does not match the specified type.
+Below we show a list of the types available. The first column
+gives an explanation, the second lists the corresponding C++ type
+and the third column shows how to use this type in <acronym>deal.II</acronym>.
+<em>Parameter values may not contain linebreaks.</em>
+<acronym>deal.II</acronym> always gets passed a pointer to a class
+handling that type. Those classes are defined in a structure
+called <code>Patterns</code>. The include file to be used is the
+same as for the <code>ParameterHandler</code> class.
+</p>
-};
+<table>
+<caption><b>Parameter types</b></caption>
+<tr>
+ <td><b>Type</b>
+ </td>
+ <td><b>Correspondig C++ type</b>
+ </td>
+ <td><b>deal.II type</b>
+ </td>
+</tr>
+<tr>
+ <td>Integer number.</td>
+ <td><code>int</code>
+ </td>
+ <td><code>Patterns::Integer()</code>
+ </td>
+</tr>
+<tr>
+ <td>Floating point number of double length.</td>
+ <td><code>double</code>
+ </td>
+ <td><code>Patterns::Double()</code>
+ </td>
+</tr>
+<tr>
+ <td>One member of a set.</td>
+ <td><code>enum</code>
+ </td>
+ <td><code>Patterns::Sequence("element 1|element 2|...")</code>
+ </td>
+</tr>
+<tr>
+ <td>An arbitrary string.</td>
+ <td><code>string</code>
+ </td>
+ <td><code>Patterns::Anything()</code>
+ </td>
+</tr>
+</table>
+<h3>Allowed characters</h3>
-int main (int argc, char **argv) {
- if (argc!=2)
- {
- cout << "Usage: grid_test parameterfile" << endl << endl;
- return 1;
- };
+<p>
+Neither the names nor the values of entries may contain the
+following characters:<br>
+<tt>\ { } | </tt><br>
+</p>
- TestCases<2> tests;
- class MultipleParameterLoop input_data; //needs at least gcc2.8
+<p>
+Besides, entries may not contain linebreaks, i.e. entries may not span
+multiple lines.
+</p>
+
+<p>
+Leading and trailing whitespace is ignored and multiple whitespace is
+condensed into one. Entry or subsection
+declarations in your code should therefore
+not contain multiple whitespace, which will not be recognized.
+</p>
+
+<h3>Different input sources</h3>
+
+<p>
+</p>
+
+<h3>Parameter output</h3>
+
+<p>
+</p>
- tests.declare_parameters(input_data);
- input_data.read_input (argv[1]);
- input_data.loop (tests);
-
- return 0;
-};
-</code>
-</pre>
<!-- Page Foot -->
<hr>