131 Main(
int argc,
char** argv,
bool ownMPI =
true);
134 Main(
const std::string& filename,
bool mpi_init =
true,
bool mpi_finalize =
true);
138 Main(
const std::string& filename,
139 std::shared_ptr<EclipseState> eclipseState,
140 std::shared_ptr<Schedule> schedule,
141 std::shared_ptr<SummaryConfig> summaryConfig,
142 bool mpi_init =
true,
143 bool mpi_finalize =
true);
147 void setArgvArgc_(
const std::string& filename);
153 int exitCode = EXIT_SUCCESS;
156 if (isSimulationRank_) {
157 return this->dispatchDynamic_();
164 template <
class TypeTag>
167 int exitCode = EXIT_SUCCESS;
169 if (isSimulationRank_) {
170 return this->dispatchStatic_<TypeTag>();
180 int exitCode = EXIT_SUCCESS;
186 int dispatchDynamic_()
188 const auto& rspec = this->eclipseState_->runspec();
189 const auto& phases = rspec.phases();
191 this->setupVanguard();
197 const bool thermal = eclipseState_->getSimulationConfig().isThermal();
201 return this->runMICP(phases);
205 else if (phases.size() == 1 && phases.active(Phase::WATER) && !thermal) {
206 return this->runWaterOnly(phases);
210 else if (phases.size() == 2 && phases.active(Phase::WATER) && thermal) {
211 return this->runWaterOnlyEnergy(phases);
215 else if (phases.size() == 2 && !thermal) {
216 return this->runTwoPhase(phases);
220 else if (phases.active(Phase::POLYMER)) {
221 return this->runPolymer(phases);
225 else if (phases.active(Phase::FOAM) && !phases.active(Phase::SOLVENT)) {
226 return this->runFoam();
230 else if (phases.active(Phase::SOLVENT)) {
231 return this->runSolvent(phases);
235 else if (phases.active(Phase::BRINE) && !thermal) {
236 return this->runBrine(phases);
240 else if (phases.active(Phase::ZFRACTION)) {
241 return this->runExtendedBlackOil();
246 return this->runThermal(phases);
250 else if (phases.size() == 3) {
251 return this->runBlackOil();
256 std::cerr <<
"No suitable configuration found, valid are "
257 <<
"Twophase, polymer, foam, brine, solvent, "
258 <<
"energy, and blackoil.\n";
265 template <
class TypeTag>
266 int dispatchStatic_()
268 this->setupVanguard();
269 return flowMain<TypeTag>(argc_, argv_, outputCout_, outputFiles_);
280 template <
class TypeTagEarlyBird>
283 Dune::Timer externalSetupTimer;
284 externalSetupTimer.start();
298 typedef TypeTagEarlyBird PreTypeTag;
301 PreProblem::setBriefDescription(
"Flow, an advanced reservoir simulator for ECL-decks provided by the Open Porous Media project.");
309 MPI_Abort(MPI_COMM_WORLD, status);
311 exitCode = (status > 0) ? status : EXIT_SUCCESS;
315 std::string deckFilename;
316 std::string outputDir;
317 if ( eclipseState_ ) {
318 deckFilename = eclipseState_->getIOConfig().fullBasePath();
319 outputDir = eclipseState_->getIOConfig().getOutputDir();
322 deckFilename = Parameters::Get<Parameters::EclDeckFileName>();
323 outputDir = Parameters::Get<Parameters::OutputDir>();
327 enableDamarisOutput_ = Parameters::Get<Parameters::EnableDamarisOutput>();
332 msg =
"\nUse of Damaris (command line argument --enable-damaris-output=true) has been disabled for run with only one rank.\n" ;
333 OpmLog::warning(msg);
334 enableDamarisOutput_ = false ;
337 if (enableDamarisOutput_) {
339 auto damarisOutputDir = outputDir;
340 if (outputDir.empty()) {
341 auto odir = std::filesystem::path{deckFilename}.parent_path();
343 damarisOutputDir =
".";
345 damarisOutputDir = odir.generic_string();
349 this->setupDamaris(damarisOutputDir);
355 if (!isSimulationRank_) {
356 exitCode = EXIT_SUCCESS;
363 outputCout_ = Parameters::Get<Parameters::EnableTerminalOutput>();
365 if (deckFilename.empty()) {
367 std::cerr <<
"No input case given. Try '--help' for a usage description.\n";
369 exitCode = EXIT_FAILURE;
375 deckFilename = PreVanguard::canonicalDeckPath(deckFilename);
377 catch (
const std::exception& e) {
378 if ( mpiRank == 0 ) {
379 std::cerr <<
"Exception received: " << e.what() <<
". Try '--help' for a usage description.\n";
382 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
384 exitCode = EXIT_FAILURE;
388 std::string cmdline_params;
393 std::ostringstream str;
394 Parameters::printValues(str);
395 cmdline_params = str.str();
400 this->readDeck(deckFilename,
402 Parameters::Get<Parameters::OutputMode>(),
403 !Parameters::Get<Parameters::SchedRestart>(),
404 Parameters::Get<Parameters::EnableLoggingFalloutWarning>(),
405 Parameters::Get<Parameters::ParsingStrictness>(),
406 Parameters::Get<Parameters::ActionParsingStrictness>(),
407 Parameters::Get<Parameters::InputSkipMode>(),
410 Parameters::Get<Parameters::EclOutputInterval>(),
414 setupTime_ = externalSetupTimer.elapsed();
416 catch (
const std::invalid_argument& e)
419 std::cerr <<
"Failed to create valid EclipseState object." << std::endl;
420 std::cerr <<
"Exception caught: " << e.what() << std::endl;
423 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
425 exitCode = EXIT_FAILURE;
429 exitCode = EXIT_SUCCESS;
433 void setupVanguard();
443 void handleVersionCmdLine_(
int argc,
char** argv,
452 void handleTestSplitCommunicatorCmdLine_();
454 int runMICP(
const Phases& phases)
456 if (!phases.active(Phase::WATER) || (phases.size() > 2)) {
458 std::cerr <<
"No valid configuration is found for MICP simulation, "
459 <<
"the only valid option is water + MICP\n";
465 return flowMICPMain(this->argc_,
471 int runTwoPhase(
const Phases& phases)
473 const bool diffusive = eclipseState_->getSimulationConfig().isDiffusive();
474 const bool disgasw = eclipseState_->getSimulationConfig().hasDISGASW();
475 const bool vapwat = eclipseState_->getSimulationConfig().hasVAPWAT();
478 if (phases.active( Phase::OIL ) && phases.active( Phase::GAS )) {
480 return flowGasOilDiffuseMain(argc_, argv_, outputCout_, outputFiles_);
482 return flowGasOilMain(argc_, argv_, outputCout_, outputFiles_);
487 else if ( phases.active( Phase::OIL ) && phases.active( Phase::WATER ) ) {
490 std::cerr <<
"The DIFFUSE option is not available for the two-phase water/oil model." << std::endl;
494 return flowOilWaterMain(argc_, argv_, outputCout_, outputFiles_);
498 else if ( phases.active( Phase::GAS ) && phases.active( Phase::WATER ) ) {
499 if (disgasw || vapwat) {
501 return flowGasWaterDissolutionDiffuseMain(argc_, argv_, outputCout_, outputFiles_);
503 return flowGasWaterDissolutionMain(argc_, argv_, outputCout_, outputFiles_);
507 std::cerr <<
"The DIFFUSE option is not available for the two-phase gas/water model without disgasw or vapwat." << std::endl;
512 return flowGasWaterMain(argc_, argv_, outputCout_, outputFiles_);
516 std::cerr <<
"No suitable configuration found, valid are Twophase (oilwater, oilgas and gaswater), polymer, solvent, or blackoil" << std::endl;
523 int runPolymer(
const Phases& phases)
525 if (! phases.active(Phase::WATER)) {
527 std::cerr <<
"No valid configuration is found for polymer simulation, valid options include "
528 <<
"oilwater + polymer and blackoil + polymer" << std::endl;
535 if (phases.active(Phase::POLYMW)) {
537 assert (phases.size() == 4);
538 return flowOilWaterPolymerInjectivityMain(argc_, argv_, outputCout_, outputFiles_);
541 if (phases.size() == 3) {
542 return flowOilWaterPolymerMain(argc_, argv_, outputCout_, outputFiles_);
545 return flowPolymerMain(argc_, argv_, outputCout_, outputFiles_);
551 return flowFoamMain(argc_, argv_, outputCout_, outputFiles_);
554 int runWaterOnly(
const Phases& phases)
556 if (!phases.active(Phase::WATER) || phases.size() != 1) {
558 std::cerr <<
"No valid configuration is found for water-only simulation, valid options include "
559 <<
"water, water + thermal" << std::endl;
564 return flowWaterOnlyMain(argc_, argv_, outputCout_, outputFiles_);
567 int runWaterOnlyEnergy(
const Phases& phases)
569 if (!phases.active(Phase::WATER) || phases.size() != 2) {
571 std::cerr <<
"No valid configuration is found for water-only simulation, valid options include "
572 <<
"water, water + thermal" << std::endl;
577 return flowWaterOnlyEnergyMain(argc_, argv_, outputCout_, outputFiles_);
580 int runBrine(
const Phases& phases)
582 if (! phases.active(Phase::WATER) || phases.size() == 2) {
584 std::cerr <<
"No valid configuration is found for brine simulation, valid options include "
585 <<
"oilwater + brine, gaswater + brine and blackoil + brine" << std::endl;
590 if (phases.size() == 3) {
592 if (phases.active(Phase::OIL)){
593 return flowOilWaterBrineMain(argc_, argv_, outputCout_, outputFiles_);
595 if (phases.active(Phase::GAS)){
596 if (eclipseState_->getSimulationConfig().hasPRECSALT() &&
597 eclipseState_->getSimulationConfig().hasVAPWAT()) {
599 return flowGasWaterSaltprecVapwatMain(argc_, argv_, outputCout_, outputFiles_);
602 return flowGasWaterBrineMain(argc_, argv_, outputCout_, outputFiles_);
606 else if (eclipseState_->getSimulationConfig().hasPRECSALT()) {
607 if (eclipseState_->getSimulationConfig().hasVAPWAT()) {
609 return flowBrinePrecsaltVapwatMain(argc_, argv_, outputCout_, outputFiles_);
612 return flowBrineSaltPrecipitationMain(argc_, argv_, outputCout_, outputFiles_);
616 return flowBrineMain(argc_, argv_, outputCout_, outputFiles_);
622 int runSolvent(
const Phases& phases)
624 if (phases.active(Phase::FOAM)) {
625 return flowSolventFoamMain(argc_, argv_, outputCout_, outputFiles_);
628 if (!phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
629 return flowGasWaterSolventMain(argc_, argv_, outputCout_, outputFiles_);
633 if (phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
634 return flowSolventMain(argc_, argv_, outputCout_, outputFiles_);
638 std::cerr <<
"No valid configuration is found for solvent simulation, valid options include "
639 <<
"gas + water + solvent and gas + oil + water + solvent" << std::endl;
644 int runExtendedBlackOil()
646 return flowExtboMain(argc_, argv_, outputCout_, outputFiles_);
649 int runThermal(
const Phases& phases)
652 if (!phases.active( Phase::WATER ) && phases.active( Phase::OIL ) && phases.active( Phase::GAS )) {
653 return flowGasOilEnergyMain(argc_, argv_, outputCout_, outputFiles_);
657 if (!phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
659 if (phases.active(Phase::BRINE)){
660 return flowGasWaterSaltprecEnergyMain(argc_, argv_, outputCout_, outputFiles_);
662 return flowGasWaterEnergyMain(argc_, argv_, outputCout_, outputFiles_);
665 return flowEnergyMain(argc_, argv_, outputCout_, outputFiles_);
670 const bool diffusive = eclipseState_->getSimulationConfig().isDiffusive();
674 return flowBlackoilMain(argc_, argv_, outputCout_, outputFiles_);
676 return flowBlackoilTpfaMain(argc_, argv_, outputCout_, outputFiles_);
680 void readDeck(
const std::string& deckFilename,
681 const std::string& outputDir,
682 const std::string& outputMode,
683 const bool init_from_restart_file,
684 const bool allRanksDbgPrtLog,
685 const std::string& parsingStrictness,
686 const std::string& actionParsingStrictness,
687 const std::string& inputSkipMode,
688 const bool keepKeywords,
689 const std::size_t numThreads,
690 const int output_param,
691 const std::string& parameters,
695 static int getNumThreads()
704 static bool first_time =
true;
705 constexpr int default_threads = 2;
706 const int requested_threads = Parameters::Get<Parameters::ThreadsPerProcess>();
707 threads = requested_threads > 0 ? requested_threads : default_threads;
709 const char* env_var = getenv(
"OMP_NUM_THREADS");
711 int omp_num_threads = -1;
712 auto result = std::from_chars(env_var, env_var + std::strlen(env_var), omp_num_threads);
714 if (result.ec == std::errc() && omp_num_threads > 0) {
716 threads = omp_num_threads;
717 if (can_output && requested_threads > 0) {
718 std::cout <<
"Warning: Environment variable OMP_NUM_THREADS takes precedence over the --threads-per-process cmdline argument."
723 std::cout << (
"Warning: Invalid value for OMP_NUM_THREADS environment variable.") << std::endl;
736 void setupDamaris(
const std::string& outputDir);
741 char** argv_{
nullptr};
742 bool outputCout_{
false};
743 bool outputFiles_{
false};
747 double setupTime_{0.0};
748 std::string deckFilename_{};
749 std::string flowProgName_{};
750 char *saveArgs_[3]{
nullptr};
751 std::unique_ptr<UDQState> udqState_{};
752 std::unique_ptr<Action::State> actionState_{};
753 std::unique_ptr<WellTestState> wtestState_{};
756 std::shared_ptr<EclipseState> eclipseState_{};
757 std::shared_ptr<Schedule> schedule_{};
758 std::shared_ptr<SummaryConfig> summaryConfig_{};
759 bool mpi_init_{
true};
760 bool mpi_finalize_{
true};
763 bool test_split_comm_ =
false;
764 bool isSimulationRank_ =
true;
766 bool enableDamarisOutput_ =
false;