Flow123d  jenkins-Flow123d-windows32-release-multijob-51
main.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id$
21  * $Revision$
22  * $LastChangedBy$
23  * $LastChangedDate$
24  *
25  * @file main.cc
26  * @brief This file should contain only creation of Application object.
27  *
28  */
29 
30 
31 #include <petsc.h>
32 
33 #include "system/system.hh"
34 #include "system/sys_profiler.hh"
35 #include "system/python_loader.hh"
37 #include "input/input_type.hh"
38 #include "input/type_output.hh"
39 #include "input/accessors.hh"
40 #include "input/json_to_storage.hh"
41 
42 #include <iostream>
43 #include <fstream>
44 #include <boost/program_options/parsers.hpp>
45 #include <boost/program_options/variables_map.hpp>
46 #include <boost/program_options/options_description.hpp>
47 
48 #include "main.h"
49 
50 #include "rev_num.h"
51 
52 /// named version of the program
53 #define _PROGRAM_VERSION_ "0.0.0"
54 
55 #ifndef _PROGRAM_REVISION_
56  #define _PROGRAM_REVISION_ "(unknown revision)"
57 #endif
58 
59 #ifndef _PROGRAM_BRANCH_
60  #define _PROGRAM_BRANCH_ "(unknown branch)"
61 #endif
62 
63 #ifndef _COMPILER_FLAGS_
64  #define _COMPILER_FLAGS_ "(unknown compiler flags)"
65 #endif
66 
67 
68 namespace it = Input::Type;
69 
70 // this should be part of a system class containing all support information
72  = it::Record("Root", "Root record of JSON input for Flow123d.")
74  "Simulation problem to be solved.")
75  .declare_key("pause_after_run", it::Bool(), it::Default("false"),
76  "If true, the program will wait for key press before it terminates.");
77 
78 
79 
80 Application::Application( int argc, char ** argv)
81 : ApplicationBase(argc, argv),
82  main_input_dir_("."),
83  main_input_filename_(""),
84  passed_argc_(0),
85  passed_argv_(0),
86  use_profiler(true)
87 {
88  // initialize python stuff if we have
89  // nonstandard python home (release builds)
90 #ifdef HAVE_PYTHON
91  PythonLoader::initialize(argv[0]);
92 #endif
93 
94 }
95 
96 
97 void Application::split_path(const string& path, string& directory, string& file_name) {
98 
99  size_t delim_pos=path.find_last_of(DIR_DELIMITER);
100  if (delim_pos < string::npos) {
101 
102  // It seems, that there is some path in fname ... separate it
103  directory =path.substr(0,delim_pos);
104  file_name =path.substr(delim_pos+1); // till the end
105  } else {
106  directory = ".";
107  file_name = path;
108  }
109 }
110 
112  // Say Hello
113  // make strings from macros in order to check type
114  string version(_VERSION_NAME_);
115  string revision(_GIT_REVISION_);
116  string branch(_GIT_BRANCH_);
117  string url(_GIT_URL_);
118  string build = string(__DATE__) + ", " + string(__TIME__) + " flags: " + string(_COMPILER_FLAGS_);
119 
120 
121  xprintf(Msg, "This is Flow123d, version %s revision: %s\n", version.c_str(), revision.c_str());
122  xprintf(Msg,
123  "Branch: %s\n"
124  "Build: %s\n"
125  "Fetch URL: %s\n",
126  branch.c_str(), build.c_str() , url.c_str() );
127  Profiler::instance()->set_program_info("Flow123d", version, branch, revision, build);
128 }
129 
130 
131 
133  if (main_input_filename_ == "") {
134  cout << "Usage error: The main input file has to be specified through -s parameter.\n\n";
135  cout << program_arguments_desc_ << "\n";
136  exit( exit_failure );
137  }
138 
139  // read main input file
141  std::ifstream in_stream(fname.c_str());
142  if (! in_stream) {
143  xprintf(UsrErr, "Can not open main input file: '%s'.\n", fname.c_str());
144  }
145  try {
146  Input::JSONToStorage json_reader(in_stream, input_type );
148  } catch (Input::JSONToStorage::ExcInputError &e ) {
149  e << Input::JSONToStorage::EI_File(fname); throw;
150  } catch (Input::JSONToStorage::ExcNotJSONFormat &e) {
151  e << Input::JSONToStorage::EI_File(fname); throw;
152  }
153 
154  return root_record;
155 }
156 
157 
158 
159 
160 void Application::parse_cmd_line(const int argc, char ** argv) {
161  namespace po = boost::program_options;
162 
163 
164  // Declare the supported options.
165  po::options_description desc("Allowed options");
166  desc.add_options()
167  ("help", "produce help message")
168  ("solve,s", po::value< string >(), "Main input file to solve.")
169  ("input_dir,i", po::value< string >()->default_value("input"), "Directory for the ${INPUT} placeholder in the main input file.")
170  ("output_dir,o", po::value< string >()->default_value("output"), "Directory for all produced output files.")
171  ("log,l", po::value< string >()->default_value("flow123"), "Set base name for log files.")
172  ("version", "Display version and build information and exit.")
173  ("no_log", "Turn off logging.")
174  ("no_profiler", "Turn off profiler output.")
175  ("full_doc", "Prints full structure of the main input file.")
176  ("JSON_template", "Prints description of the main input file as a valid CON file.")
177  ("latex_doc", "Prints description of the main input file in Latex format using particular macros.")
178  ("JSON_machine", "Prints full structure of the main input file as a valid CON file.")
179  ("petsc_redirect", po::value<string>(), "Redirect all PETSc stdout and stderr to given file.");
180 
181  ;
182 
183  // parse the command line
184  po::variables_map vm;
185  po::parsed_options parsed = po::basic_command_line_parser<char>(argc, argv).options(desc).allow_unregistered().run();
186  po::store(parsed, vm);
187  po::notify(vm);
188 
189  // get unknown options
190  vector<string> to_pass_further = po::collect_unrecognized(parsed.options, po::include_positional);
191  passed_argc_ = to_pass_further.size();
192  passed_argv_ = new char * [passed_argc_+1];
193 
194  // first copy the program executable in argv[0]
195  int arg_i=0;
196  if (argc > 0) passed_argv_[arg_i++] = xstrcpy( argv[0] );
197 
198  for(int i=0; i < passed_argc_; i++) {
199  passed_argv_[arg_i++] = xstrcpy( to_pass_further[i].c_str() );
200  }
201  passed_argc_ = arg_i;
202 
203  // if there is "help" option
204  if (vm.count("help")) {
205  cout << desc << "\n";
206  exit( exit_output );
207  }
208 
209  if (vm.count("version")) {
210  display_version();
211  exit( exit_output );
212  }
213 
214  // if there is "full_doc" option
215  if (vm.count("full_doc")) {
217  Input::Type::OutputText type_output(&input_type);
218  type_output.set_filter(":Field:.*");
219  cout << type_output;
220  exit( exit_output );
221  }
222 
223  if (vm.count("JSON_template")) {
226  exit( exit_output );
227  }
228 
229  if (vm.count("latex_doc")) {
231  Input::Type::OutputLatex type_output(&input_type);
232  type_output.set_filter("");
233  cout << type_output;
234  exit( exit_output );
235  }
236 
237  if (vm.count("JSON_machine")) {
240  exit( exit_output );
241  }
242 
243  if (vm.count("petsc_redirect")) {
244  this->petsc_redirect_file_ = vm["petsc_redirect"].as<string>();
245  }
246 
247  // if there is "solve" option
248  if (vm.count("solve")) {
249  string input_filename = vm["solve"].as<string>();
251  }
252 
253  // possibly turn off profilling
254  if (vm.count("no_profiler")) use_profiler=false;
255 
256  string input_dir;
257  string output_dir;
258  if (vm.count("input_dir")) {
259  input_dir = vm["input_dir"].as<string>();
260  }
261  if (vm.count("output_dir")) {
262  output_dir = vm["output_dir"].as<string>();
263  }
264 
265  // assumes working directory "."
266  FilePath::set_io_dirs(".", main_input_dir_, input_dir, output_dir );
267 
268  if (vm.count("log")) {
269  this->log_filename_ = vm["log"].as<string>();
270  }
271 
272  if (vm.count("no_log")) {
273  this->log_filename_="//"; // override; do not open log files
274  }
275 
276  ostringstream tmp_stream(program_arguments_desc_);
277  tmp_stream << desc;
278  // TODO: catch specific exceptions and output usage messages
279 }
280 
281 
282 
283 
284 
286 
287  display_version();
288 
289  Input::Record i_rec = read_input();
290 
291 
292  {
293  using namespace Input;
294 
295  // get main input record handle
296 
297  // should flow123d wait for pressing "Enter", when simulation is completed
298  sys_info.pause_after_run = i_rec.val<bool>("pause_after_run");
299  // read record with problem configuration
300  Input::AbstractRecord i_problem = i_rec.val<AbstractRecord>("problem");
301 
302  if (i_problem.type() == HC_ExplicitSequential::input_type ) {
303 
304  HC_ExplicitSequential *problem = new HC_ExplicitSequential(i_problem);
305 
306  // run simulation
307  problem->run_simulation();
308 
309  delete problem;
310  } else {
311  xprintf(UsrErr,"Problem type not implemented.");
312  }
313 
314  }
315 }
316 
317 
318 
319 
322  printf("\nPress <ENTER> for closing the window\n");
323  getchar();
324  }
325 }
326 
327 
328 
329 
332  Profiler::instance()->output(PETSC_COMM_WORLD);
334  }
335 }
336 
337 
338 //=============================================================================
339 
340 /**
341  * FUNCTION "MAIN"
342  */
343 int main(int argc, char **argv) {
344  try {
345  Application app(argc, argv);
346  app.init(argc, argv);
347  } catch (std::exception & e) {
348  std::cerr << e.what();
350  } catch (...) {
351  std::cerr << "Unknown exception" << endl;
353  }
354 
355  // Say Goodbye
357 }
358 
virtual void run()
Definition: main.cc:285
Definition: system.hh:72
virtual void parse_cmd_line(const int argc, char **argv)
Definition: main.cc:160
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:39
Class for declaration of the input of type Bool.
Definition: type_base.hh:321
string main_input_filename_
filename of main input file
Definition: main.h:100
static Profiler * instance()
virtual void after_run()
Definition: main.cc:320
Application(int argc, char **argv)
Application constructor.
Definition: main.cc:80
static Input::Type::AbstractRecord input_type
static Default obligatory()
Definition: type_record.hh:87
Class for create JSON machine readable documentation.
Definition: type_output.hh:421
void set_filter(string regex_filter)
Initializes and allocates regular expression filter regex_filter.
Definition: type_output.cc:47
char * xstrcpy(const char *src)
MAKE BRAND NEW COPY OF STRING.
Definition: system.cc:312
bool use_profiler
If true, we do output of profiling information.
Definition: main.h:109
???
static void uninitialize()
static const int exit_failure
static void lazy_finish()
Finishes all registered lazy types.
Definition: type_base.cc:86
static const int exit_success
Return codes of application.
Accessor to the data with type Type::Record.
Definition: accessors.hh:308
const Ret val(const string &key) const
#define xprintf(...)
Definition: system.hh:100
string main_input_dir_
directory of main input file (used to resolve relative paths of other input files) ...
Definition: main.h:98
void display_version()
Definition: main.cc:111
void split_path(const string &path, string &directory, string &file_name)
Definition: main.cc:97
char ** passed_argv_
Definition: main.h:103
void set_program_info(string program_name, string program_version, string branch, string revision, string build)
static Input::Type::Record input_type
int passed_argc_
Definition: main.h:102
int main(int argc, char **argv)
Definition: main.cc:343
void init(int argc, char **argv)
Accessor to the polymorphic input data of a type given by an AbstracRecord object.
Definition: accessors.hh:423
#define _COMPILER_FLAGS_
Definition: main.cc:64
Definition: system.hh:72
Class for create documentation in Latex format using particular macros.
Definition: type_output.hh:382
static void set_io_dirs(const string working_dir, const string root_input, const string input, const string output)
Definition: file_path.cc:42
static Input::Type::Record input_type
Root of the Input::Type tree. Description of whole input structure.
Definition: main.h:45
Class for create and JSON template documentation.
Definition: type_output.hh:322
static const int exit_output
string program_arguments_desc_
Description of possible command line arguments.
Definition: main.h:106
#define DIR_DELIMITER
Definition: system.hh:56
SystemInfo sys_info
Definition: system.cc:53
Class for create text documentation.
Definition: type_output.hh:286
Record type proxy class.
Definition: type_record.hh:161
Class for solution of steady or unsteady flow with sequentially coupled explicit transport.
static bool is_initialized()
Reader for (slightly) modified JSON files.
virtual ~Application()
Destructor.
Definition: main.cc:330
Input::Record root_record
root input record
Definition: main.h:112
void output(MPI_Comm comm, ostream &os)
int pause_after_run
Definition: system.hh:81
Input::Record read_input()
Definition: main.cc:132
Record & declare_key(const string &key, const KeyType &type, const Default &default_value, const string &description)
Definition: type_record.cc:386