diff --git a/dumux/common/defaultusagemessage.hh b/dumux/common/defaultusagemessage.hh new file mode 100644 index 0000000000000000000000000000000000000000..cc2989908e122b1f6b9834830c1453840a6b80f1 --- /dev/null +++ b/dumux/common/defaultusagemessage.hh @@ -0,0 +1,69 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Function printing a default usage message + */ +#ifndef DUMUX_DEFAULT_USAGE_MESSAGE_HH +#define DUMUX_DEFAULT_USAGE_MESSAGE_HH + +namespace Dumux +{ + +/*! + * \ingroup Start + * + * \brief Provides a general text block, that is part of error/ help messages. + * + * \return The string that is the help / error message. + */ +inline std::string defaultUsageMessage(const std::string& programName) +{ + return "Usage: " + programName + " [options] \n" + "Options usually are parameters given to the simulation, \n" + "and have to be specified with this syntax: \n" + "\t-GroupName.ParameterName VALUE, for example -TimeManager.TEnd 100\n" + "\n" + "If -ParameterFile is specified, parameters can also be defined there. In this case,\n" + "lines of the form \n" + "GroupName.ParameterName = VALUE # comment \n" + "have to be used. More conveniently, group names can be specified in square brackets, \n" + "such that each following parameter name belongs to that group, \n" + "[GroupName] \n" + "ParameterName = VALUE \n" + "See test/boxmodels/2p/test_2p.input for an example of a parameter file \n" + "and the Dune documentation of ParameterTreeParser for the format specification. \n" + "\n" + "Parameters specified on the command line have priority over those in the parameter file.\n" + "If no parameter file name is given, './<programname>.input' is chosen as default.\n" + "\n" + "Important options include:\n" + "\t-h, --help Print this usage message and exit\n" + "\t-PrintParameters [true|false] Print the run-time modifiable parameters _after_ \n" + "\t the simulation [default: true]\n" + "\t-PrintProperties [true|false] Print the compile-time parameters _before_ \n" + "\t the simulation [default: false]\n" + "\t-ParameterFile FILENAME File with parameter definitions\n" + "\t-TimeManager.Restart RESTARTTIME Restart simulation from a restart file\n" + "\n\n"; +} + +} // end namespace Dumux + +#endif diff --git a/dumux/common/dumuxmessage.hh b/dumux/common/dumuxmessage.hh new file mode 100644 index 0000000000000000000000000000000000000000..825857b3cf92013950a165eecd18bd198d763080 --- /dev/null +++ b/dumux/common/dumuxmessage.hh @@ -0,0 +1,180 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Provides the class creating the famous dumux start and end messages + */ +#ifndef DUMUX_MESSAGE_HH +#define DUMUX_MESSAGE_HH + +#include <iostream> +#include <ctime> + +namespace Dumux +{ + +/*! + * \ingroup Start + * \brief Dumux start and end message. + */ +class DumuxMessage +{ + //! The current number of messages. Please adjust if you add one. + static const int nMessages_ = 11; + +public: + + /*! + * \brief Selects random messages to write out at the start and end of a simulation run. + * \param firstCall Indicates if it's the first call and we have to dice (simulation is starting). + */ + static void print(bool firstCall = false) + { + // initialize in case someone forgets to set first call + static int dice = 8; + + if(firstCall) + { + // roll the dice to decide which start message will be displayed + std::srand(std::time(0)); + dice = std::rand() % (nMessages_ + 1); + } + + std::cout << std::endl; + + switch (dice) + { + case 0: + if(firstCall) + std::cout << "Welcome aboard DuMuX airlines. Please fasten your seatbelts! " + << "Emergency exits are near the time integration." << std::endl; + else + std::cout << "We hope that you enjoyed simulating with us " << std::endl + << "and that you will choose us next time, too." << std::endl; + break; + case 1: + if(firstCall) + std::cout << "Let's get the cow off the ice." << std::endl; + else + std::cout << "DuMuX got the cow off the ice." << std::endl; + break; + case 2: + if(firstCall) + std::cout << "Science, my lad, is made up of mistakes, but they are " + << "mistakes which it is useful to make, because they lead little " + << "by little to the truth." << std::endl + << " - Jules Verne, A journey to the center of the earth" << std::endl; + else + std::cout << "[We see that] science is eminently perfectible, and that each theory has " + << "constantly to give way to a fresh one." << std::endl + << " - Jules Verne, Journey to the Center of the Earth" << std::endl; + + break; + case 3: + if(firstCall) + std::cout << "Wherever he saw a hole he always wanted to know the depth of it. " + << "To him this was important." << std::endl + << " - Jules Verne, A journey to the center of the earth" << std::endl; + else + std::cout << "We may brave human laws, but we cannot resist natural ones." << std::endl + << " - Jules Verne, 20,000 Leagues Under the Sea" << std::endl; + break; + case 4: + if(firstCall) + std::cout << "Silence - to delight Bernd." << std::endl; + else + std::cout << std::endl << std::endl; + break; + case 5: + std::cout << "Don't panic... !" << std::endl; + break; + case 6: + if(firstCall) + std::cout << "You idiot! You signed the order to destroy Earth!" << std::endl + << " - Douglas Adams, HGttG" << std::endl; + else + std::cout << "Marvin: I've been talking to the main computer." << std::endl + << "Arthur: And?" << std::endl + << "Marvin: It hates me." << std::endl + << " - Douglas Adams, HGttG" << std::endl; + break; + case 7: + if(firstCall) + std::cout << "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.!" << std::endl + << " - Douglas Adams, HGttG " << std::endl; + else + std::cout << "Forty-two. I checked it very thoroughly, and that quite definitely is the answer. I think " + << "the problem, to be quite honest with you, is that you\'ve never actually known what the question is." << std::endl + << " - Douglas Adams, HGttG " << std::endl; + break; + case 8: + std::cout << " ## @@@@ @ @ @ @" << std::endl; + std::cout << " ### # @ @ @@ @@ @ " << std::endl; + std::cout << " ## # @ @ @ @ @ @ @ @ @ @ @" << std::endl; + std::cout << " ## # @ @ @ @ @ @ @ @ " << std::endl; + std::cout << " # # @@@@ @@@ @ @ @@@ " << std::endl; + std::cout << " # # " << std::endl; + std::cout << " # # " << std::endl; + std::cout << " # ## %%% " << std::setw(8) << std::right << DUMUX_VERSION << std::endl; + std::cout << " # ### % % %% %% " << std::endl; + std::cout << "#### #%%% %% %%%%% %%%%%%%%%%%%%%%%%" << std::endl; + break; + case 9: + std::cout << "### # # # # " << std::endl; + std::cout << "# # # # ## ## # # # " << std::endl; + std::cout << "# # # # # # # # # # # " << std::endl; + std::cout << "### ## # # ## " << std::endl; + std::cout << " " << std::endl; + std::cout << "Dune for Multi-{ Phase, " << std::endl; + std::cout << " Component, " << std::endl; + std::cout << " Scale, " << std::endl; + std::cout << " Physics, " << std::endl; + std::cout << " ...} flow and transport in porous media" << std::endl; + break; + case 10: + if(firstCall) + std::cout << "Elliot Carver: Mr. Jones, are we ready to release our new software?" << std::endl + << "Jones: Yes, sir. As requested, it's full of bugs, which means people will be forced to upgrade for years." << std::endl + << " - James Bond, Tomorrow Never Dies" << std::endl; + else + { + std::cout << "Elliot Carver: Outstanding." << std::endl + << " - James Bond, Tomorrow Never Dies" << std::endl; + } + break; + case 11: + if(firstCall) + std::cout << "Chuck Norris has successfully compiled DuMuX." << std::endl; + else + std::cout << "Chuck Norris has compiled DuMuX even two times in a row!" << std::endl; + break; + + // Note: If you add a case, you have to increase the number of messages (nMessages_ variable). + + default: // silence to delight Bernd + return; + } + std::cout << std::endl; + } +}; + +} // end namespace Dumux + +#endif diff --git a/dumux/common/parameterparser.hh b/dumux/common/parameterparser.hh new file mode 100644 index 0000000000000000000000000000000000000000..5711c18d5fb9ce13fae016b1da8dbb01eb004445 --- /dev/null +++ b/dumux/common/parameterparser.hh @@ -0,0 +1,187 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +/*! + * \file + * \brief Provides a class parsing parameters from command line and from input files + */ +#ifndef DUMUX_PARAMETER_PARSER_HH +#define DUMUX_PARAMETER_PARSER_HH + +#include <iostream> + +#include <dune/common/parametertreeparser.hh> +#include <dune/common/exceptions.hh> +#include <dune/common/parallel/mpihelper.hh> + +#include <dumux/common/propertysystem.hh> +#include <dumux/common/parameters.hh> +#include <dumux/common/defaultusagemessage.hh> +#include <dumux/common/exceptions.hh> + +namespace Dumux +{ + +/*! + * \ingroup Start + * \brief Parses parameters in the command line and input files + */ +template<class TypeTag> +class ParameterParser +{ + +public: + + /*! + * \brief Read the command line arguments and write them into the parameter tree. + * Do some syntax checks. Check also if an input file was specified in the command line. + * In parallel the parameter are currently read on all processors. + * + * \param argc The 'argc' argument of the main function: count of arguments (1 if there are no arguments) + * \param argv The 'argv' argument of the main function: array of pointers to the argument strings + * \param params A parameter tree. It can be filled from an input file or the command line. + * \param usage Callback function for printing the usage message + * \return bool True if everything succeeded, false if the help message has to be shown + */ + static bool parseCommandLineArguments(int argc, + char **argv, + Dune::ParameterTree ¶ms, + void (*usage)(const char *, const std::string &) = [](const char *, const std::string &){}) + { + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); + + // check whether the user did not specify any parameter then we are done + if (argc == 1) + return true; + + // check whether the user wanted to see the help message + if (mpiHelper.rank() == 0) + for (int i = 1; i < argc; ++i) + if (std::string("--help") == argv[i] || std::string("-h") == argv[i]) + return false; + + // fill the parameter tree with the parameters from the command line + readOptions_(argc, argv, params); + + return true; + } + + /*! + * \brief Parse the input file. If the user didn't specify anything in the parameter tree (that contains + * command line options if parseCommandLineArguments was called before) we default to the + * program name + input. When calling this function we consider it an error if no input file is found. + * + * \param argc The 'argc' argument of the main function: count of arguments (1 if there are no arguments) + * \param argv The 'argv' argument of the main function: array of pointers to the argument strings + * \param params A parameter tree. It can be filled from an input file or the command line. + * \param usage Callback function for printing the usage message + */ + static void parseInputFile(int argc, + char **argv, + Dune::ParameterTree ¶ms, + void (*usage)(const char *, const std::string &) = [](const char *, const std::string &){}) + { + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); + + std::string parameterFileName = ""; + + // check the parameter tree for a user specified input file + if (params.hasKey("ParameterFile")) + // this is the only reason why this class needs a TypeTag -- sigh + // if the parameter tree is used directly this appears in the unused properties list + parameterFileName = GET_RUNTIME_PARAM(TypeTag, std::string, ParameterFile); + + // otherwise use the default + else + { + if (mpiHelper.size() > 1) + std::cout << "Rank " << mpiHelper.rank() << ": "; + std::cout << "No parameter file given. " + << "Defaulting to '" + << argv[0] + << ".input' for input file.\n"; + + parameterFileName = std::string(argv[0]) + ".input"; + } + + // open and check whether the parameter file exists. + std::ifstream parameterFile(parameterFileName.c_str()); + if (!parameterFile.is_open()) + { + if (mpiHelper.size() > 1) + std::cout << "Rank " << mpiHelper.rank() << ": "; + std::cout << " -> Could not open file '" + << parameterFileName + << "'. <- \n\n"; + + usage(argv[0], defaultUsageMessage(argv[0])); + + DUNE_THROW(ParameterException, "Error opening input file " << parameterFileName << "."); + } + else + { + // read parameters from the file without overwriting + Dune::ParameterTreeParser::readINITree(parameterFileName, + params, + /*overwrite=*/false); + } + parameterFile.close(); + } + +private: + /*! + * \brief Read the command line arguments and write them into the parameter tree. + * Do some syntax checks. + * + * \param argc The 'argc' argument of the main function: count of arguments (1 if there are no arguments) + * \param argv The 'argv' argument of the main function: array of pointers to the argument strings + * \param paramTree The parameterTree. It can be filled from an input file or the command line. + * \return Empty string if everything worked out. Otherwise the thing that could not be read. + */ + static void readOptions_(int argc, char **argv, Dune::ParameterTree ¶mTree) + { + // All command line options need to start with '-' + for (int i = 1; i < argc; ++i) + { + if (argv[i][0] != '-' && i == 1) + { + // try to pass first argument as parameter file + paramTree["ParameterFile"] = argv[1]; + continue; + } + + if (argv[i][0] != '-') + DUNE_THROW(ParameterException, "-> Command line argument " << i << " (='" << argv[i] << "') is invalid. <-"); + + if (i+1 == argc) + DUNE_THROW(ParameterException, "-> No argument given for parameter '" << argv[i] << "'! <-"); + + // read a -MyOpt VALUE option + std::string paramName = argv[i] + 1; + std::string paramValue = argv[i+1]; + ++i; // In the case of '-MyOpt VALUE' each pair counts as two arguments + + // Put the key=value pair into the parameter tree + paramTree[paramName] = paramValue; + } + } +}; + +} // end namespace Dumux + +#endif diff --git a/dumux/common/start.hh b/dumux/common/start.hh index 57c73fef46ad4bc3ef7392fdcc428bb45a360ed0..ac74ec38506263e7828a33865c2d6584e43ade76 100644 --- a/dumux/common/start.hh +++ b/dumux/common/start.hh @@ -26,17 +26,14 @@ #include <ctime> #include <iostream> -#include <dune/common/parametertreeparser.hh> #include <dune/common/parallel/mpihelper.hh> -#include <dune/grid/io/file/dgfparser.hh> -#if HAVE_DUNE_ALUGRID -#include <dune/alugrid/dgf.hh> -#endif // HAVE_DUNE_ALUGRID - -#include "propertysystem.hh" -#include "parameters.hh" -#include "valgrind.hh" +#include <dumux/common/propertysystem.hh> +#include <dumux/common/parameters.hh> +#include <dumux/common/valgrind.hh> +#include <dumux/common/dumuxmessage.hh> +#include <dumux/common/defaultusagemessage.hh> +#include <dumux/common/parameterparser.hh> namespace Dumux { @@ -49,230 +46,6 @@ NEW_PROP_TAG(Problem); NEW_PROP_TAG(TimeManager); } -/*! - * \ingroup Start - * \brief Read the command line arguments and write them into the parameter tree. - * Do some syntax checks. - * - * \param argc The 'argc' argument of the main function: count of arguments (1 if there are no arguments) - * \param argv The 'argv' argument of the main function: array of pointers to the argument strings - * \param paramTree The parameterTree. It can be filled from an input file or the command line. - * \return Empty string if everything worked out. Otherwise the thing that could not be read. - */ -std::string readOptions_(int argc, char **argv, Dune::ParameterTree ¶mTree) -{ - // All command line options need to start with '-' - for (int i = 1; i < argc; ++i) - { - if (argv[i][0] != '-' && i == 1) - { - // try to pass first argument as parameter file - paramTree["ParameterFile"] = argv[1]; - continue; - } - - std::ostringstream oss; - if (argv[i][0] != '-') - { - oss << "\n -> Command line argument " << i << " (='" << argv[i] << "') is invalid. <- \n\n\n\n"; - return oss.str(); - } - - if (i+1 == argc) - { - oss << "\n -> No argument2 given for parameter '" << argv[i] << "'! <- \n\n\n\n"; - return oss.str(); - } - - // read a -MyOpt VALUE option - std::string paramName = argv[i] + 1; - std::string paramValue = argv[i+1]; - ++i; // In the case of '-MyOpt VALUE' each pair counts as two arguments - - // Put the key=value pair into the parameter tree - paramTree[paramName] = paramValue; - } - return ""; -} - - -/*! - * \ingroup Start - * - * \brief Provides a general text block, that is part of error/ help messages. - * - * \return The string that is the help / error message. - */ -std::string usageTextBlock() -{ - return "Options usually are parameters given to the simulation, \n" - "and have to be specified with this syntax: \n" - "\t-GroupName.ParameterName VALUE, for example -TimeManager.TEnd 100\n" - "\n" - "If -ParameterFile is specified, parameters can also be defined there. In this case,\n" - "lines of the form \n" - "GroupName.ParameterName = VALUE # comment \n" - "have to be used. More conveniently, group names can be specified in square brackets, \n" - "such that each following parameter name belongs to that group, \n" - "[GroupName] \n" - "ParameterName = VALUE \n" - "See test/boxmodels/2p/test_2p.input for an example of a parameter file \n" - "and the Dune documentation of ParameterTreeParser for the format specification. \n" - "\n" - "Parameters specified on the command line have priority over those in the parameter file.\n" - "If no parameter file name is given, './<programname>.input' is chosen as default.\n" - "\n" - "Important options include:\n" - "\t-h, --help Print this usage message and exit\n" - "\t-PrintParameters [true|false] Print the run-time modifiable parameters _after_ \n" - "\t the simulation [default: true]\n" - "\t-PrintProperties [true|false] Print the compile-time parameters _before_ \n" - "\t the simulation [default: false]\n" - "\t-ParameterFile FILENAME File with parameter definitions\n" - "\t-TimeManager.Restart RESTARTTIME Restart simulation from a restart file\n" - "\n" - "\n"; -} - -/*! - * \ingroup Start - * \brief Dumux start and end message. - * - * Selects random messages to write out at the start and end of a simulation run. - * \param start Indicates if the simulation is starting (=true) or ending (=false). - */ -void dumuxMessage_(bool start) -{ - static int dice_; - if(start) - { - std::srand(std::time(0)); - // roll the dice to decide which start message will be displayed: - dice_ = std::rand() % 12; // has to be n+1 - } - - - std::cout << "" << std::endl; - switch (dice_) - { - case 0: - if(start) - std::cout << "Welcome aboard DuMuX airlines. Please fasten your seatbelts! " - << "Emergency exits are near the time integration." << std::endl; - else - std::cout << "We hope that you enjoyed simulating with us " << std::endl - << "and that you will choose us next time, too." << std::endl; - break; - case 1: - if(start) - std::cout << "Let's get the cow off the ice." << std::endl; - else - std::cout << "DuMuX got the cow off the ice." << std::endl; - break; - case 2: - if(start) - std::cout << "Science, my lad, is made up of mistakes, but they are " - << "mistakes which it is useful to make, because they lead little " - << "by little to the truth." << std::endl - << " - Jules Verne, A journey to the center of the earth" << std::endl; - else - std::cout << "[We see that] science is eminently perfectible, and that each theory has " - << "constantly to give way to a fresh one." << std::endl - << " - Jules Verne, Journey to the Center of the Earth" << std::endl; - - break; - case 3: - if(start) - std::cout << "Wherever he saw a hole he always wanted to know the depth of it. " - << "To him this was important." << std::endl - << " - Jules Verne, A journey to the center of the earth" << std::endl; - else - std::cout << "We may brave human laws, but we cannot resist natural ones." << std::endl - << " - Jules Verne, 20,000 Leagues Under the Sea" << std::endl; - break; - case 4: - if(start) - std::cout << "Silence - to delight Bernd." << std::endl; - else - std::cout << "\n " << std::endl; - break; - case 5: - std::cout << "Don't panic... !" << std::endl; - break; - case 6: - if(start) - std::cout << "You idiot! You signed the order to destroy Earth!" << std::endl - << " - Douglas Adams, HGttG" << std::endl; - else - std::cout << "Marvin: I've been talking to the main computer.\n Arthur: And?" << std::endl - << "Marvin: It hates me." << std::endl - << " - Douglas Adams, HGttG" << std::endl; - break; - case 7: - if(start) - std::cout << "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.!" << std::endl - << " - Douglas Adams, HGttG " << std::endl; - else - std::cout << "Forty-two. I checked it very thoroughly, and that quite definitely is the answer. I think " - << "the problem, to be quite honest with you, is that you\'ve never actually known what the question is." << std::endl - << " - Douglas Adams, HGttG " << std::endl; - break; - case 8: - std::cout << " ## @@@@ @ @ @ @" << std::endl; - std::cout << " ### # @ @ @@ @@ @ " << std::endl; - std::cout << " ## # @ @ @ @ @ @ @ @ @ @ @" << std::endl; - std::cout << " ## # @ @ @ @ @ @ @ @ " << std::endl; - std::cout << " # # @@@@ @@@ @ @ @@@ " << std::endl; - std::cout << " # # " << std::endl; - std::cout << " # # " << std::endl; - std::cout << " # ## %%% " << std::setw(8) << std::right << DUMUX_VERSION << std::endl; - std::cout << " # ### % % %% %% " << std::endl; - std::cout << "#### #%%% %% %%%%% %%%%%%%%%%%%%%%%%" << std::endl; - break; - case 9: - std::cout << "### # # # # " << std::endl; - std::cout << "# # # # ## ## # # # " << std::endl; - std::cout << "# # # # # # # # # # # " << std::endl; - std::cout << "### ## # # ## " << std::endl; - std::cout << " " << std::endl; - std::cout << "Dune for Multi-{ Phase, " << std::endl; - std::cout << " Component, " << std::endl; - std::cout << " Scale, " << std::endl; - std::cout << " Physics, " << std::endl; - std::cout << " ...} flow and transport in porous media" << std::endl; - break; - case 10: - if(start) - { - std::cout << "Elliot Carver: Mr. Jones, are we ready to release our new software?" << std::endl; - std::cout << "Jones: Yes, sir. As requested, it's full of bugs, which means people will be forced to upgrade for years." << std::endl; - std::cout << " - James Bond, Tomorrow Never Dies" << std::endl; - } - else - { - std::cout << "Elliot Carver: Outstanding." << std::endl; - std::cout << " - James Bond, Tomorrow Never Dies" << std::endl; - } - break; - case 11: - if(start) - { - std::cout << "Chuck Norris has successfully compiled DuMuX." << std::endl; - } - else - { - std::cout << "Chuck Norris has compiled DuMuX even two times in a row!" << std::endl; - } - break; - // Note: If you add a case, you have to increase the modulus at the beginning of this function! - - default: // silence to delight Bernd - return ; - } - std::cout << std::endl; -} - /*! * \ingroup Start * @@ -290,187 +63,92 @@ int start_(int argc, char **argv, void (*usage)(const char *, const std::string &)) { - typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; - // Set by default (dumux/common/basicproperties.hh) to DgfGridCreator (dumux/io/dgfgridcreator.hh) - typedef typename GET_PROP_TYPE(TypeTag, GridCreator) GridCreator; - typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem; - typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager; + // some aliases for better readability + using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); + using GridCreator = typename GET_PROP_TYPE(TypeTag, GridCreator); + using Problem = typename GET_PROP_TYPE(TypeTag, Problem); + using TimeManager = typename GET_PROP_TYPE(TypeTag, TimeManager); + using ParameterTree = typename GET_PROP(TypeTag, ParameterTree); // initialize MPI, finalize is done automatically on exit - const Dune::MPIHelper &mpiHelper = Dune::MPIHelper::instance(argc, argv); + const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); // print dumux start message if (mpiHelper.rank() == 0) - dumuxMessage_(true); + DumuxMessage::print(/*firstCall=*/true); //////////////////////////////////////////////////////////// - // parse the command line arguments + // parse the command line arguments and input file //////////////////////////////////////////////////////////// - // check whether the user did not specify any parameter. in this - // case print the usage message - if (argc == 1) { - if (mpiHelper.size() > 0) - std::cout << "Rank " << mpiHelper.rank() << ": "; - std::cout << "No parameter file given. " - << "Defaulting to '" - << argv[0] - << ".input' for input file.\n"; - std::ifstream parameterFile; - // check whether the parameter file exists. - std::string defaultName = argv[0]; - defaultName += ".input"; - parameterFile.open(defaultName.c_str()); - if (not parameterFile.is_open()){ - if (mpiHelper.size() > 0) - std::cout << "Rank " << mpiHelper.rank() << ": "; - std::cout << " -> Could not open file '" - << defaultName - << "'. <- \n\n\n\n"; - usage(argv[0], usageTextBlock()); - return 1; - } - parameterFile.close(); - } - - - // check whether the user wanted to see the help message - if (mpiHelper.rank() == 0) + // if the user just wanted to see the help / usage message show usage and stop program + if(!ParameterParser<TypeTag>::parseCommandLineArguments(argc, argv, ParameterTree::tree(), usage)) { - for (int i = 1; i < argc; ++i) - { - if (std::string("--help") == argv[i] || std::string("-h") == argv[i]) - { - usage(argv[0], usageTextBlock()); - return 0; - } - } + usage(argv[0], defaultUsageMessage(argv[0])); + return 0; } + // parse the input file into the parameter tree + ParameterParser<TypeTag>::parseInputFile(argc, argv, ParameterTree::tree(), usage); - // fill the parameter tree with the options from the command line - typedef typename GET_PROP(TypeTag, ParameterTree) ParameterTree; - std::string s = readOptions_(argc, argv, ParameterTree::tree()); - if (!s.empty()) { - std::string usageMessage = s ; - usageMessage += usageTextBlock(); - usage(argv[0], usageMessage); - return 1; - } - // obtain the name of the parameter file - std::string parameterFileName; - if (ParameterTree::tree().hasKey("ParameterFile")) - { - // set the name to the one provided by the user - parameterFileName = GET_RUNTIME_PARAM(TypeTag, std::string, ParameterFile); // otherwise we read from the command line - } - else - { - // set the name to the default ./<programname>.input - parameterFileName = argv[0]; - parameterFileName += ".input"; - } - - // open and check whether the parameter file exists. - std::ifstream parameterFile(parameterFileName.c_str()); - if (not parameterFile.is_open()) { - // if the name of the file has been specified, - // this must be an error. Otherwise proceed. - if (ParameterTree::tree().hasKey("ParameterFile")) - { - std::cout << "\n\t -> Could not open file '" - << parameterFileName - << "'. <- \n\n\n\n"; - usage(argv[0], usageTextBlock()); - return 1; - } - } - else - { - // read parameters from the file without overwriting - Dune::ParameterTreeParser::readINITree(parameterFileName, - ParameterTree::tree(), - /*overwrite=*/false); - } - parameterFile.close(); + //////////////////////////////////////////////////////////// + // check for some user debugging parameters + //////////////////////////////////////////////////////////// - bool printProps = false; - if (ParameterTree::tree().hasKey("PrintProperties") - || ParameterTree::tree().hasKey("TimeManager.PrintProperties")) + bool printProps = false; // per default don't print all properties + if (ParameterTree::tree().hasKey("PrintProperties") || ParameterTree::tree().hasKey("TimeManager.PrintProperties")) printProps = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, TimeManager, PrintProperties); - if (printProps && mpiHelper.rank() == 0) { + if (printProps && mpiHelper.rank() == 0) Properties::print<TypeTag>(); - } - - // deal with the restart stuff - bool restart = false; - Scalar restartTime = 0; - if (ParameterTree::tree().hasKey("Restart") - || ParameterTree::tree().hasKey("TimeManager.Restart")) { - restart = true; - restartTime = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, Restart); - } - // read the PrintParams parameter - bool printParams = true; - if (ParameterTree::tree().hasKey("PrintParameters") - || ParameterTree::tree().hasKey("TimeManager.PrintParameters")) + bool printParams = true; // per default print all properties + if (ParameterTree::tree().hasKey("PrintParameters") || ParameterTree::tree().hasKey("TimeManager.PrintParameters")) printParams = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, TimeManager, PrintParameters); - // try to create a grid (from the given grid file) + ////////////////////////////////////////////////////////////////////// + // try to create a grid (from the given grid file or the input file) + ///////////////////////////////////////////////////////////////////// + try { GridCreator::makeGrid(); } catch (...) { - std::string usageMessage = "\n\t -> Creation of the grid failed! <- \n\n\n\n"; - usageMessage += usageTextBlock(); + std::string usageMessage = "\n\t -> Creation of the grid failed! <- \n\n"; + usageMessage += defaultUsageMessage(argv[0]); usage(argv[0], usageMessage); throw; } GridCreator::loadBalance(); - // read the initial time step and the end time - double tEnd; - double dt; + ////////////////////////////////////////////////////////////////////// + // run the simulation + ///////////////////////////////////////////////////////////////////// - try { tEnd = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, TEnd); } - catch (...) { - std::string usageMessage = "\n\t -> Mandatory parameter 'TimeManager.TEnd'" - " not specified! <- \n\n\n\n"; - usageMessage += usageTextBlock(); - usage(argv[0], usageMessage); - throw; - } + // read the initial time step and the end time (mandatory parameters) + auto tEnd = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, TEnd); + auto dt = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, DtInitial); - try { dt = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, DtInitial); } - catch (...) { - std::string usageMessage = "\n\t -> Mandatory parameter 'TimeManager.DtInitial'" - " not specified! <- \n\n\n\n"; - usageMessage += usageTextBlock(); - usage(argv[0], usageMessage); - throw; + // check if we are about to restart a previously interrupted simulation + bool restart = false; + Scalar restartTime = 0; + if (ParameterTree::tree().hasKey("Restart") || ParameterTree::tree().hasKey("TimeManager.Restart")) + { + restart = true; + restartTime = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, Restart); } - // instantiate and run the concrete problem + // instantiate and run the problem TimeManager timeManager; Problem problem(timeManager, GridCreator::grid().leafGridView()); timeManager.init(problem, restartTime, dt, tEnd, restart); timeManager.run(); - // print dumux end message - if (mpiHelper.rank() == 0) - dumuxMessage_(false); - - if (printParams && mpiHelper.rank() == 0) { - Parameters::print<TypeTag>(); - } - // check if a deprecated TypeTag has been used - Properties::TypeTagAncestors<TypeTag>::addAncestors(); - if (Properties::TypeTagAncestors<TypeTag>::contains("Decoupled")) + // print dumux end message and maybe the parameters for debugging + if (mpiHelper.rank() == 0) { - std::cout << "\nAt least one of the used TypeTags contains the " - << "deprecated name \"Decoupled\":" << std::endl; - Properties::TypeTagAncestors<TypeTag>::print(std::cout); - std::cout << "Please use \"Sequential\" instead." << std::endl; + DumuxMessage::print(/*firstCall=*/false); + + if (printParams) + Parameters::print<TypeTag>(); } return 0; @@ -479,11 +157,7 @@ int start_(int argc, /*! * \ingroup Start * - * \brief Provides a main function which reads in parameters from the - * command line and a parameter file. - * - * In this function only the differentiation between debugger - * or not is made. + * \brief Provides a main function with error handling * * \tparam TypeTag The type tag of the problem which needs to be solved * @@ -501,7 +175,7 @@ int start(int argc, } catch (ParameterException &e) { Parameters::print<TypeTag>(); - std::cerr << e << ". Abort!\n"; + std::cerr << std::endl << e << ". Abort!" << std::endl; return 1; } catch (Dune::DGFException & e) { @@ -522,6 +196,6 @@ int start(int argc, } } -} // namespace Dumux +} // end namespace Dumux #endif