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::registerParam<TypeTag, Properties::ParameterFile>
82 ("An .ini file which contains a set of run-time parameters");
83 Parameters::registerParam<TypeTag, Properties::PrintProperties>
84 ("Print the values of the compile time properties at "
85 "the start of the simulation");
86 Parameters::registerParam<TypeTag, Properties::PrintParameters>
87 ("Print the values of the run-time parameters at the "
88 "start of the simulation");
89
92
93 if (finalizeRegistration) {
94 Parameters::endParamRegistration<TypeTag>();
95 }
96}
97
107template <class TypeTag>
108static inline int setupParameters_(int argc,
109 const char **argv,
110 bool registerParams=true,
111 bool allowUnused=false,
112 bool handleHelp = true)
113{
114 using Problem = GetPropType<TypeTag, Properties::Problem>;
115
116 // first, get the MPI rank of the current process
117 int myRank = 0;
118
120 // Register all parameters
122 if (registerParams)
123 registerAllParameters_<TypeTag>();
124
126 // set the parameter values
128
129 // fill the parameter tree with the options from the command line
130 const auto& positionalParamCallback = Problem::handlePositionalParameter;
131 std::string helpPreamble = ""; // print help if non-empty!
132 if (myRank == 0 && handleHelp)
133 helpPreamble = Problem::helpPreamble(argc, argv);
134 std::string s =
135 Parameters::parseCommandLineOptions<TypeTag>(argc,
136 argv,
137 helpPreamble,
138 positionalParamCallback);
139 if (!s.empty())
140 {
141 int status = 1;
142 if (s == "Help called") // only on master process
143 status = -1; // Use negative values to indicate --help argument
144#if HAVE_MPI
145 // Force -1 if the master process has that.
146 int globalStatus;
147 MPI_Allreduce(&status, &globalStatus, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
148 return globalStatus;
149#endif
150 return status;
151 }
152
153 const std::string paramFileName = Parameters::get<TypeTag, Properties::ParameterFile>(false);
154 if (!paramFileName.empty()) {
156 // add the parameters specified using an .ini file
158
159 // check whether the parameter file is readable.
160 std::ifstream tmp;
161 tmp.open(paramFileName.c_str());
162 if (!tmp.is_open()) {
163 std::ostringstream oss;
164 if (myRank == 0) {
165 oss << "Parameter file \"" << paramFileName
166 << "\" does not exist or is not readable.";
167 Parameters::printUsage<TypeTag>(argv[0], oss.str());
168 }
169 return /*status=*/1;
170 }
171
172 // read the parameter file.
173 Parameters::parseParameterFile<TypeTag>(paramFileName, /*overwrite=*/false);
174 }
175
176 // make sure that no unknown parameters are encountered
177 using KeyValuePair = std::pair<std::string, std::string>;
178 using ParamList = std::list<KeyValuePair>;
179
180 ParamList usedParams;
181 ParamList unusedParams;
182
183 Parameters::getLists<TypeTag>(usedParams, unusedParams);
184 if (!allowUnused && !unusedParams.empty()) {
185 if (myRank == 0) {
186 if (unusedParams.size() == 1)
187 std::cerr << "The following explicitly specified parameter is unknown:\n";
188 else
189 std::cerr << "The following " << unusedParams.size()
190 << " explicitly specified parameters are unknown:\n";
191
192 std::cerr << "\n";
193 for (const auto& keyValue : unusedParams)
194 std::cerr << " " << keyValue.first << "=\"" << keyValue.second << "\"\n";
195 std::cerr << "\n";
196
197 std::cerr << "Use\n"
198 << "\n"
199 << " " << argv[0] << " --help\n"
200 << "\n"
201 <<"to obtain the list of recognized command line parameters.\n\n";
202 }
203 return /*status=*/1;
204 }
205
206 return /*status=*/0;
207}
208
214static inline void resetTerminal_()
215{
216 // make sure stderr and stderr do not contain any unwritten data and make sure that
217 // the TTY does not see any unfinished ANSI escape sequence.
218 std::cerr << " \r\n";
219 std::cerr.flush();
220 std::cout << " \r\n";
221 std::cout.flush();
222
223 // it seems like some terminals sometimes takes their time to react, so let's
224 // accommodate them.
225 usleep(/*usec=*/500*1000);
226
227 // this requires the 'stty' command to be available in the command search path. on
228 // most linux systems, is the case. (but even if the system() function fails, the
229 // worst thing which can happen is that the TTY stays potentially choked up...)
230 if (system("stty sane") != 0)
231 std::cout << "Executing the 'stty' command failed."
232 << " Terminal might be left in an undefined state!\n";
233}
234
239static inline void resetTerminal_(int signum)
240{
241 // first thing to do when a nuke hits: restore the default signal handler
242 signal(signum, SIG_DFL);
243
244#if HAVE_MPI
245 int rank = 0;
246 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
247 if (rank != 0) {
248 // re-raise the signal
249 raise(signum);
250
251 return;
252 }
253#endif
254
255 if (isatty(fileno(stdout)) && isatty(fileno(stdin))) {
256 std::cout << "\n\nReceived signal " << signum
257 << " (\"" << strsignal(signum) << "\")."
258 << " Trying to reset the terminal.\n";
259
260 resetTerminal_();
261 }
262
263 // after we did our best to clean the pedestrian way, re-raise the signal
264 raise(signum);
265}
267
279template <class TypeTag>
280static inline int start(int argc, char **argv, bool registerParams=true)
281{
282 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
283 using Simulator = GetPropType<TypeTag, Properties::Simulator>;
284 using Problem = GetPropType<TypeTag, Properties::Problem>;
285 using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
286
287 // set the signal handlers to reset the TTY to a well defined state on unexpected
288 // program aborts
289 if (isatty(STDIN_FILENO)) {
290 signal(SIGINT, resetTerminal_);
291 signal(SIGHUP, resetTerminal_);
292 signal(SIGABRT, resetTerminal_);
293 signal(SIGFPE, resetTerminal_);
294 signal(SIGSEGV, resetTerminal_);
295 signal(SIGPIPE, resetTerminal_);
296 signal(SIGTERM, resetTerminal_);
297 }
298
299 resetLocale();
300
301 int myRank = 0;
302 try
303 {
304 int paramStatus = setupParameters_<TypeTag>(argc, const_cast<const char**>(argv), registerParams);
305 if (paramStatus == 1)
306 return 1;
307 if (paramStatus == 2)
308 return 0;
309
311
312 // initialize MPI, finalize is done automatically on exit
313#if HAVE_DUNE_FEM
314 Dune::Fem::MPIManager::initialize(argc, argv);
315 myRank = Dune::Fem::MPIManager::rank();
316#else
317 myRank = Dune::MPIHelper::instance(argc, argv).rank();
318#endif
319
320 // read the initial time step and the end time
321 Scalar endTime = Parameters::get<TypeTag, Properties::EndTime>();
322 if (endTime < -1e50) {
323 if (myRank == 0)
324 Parameters::printUsage<TypeTag>(argv[0],
325 "Mandatory parameter '--end-time' not specified!");
326 return 1;
327 }
328
329 Scalar initialTimeStepSize = Parameters::get<TypeTag, Properties::InitialTimeStepSize>();
330 if (initialTimeStepSize < -1e50) {
331 if (myRank == 0)
332 Parameters::printUsage<TypeTag>(argv[0],
333 "Mandatory parameter '--initial-time-step-size' "
334 "not specified!");
335 return 1;
336 }
337
338 if (myRank == 0) {
339#ifdef EWOMS_VERSION
340 std::string versionString = EWOMS_VERSION;
341#else
342 std::string versionString = "";
343#endif
344 const std::string briefDescription = Problem::briefDescription();
345 if (!briefDescription.empty()) {
346 std::string tmp = Parameters::breakLines_(briefDescription,
347 /*indentWidth=*/0,
349 std::cout << tmp << std::endl << std::endl;
350 }
351 else
352 std::cout << "opm models " << versionString
353 << " will now start the simulation. " << std::endl;
354 }
355
356 // print the parameters if requested
357 int printParams = Parameters::get<TypeTag, Properties::PrintParameters>();
358 if (myRank == 0) {
359 std::string endParametersSeparator("# [end of parameters]\n");
360 if (printParams) {
361 bool printSeparator = false;
362 if (printParams == 1 || !isatty(fileno(stdout))) {
363 Parameters::printValues<TypeTag>();
364 printSeparator = true;
365 }
366 else
367 // always print the list of specified but unused parameters
368 printSeparator =
369 printSeparator ||
370 Parameters::printUnused<TypeTag>();
371 if (printSeparator)
372 std::cout << endParametersSeparator;
373 }
374 else
375 // always print the list of specified but unused parameters
376 if (Parameters::printUnused<TypeTag>())
377 std::cout << endParametersSeparator;
378 }
379
380 // print the properties if requested
381 int printProps = Parameters::get<TypeTag, Properties::PrintProperties>();
382 if (printProps && myRank == 0) {
383 if (printProps == 1 || !isatty(fileno(stdout)))
384 Properties::printValues<TypeTag>(std::cout);
385 }
386
387 // instantiate and run the concrete problem. make sure to
388 // deallocate the problem and before the time manager and the
389 // grid
390 Simulator simulator;
391 simulator.run();
392
393 if (myRank == 0) {
394 std::cout << "Simulation completed" << std::endl;
395 }
396 return 0;
397 }
398 catch (std::exception& e)
399 {
400 if (myRank == 0) {
401 std::cout << e.what() << ". Abort!\n" << std::flush;
402
403 std::cout << "Trying to reset TTY.\n";
404 resetTerminal_();
405 }
406
407 return 1;
408 }
409 catch (...)
410 {
411 if (myRank == 0) {
412 std::cout << "Unknown exception thrown!\n" << std::flush;
413
414 std::cout << "Trying to reset TTY.\n";
415 resetTerminal_();
416 }
417
418 return 3;
419 }
420}
421
422} // namespace Opm
423
424#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:280
int getTtyWidth_()
Definition: parametersystem.hh:246
std::string breakLines_(const std::string &msg, int indentWidth, int maxWidth)
Definition: parametersystem.hh:197
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.