My Project
FlowMainEbos.hpp
1 /*
2  Copyright 2013, 2014, 2015 SINTEF ICT, Applied Mathematics.
3  Copyright 2014 Dr. Blatt - HPC-Simulation-Software & Services
4  Copyright 2015 IRIS AS
5  Copyright 2014 STATOIL ASA.
6 
7  This file is part of the Open Porous Media project (OPM).
8 
9  OPM is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OPM is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OPM. If not, see <http://www.gnu.org/licenses/>.
21 */
22 #ifndef OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED
23 #define OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED
24 
25 
26 #include <sys/utsname.h>
27 
28 #include <opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp>
29 #include <opm/simulators/utils/ParallelFileMerger.hpp>
30 #include <opm/simulators/utils/moduleVersion.hpp>
31 #include <opm/simulators/utils/ParallelEclipseState.hpp>
32 #include <flow/flow_ebos_blackoil.hpp>
33 
34 #include <opm/input/eclipse/EclipseState/EclipseState.hpp>
35 #include <opm/input/eclipse/EclipseState/IOConfig/IOConfig.hpp>
36 #include <opm/input/eclipse/EclipseState/InitConfig/InitConfig.hpp>
37 #include <opm/input/eclipse/Schedule/UDQ/UDQState.hpp>
38 #include <opm/common/utility/String.hpp>
39 
40 #include <fmt/format.h>
41 #include <filesystem>
42 
43 #if HAVE_DUNE_FEM
44 #include <dune/fem/misc/mpimanager.hh>
45 #else
46 #include <dune/common/parallel/mpihelper.hh>
47 #endif
48 
49 namespace Opm::Properties {
50 
51 template<class TypeTag, class MyTypeTag>
52 struct EnableDryRun {
53  using type = UndefinedProperty;
54 };
55 template<class TypeTag, class MyTypeTag>
57  using type = UndefinedProperty;
58 };
59 template<class TypeTag, class MyTypeTag>
61  using type = UndefinedProperty;
62 };
63 
64 // TODO: enumeration parameters. we use strings for now.
65 template<class TypeTag>
66 struct EnableDryRun<TypeTag, TTag::EclFlowProblem> {
67  static constexpr auto value = "auto";
68 };
69 // Do not merge parallel output files or warn about them
70 template<class TypeTag>
71 struct EnableLoggingFalloutWarning<TypeTag, TTag::EclFlowProblem> {
72  static constexpr bool value = false;
73 };
74 template<class TypeTag>
75 struct OutputInterval<TypeTag, TTag::EclFlowProblem> {
76  static constexpr int value = 1;
77 };
78 
79 } // namespace Opm::Properties
80 
81 namespace Opm
82 {
83 
84  class Deck;
85 
86  // The FlowMain class is the ebos based black-oil simulator.
87  template <class TypeTag>
89  {
90  public:
91  using MaterialLawManager = typename GetProp<TypeTag, Properties::MaterialLaw>::EclMaterialLawManager;
92  using EbosSimulator = GetPropType<TypeTag, Properties::Simulator>;
93  using Grid = GetPropType<TypeTag, Properties::Grid>;
94  using GridView = GetPropType<TypeTag, Properties::GridView>;
95  using Problem = GetPropType<TypeTag, Properties::Problem>;
96  using Scalar = GetPropType<TypeTag, Properties::Scalar>;
97  using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
98 
100 
101  FlowMainEbos(int argc, char **argv, bool output_cout, bool output_files )
102  : argc_{argc}, argv_{argv},
103  output_cout_{output_cout}, output_files_{output_files}
104  {
105 
106  }
107 
108  // Read the command line parameters. Throws an exception if something goes wrong.
109  static int setupParameters_(int argc, char** argv, Parallel::Communication comm)
110  {
111  using ParamsMeta = GetProp<TypeTag, Properties::ParameterMetaData>;
112  if (!ParamsMeta::registrationOpen()) {
113  // We have already successfully run setupParameters_().
114  // For the dynamically chosen runs (as from the main flow
115  // executable) we must run this function again with the
116  // real typetag to be used, as the first time was with the
117  // "FlowEarlyBird" typetag. However, for the static ones (such
118  // as 'flow_onephase_energy') it has already been run with the
119  // correct typetag.
120  return EXIT_SUCCESS;
121  }
122  // register the flow specific parameters
123  EWOMS_REGISTER_PARAM(TypeTag, std::string, EnableDryRun,
124  "Specify if the simulation ought to be actually run, or just pretended to be");
125  EWOMS_REGISTER_PARAM(TypeTag, int, OutputInterval,
126  "Specify the number of report steps between two consecutive writes of restart data");
127  EWOMS_REGISTER_PARAM(TypeTag, bool, EnableLoggingFalloutWarning,
128  "Developer option to see whether logging was on non-root processors. In that case it will be appended to the *.DBG or *.PRT files");
129 
130  Simulator::registerParameters();
131 
132  // register the parameters inherited from ebos
133  registerAllParameters_<TypeTag>(/*finalizeRegistration=*/false);
134 
135  // hide the parameters unused by flow. TODO: this is a pain to maintain
136  EWOMS_HIDE_PARAM(TypeTag, EnableGravity);
137  EWOMS_HIDE_PARAM(TypeTag, EnableGridAdaptation);
138 
139  // this parameter is actually used in eWoms, but the flow well model
140  // hard-codes the assumption that the intensive quantities cache is enabled,
141  // so flow crashes. Let's hide the parameter for that reason.
142  EWOMS_HIDE_PARAM(TypeTag, EnableIntensiveQuantityCache);
143 
144  // thermodynamic hints are not implemented/required by the eWoms blackoil
145  // model
146  EWOMS_HIDE_PARAM(TypeTag, EnableThermodynamicHints);
147 
148  // in flow only the deck file determines the end time of the simulation
149  EWOMS_HIDE_PARAM(TypeTag, EndTime);
150 
151  // time stepping is not done by the eWoms code in flow
152  EWOMS_HIDE_PARAM(TypeTag, InitialTimeStepSize);
153  EWOMS_HIDE_PARAM(TypeTag, MaxTimeStepDivisions);
154  EWOMS_HIDE_PARAM(TypeTag, MaxTimeStepSize);
155  EWOMS_HIDE_PARAM(TypeTag, MinTimeStepSize);
156  EWOMS_HIDE_PARAM(TypeTag, PredeterminedTimeStepsFile);
157 
158  EWOMS_HIDE_PARAM(TypeTag, EclMaxTimeStepSizeAfterWellEvent);
159  EWOMS_HIDE_PARAM(TypeTag, EclRestartShrinkFactor);
160  EWOMS_HIDE_PARAM(TypeTag, EclEnableTuning);
161 
162  // flow also does not use the eWoms Newton method
163  EWOMS_HIDE_PARAM(TypeTag, NewtonMaxError);
164  EWOMS_HIDE_PARAM(TypeTag, NewtonTolerance);
165  EWOMS_HIDE_PARAM(TypeTag, NewtonTargetIterations);
166  EWOMS_HIDE_PARAM(TypeTag, NewtonVerbose);
167  EWOMS_HIDE_PARAM(TypeTag, NewtonWriteConvergence);
168  EWOMS_HIDE_PARAM(TypeTag, EclNewtonSumTolerance);
169  EWOMS_HIDE_PARAM(TypeTag, EclNewtonSumToleranceExponent);
170  EWOMS_HIDE_PARAM(TypeTag, EclNewtonStrictIterations);
171  EWOMS_HIDE_PARAM(TypeTag, EclNewtonRelaxedVolumeFraction);
172  EWOMS_HIDE_PARAM(TypeTag, EclNewtonRelaxedTolerance);
173 
174  // the default eWoms checkpoint/restart mechanism does not work with flow
175  EWOMS_HIDE_PARAM(TypeTag, RestartTime);
176  EWOMS_HIDE_PARAM(TypeTag, RestartWritingInterval);
177  // hide all vtk related it is not currently possible to do this dependet on if the vtk writing is used
178  //if(not(EWOMS_GET_PARAM(TypeTag,bool,EnableVtkOutput))){
179  EWOMS_HIDE_PARAM(TypeTag, VtkWriteOilFormationVolumeFactor);
180  EWOMS_HIDE_PARAM(TypeTag, VtkWriteOilSaturationPressure);
181  EWOMS_HIDE_PARAM(TypeTag, VtkWriteOilVaporizationFactor);
182  EWOMS_HIDE_PARAM(TypeTag, VtkWritePorosity);
183  EWOMS_HIDE_PARAM(TypeTag, VtkWritePotentialGradients);
184  EWOMS_HIDE_PARAM(TypeTag, VtkWritePressures);
185  EWOMS_HIDE_PARAM(TypeTag, VtkWritePrimaryVars);
186  EWOMS_HIDE_PARAM(TypeTag, VtkWritePrimaryVarsMeaning);
187  EWOMS_HIDE_PARAM(TypeTag, VtkWriteProcessRank);
188  EWOMS_HIDE_PARAM(TypeTag, VtkWriteRelativePermeabilities);
189  EWOMS_HIDE_PARAM(TypeTag, VtkWriteSaturatedGasOilVaporizationFactor);
190  EWOMS_HIDE_PARAM(TypeTag, VtkWriteSaturatedOilGasDissolutionFactor);
191  EWOMS_HIDE_PARAM(TypeTag, VtkWriteSaturationRatios);
192  EWOMS_HIDE_PARAM(TypeTag, VtkWriteSaturations);
193  EWOMS_HIDE_PARAM(TypeTag, VtkWriteTemperature);
194  EWOMS_HIDE_PARAM(TypeTag, VtkWriteViscosities);
195  EWOMS_HIDE_PARAM(TypeTag, VtkWriteWaterFormationVolumeFactor);
196  EWOMS_HIDE_PARAM(TypeTag, VtkWriteGasDissolutionFactor);
197  EWOMS_HIDE_PARAM(TypeTag, VtkWriteGasFormationVolumeFactor);
198  EWOMS_HIDE_PARAM(TypeTag, VtkWriteGasSaturationPressure);
199  EWOMS_HIDE_PARAM(TypeTag, VtkWriteIntrinsicPermeabilities);
200  EWOMS_HIDE_PARAM(TypeTag, VtkWriteEclTracerConcentration);
201  EWOMS_HIDE_PARAM(TypeTag, VtkWriteExtrusionFactor);
202  EWOMS_HIDE_PARAM(TypeTag, VtkWriteFilterVelocities);
203  EWOMS_HIDE_PARAM(TypeTag, VtkWriteDensities);
204  EWOMS_HIDE_PARAM(TypeTag, VtkWriteDofIndex);
205  EWOMS_HIDE_PARAM(TypeTag, VtkWriteMobilities);
206  //}
207  EWOMS_HIDE_PARAM(TypeTag, VtkWriteAverageMolarMasses);
208  EWOMS_HIDE_PARAM(TypeTag, VtkWriteFugacities);
209  EWOMS_HIDE_PARAM(TypeTag, VtkWriteFugacityCoeffs);
210  EWOMS_HIDE_PARAM(TypeTag, VtkWriteMassFractions);
211  EWOMS_HIDE_PARAM(TypeTag, VtkWriteMolarities);
212  EWOMS_HIDE_PARAM(TypeTag, VtkWriteMoleFractions);
213  EWOMS_HIDE_PARAM(TypeTag, VtkWriteTotalMassFractions);
214  EWOMS_HIDE_PARAM(TypeTag, VtkWriteTotalMoleFractions);
215 
216  EWOMS_HIDE_PARAM(TypeTag, VtkWriteTortuosities);
217  EWOMS_HIDE_PARAM(TypeTag, VtkWriteDiffusionCoefficients);
218  EWOMS_HIDE_PARAM(TypeTag, VtkWriteEffectiveDiffusionCoefficients);
219 
220  EWOMS_END_PARAM_REGISTRATION(TypeTag);
221 
222  int mpiRank = comm.rank();
223 
224  // read in the command line parameters
225  int status = ::Opm::setupParameters_<TypeTag>(argc, const_cast<const char**>(argv), /*doRegistration=*/false, /*allowUnused=*/true, /*handleHelp=*/(mpiRank==0));
226  if (status == 0) {
227 
228  // deal with unknown parameters.
229 
230  int unknownKeyWords = 0;
231  if (mpiRank == 0) {
232  unknownKeyWords = Parameters::printUnused<TypeTag>(std::cerr);
233  }
234  int globalUnknownKeyWords = comm.sum(unknownKeyWords);
235  unknownKeyWords = globalUnknownKeyWords;
236  if ( unknownKeyWords )
237  {
238  if ( mpiRank == 0 )
239  {
240  std::string msg = "Aborting simulation due to unknown "
241  "parameters. Please query \"flow --help\" for "
242  "supported command line parameters.";
243  if (OpmLog::hasBackend("STREAMLOG"))
244  {
245  OpmLog::error(msg);
246  }
247  else {
248  std::cerr << msg << std::endl;
249  }
250  }
251  return EXIT_FAILURE;
252  }
253 
254  // deal with --print-properties and --print-parameters and unknown parameters.
255 
256  bool doExit = false;
257 
258  if (EWOMS_GET_PARAM(TypeTag, int, PrintProperties) == 1) {
259  doExit = true;
260  if (mpiRank == 0)
261  Properties::printValues<TypeTag>();
262  }
263 
264  if (EWOMS_GET_PARAM(TypeTag, int, PrintParameters) == 1) {
265  doExit = true;
266  if (mpiRank == 0)
267  Parameters::printValues<TypeTag>();
268  }
269 
270  if (doExit)
271  return -1;
272  }
273 
274  return status;
275  }
276 
277  static void printBanner(Parallel::Communication comm)
278  {
279  const int lineLen = 70;
280  const std::string version = moduleVersionName();
281  const std::string banner = "This is flow "+version;
282  const int bannerPreLen = (lineLen - 2 - banner.size())/2;
283  const int bannerPostLen = bannerPreLen + (lineLen - 2 - banner.size())%2;
284  std::cout << "**********************************************************************\n";
285  std::cout << "* *\n";
286  std::cout << "*" << std::string(bannerPreLen, ' ') << banner << std::string(bannerPostLen, ' ') << "*\n";
287  std::cout << "* *\n";
288  std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow, *\n";
289  std::cout << "* including solvent and polymer capabilities. *\n";
290  std::cout << "* For more information, see https://opm-project.org *\n";
291  std::cout << "* *\n";
292  std::cout << "**********************************************************************\n\n";
293 
294  int threads = 1;
295 
296 #ifdef _OPENMP
297  // This function is called before the parallel OpenMP stuff gets initialized.
298  // That initialization happends after the deck is read and we want this message.
299  // Hence we duplicate the code of setupParallelism to get the number of threads.
300  if (getenv("OMP_NUM_THREADS"))
301  threads = omp_get_max_threads();
302  else
303  threads = std::min(2, omp_get_max_threads());
304 
305  const int input_threads = EWOMS_GET_PARAM(TypeTag, int, ThreadsPerProcess);
306 
307  if (input_threads > 0)
308  threads = std::min(input_threads, omp_get_max_threads());
309 #endif
310 
311  int mpiSize = comm.size();
312 
313  std::cout << "Using "<< mpiSize << " MPI processes with "<< threads <<" OMP threads on each \n\n";
314  }
315 
319  int execute()
320  {
321  return execute_(&FlowMainEbos::runSimulator, /*cleanup=*/true);
322  }
323 
324  int executeInitStep()
325  {
326  return execute_(&FlowMainEbos::runSimulatorInit, /*cleanup=*/false);
327  }
328 
329  // Returns true unless "EXIT" was encountered in the schedule
330  // section of the input datafile.
331  int executeStep()
332  {
333  return simulator_->runStep(*simtimer_);
334  }
335 
336  // Called from Python to cleanup after having executed the last
337  // executeStep()
338  int executeStepsCleanup()
339  {
340  SimulatorReport report = simulator_->finalize();
341  runSimulatorAfterSim_(report);
342  return report.success.exit_status;
343  }
344 
345  // Print an ASCII-art header to the PRT and DEBUG files.
346  // \return Whether unkown keywords were seen during parsing.
347  static void printPRTHeader(bool output_cout)
348  {
349  if (output_cout) {
350  const std::string version = moduleVersion();
351  const double megabyte = 1024 * 1024;
352  unsigned num_cpu = std::thread::hardware_concurrency();
353  struct utsname arch;
354  const char* user = getlogin();
355  time_t now = std::time(0);
356  struct tm tstruct;
357  char tmstr[80];
358  tstruct = *localtime(&now);
359  strftime(tmstr, sizeof(tmstr), "%d-%m-%Y at %X", &tstruct);
360  const double mem_size = getTotalSystemMemory() / megabyte;
361  std::ostringstream ss;
362  ss << "\n\n\n";
363  ss << " ######## # ###### # #\n";
364  ss << " # # # # # # \n";
365  ss << " ##### # # # # # # \n";
366  ss << " # # # # # # # # \n";
367  ss << " # ####### ###### # # \n\n";
368  ss << "Flow is a simulator for fully implicit three-phase black-oil flow,";
369  ss << " and is part of OPM.\nFor more information visit: https://opm-project.org \n\n";
370  ss << "Flow Version = " + version + "\n";
371  if (uname(&arch) == 0) {
372  ss << "Machine name = " << arch.nodename << " (Number of logical cores: " << num_cpu;
373  ss << ", Memory size: " << std::fixed << std::setprecision (2) << mem_size << " MB) \n";
374  ss << "Operating system = " << arch.sysname << " " << arch.machine << " (Kernel: " << arch.release;
375  ss << ", " << arch.version << " )\n";
376  ss << "Build time = " << compileTimestamp() << "\n";
377  }
378  if (user) {
379  ss << "User = " << user << std::endl;
380  }
381  ss << "Simulation started on " << tmstr << " hrs\n";
382 
383  ss << "Parameters used by Flow:\n";
384  Parameters::printValues<TypeTag>(ss);
385 
386  OpmLog::note(ss.str());
387  }
388  }
389 
390  EbosSimulator *getSimulatorPtr() {
391  return ebosSimulator_.get();
392  }
393 
394  SimulatorTimer* getSimTimer() {
395  return simtimer_.get();
396  }
397 
398  private:
399  // called by execute() or executeInitStep()
400  int execute_(int (FlowMainEbos::* runOrInitFunc)(), bool cleanup)
401  {
402  try {
403  // deal with some administrative boilerplate
404 
405  int status = setupParameters_(this->argc_, this->argv_, EclGenericVanguard::comm());
406  if (status)
407  return status;
408 
409  setupParallelism();
410  setupEbosSimulator();
411  createSimulator();
412 
413  // if run, do the actual work, else just initialize
414  int exitCode = (this->*runOrInitFunc)();
415  if (cleanup) {
416  executeCleanup_();
417  }
418  return exitCode;
419  }
420  catch (const std::exception& e) {
421  std::ostringstream message;
422  message << "Program threw an exception: " << e.what();
423 
424  if (this->output_cout_) {
425  // in some cases exceptions are thrown before the logging system is set
426  // up.
427  if (OpmLog::hasBackend("STREAMLOG")) {
428  OpmLog::error(message.str());
429  }
430  else {
431  std::cout << message.str() << "\n";
432  }
433  }
434 #if HAVE_MPI
435  if (this->mpi_size_ > 1)
436  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
437 #endif
438  return EXIT_FAILURE;
439  }
440  }
441 
442  void executeCleanup_() {
443  // clean up
444  mergeParallelLogFiles();
445  }
446 
447  protected:
448  void setupParallelism()
449  {
450  // determine the rank of the current process and the number of processes
451  // involved in the simulation. MPI must have already been initialized
452  // here. (yes, the name of this method is misleading.)
453  auto comm = EclGenericVanguard::comm();
454  mpi_rank_ = comm.rank();
455  mpi_size_ = comm.size();
456 
457 #if _OPENMP
458  // if openMP is available, default to 2 threads per process.
459  if (!getenv("OMP_NUM_THREADS"))
460  omp_set_num_threads(std::min(2, omp_get_num_procs()));
461 #endif
462 
463  using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
464  ThreadManager::init();
465  }
466 
467 
468 
469  void mergeParallelLogFiles()
470  {
471  // force closing of all log files.
472  OpmLog::removeAllBackends();
473 
474  if (mpi_rank_ != 0 || mpi_size_ < 2 || !this->output_files_) {
475  return;
476  }
477 
478  namespace fs = ::std::filesystem;
479  const std::string& output_dir = eclState().getIOConfig().getOutputDir();
480  fs::path output_path(output_dir);
481  fs::path deck_filename(EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName));
482  std::string basename;
483  // Strip extension "." and ".DATA"
484  std::string extension = uppercase(deck_filename.extension().string());
485  if ( extension == ".DATA" || extension == "." )
486  {
487  basename = uppercase(deck_filename.stem().string());
488  }
489  else
490  {
491  basename = uppercase(deck_filename.filename().string());
492  }
493  std::for_each(fs::directory_iterator(output_path),
494  fs::directory_iterator(),
495  detail::ParallelFileMerger(output_path, basename,
496  EWOMS_GET_PARAM(TypeTag, bool, EnableLoggingFalloutWarning)));
497  }
498 
499  void setupEbosSimulator()
500  {
501  ebosSimulator_.reset(new EbosSimulator(EclGenericVanguard::comm(), /*verbose=*/false));
502  ebosSimulator_->executionTimer().start();
503  ebosSimulator_->model().applyInitialSolution();
504 
505  try {
506  // Possible to force initialization only behavior (NOSIM).
507  const std::string& dryRunString = EWOMS_GET_PARAM(TypeTag, std::string, EnableDryRun);
508  if (dryRunString != "" && dryRunString != "auto") {
509  bool yesno;
510  if (dryRunString == "true"
511  || dryRunString == "t"
512  || dryRunString == "1")
513  yesno = true;
514  else if (dryRunString == "false"
515  || dryRunString == "f"
516  || dryRunString == "0")
517  yesno = false;
518  else
519  throw std::invalid_argument("Invalid value for parameter EnableDryRun: '"
520  +dryRunString+"'");
521  auto& ioConfig = eclState().getIOConfig();
522  ioConfig.overrideNOSIM(yesno);
523  }
524  }
525  catch (const std::invalid_argument& e) {
526  std::cerr << "Failed to create valid EclipseState object" << std::endl;
527  std::cerr << "Exception caught: " << e.what() << std::endl;
528  throw;
529  }
530  }
531 
532  const Deck& deck() const
533  { return ebosSimulator_->vanguard().deck(); }
534 
535  Deck& deck()
536  { return ebosSimulator_->vanguard().deck(); }
537 
538  const EclipseState& eclState() const
539  { return ebosSimulator_->vanguard().eclState(); }
540 
541  EclipseState& eclState()
542  { return ebosSimulator_->vanguard().eclState(); }
543 
544  const Schedule& schedule() const
545  { return ebosSimulator_->vanguard().schedule(); }
546 
547  // Run the simulator.
548  int runSimulator()
549  {
550  return runSimulatorInitOrRun_(&FlowMainEbos::runSimulatorRunCallback_);
551  }
552 
553  int runSimulatorInit()
554  {
555  return runSimulatorInitOrRun_(&FlowMainEbos::runSimulatorInitCallback_);
556  }
557 
558  private:
559  // Callback that will be called from runSimulatorInitOrRun_().
560  int runSimulatorRunCallback_()
561  {
562  SimulatorReport report = simulator_->run(*simtimer_);
563  runSimulatorAfterSim_(report);
564  return report.success.exit_status;
565  }
566 
567  // Callback that will be called from runSimulatorInitOrRun_().
568  int runSimulatorInitCallback_()
569  {
570  simulator_->init(*simtimer_);
571  return EXIT_SUCCESS;
572  }
573 
574  // Output summary after simulation has completed
575  void runSimulatorAfterSim_(SimulatorReport &report)
576  {
577  if (this->output_cout_) {
578  std::ostringstream ss;
579  ss << "\n\n================ End of simulation ===============\n\n";
580  ss << fmt::format("Number of MPI processes: {:9}\n", mpi_size_ );
581 #if _OPENMP
582  int threads = omp_get_max_threads();
583 #else
584  int threads = 1;
585 #endif
586  ss << fmt::format("Threads per MPI process: {:9}\n", threads);
587  report.reportFullyImplicit(ss);
588  OpmLog::info(ss.str());
589  const std::string dir = eclState().getIOConfig().getOutputDir();
590  namespace fs = ::std::filesystem;
591  fs::path output_dir(dir);
592  {
593  std::string filename = eclState().getIOConfig().getBaseName() + ".INFOSTEP";
594  fs::path fullpath = output_dir / filename;
595  std::ofstream os(fullpath.string());
596  report.fullReports(os);
597  }
598  }
599  }
600 
601  // Run the simulator.
602  int runSimulatorInitOrRun_(int (FlowMainEbos::* initOrRunFunc)())
603  {
604 
605  const auto& schedule = this->schedule();
606  auto& ioConfig = eclState().getIOConfig();
607  simtimer_ = std::make_unique<SimulatorTimer>();
608 
609  // initialize variables
610  const auto& initConfig = eclState().getInitConfig();
611  simtimer_->init(schedule, (size_t)initConfig.getRestartStep());
612 
613  if (this->output_cout_) {
614  std::ostringstream oss;
615 
616  // This allows a user to catch typos and misunderstandings in the
617  // use of simulator parameters.
618  if (Parameters::printUnused<TypeTag>(oss)) {
619  std::cout << "----------------- Unrecognized parameters: -----------------\n";
620  std::cout << oss.str();
621  std::cout << "----------------------------------------------------------------" << std::endl;
622  }
623  }
624 
625  if (!ioConfig.initOnly()) {
626  if (this->output_cout_) {
627  std::string msg;
628  msg = "\n\n================ Starting main simulation loop ===============\n";
629  OpmLog::info(msg);
630  }
631 
632  return (this->*initOrRunFunc)();
633  }
634  else {
635  if (this->output_cout_) {
636  std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;
637  }
638  return EXIT_SUCCESS;
639  }
640  }
641 
642  protected:
643 
645  // Create simulator instance.
646  // Writes to:
647  // simulator_
649  {
650  // Create the simulator instance.
651  simulator_.reset(new Simulator(*ebosSimulator_));
652  }
653 
654  static unsigned long long getTotalSystemMemory()
655  {
656  long pages = sysconf(_SC_PHYS_PAGES);
657  long page_size = sysconf(_SC_PAGE_SIZE);
658  return pages * page_size;
659  }
660 
661 
662  Grid& grid()
663  { return ebosSimulator_->vanguard().grid(); }
664 
665  private:
666  std::unique_ptr<EbosSimulator> ebosSimulator_;
667  int mpi_rank_ = 0;
668  int mpi_size_ = 1;
669  std::any parallel_information_;
670  std::unique_ptr<Simulator> simulator_;
671  std::unique_ptr<SimulatorTimer> simtimer_;
672  int argc_;
673  char **argv_;
674  bool output_cout_;
675  bool output_files_;
676  };
677 } // namespace Opm
678 
679 #endif // OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED
Definition: FlowMainEbos.hpp:89
int execute()
This is the main function of Flow.
Definition: FlowMainEbos.hpp:319
void createSimulator()
This is the main function of Flow.
Definition: FlowMainEbos.hpp:648
a simulator for the blackoil model
Definition: SimulatorFullyImplicitBlackoilEbos.hpp:72
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
std::string moduleVersionName()
Return the version name of the module, for example "2015.10" (for a release branch) or "2016....
Definition: moduleVersion.cpp:34
std::string compileTimestamp()
Return a string "dd-mm-yyyy at HH::MM::SS hrs" which is the time the binary was compiled.
Definition: moduleVersion.cpp:57
std::string moduleVersion()
Return a string containing both the name and hash, if N is the name and H is the hash it will be "N (...
Definition: moduleVersion.cpp:50
Definition: FlowMainEbos.hpp:52
Definition: FlowMainEbos.hpp:60
Definition: FlowMainEbos.hpp:56