start.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
27#ifndef EWOMS_START_HH
28#define EWOMS_START_HH
29
31// the following header is not required here, but it must be included before
32// dune/common/densematrix.hh because of some c++ ideosyncrasies
33#include <opm/material/densead/Evaluation.hpp>
34
35#include "parametersystem.hh"
36
39
40#include <opm/material/common/Valgrind.hpp>
41
42#include <opm/material/common/ResetLocale.hpp>
43
44#include <dune/grid/io/file/dgfparser/dgfparser.hh>
45#include <dune/common/version.hh>
46#include <dune/common/parametertreeparser.hh>
47#include <dune/common/parallel/mpihelper.hh>
48
49#if HAVE_DUNE_FEM
50#include <dune/fem/misc/mpimanager.hh>
51#endif
52
53#include <fstream>
54#include <iostream>
55#include <sstream>
56#include <string>
57#include <locale>
58
59#include <stdio.h>
60#include <unistd.h>
61#include <time.h>
62#include <signal.h>
63#include <string.h>
64
65#if HAVE_MPI
66#include <mpi.h>
67#endif
68
70
71namespace Opm {
75template <class TypeTag>
76static inline void registerAllParameters_(bool finalizeRegistration = true)
77{
78 using Simulator = GetPropType<TypeTag, Properties::Simulator>;
79 using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
80
81 Parameters::Register<Parameters::ParameterFile>
82 ("An .ini file which contains a set of run-time parameters");
83 Parameters::Register<Parameters::PrintParameters>
84 ("Print the values of the run-time parameters at the "
85 "start of the simulation");
86
89
90 if (finalizeRegistration) {
92 }
93}
94
104template <class TypeTag>
105static inline int setupParameters_(int argc,
106 const char **argv,
107 bool registerParams=true,
108 bool allowUnused=false,
109 bool handleHelp = true)
110{
111 using Problem = GetPropType<TypeTag, Properties::Problem>;
112
113 // first, get the MPI rank of the current process
114 int myRank = 0;
115
117 // Register all parameters
119 if (registerParams)
120 registerAllParameters_<TypeTag>();
121
123 // set the parameter values
125
126 // fill the parameter tree with the options from the command line
127 const auto& positionalParamCallback = Problem::handlePositionalParameter;
128 std::string helpPreamble = ""; // print help if non-empty!
129 if (myRank == 0 && handleHelp)
130 helpPreamble = Problem::helpPreamble(argc, argv);
131 std::string s =
133 argv,
134 helpPreamble,
135 positionalParamCallback);
136 if (!s.empty())
137 {
138 int status = 1;
139 if (s == "Help called") // only on master process
140 status = -1; // Use negative values to indicate --help argument
141#if HAVE_MPI
142 // Force -1 if the master process has that.
143 int globalStatus;
144 MPI_Allreduce(&status, &globalStatus, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
145 return globalStatus;
146#endif
147 return status;
148 }
149
150 const std::string paramFileName = Parameters::Get<Parameters::ParameterFile>(false);
151 if (!paramFileName.empty()) {
153 // add the parameters specified using an .ini file
155
156 // check whether the parameter file is readable.
157 std::ifstream tmp;
158 tmp.open(paramFileName.c_str());
159 if (!tmp.is_open()) {
160 std::ostringstream oss;
161 if (myRank == 0) {
162 oss << "Parameter file \"" << paramFileName
163 << "\" does not exist or is not readable.";
164 Parameters::printUsage(argv[0], oss.str());
165 }
166 return /*status=*/1;
167 }
168
169 // read the parameter file.
170 Parameters::parseParameterFile(paramFileName, /*overwrite=*/false);
171 }
172
173 // make sure that no unknown parameters are encountered
174 using KeyValuePair = std::pair<std::string, std::string>;
175 using ParamList = std::list<KeyValuePair>;
176
177 ParamList usedParams;
178 ParamList unusedParams;
179
180 Parameters::getLists(usedParams, unusedParams);
181 if (!allowUnused && !unusedParams.empty()) {
182 if (myRank == 0) {
183 if (unusedParams.size() == 1)
184 std::cerr << "The following explicitly specified parameter is unknown:\n";
185 else
186 std::cerr << "The following " << unusedParams.size()
187 << " explicitly specified parameters are unknown:\n";
188
189 std::cerr << "\n";
190 for (const auto& keyValue : unusedParams)
191 std::cerr << " " << keyValue.first << "=\"" << keyValue.second << "\"\n";
192 std::cerr << "\n";
193
194 std::cerr << "Use\n"
195 << "\n"
196 << " " << argv[0] << " --help\n"
197 << "\n"
198 <<"to obtain the list of recognized command line parameters.\n\n";
199 }
200 return /*status=*/1;
201 }
202
203 return /*status=*/0;
204}
205
211static inline void resetTerminal_()
212{
213 // make sure stderr and stderr do not contain any unwritten data and make sure that
214 // the TTY does not see any unfinished ANSI escape sequence.
215 std::cerr << " \r\n";
216 std::cerr.flush();
217 std::cout << " \r\n";
218 std::cout.flush();
219
220 // it seems like some terminals sometimes takes their time to react, so let's
221 // accommodate them.
222 usleep(/*usec=*/500*1000);
223
224 // this requires the 'stty' command to be available in the command search path. on
225 // most linux systems, is the case. (but even if the system() function fails, the
226 // worst thing which can happen is that the TTY stays potentially choked up...)
227 if (system("stty sane") != 0)
228 std::cout << "Executing the 'stty' command failed."
229 << " Terminal might be left in an undefined state!\n";
230}
231
236static inline void resetTerminal_(int signum)
237{
238 // first thing to do when a nuke hits: restore the default signal handler
239 signal(signum, SIG_DFL);
240
241#if HAVE_MPI
242 int rank = 0;
243 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
244 if (rank != 0) {
245 // re-raise the signal
246 raise(signum);
247
248 return;
249 }
250#endif
251
252 if (isatty(fileno(stdout)) && isatty(fileno(stdin))) {
253 std::cout << "\n\nReceived signal " << signum
254 << " (\"" << strsignal(signum) << "\")."
255 << " Trying to reset the terminal.\n";
256
257 resetTerminal_();
258 }
259
260 // after we did our best to clean the pedestrian way, re-raise the signal
261 raise(signum);
262}
264
276template <class TypeTag>
277static inline int start(int argc, char **argv, bool registerParams=true)
278{
279 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
280 using Simulator = GetPropType<TypeTag, Properties::Simulator>;
281 using Problem = GetPropType<TypeTag, Properties::Problem>;
282 using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
283
284 // set the signal handlers to reset the TTY to a well defined state on unexpected
285 // program aborts
286 if (isatty(STDIN_FILENO)) {
287 signal(SIGINT, resetTerminal_);
288 signal(SIGHUP, resetTerminal_);
289 signal(SIGABRT, resetTerminal_);
290 signal(SIGFPE, resetTerminal_);
291 signal(SIGSEGV, resetTerminal_);
292 signal(SIGPIPE, resetTerminal_);
293 signal(SIGTERM, resetTerminal_);
294 }
295
296 resetLocale();
297
298 int myRank = 0;
299 try
300 {
301 int paramStatus = setupParameters_<TypeTag>(argc, const_cast<const char**>(argv), registerParams);
302 if (paramStatus == 1)
303 return 1;
304 if (paramStatus == 2)
305 return 0;
306
308
309 // initialize MPI, finalize is done automatically on exit
310#if HAVE_DUNE_FEM
311 Dune::Fem::MPIManager::initialize(argc, argv);
312 myRank = Dune::Fem::MPIManager::rank();
313#else
314 myRank = Dune::MPIHelper::instance(argc, argv).rank();
315#endif
316
317 // read the initial time step and the end time
318 Scalar endTime = Parameters::Get<Parameters::EndTime<Scalar>>();
319 if (endTime < -1e50) {
320 if (myRank == 0)
322 "Mandatory parameter '--end-time' not specified!");
323 return 1;
324 }
325
326 Scalar initialTimeStepSize = Parameters::Get<Parameters::InitialTimeStepSize<Scalar>>();
327 if (initialTimeStepSize < -1e50) {
328 if (myRank == 0)
330 "Mandatory parameter '--initial-time-step-size' "
331 "not specified!");
332 return 1;
333 }
334
335 if (myRank == 0) {
336#ifdef EWOMS_VERSION
337 std::string versionString = EWOMS_VERSION;
338#else
339 std::string versionString = "";
340#endif
341 const std::string briefDescription = Problem::briefDescription();
342 if (!briefDescription.empty()) {
343 std::string tmp = Parameters::breakLines_(briefDescription,
344 /*indentWidth=*/0,
346 std::cout << tmp << std::endl << std::endl;
347 }
348 else
349 std::cout << "opm models " << versionString
350 << " will now start the simulation. " << std::endl;
351 }
352
353 // print the parameters if requested
354 int printParams = Parameters::Get<Parameters::PrintParameters>();
355 if (myRank == 0) {
356 std::string endParametersSeparator("# [end of parameters]\n");
357 if (printParams) {
358 bool printSeparator = false;
359 if (printParams == 1 || !isatty(fileno(stdout))) {
361 printSeparator = true;
362 }
363 else
364 // always print the list of specified but unused parameters
365 printSeparator =
366 printSeparator ||
368 if (printSeparator)
369 std::cout << endParametersSeparator;
370 }
371 else
372 // always print the list of specified but unused parameters
374 std::cout << endParametersSeparator;
375 }
376
377 // instantiate and run the concrete problem. make sure to
378 // deallocate the problem and before the time manager and the
379 // grid
380 Simulator simulator;
381 simulator.run();
382
383 if (myRank == 0) {
384 std::cout << "Simulation completed" << std::endl;
385 }
386 return 0;
387 }
388 catch (std::exception& e)
389 {
390 if (myRank == 0) {
391 std::cout << e.what() << ". Abort!\n" << std::flush;
392
393 std::cout << "Trying to reset TTY.\n";
394 resetTerminal_();
395 }
396
397 return 1;
398 }
399 catch (...)
400 {
401 if (myRank == 0) {
402 std::cout << "Unknown exception thrown!\n" << std::flush;
403
404 std::cout << "Trying to reset TTY.\n";
405 resetTerminal_();
406 }
407
408 return 3;
409 }
410}
411
412} // namespace Opm
413
414#endif
static void registerParameters()
Registers all runtime parameters used by the simulation.
Definition: simulator.hh:255
static void init(bool queryCommandLineParameter=true)
Initialize number of threads used thread manager.
Definition: threadmanager.hh:77
static void registerParameters()
Register all run-time parameters of the thread manager.
Definition: threadmanager.hh:61
static int start(int argc, char **argv, bool registerParams=true)
Provides a main function which reads in parameters from the command line and a parameter file and run...
Definition: start.hh:277
bool printUnused(std::ostream &os=std::cout)
Print the list of unused run-time parameters.
Definition: parametersystem.hh:815
void printUsage(const std::string &helpPreamble, const std::string &errorMsg="", std::ostream &os=std::cerr, const bool showAll=false)
Print a usage message for all run-time parameters.
Definition: parametersystem.hh:421
void parseParameterFile(const std::string &fileName, bool overwrite=true)
Read the parameters from an INI-style file.
Definition: parametersystem.hh:693
std::string parseCommandLineOptions(int argc, const char **argv, const std::string &helpPreamble="", const PositionalArgumentCallback &posArgCallback=noPositionalParameters_)
Parse the parameters provided on the command line.
Definition: parametersystem.hh:587
void printValues(std::ostream &os=std::cout)
Print values of the run-time parameters.
Definition: parametersystem.hh:758
int getTtyWidth_()
Definition: parametersystem.hh:269
void endRegistration()
Indicate that all parameters are registered for a given type tag.
Definition: parametersystem.hh:1052
std::string breakLines_(const std::string &msg, int indentWidth, int maxWidth)
Definition: parametersystem.hh:220
void getLists(Container &usedParams, Container &unusedParams)
Retrieves the lists of parameters specified at runtime and their values.
Definition: parametersystem.hh:910
Definition: blackoilboundaryratevector.hh:37
int signum(Scalar val)
Template function which returns the sign of a floating point value.
Definition: signum.hh:40
This file provides the infrastructure to retrieve run-time parameters.
The Opm property system, traits with inheritance.