Flow123d
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 //#include "io/output.h"
42 
43 #include <iostream>
44 #include <fstream>
45 #include <boost/program_options/parsers.hpp>
46 #include <boost/program_options/variables_map.hpp>
47 #include <boost/program_options/options_description.hpp>
48 
49 #include "main.h"
50 //#include "io/read_ini.h"
51 
52 #include "rev_num.h"
53 
54 /// named version of the program
55 #define _PROGRAM_VERSION_ "1.8.1"
56 
57 #ifndef _PROGRAM_REVISION_
58  #define _PROGRAM_REVISION_ "(unknown revision)"
59 #endif
60 
61 #ifndef _PROGRAM_BRANCH_
62  #define _PROGRAM_BRANCH_ "(unknown branch)"
63 #endif
64 
65 #ifndef _COMPILER_FLAGS_
66  #define _COMPILER_FLAGS_ "(unknown compiler flags)"
67 #endif
68 
69 static void main_convert_to_output();
70 
71 
72 namespace it = Input::Type;
73 
74 // this should be part of a system class containing all support information
75 //static Record system_rec("System", "Record with general support data.");
76 //system_rec.finish();
78  = it::Record("Root", "Root record of JSON input for Flow123d.")
79  //main_rec.declare_key("system", system_rec, "");
81  "Simulation problem to be solved.")
82  .declare_key("pause_after_run", it::Bool(), it::Default("false"),
83  "If true, the program will wait for key press before it terminates.");
84 // .declare_key("output_streams", it::Array( OutputTime::input_type ),
85 // "Array of formated output streams to open.");
86 
87 
88 
89 Application::Application( int argc, char ** argv)
90 : ApplicationBase(argc, argv),
91  main_input_dir_("."),
92  main_input_filename_(""),
93  passed_argc_(0),
94  passed_argv_(0),
95  use_profiler(true)
96 {
97  // initialize python stuff if we have
98  // nonstandard python home (release builds)
99  std::cout << "Application constructor" << std::endl;
100 #ifdef HAVE_PYTHON
101 #ifdef PYTHON_HOME
102  PythonLoader::initialize(argv[0]);
103 #endif
104 #endif
105 
106 }
107 
108 
109 void Application::split_path(const string& path, string& directory, string& file_name) {
110 
111  size_t delim_pos=path.find_last_of(DIR_DELIMITER);
112  if (delim_pos < string::npos) {
113 
114  // It seems, that there is some path in fname ... separate it
115  directory =path.substr(0,delim_pos);
116  file_name =path.substr(delim_pos+1); // till the end
117  } else {
118  directory = ".";
119  file_name = path;
120  }
121 }
122 
124  // Say Hello
125  // make strings from macros in order to check type
126  string version(_PROGRAM_VERSION_);
127  string revision(_GIT_REVISION_);
128  string branch(_GIT_BRANCH_);
129  string url(_GIT_URL_);
130  string build = string(__DATE__) + ", " + string(__TIME__) + " flags: " + string(_COMPILER_FLAGS_);
131 
132 
133  xprintf(Msg, "This is Flow123d, version %s revision: %s\n", version.c_str(), revision.c_str());
134  xprintf(Msg,
135  "Branch: %s\n"
136  "Build: %s\n"
137  "Fetch URL: %s\n",
138  branch.c_str(), build.c_str() , url.c_str() );
139  Profiler::instance()->set_program_info("Flow123d", version, branch, revision, build);
140 }
141 
142 
143 
145  if (main_input_filename_ == "") {
146  cout << "Usage error: The main input file has to be specified through -s parameter.\n\n";
147  cout << program_arguments_desc_ << "\n";
148  exit( exit_failure );
149  }
150 
151  // read main input file
153  std::ifstream in_stream(fname.c_str());
154  if (! in_stream) {
155  xprintf(UsrErr, "Can not open main input file: '%s'.\n", fname.c_str());
156  }
157  try {
158  Input::JSONToStorage json_reader(in_stream, input_type );
160  } catch (Input::JSONToStorage::ExcInputError &e ) {
161  e << Input::JSONToStorage::EI_File(fname); throw;
162  } catch (Input::JSONToStorage::ExcNotJSONFormat &e) {
163  e << Input::JSONToStorage::EI_File(fname); throw;
164  }
165 
166  return root_record;
167 }
168 
169 
170 
171 
172 void Application::parse_cmd_line(const int argc, char ** argv) {
173  namespace po = boost::program_options;
174 
175 
176  // Declare the supported options.
177  po::options_description desc("Allowed options");
178  desc.add_options()
179  ("help", "produce help message")
180  ("solve,s", po::value< string >(), "Main input file to solve.")
181  ("input_dir,i", po::value< string >()->default_value("input"), "Directory for the ${INPUT} placeholder in the main input file.")
182  ("output_dir,o", po::value< string >()->default_value("output"), "Directory for all produced output files.")
183  ("log,l", po::value< string >()->default_value("flow123"), "Set base name for log files.")
184  ("version", "Display version and build information and exit.")
185  ("no_log", "Turn off logging.")
186  ("no_profiler", "Turn off profiler output.")
187  ("full_doc", "Prints full structure of the main input file.")
188  ("JSON_template", "Prints description of the main input file as a valid CON file.")
189  ("latex_doc", "Prints description of the main input file in Latex format using particular macros.")
190  ("JSON_machine", "Prints full structure of the main input file as a valid CON file.")
191  ("petsc_redirect", po::value<string>(), "Redirect all PETSc stdout and stderr to given file.");
192 
193  ;
194 
195  // parse the command line
196  po::variables_map vm;
197  po::parsed_options parsed = po::basic_command_line_parser<char>(argc, argv).options(desc).allow_unregistered().run();
198  po::store(parsed, vm);
199  po::notify(vm);
200 
201  // get unknown options
202  vector<string> to_pass_further = po::collect_unrecognized(parsed.options, po::include_positional);
203  passed_argc_ = to_pass_further.size();
204  passed_argv_ = new char * [passed_argc_+1];
205 
206  // first copy the program executable in argv[0]
207  int arg_i=0;
208  if (argc > 0) passed_argv_[arg_i++] = xstrcpy( argv[0] );
209 
210  for(int i=0; i < passed_argc_; i++) {
211  passed_argv_[arg_i++] = xstrcpy( to_pass_further[i].c_str() );
212  }
213  passed_argc_ = arg_i;
214 
215  // if there is "help" option
216  if (vm.count("help")) {
217  cout << desc << "\n";
218  exit( exit_output );
219  }
220 
221  if (vm.count("version")) {
222  display_version();
223  exit( exit_output );
224  }
225 
226  // if there is "full_doc" option
227  if (vm.count("full_doc")) {
229  Input::Type::OutputText type_output(&input_type);
230  type_output.set_filter(":Field:.*");
231  cout << type_output;
232  exit( exit_output );
233  }
234 
235  if (vm.count("JSON_template")) {
238  exit( exit_output );
239  }
240 
241  if (vm.count("latex_doc")) {
243  Input::Type::OutputLatex type_output(&input_type);
244  type_output.set_filter("");
245  cout << type_output;
246  exit( exit_output );
247  }
248 
249  if (vm.count("JSON_machine")) {
252  exit( exit_output );
253  }
254 
255  if (vm.count("petsc_redirect")) {
256  this->petsc_redirect_file_ = vm["petsc_redirect"].as<string>();
257  }
258 
259  // if there is "solve" option
260  if (vm.count("solve")) {
261  string input_filename = vm["solve"].as<string>();
263  }
264 
265  // possibly turn off profilling
266  if (vm.count("no_profiler")) use_profiler=false;
267 
268  string input_dir;
269  string output_dir;
270  if (vm.count("input_dir")) {
271  input_dir = vm["input_dir"].as<string>();
272  }
273  if (vm.count("output_dir")) {
274  output_dir = vm["output_dir"].as<string>();
275  }
276 
277  // assumes working directory "."
278  FilePath::set_io_dirs(".", main_input_dir_, input_dir, output_dir );
279 
280  if (vm.count("log")) {
281  this->log_filename_ = vm["log"].as<string>();
282  }
283 
284  if (vm.count("no_log")) {
285  this->log_filename_="//"; // override; do not open log files
286  }
287 
288  ostringstream tmp_stream(program_arguments_desc_);
289  tmp_stream << desc;
290  // TODO: catch specific exceptions and output usage messages
291 }
292 
293 
294 
295 
296 
298  //use_profiler=true;
299 
300 
301  display_version();
302 
303  Input::Record i_rec = read_input();
304 
305 
306  {
307  using namespace Input;
308  int i;
309 
310  // get main input record handle
311 
312  // should flow123d wait for pressing "Enter", when simulation is completed
313  sys_info.pause_after_run = i_rec.val<bool>("pause_after_run");
314  // read record with problem configuration
315  Input::AbstractRecord i_problem = i_rec.val<AbstractRecord>("problem");
316 
317  if (i_problem.type() == HC_ExplicitSequential::input_type ) {
318 
319  HC_ExplicitSequential *problem = new HC_ExplicitSequential(i_problem);
320 
321  // run simulation
322  problem->run_simulation();
323 
324  delete problem;
325  } else {
326  xprintf(UsrErr,"Problem type not implemented.");
327  }
328 
329  }
330 }
331 
332 
333 
334 
337  printf("\nPress <ENTER> for closing the window\n");
338  getchar();
339  }
340 }
341 
342 
343 
344 
347  Profiler::instance()->output(PETSC_COMM_WORLD);
349  }
350 }
351 
352 
353 //=============================================================================
354 
355 /**
356  * FUNCTION "MAIN"
357  */
358 int main(int argc, char **argv) {
359  try {
360  Application app(argc, argv);
361  app.init(argc, argv);
362  } catch (std::exception & e) {
363  std::cerr << e.what();
365  } catch (...) {
366  std::cerr << "Unknown exception" << endl;
368  }
369 
370  // Say Goodbye
372 }
373 
374 
375 
376 
377 
378 
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 
389 
390 
391 
392 
393 
394 
395 
396 
397 
398 
399 
400 
401 
402 
403 /**
404  * FUNCTION "MAIN" FOR CONVERTING FILES TO POS
405  */
407  // TODO: implement output of input data fields
408  // Fields to output:
409  // 1) volume data (simple)
410  // sources (Darcy flow and transport), initial condition, material id, partition id
411  // 2) boundary data (needs "virtual fractures" in output mesh)
412  // flow and transport bcd
413 
414  xprintf(Err, "Not implemented yet in this version\n");
415 }
416 #if 0
417 /**
418  * FUNCTION "MAIN" FOR COMPUTING MIXED-HYBRID PROBLEM
419  */
420 void main_compute_mh(struct Problem *problem) {
421  int type=OptGetInt("Global", "Problem_type", NULL);
422  switch (type) {
423  case STEADY_SATURATED:
424  main_compute_mh_steady_saturated(problem);
425  break;
426  case UNSTEADY_SATURATED:
427  main_compute_mh_unsteady_saturated(problem);
428  break;
429  case PROBLEM_DENSITY:
430  // main_compute_mh_density(problem);
431  break;
432  default:
433  xprintf(UsrErr,"Unsupported problem type: %d.",type);
434  }
435 }
436 
437 /**
438  * FUNCTION "MAIN" FOR COMPUTING MIXED-HYBRID PROBLEM FOR UNSTEADY SATURATED FLOW
439  */
440 void main_compute_mh_unsteady_saturated(struct Problem *problem)
441 {
442 
443  const string& mesh_file_name = IONameHandler::get_instance()->get_input_file_name(OptGetStr("Input", "Mesh", NULL));
444  MeshReader* meshReader = new GmshMeshReader();
445 
446  Mesh* mesh = new Mesh();
447  meshReader->read(mesh_file_name, mesh);
448  mesh->setup_topology();
449  mesh->setup_materials(* problem->material_database);
450  Profiler::instance()->set_task_size(mesh->n_elements());
451  OutputTime *output_time;
452  TimeMarks * main_time_marks = new TimeMarks();
453  int i;
454 
455  // setup output
456  string output_file = IONameHandler::get_instance()->get_output_file_name(OptGetFileName("Output", "Output_file", "\\"));
457  output_time = new OutputTime(mesh, output_file);
458 
459  DarcyFlowMH *water = new DarcyFlowLMH_Unsteady(main_time_marks,mesh, problem->material_database);
460  DarcyFlowMHOutput *water_output = new DarcyFlowMHOutput(water);
461  const TimeGovernor &water_time=water->get_time();
462 
463  // set output time marks
464  TimeMark::Type output_mark_type = main_time_marks->new_strict_mark_type();
465  main_time_marks->add_time_marks(0.0, OptGetDbl("Global", "Save_step", "1.0"), water_time.end_time(), output_mark_type );
466 
467  while (! water_time.is_end()) {
468  water->compute_one_step();
469  water_output->postprocess();
470 
471  if ( main_time_marks->is_current(water_time, output_mark_type) ) {
472  output_time->get_data_from_mesh();
473  // call output_time->register_node_data(name, unit, 0, data) to register other data on nodes
474  // call output_time->register_elem_data(name, unit, 0, data) to register other data on elements
475  output_time->write_data(water_time.t());
476  output_time->free_data_from_mesh();
477  }
478  }
479 }
480 
481 /**
482  * FUNCTION "MAIN" FOR COMPUTING MIXED-HYBRID PROBLEM FOR STEADY SATURATED FLOW
483  */
484 void main_compute_mh_steady_saturated(struct Problem *problem)
485 {
486  const string& mesh_file_name = IONameHandler::get_instance()->get_input_file_name(OptGetStr("Input", "Mesh", NULL));
487  MeshReader* meshReader = new GmshMeshReader();
488 
489  Mesh* mesh = new Mesh();
490  meshReader->read(mesh_file_name, mesh);
491  mesh->setup_topology();
492  mesh->setup_materials(* problem->material_database);
493  Profiler::instance()->set_task_size(mesh->n_elements());
494 
495  TimeMarks * main_time_marks = new TimeMarks();
496 
497  /*
498  Mesh* mesh;
499  ElementIter elm;
500  struct Side *sde;
501  FILE *out;
502  int i;
503  mesh=problem->mesh;
504  */
505 
506  problem->water=new DarcyFlowMH_Steady(main_time_marks, mesh, problem->material_database);
507  // Pointer at Output should be in this object
508  DarcyFlowMHOutput *water_output = new DarcyFlowMHOutput(problem->water);
509 
510  problem->water->compute_one_step();
511 
512  if (OptGetBool("Transport", "Transport_on", "no") == true) {
513  problem->otransport = new ConvectionTransport(problem->material_database, mesh);
514  problem->transport_os = new TransportOperatorSplitting(problem->material_database, mesh);
515  }
516 
517 
518  water_output->postprocess();
519 
520  /* Write static data to output file */
521  string out_fname = IONameHandler::get_instance()->get_output_file_name(OptGetFileName("Output", "Output_file", NULL));
522  Output *output = new Output(mesh, out_fname);
523  output->get_data_from_mesh();
524  // call output->register_node_data(name, unit, data) here to register other data on nodes
525  // call output->register_elem_data(name, unit, data) here to register other data on elements
526  output->write_data();
527  output->free_data_from_mesh();
528  delete output;
529 
530  // pracovni vystup nekompatibilniho propojeni
531  // melo by to byt ve water*
532  /*
533  {
534  ElementIter ele;
535  Element *ele2;
536  int ngi;
537  Neighbour *ngh;
538  Mesh* mesh = problem->mesh;
539 
540  double sum1,sum2;
541  DarcyFlowMH *w=problem->water;
542  double *x = w->schur0->vx;
543 
544 
545  FOR_ELEMENTS_IT( ele ) {
546  FOR_ELM_NEIGHS_VV( ele, ngi ) {
547  ngh = ele->neigh_vv[ ngi ];
548  // get neigbour element, and set appropriate column
549  ele2 = ( ngh->element[ 0 ] == &(*ele) ) ? ngh->element[ 1 ] : ngh->element[ 0 ];
550 
551  double out_flux=0.0;
552  for(i=0;i<=ele->dim;i++) out_flux+=x[w->side_row_4_id[ele->side[i]->id]];
553  xprintf(Msg,"El 1 (%f,%f) %d %f %g\n",
554  ele->centre[0],
555  ele->centre[1],
556  ele->dim,
557  x[w->el_row_4_id[ele->id]],out_flux);
558 
559  out_flux=0.0;
560  for(i=0;i<=ele2->dim;i++) out_flux+=x[w->side_row_4_id[ele2->side[i]->id]];
561 
562  xprintf(Msg,"El 2 (%f,%f) %d %f %g\n",
563  ele2->centre[0],
564  ele2->centre[1],
565  ele2->dim,
566  x[w->el_row_4_id[ele2->id]],out_flux);
567  }
568  }
569  }
570 
571  out = xfopen("pepa.txt","wt");
572 
573  FOR_ELEMENTS(elm)
574  elm->aux = 0;
575 
576  FOR_ELEMENTS(elm)
577  FOR_ELEMENT_SIDES(elm,i)
578  if(elm->side[i]->type == EXTERNAL)
579  if((elm->side[i]->centre[2] - elm->centre[2]) > 0.0)
580  if(elm->side[i]->normal[2] != 0.0)
581  if((elm->side[i]->centre[2]) > 300.0)
582  if((elm->material->id == 2200) || (elm->material->id == 2207) || (elm->material->id == 2212) || (elm->material->id == 2217) || (elm->material->id == 9100) || (elm->material->id == 9107) || (elm->material->id == 9112) || (elm->material->id == 9117))
583  elm->aux = 1;
584 
585  FOR_ELEMENTS(elm)
586  if(elm->aux == 1)
587  xfprintf(out,"%d\n",elm->id);
588 
589  xfclose(out);
590  */
591 
592  if (OptGetBool("Transport", "Transport_on", "no") == true) {
593  problem->otransport->convection();
594  }
595 
596  /*
597  if (OptGetBool("Transport", "Reactions", "no") == true) {
598  read_reaction_list(transport);
599  }
600 */
601  //if (rank == 0) {
602 
603  //}
604 
605  // TODO: there is an uncoditioned jump in open_temp_files
606  // also this function should be moved to btc.*
607  // btc should be documented and have an clearly defined interface
608  // not strictly dependent on Transport.
609  //btc_check(transport);
610 
611 
612 
613  /*
614  if(problem->cross_section == true)
615  {
616  elect_cross_section_element(problem);
617  output_transport_init_CS(problem);
618  output_transport_time_CS(problem, 0 * problem->time_step);
619  }
620  */
621 }
622 //-----------------------------------------------------------------------------
623 // vim: set cindent:
624 //-----------------------------------------------------------------------------
625 #endif
626 #if 0
627 
628 /**
629  * FUNCTION "MAIN" FOR COMPUTING MIXED-HYBRID PROBLEM FOR UNSTEADY SATURATED FLOW
630  */
631 void main_compute_mh_density(struct Problem *problem)
632 {
633  Mesh* mesh = (Mesh*) ConstantDB::getInstance()->getObject(MESH::MAIN_INSTANCE);
634  int i, j, dens_step, n_step, frame = 0, rank;
635  double save_step, stop_time; // update_dens_time
636  char statuslog[255];
637  FILE *log;
638  OutputTime *output_time = NULL;
639 
640  MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
641 
642 /*
643  transport_output_init(problem->otransport->transport_out_fname);
644  transport_output(problem->otransport->out_conc,problem->otransport->substance_name ,problem->otransport->n_substances, 0.0, ++frame,problem->otransport->transport_out_fname);
645 */
646 
647  if(rank == 0) {
648  output_time = new OutputTime(mesh, problem->otransport->transport_out_fname);
649  }
650 
651  //save_step = problem->save_step;
652  //stop_time = problem->stop_time;
653  //trans->update_dens_time = problem->save_step / (ceil(problem->save_step / trans->dens_step));
654  //dens_step = (int) ceil(problem->stop_time / trans->update_dens_time);
655  //n_step = (int) (problem->save_step / trans->update_dens_time);
656 
657  // DF problem - I don't understend to this construction !!!
658  //problem->save_step = problem->stop_time = trans->update_dens_time;
659 
660 
661  /*
662 
663 
664 
665  //------------------------------------------------------------------------------
666  // Status LOG head
667  //------------------------------------------------------------------------------
668  //sprintf( statuslog,"%s.txt",problem->log_fname);
669  sprintf(statuslog, "density_log.txt");
670  log = xfopen(statuslog, "wt");
671 
672  xfprintf(log, "Stop time = %f (%f) \n", trans->update_dens_time * dens_step, stop_time);
673  xfprintf(log, "Save step = %f \n", save_step);
674  xfprintf(log, "Density step = %f (%d) \n\n", trans->update_dens_time, trans->dens_step);
675  xfprintf(log, "Time\t Iteration number\n");
676  //------------------------------------------------------------------------------
677 
678  for (i = 0; i < dens_step; i++) {
679  xprintf(Msg, "dens step %d \n", i);
680  save_time_step_C(problem);
681 
682  for (j = 0; j < trans->max_dens_it; j++) {
683  xprintf(Msg, "dens iter %d \n", j);
684  save_restart_iteration_H(problem);
685  //restart_iteration(problem);
686  //calculation_mh(problem);
687  //problem->water=new DarcyFlowMH(*mesh);
688  //problem->water->solve();
689  restart_iteration_C(problem);
690  //postprocess(problem);
691  convection(trans, output_time);
692 
693  if (trans->dens_implicit == 0) {
694  xprintf(Msg, "no density iterations (explicit)", j);
695  break;
696  }
697  if (compare_dens_iter(problem) && (j > 0)) {
698  break; //at least one repeat of iteration is necessary to update both conc and pressure
699  }
700  }
701 
702  xprintf(Msg, "step %d finished at %d density iterations\n", i, j);
703  xfprintf(log, "%f \t %d\n", (i + 1) * trans->update_dens_time, j); // Status LOG
704  }
705 
706  if(rank == 0) {
707  delete output_time;
708  }
709 
710  xfclose(log); */
711 //}
712 #endif
713