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