My Project
Main.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_MAIN_HEADER_INCLUDED
23 #define OPM_MAIN_HEADER_INCLUDED
24 
25 #include <flow/flow_ebos_blackoil.hpp>
26 
27 # ifndef FLOW_BLACKOIL_ONLY
28 # include <flow/flow_ebos_gasoil.hpp>
29 # include <flow/flow_ebos_oilwater.hpp>
30 # include <flow/flow_ebos_gaswater.hpp>
31 # include <flow/flow_ebos_solvent.hpp>
32 # include <flow/flow_ebos_polymer.hpp>
33 # include <flow/flow_ebos_extbo.hpp>
34 # include <flow/flow_ebos_foam.hpp>
35 # include <flow/flow_ebos_brine.hpp>
36 # include <flow/flow_ebos_oilwater_brine.hpp>
37 # include <flow/flow_ebos_energy.hpp>
38 # include <flow/flow_ebos_oilwater_polymer.hpp>
39 # include <flow/flow_ebos_oilwater_polymer_injectivity.hpp>
40 # include <flow/flow_ebos_micp.hpp>
41 # endif
42 
43 #include <opm/parser/eclipse/Deck/Deck.hpp>
44 #include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
45 #include <opm/parser/eclipse/Parser/Parser.hpp>
46 #include <opm/parser/eclipse/Parser/ParseContext.hpp>
47 #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
48 #include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
49 #include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
50 #include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp>
51 #include <opm/parser/eclipse/EclipseState/Schedule/Action/State.hpp>
52 #include <opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp>
53 
54 #include <opm/models/utils/propertysystem.hh>
55 #include <opm/models/utils/parametersystem.hh>
56 
57 #include <opm/simulators/flow/FlowMainEbos.hpp>
58 #include <opm/simulators/utils/readDeck.hpp>
59 
60 #if HAVE_DUNE_FEM
61 #include <dune/fem/misc/mpimanager.hh>
62 #else
63 #include <dune/common/parallel/mpihelper.hh>
64 #endif
65 
66 #if HAVE_MPI
67 #include <opm/simulators/utils/ParallelEclipseState.hpp>
68 #endif
69 
70 #include <cassert>
71 #include <cstdlib>
72 #include <iostream>
73 #include <memory>
74 #include <stdexcept>
75 #include <string>
76 #include <type_traits>
77 #include <utility>
78 
79 namespace Opm::Properties {
80 
81 // this is a dummy type tag that is used to setup the parameters before the actual
82 // simulator.
83 namespace TTag {
84 struct FlowEarlyBird {
85  using InheritsFrom = std::tuple<EclFlowProblem>;
86 };
87 }
88 
89 } // namespace Opm::Properties
90 
91 namespace Opm {
92  template <class TypeTag>
93  void flowEbosSetDeck(std::shared_ptr<Deck> deck,
94  std::shared_ptr<EclipseState> eclState,
95  std::shared_ptr<Schedule> schedule,
96  std::shared_ptr<SummaryConfig> summaryConfig)
97  {
98  using Vanguard = GetPropType<TypeTag, Properties::Vanguard>;
99 
100  Vanguard::setExternalDeck(deck);
101  Vanguard::setExternalEclState(eclState);
102  Vanguard::setExternalSchedule(schedule);
103  Vanguard::setExternalSummaryConfig(summaryConfig);
104  }
105 
106  // ----------------- Main program -----------------
107  template <class TypeTag>
108  int flowEbosMain(int argc, char** argv, bool outputCout, bool outputFiles)
109  {
110  // we always want to use the default locale, and thus spare us the trouble
111  // with incorrect locale settings.
112  resetLocale();
113 
114  FlowMainEbos<TypeTag> mainfunc(argc, argv, outputCout, outputFiles);
115  return mainfunc.execute();
116  }
117 }
118 
119 
120 namespace Opm
121 {
122 
123  // ----------------- Main class -----------------
124  // For now, we will either be instantiated from main() in flow.cpp,
125  // or from a Python pybind11 module..
126  // NOTE (March 2020): When used from a pybind11 module, we do not neccessarily
127  // want to run the whole simulation by calling run(), it is also
128  // useful to just run one report step at a time. According to these different
129  // usage scenarios, we refactored the original run() in flow.cpp into this class.
130  class Main
131  {
132  private:
134 
135  public:
136  Main(int argc, char** argv) : argc_(argc), argv_(argv) { initMPI(); }
137 
138  // This constructor can be called from Python
139  Main(const std::string& filename)
140  {
141  setArgvArgc_(filename);
142  initMPI();
143  }
144 
145  // This constructor can be called from Python when Python has
146  // already parsed a deck
147  Main(std::shared_ptr<Deck> deck,
148  std::shared_ptr<EclipseState> eclipseState,
149  std::shared_ptr<Schedule> schedule,
150  std::shared_ptr<SummaryConfig> summaryConfig)
151  : deck_{std::move(deck)}
152  , eclipseState_{std::move(eclipseState)}
153  , schedule_{std::move(schedule)}
154  , summaryConfig_{std::move(summaryConfig)}
155  {
156  setArgvArgc_(deck_->getDataFile());
157  initMPI();
158  }
159 
160 #define DEMONSTRATE_RUN_WITH_NONWORLD_COMM 0
161 
162  ~Main()
163  {
164 #if DEMONSTRATE_RUN_WITH_NONWORLD_COMM
165 #if HAVE_MPI
166  // Cannot use EclGenericVanguard::comm()
167  // to get world size here, as it may be
168  // a split communication at this point.
169  int world_size;
170  MPI_Comm_size(MPI_COMM_WORLD, &world_size);
171  if (world_size > 1) {
172  MPI_Comm new_comm = EclGenericVanguard::comm();
173  int result;
174  MPI_Comm_compare(MPI_COMM_WORLD, new_comm, &result);
175  assert(result == MPI_UNEQUAL);
176  MPI_Comm_free(&new_comm);
177  }
178 #endif // HAVE_MPI
179 #endif // DEMONSTRATE_RUN_WITH_NONWORLD_COMM
180 
181  EclGenericVanguard::setCommunication(nullptr);
182 
183 #if HAVE_MPI && !HAVE_DUNE_FEM
184  MPI_Finalize();
185 #endif
186  }
187 
188  void setArgvArgc_(const std::string& filename)
189  {
190  this->deckFilename_ = filename;
191  this->flowProgName_ = "flow";
192 
193  this->argc_ = 2;
194  this->saveArgs_[0] = const_cast<char *>(this->flowProgName_.c_str());
195  this->saveArgs_[1] = const_cast<char *>(this->deckFilename_.c_str());
196 
197  // Note: argv[argc] must exist and be nullptr
198  assert ((sizeof this->saveArgs_) > (this->argc_ * sizeof this->saveArgs_[0]));
199  this->saveArgs_[this->argc_] = nullptr;
200 
201  this->argv_ = this->saveArgs_;
202  }
203 
204  void initMPI()
205  {
206 #if HAVE_DUNE_FEM
207  Dune::Fem::MPIManager::initialize(argc_, argv_);
208 #elif HAVE_MPI
209  MPI_Init(&argc_, &argv_);
210 #endif
211  EclGenericVanguard::setCommunication(std::make_unique<Parallel::Communication>());
212 
213 #if DEMONSTRATE_RUN_WITH_NONWORLD_COMM
214 #if HAVE_MPI
215  if (EclGenericVanguard::comm().size() > 1) {
216  int world_rank = EclGenericVanguard::comm().rank();
217  int color = (world_rank == 0);
218  MPI_Comm new_comm;
219  MPI_Comm_split(EclGenericVanguard::comm(), color, world_rank, &new_comm);
220  isSimulationRank_ = (world_rank > 0);
221  EclGenericVanguard::setCommunication(std::make_unique<Parallel::Communication>(new_comm));
222  }
223 #endif // HAVE_MPI
224 #endif // DEMONSTRATE_RUN_WITH_NONWORLD_COMM
225  }
226 
227  int runDynamic()
228  {
229  int exitCode = EXIT_SUCCESS;
230  if (isSimulationRank_) {
231  if (initialize_<Properties::TTag::FlowEarlyBird>(exitCode)) {
232  return this->dispatchDynamic_();
233  }
234  }
235 
236  return exitCode;
237  }
238 
239  template <class TypeTag>
240  int runStatic()
241  {
242  int exitCode = EXIT_SUCCESS;
243  if (isSimulationRank_) {
244  if (initialize_<TypeTag>(exitCode)) {
245  return this->dispatchStatic_<TypeTag>();
246  }
247  }
248 
249  return exitCode;
250  }
251 
252  // To be called from the Python interface code. Only do the
253  // initialization and then return a pointer to the FlowEbosMain
254  // object that can later be accessed directly from the Python interface
255  // to e.g. advance the simulator one report step
256  std::unique_ptr<FlowMainEbosType> initFlowEbosBlackoil(int& exitCode)
257  {
258  exitCode = EXIT_SUCCESS;
259  if (initialize_<Properties::TTag::FlowEarlyBird>(exitCode)) {
260  // TODO: check that this deck really represents a blackoil
261  // case. E.g. check that number of phases == 3
262  flowEbosBlackoilSetDeck(
263  setupTime_,
264  deck_,
265  eclipseState_,
266  schedule_,
267  std::move(udqState_),
268  std::move(this->actionState_),
269  std::move(this->wtestState_),
270  summaryConfig_);
271  return flowEbosBlackoilMainInit(
272  argc_, argv_, outputCout_, outputFiles_);
273  } else {
274  //NOTE: exitCode was set by initialize_() above;
275  return std::unique_ptr<FlowMainEbosType>(); // nullptr
276  }
277  }
278 
279  private:
280  int dispatchDynamic_()
281  {
282  const auto& phases = eclipseState_->runspec().phases();
283 
284  // run the actual simulator
285  //
286  // TODO: make sure that no illegal combinations like thermal and
287  // twophase are requested.
288 
289  if (false) {}
290 
291 #ifndef FLOW_BLACKOIL_ONLY
292  // Single-phase case
293  else if( eclipseState_->runspec().micp() ) {
294  // micp
295  if ( !phases.active( Phase::WATER) || phases.size() > 2) {
296  if (outputCout_)
297  std::cerr << "No valid configuration is found for MICP simulation, the only valid option is "
298  << "water + MICP" << std::endl;
299  return EXIT_FAILURE;
300  }
301  flowEbosMICPSetDeck(
302  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
303  return flowEbosMICPMain(argc_, argv_, outputCout_, outputFiles_);
304  }
305  // Twophase cases
306  else if (phases.size() == 2) {
307  return this->runTwoPhase(phases);
308  }
309 
310  // Polymer case
311  else if (phases.active(Phase::POLYMER)) {
312  return this->runPolymer(phases);
313  }
314 
315  // Foam case
316  else if (phases.active(Phase::FOAM)) {
317  return this->runFoam();
318  }
319 
320  // Brine case
321  else if (phases.active(Phase::BRINE)) {
322  return this->runBrine(phases);
323  }
324 
325  // Solvent case
326  else if (phases.active(Phase::SOLVENT)) {
327  return this->runSolvent();
328  }
329 
330  // Extended BO case
331  else if (phases.active(Phase::ZFRACTION)) {
332  return this->runExtendedBlackOil();
333  }
334 
335  // Energy case
336  else if (eclipseState_->getSimulationConfig().isThermal()) {
337  return this->runThermal();
338  }
339 #endif // FLOW_BLACKOIL_ONLY
340 
341  // Blackoil case
342  else if (phases.size() == 3) {
343  return this->runBlackOil();
344  }
345 
346  else {
347  if (outputCout_) {
348  std::cerr << "No suitable configuration found, valid are "
349  << "Twophase, polymer, foam, brine, solvent, "
350  << "energy, and blackoil.\n";
351  }
352 
353  return EXIT_FAILURE;
354  }
355  }
356 
357  template <class TypeTag>
358  int dispatchStatic_()
359  {
360  flowEbosSetDeck<TypeTag>(
361  deck_, eclipseState_, schedule_, summaryConfig_);
362  return flowEbosMain<TypeTag>(argc_, argv_, outputCout_, outputFiles_);
363  }
364 
371  template <class TypeTagEarlyBird>
372  bool initialize_(int& exitCode)
373  {
374  Dune::Timer externalSetupTimer;
375  externalSetupTimer.start();
376 
377  handleVersionCmdLine_(argc_, argv_);
378 #if HAVE_DUNE_FEM
379  int mpiRank = Dune::Fem::MPIManager::rank();
380 #else
381  int mpiRank = EclGenericVanguard::comm().rank();
382 #endif
383 
384  // we always want to use the default locale, and thus spare us the trouble
385  // with incorrect locale settings.
386  resetLocale();
387 
388  // this is a work-around for a catch 22: we do not know what code path to use without
389  // parsing the deck, but we don't know the deck without having access to the
390  // parameters and this requires to know the type tag to be used. To solve this, we
391  // use a type tag just for parsing the parameters before we instantiate the actual
392  // simulator object. (Which parses the parameters again, but since this is done in an
393  // identical manner it does not matter.)
394  typedef TypeTagEarlyBird PreTypeTag;
395  using PreProblem = GetPropType<PreTypeTag, Properties::Problem>;
396 
397  PreProblem::setBriefDescription("Flow, an advanced reservoir simulator for ECL-decks provided by the Open Porous Media project.");
398  int status = FlowMainEbos<PreTypeTag>::setupParameters_(argc_, argv_, EclGenericVanguard::comm());
399  if (status != 0) {
400  // if setupParameters_ returns a value smaller than 0, there was no error, but
401  // the program should abort. This is the case e.g. for the --help and the
402  // --print-properties parameters.
403 #if HAVE_MPI
404  if (status >= 0)
405  MPI_Abort(MPI_COMM_WORLD, status);
406 #endif
407  exitCode = (status > 0) ? status : EXIT_SUCCESS;
408  return false; // Whether to run the simulator
409  }
410 
412  outputCout_ = false;
413  if (mpiRank == 0)
414  outputCout_ = EWOMS_GET_PARAM(PreTypeTag, bool, EnableTerminalOutput);
415 
416  std::string deckFilename;
417  std::string outputDir;
418  if ( eclipseState_ ) {
419  deckFilename = eclipseState_->getIOConfig().fullBasePath();
420  outputDir = eclipseState_->getIOConfig().getOutputDir();
421  }
422  else {
423  deckFilename = EWOMS_GET_PARAM(PreTypeTag, std::string, EclDeckFileName);
424  }
425 
426  if (deckFilename.empty()) {
427  if (mpiRank == 0) {
428  std::cerr << "No input case given. Try '--help' for a usage description.\n";
429  }
430  exitCode = EXIT_FAILURE;
431  return false;
432  }
433 
434  using PreVanguard = GetPropType<PreTypeTag, Properties::Vanguard>;
435  try {
436  deckFilename = PreVanguard::canonicalDeckPath(deckFilename);
437  }
438  catch (const std::exception& e) {
439  if ( mpiRank == 0 ) {
440  std::cerr << "Exception received: " << e.what() << ". Try '--help' for a usage description.\n";
441  }
442 #if HAVE_MPI
443  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
444 #endif
445  exitCode = EXIT_FAILURE;
446  return false;
447  }
448  if (outputCout_) {
449  FlowMainEbos<PreTypeTag>::printBanner(EclGenericVanguard::comm());
450  }
451  // Create Deck and EclipseState.
452  try {
453  auto python = std::make_shared<Python>();
454  const bool init_from_restart_file = !EWOMS_GET_PARAM(PreTypeTag, bool, SchedRestart);
455  if (outputDir.empty())
456  outputDir = EWOMS_GET_PARAM(PreTypeTag, std::string, OutputDir);
457  outputMode = setupLogging(mpiRank,
458  deckFilename,
459  outputDir,
460  EWOMS_GET_PARAM(PreTypeTag, std::string, OutputMode),
461  outputCout_, "STDOUT_LOGGER");
462  auto parseContext =
463  std::make_unique<ParseContext>(std::vector<std::pair<std::string , InputError::Action>>
464  {{ParseContext::PARSE_RANDOM_SLASH, InputError::IGNORE},
465  {ParseContext::PARSE_MISSING_DIMS_KEYWORD, InputError::WARN},
466  {ParseContext::SUMMARY_UNKNOWN_WELL, InputError::WARN},
467  {ParseContext::SUMMARY_UNKNOWN_GROUP, InputError::WARN}});
468  if (EWOMS_GET_PARAM(PreTypeTag, bool, EclStrictParsing))
469  parseContext->update(InputError::DELAYED_EXIT1);
470 
472 
473  if (outputCout_) {
474  OpmLog::info("Reading deck file '" + deckFilename + "'");
475  }
476 
477  std::optional<int> outputInterval;
478  int output_param = EWOMS_GET_PARAM(PreTypeTag, int, EclOutputInterval);
479  if (output_param >= 0)
480  outputInterval = output_param;
481 
482  readDeck(EclGenericVanguard::comm(), deckFilename, deck_, eclipseState_, schedule_, udqState_, actionState_, wtestState_,
483  summaryConfig_, nullptr, python, std::move(parseContext),
484  init_from_restart_file, outputCout_, outputInterval);
485 
486  setupTime_ = externalSetupTimer.elapsed();
487  outputFiles_ = (outputMode != FileOutputMode::OUTPUT_NONE);
488  }
489  catch (const std::invalid_argument& e)
490  {
491  if (outputCout_) {
492  std::cerr << "Failed to create valid EclipseState object." << std::endl;
493  std::cerr << "Exception caught: " << e.what() << std::endl;
494  }
495 #if HAVE_MPI
496  MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
497 #endif
498  exitCode = EXIT_FAILURE;
499  return false;
500  }
501 
502  exitCode = EXIT_SUCCESS;
503  return true;
504  }
505 
506  filesystem::path simulationCaseName_(const std::string& casename)
507  {
508  namespace fs = ::Opm::filesystem;
509 
510  auto exists = [](const fs::path& f)
511  {
512  return (fs::exists(f) && fs::is_regular_file(f))
513  || (fs::is_symlink(f) &&
514  fs::is_regular_file(fs::read_symlink(f)));
515  };
516 
517  auto simcase = fs::path { casename };
518 
519  if (exists(simcase)) {
520  return simcase;
521  }
522 
523  for (const auto& ext : { std::string("DATA"), std::string("data") }) {
524  if (exists(simcase.replace_extension(ext))) {
525  return simcase;
526  }
527  }
528 
529  throw std::invalid_argument {
530  "Cannot find input case '" + casename + '\''
531  };
532  }
533 
534  // This function is an extreme special case, if the program has been invoked
535  // *exactly* as:
536  //
537  // flow --version
538  //
539  // the call is intercepted by this function which will print "flow $version"
540  // on stdout and exit(0).
541  void handleVersionCmdLine_(int argc, char** argv)
542  {
543  auto pos = std::find_if(argv, argv + argc,
544  [](const char* arg)
545  {
546  return std::strcmp(arg, "--version") == 0;
547  });
548 
549  if (pos != argv + argc) {
550  std::cout << "flow " << moduleVersionName() << std::endl;
551  std::exit(EXIT_SUCCESS);
552  }
553  }
554 
555 #ifndef FLOW_BLACKOIL_ONLY
556  int runTwoPhase(const Phases& phases)
557  {
558  // oil-gas
559  if (phases.active( Phase::OIL ) && phases.active( Phase::GAS )) {
560  flowEbosGasOilSetDeck(
561  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
562  return flowEbosGasOilMain(argc_, argv_, outputCout_, outputFiles_);
563  }
564 
565  // oil-water
566  else if ( phases.active( Phase::OIL ) && phases.active( Phase::WATER ) ) {
567  flowEbosOilWaterSetDeck(
568  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
569  return flowEbosOilWaterMain(argc_, argv_, outputCout_, outputFiles_);
570  }
571 
572  // gas-water
573  else if ( phases.active( Phase::GAS ) && phases.active( Phase::WATER ) ) {
574  flowEbosGasWaterSetDeck(
575  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
576  return flowEbosGasWaterMain(argc_, argv_, outputCout_, outputFiles_);
577  }
578  else {
579  if (outputCout_) {
580  std::cerr << "No suitable configuration found, valid are Twophase (oilwater, oilgas and gaswater), polymer, solvent, or blackoil" << std::endl;
581  }
582 
583  return EXIT_FAILURE;
584  }
585  }
586 
587  int runPolymer(const Phases& phases)
588  {
589  if (! phases.active(Phase::WATER)) {
590  if (outputCout_)
591  std::cerr << "No valid configuration is found for polymer simulation, valid options include "
592  << "oilwater + polymer and blackoil + polymer" << std::endl;
593 
594  return EXIT_FAILURE;
595  }
596 
597  // Need to track the polymer molecular weight
598  // for the injectivity study
599  if (phases.active(Phase::POLYMW)) {
600  // only oil water two phase for now
601  assert (phases.size() == 4);
602  return flowEbosOilWaterPolymerInjectivityMain(argc_, argv_, outputCout_, outputFiles_);
603  }
604 
605  if (phases.size() == 3) { // oil water polymer case
606  flowEbosOilWaterPolymerSetDeck(
607  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
608  return flowEbosOilWaterPolymerMain(argc_, argv_, outputCout_, outputFiles_);
609  }
610  else {
611  flowEbosPolymerSetDeck(
612  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
613  return flowEbosPolymerMain(argc_, argv_, outputCout_, outputFiles_);
614  }
615  }
616 
617  int runFoam()
618  {
619  flowEbosFoamSetDeck(
620  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
621 
622  return flowEbosFoamMain(argc_, argv_, outputCout_, outputFiles_);
623  }
624 
625  int runBrine(const Phases& phases)
626  {
627  if (! phases.active(Phase::WATER)) {
628  if (outputCout_)
629  std::cerr << "No valid configuration is found for brine simulation, valid options include "
630  << "oilwater + brine and blackoil + brine" << std::endl;
631 
632  return EXIT_FAILURE;
633  }
634 
635  if (phases.size() == 3) { // oil water brine case
636  flowEbosOilWaterBrineSetDeck(
637  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
638  return flowEbosOilWaterBrineMain(argc_, argv_, outputCout_, outputFiles_);
639  }
640  else {
641  flowEbosBrineSetDeck(
642  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
643  return flowEbosBrineMain(argc_, argv_, outputCout_, outputFiles_);
644  }
645  }
646 
647  int runSolvent()
648  {
649  flowEbosSolventSetDeck(
650  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
651 
652  return flowEbosSolventMain(argc_, argv_, outputCout_, outputFiles_);
653  }
654 
655  int runExtendedBlackOil()
656  {
657  flowEbosExtboSetDeck(
658  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
659 
660  return flowEbosExtboMain(argc_, argv_, outputCout_, outputFiles_);
661  }
662 
663  int runThermal()
664  {
665  flowEbosEnergySetDeck(
666  setupTime_, deck_, eclipseState_, schedule_, summaryConfig_);
667 
668  return flowEbosEnergyMain(argc_, argv_, outputCout_, outputFiles_);
669  }
670 #endif // FLOW_BLACKOIL_ONLY
671 
672  int runBlackOil()
673  {
674  flowEbosBlackoilSetDeck(this->setupTime_,
675  this->deck_,
676  this->eclipseState_,
677  this->schedule_,
678  std::move(this->udqState_),
679  std::move(this->actionState_),
680  std::move(this->wtestState_),
681  this->summaryConfig_);
682 
683  return flowEbosBlackoilMain(argc_, argv_, outputCout_, outputFiles_);
684  }
685 
686  int argc_{0};
687  char** argv_{nullptr};
688  bool outputCout_{false};
689  bool outputFiles_{false};
690  double setupTime_{0.0};
691  std::string deckFilename_{};
692  std::string flowProgName_{};
693  char *saveArgs_[3]{nullptr};
694  std::unique_ptr<UDQState> udqState_{};
695  std::unique_ptr<Action::State> actionState_{};
696  std::unique_ptr<WellTestState> wtestState_{};
697 
698  // These variables may be owned by both Python and the simulator
699  std::shared_ptr<Deck> deck_{};
700  std::shared_ptr<EclipseState> eclipseState_{};
701  std::shared_ptr<Schedule> schedule_{};
702  std::shared_ptr<SummaryConfig> summaryConfig_{};
703 
704  // To demonstrate run with non_world_comm
705  bool isSimulationRank_ = true;
706  };
707 
708 } // namespace Opm
709 
710 #endif // OPM_MAIN_HEADER_INCLUDED
Definition: FlowMainEbos.hpp:87
Definition: Main.hpp:131
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:26
std::string moduleVersionName()
Return the version name of the module, for example "2015.10" (for a release branch) or "2016....
Definition: moduleVersion.cpp:29
FileOutputMode
Definition: readDeck.hpp:49
@ OUTPUT_NONE
No file output.
void readDeck(Parallel::Communication comm, const std::string &deckFilename, std::shared_ptr< Deck > &deck, std::shared_ptr< EclipseState > &eclipseState, std::shared_ptr< Schedule > &schedule, std::unique_ptr< UDQState > &udqState, std::unique_ptr< Action::State > &actionState, std::unique_ptr< WellTestState > &wtestState, std::shared_ptr< SummaryConfig > &summaryConfig, std::unique_ptr< ErrorGuard > errorGuard, std::shared_ptr< Python > python, std::unique_ptr< ParseContext > parseContext, bool initFromRestart, bool checkDeck, const std::optional< int > &outputInterval)
Reads the deck and creates all necessary objects if needed.
Definition: readDeck.cpp:424