Main.hpp
Go to the documentation of this file.
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 Copyright 2023 Inria
7
8 This file is part of the Open Porous Media project (OPM).
9
10 OPM is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14
15 OPM is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with OPM. If not, see <http://www.gnu.org/licenses/>.
22*/
23#ifndef OPM_MAIN_HEADER_INCLUDED
24#define OPM_MAIN_HEADER_INCLUDED
25
26#include <flow/flow_blackoil.hpp>
27#include <flow/flow_blackoil_legacyassembly.hpp>
28
29#include <flow/flow_gasoil.hpp>
30#include <flow/flow_gasoildiffuse.hpp>
31#include <flow/flow_gasoil_energy.hpp>
32#include <flow/flow_oilwater.hpp>
33#include <flow/flow_gaswater.hpp>
34#include <flow/flow_gaswater_solvent.hpp>
35#include <flow/flow_solvent.hpp>
36#include <flow/flow_solvent_foam.hpp>
37#include <flow/flow_polymer.hpp>
38#include <flow/flow_extbo.hpp>
39#include <flow/flow_foam.hpp>
40#include <flow/flow_brine.hpp>
41#include <flow/flow_brine_saltprecipitation.hpp>
42#include <flow/flow_gaswater_saltprec_vapwat.hpp>
43#include <flow/flow_gaswater_saltprec_energy.hpp>
44#include <flow/flow_brine_precsalt_vapwat.hpp>
45#include <flow/flow_onephase.hpp>
46#include <flow/flow_onephase_energy.hpp>
47#include <flow/flow_oilwater_brine.hpp>
48#include <flow/flow_gaswater_brine.hpp>
49#include <flow/flow_gaswater_energy.hpp>
50#include <flow/flow_gaswater_dissolution.hpp>
51#include <flow/flow_gaswater_dissolution_diffuse.hpp>
52#include <flow/flow_energy.hpp>
53#include <flow/flow_oilwater_polymer.hpp>
54#include <flow/flow_oilwater_polymer_injectivity.hpp>
55#include <flow/flow_micp.hpp>
56
57#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
58
59#include <opm/models/utils/propertysystem.hh>
60#include <opm/models/utils/parametersystem.hh>
61
64
65#if HAVE_DUNE_FEM
66#include <dune/fem/misc/mpimanager.hh>
67#else
68#include <dune/common/parallel/mpihelper.hh>
69#endif
70
71#if HAVE_MPI
73#endif
74
75#if HAVE_DAMARIS
77#endif
78
79#include <cassert>
80#include <cstdlib>
81#include <filesystem>
82#include <iostream>
83#include <memory>
84#include <stdexcept>
85#include <string>
86#include <string_view>
87#include <type_traits>
88#include <utility>
89
90namespace Opm::Properties {
91
92// this is a dummy type tag that is used to setup the parameters before the actual
93// simulator.
94namespace TTag {
96 using InheritsFrom = std::tuple<FlowProblem>;
97};
98}
99
100} // namespace Opm::Properties
101
102namespace Opm {
103
104namespace Action { class State; }
105class UDQState;
106class WellTestState;
107
108// ----------------- Main program -----------------
109template <class TypeTag>
110int flowMain(int argc, char** argv, bool outputCout, bool outputFiles)
111{
112 // we always want to use the default locale, and thus spare us the trouble
113 // with incorrect locale settings.
114 resetLocale();
115
116 FlowMain<TypeTag> mainfunc(argc, argv, outputCout, outputFiles);
117 return mainfunc.execute();
118}
119
120// ----------------- Main class -----------------
121// For now, we will either be instantiated from main() in flow.cpp,
122// or from a Python pybind11 module..
123// NOTE (March 2020): When used from a pybind11 module, we do not neccessarily
124// want to run the whole simulation by calling run(), it is also
125// useful to just run one report step at a time. According to these different
126// usage scenarios, we refactored the original run() in flow.cpp into this class.
127class Main
128{
129public:
130 Main(int argc, char** argv, bool ownMPI = true);
131
132 // This constructor can be called from Python
133 Main(const std::string& filename, bool mpi_init = true, bool mpi_finalize = true);
134
135 // This constructor can be called from Python when Python has
136 // already parsed a deck
137 Main(const std::string& filename,
138 std::shared_ptr<EclipseState> eclipseState,
139 std::shared_ptr<Schedule> schedule,
140 std::shared_ptr<SummaryConfig> summaryConfig,
141 bool mpi_init = true,
142 bool mpi_finalize = true);
143
145
146 void setArgvArgc_(const std::string& filename);
147
148 void initMPI();
149
151 {
152 int exitCode = EXIT_SUCCESS;
153 if (initialize_<Properties::TTag::FlowEarlyBird>(exitCode)) {
154 if (isSimulationRank_) {
155 return this->dispatchDynamic_();
156 }
157 }
158
159 return exitCode;
160 }
161
162 template <class TypeTag>
164 {
165 int exitCode = EXIT_SUCCESS;
166 if (initialize_<TypeTag>(exitCode)) {
167 if (isSimulationRank_) {
168 return this->dispatchStatic_<TypeTag>();
169 }
170 }
171
172 return exitCode;
173 }
174
176 // To be called from the Python interface code. Only do the
177 // initialization and then return a pointer to the FlowMain
178 // object that can later be accessed directly from the Python interface
179 // to e.g. advance the simulator one report step
180 std::unique_ptr<FlowMainType> initFlowBlackoil(int& exitCode)
181 {
182 exitCode = EXIT_SUCCESS;
183 if (initialize_<Properties::TTag::FlowEarlyBird>(exitCode)) {
184 // TODO: check that this deck really represents a blackoil
185 // case. E.g. check that number of phases == 3
186 this->setupVanguard();
187 return flowBlackoilTpfaMainInit(
188 argc_, argv_, outputCout_, outputFiles_);
189 } else {
190 //NOTE: exitCode was set by initialize_() above;
191 return std::unique_ptr<FlowMainType>(); // nullptr
192 }
193 }
194
197 {
198 int exitCode = EXIT_SUCCESS;
199 initialize_<Properties::TTag::FlowEarlyBird>(exitCode);
200 return exitCode;
201 }
202
203private:
204 int dispatchDynamic_()
205 {
206 const auto& rspec = this->eclipseState_->runspec();
207 const auto& phases = rspec.phases();
208
209 this->setupVanguard();
210
211 // run the actual simulator
212 //
213 // TODO: make sure that no illegal combinations like thermal and
214 // twophase are requested.
215 const bool thermal = eclipseState_->getSimulationConfig().isThermal();
216
217 // Single-phase case
218 if (rspec.micp()) {
219 return this->runMICP(phases);
220 }
221
222 // water-only case
223 else if (phases.size() == 1 && phases.active(Phase::WATER) && !thermal) {
224 return this->runWaterOnly(phases);
225 }
226
227 // water-only case with energy
228 else if (phases.size() == 2 && phases.active(Phase::WATER) && thermal) {
229 return this->runWaterOnlyEnergy(phases);
230 }
231
232 // Twophase cases
233 else if (phases.size() == 2 && !thermal) {
234 return this->runTwoPhase(phases);
235 }
236
237 // Polymer case
238 else if (phases.active(Phase::POLYMER)) {
239 return this->runPolymer(phases);
240 }
241
242 // Foam case
243 else if (phases.active(Phase::FOAM) && !phases.active(Phase::SOLVENT)) {
244 return this->runFoam();
245 }
246
247 // Solvent case
248 else if (phases.active(Phase::SOLVENT)) {
249 return this->runSolvent(phases);
250 }
251
252 // Brine case
253 else if (phases.active(Phase::BRINE) && !thermal) {
254 return this->runBrine(phases);
255 }
256
257 // Extended BO case
258 else if (phases.active(Phase::ZFRACTION)) {
259 return this->runExtendedBlackOil();
260 }
261
262 // Energy case
263 else if (thermal) {
264 return this->runThermal(phases);
265 }
266
267 // Blackoil case
268 else if (phases.size() == 3) {
269 return this->runBlackOil();
270 }
271
272 else {
273 if (outputCout_) {
274 std::cerr << "No suitable configuration found, valid are "
275 << "Twophase, polymer, foam, brine, solvent, "
276 << "energy, and blackoil.\n";
277 }
278
279 return EXIT_FAILURE;
280 }
281 }
282
283 template <class TypeTag>
284 int dispatchStatic_()
285 {
286 this->setupVanguard();
287 return flowMain<TypeTag>(argc_, argv_, outputCout_, outputFiles_);
288 }
289
296 template <class TypeTagEarlyBird>
297 bool initialize_(int& exitCode)
298 {
299 Dune::Timer externalSetupTimer;
300 externalSetupTimer.start();
301
302 handleVersionCmdLine_(argc_, argv_, Opm::moduleVersionName());
303
304 // we always want to use the default locale, and thus spare us the trouble
305 // with incorrect locale settings.
306 resetLocale();
307
308 // this is a work-around for a catch 22: we do not know what code path to use without
309 // parsing the deck, but we don't know the deck without having access to the
310 // parameters and this requires to know the type tag to be used. To solve this, we
311 // use a type tag just for parsing the parameters before we instantiate the actual
312 // simulator object. (Which parses the parameters again, but since this is done in an
313 // identical manner it does not matter.)
314 typedef TypeTagEarlyBird PreTypeTag;
315 using PreProblem = GetPropType<PreTypeTag, Properties::Problem>;
316
317 PreProblem::setBriefDescription("Flow, an advanced reservoir simulator for ECL-decks provided by the Open Porous Media project.");
319 if (status != 0) {
320 // if setupParameters_ returns a value smaller than 0, there was no error, but
321 // the program should abort. This is the case e.g. for the --help and the
322 // --print-properties parameters.
323#if HAVE_MPI
324 if (status >= 0)
325 MPI_Abort(MPI_COMM_WORLD, status);
326#endif
327 exitCode = (status > 0) ? status : EXIT_SUCCESS;
328 return false; // Whether to run the simulator
329 }
330
331 std::string deckFilename;
332 std::string outputDir;
333 if ( eclipseState_ ) {
334 deckFilename = eclipseState_->getIOConfig().fullBasePath();
335 outputDir = eclipseState_->getIOConfig().getOutputDir();
336 }
337 else {
338 deckFilename = Parameters::get<PreTypeTag, Properties::EclDeckFileName>();
339 outputDir = Parameters::get<PreTypeTag, Properties::OutputDir>();
340 }
341
342#if HAVE_DAMARIS
343 enableDamarisOutput_ = Parameters::get<PreTypeTag, Properties::EnableDamarisOutput>();
344
345 // Reset to false as we cannot use Damaris if there is only one rank.
346 if ((enableDamarisOutput_ == true) && (FlowGenericVanguard::comm().size() == 1)) {
347 std::string msg ;
348 msg = "\nUse of Damaris (command line argument --enable-damaris-output=true) has been disabled for run with only one rank.\n" ;
349 OpmLog::warning(msg);
350 enableDamarisOutput_ = false ;
351 }
352
353 if (enableDamarisOutput_) {
354 // Deal with empty (defaulted) output dir, should be deck dir
355 auto damarisOutputDir = outputDir;
356 if (outputDir.empty()) {
357 auto odir = std::filesystem::path{deckFilename}.parent_path();
358 if (odir.empty()) {
359 damarisOutputDir = ".";
360 } else {
361 damarisOutputDir = odir.generic_string();
362 }
363 }
364 // Damaris server ranks will block here until damaris_stop() is called by client ranks
365 this->setupDamaris(damarisOutputDir);
366 }
367#endif // HAVE_DAMARIS
368
369 // Guard for when the Damaris core(s) return from damaris_start()
370 // which happens when damaris_stop() is called in main simulation
371 if (!isSimulationRank_) {
372 exitCode = EXIT_SUCCESS;
373 return true;
374 }
375
376 int mpiRank = FlowGenericVanguard::comm().rank();
377 outputCout_ = false;
378 if (mpiRank == 0)
379 outputCout_ = Parameters::get<PreTypeTag, Properties::EnableTerminalOutput>();
380
381 if (deckFilename.empty()) {
382 if (mpiRank == 0) {
383 std::cerr << "No input case given. Try '--help' for a usage description.\n";
384 }
385 exitCode = EXIT_FAILURE;
386 return false;
387 }
388
389 using PreVanguard = GetPropType<PreTypeTag, Properties::Vanguard>;
390 try {
391 deckFilename = PreVanguard::canonicalDeckPath(deckFilename);
392 }
393 catch (const std::exception& e) {
394 if ( mpiRank == 0 ) {
395 std::cerr << "Exception received: " << e.what() << ". Try '--help' for a usage description.\n";
396 }
397#if HAVE_MPI
398 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
399#endif
400 exitCode = EXIT_FAILURE;
401 return false;
402 }
403
404 std::string cmdline_params;
405 if (outputCout_) {
407 getNumThreads<PreTypeTag>(),
409 std::ostringstream str;
410 Parameters::printValues<PreTypeTag>(str);
411 cmdline_params = str.str();
412 }
413
414 // Create Deck and EclipseState.
415 try {
416 this->readDeck(deckFilename,
417 outputDir,
418 Parameters::get<PreTypeTag, Properties::OutputMode>(),
419 !Parameters::get<PreTypeTag, Properties::SchedRestart>(),
420 Parameters::get<PreTypeTag, Properties::EnableLoggingFalloutWarning>(),
421 Parameters::get<PreTypeTag, Properties::ParsingStrictness>(),
422 Parameters::get<PreTypeTag, Properties::InputSkipMode>(),
423 getNumThreads<PreTypeTag>(),
424 Parameters::get<PreTypeTag, Properties::EclOutputInterval>(),
425 cmdline_params,
428 setupTime_ = externalSetupTimer.elapsed();
429 }
430 catch (const std::invalid_argument& e)
431 {
432 if (outputCout_) {
433 std::cerr << "Failed to create valid EclipseState object." << std::endl;
434 std::cerr << "Exception caught: " << e.what() << std::endl;
435 }
436#if HAVE_MPI
437 MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
438#endif
439 exitCode = EXIT_FAILURE;
440 return false;
441 }
442
443 exitCode = EXIT_SUCCESS;
444 return true;
445 }
446
447 // This function is an extreme special case, if the program has been invoked
448 // *exactly* as:
449 //
450 // flow --version
451 //
452 // the call is intercepted by this function which will print "flow $version"
453 // on stdout and exit(0).
454 void handleVersionCmdLine_(int argc, char** argv,
455 std::string_view moduleVersionName);
456
457 // This function is a special case, if the program has been invoked
458 // with the argument "--test-split-communicator=true" as the FIRST
459 // argument, it will be removed from the argument list and we set the
460 // test_split_comm_ flag to true.
461 // Note: initializing the parameter system before MPI could make this
462 // use the parameter system instead.
463 void handleTestSplitCommunicatorCmdLine_();
464
465 int runMICP(const Phases& phases)
466 {
467 if (!phases.active(Phase::WATER) || (phases.size() > 2)) {
468 if (outputCout_) {
469 std::cerr << "No valid configuration is found for MICP simulation, "
470 << "the only valid option is water + MICP\n";
471 }
472
473 return EXIT_FAILURE;
474 }
475
476 return flowMICPMain(this->argc_,
477 this->argv_,
478 this->outputCout_,
479 this->outputFiles_);
480 }
481
482 int runTwoPhase(const Phases& phases)
483 {
484 const bool diffusive = eclipseState_->getSimulationConfig().isDiffusive();
485 const bool disgasw = eclipseState_->getSimulationConfig().hasDISGASW();
486 const bool vapwat = eclipseState_->getSimulationConfig().hasVAPWAT();
487
488 // oil-gas
489 if (phases.active( Phase::OIL ) && phases.active( Phase::GAS )) {
490 if (diffusive) {
491 return flowGasOilDiffuseMain(argc_, argv_, outputCout_, outputFiles_);
492 } else {
493 return flowGasOilMain(argc_, argv_, outputCout_, outputFiles_);
494 }
495 }
496
497 // oil-water
498 else if ( phases.active( Phase::OIL ) && phases.active( Phase::WATER ) ) {
499 if (diffusive) {
500 if (outputCout_) {
501 std::cerr << "The DIFFUSE option is not available for the two-phase water/oil model." << std::endl;
502 }
503 return EXIT_FAILURE;
504 }
505 return flowOilWaterMain(argc_, argv_, outputCout_, outputFiles_);
506 }
507
508 // gas-water
509 else if ( phases.active( Phase::GAS ) && phases.active( Phase::WATER ) ) {
510 if (disgasw || vapwat) {
511 if (diffusive) {
512 return flowGasWaterDissolutionDiffuseMain(argc_, argv_, outputCout_, outputFiles_);
513 }
514 return flowGasWaterDissolutionMain(argc_, argv_, outputCout_, outputFiles_);
515 }
516 if (diffusive) {
517 if (outputCout_) {
518 std::cerr << "The DIFFUSE option is not available for the two-phase gas/water model without disgasw or vapwat." << std::endl;
519 }
520 return EXIT_FAILURE;
521 }
522
523 return flowGasWaterMain(argc_, argv_, outputCout_, outputFiles_);
524 }
525 else {
526 if (outputCout_) {
527 std::cerr << "No suitable configuration found, valid are Twophase (oilwater, oilgas and gaswater), polymer, solvent, or blackoil" << std::endl;
528 }
529
530 return EXIT_FAILURE;
531 }
532 }
533
534 int runPolymer(const Phases& phases)
535 {
536 if (! phases.active(Phase::WATER)) {
537 if (outputCout_)
538 std::cerr << "No valid configuration is found for polymer simulation, valid options include "
539 << "oilwater + polymer and blackoil + polymer" << std::endl;
540
541 return EXIT_FAILURE;
542 }
543
544 // Need to track the polymer molecular weight
545 // for the injectivity study
546 if (phases.active(Phase::POLYMW)) {
547 // only oil water two phase for now
548 assert (phases.size() == 4);
549 return flowOilWaterPolymerInjectivityMain(argc_, argv_, outputCout_, outputFiles_);
550 }
551
552 if (phases.size() == 3) { // oil water polymer case
553 return flowOilWaterPolymerMain(argc_, argv_, outputCout_, outputFiles_);
554 }
555 else {
556 return flowPolymerMain(argc_, argv_, outputCout_, outputFiles_);
557 }
558 }
559
560 int runFoam()
561 {
562 return flowFoamMain(argc_, argv_, outputCout_, outputFiles_);
563 }
564
565 int runWaterOnly(const Phases& phases)
566 {
567 if (!phases.active(Phase::WATER) || phases.size() != 1) {
568 if (outputCout_)
569 std::cerr << "No valid configuration is found for water-only simulation, valid options include "
570 << "water, water + thermal" << std::endl;
571
572 return EXIT_FAILURE;
573 }
574
575 return flowWaterOnlyMain(argc_, argv_, outputCout_, outputFiles_);
576 }
577
578 int runWaterOnlyEnergy(const Phases& phases)
579 {
580 if (!phases.active(Phase::WATER) || phases.size() != 2) {
581 if (outputCout_)
582 std::cerr << "No valid configuration is found for water-only simulation, valid options include "
583 << "water, water + thermal" << std::endl;
584
585 return EXIT_FAILURE;
586 }
587
588 return flowWaterOnlyEnergyMain(argc_, argv_, outputCout_, outputFiles_);
589 }
590
591 int runBrine(const Phases& phases)
592 {
593 if (! phases.active(Phase::WATER) || phases.size() == 2) {
594 if (outputCout_)
595 std::cerr << "No valid configuration is found for brine simulation, valid options include "
596 << "oilwater + brine, gaswater + brine and blackoil + brine" << std::endl;
597
598 return EXIT_FAILURE;
599 }
600
601 if (phases.size() == 3) {
602
603 if (phases.active(Phase::OIL)){ // oil water brine case
604 return flowOilWaterBrineMain(argc_, argv_, outputCout_, outputFiles_);
605 }
606 if (phases.active(Phase::GAS)){ // gas water brine case
607 if (eclipseState_->getSimulationConfig().hasPRECSALT() &&
608 eclipseState_->getSimulationConfig().hasVAPWAT()) {
609 //case with water vaporization into gas phase and salt precipitation
610 return flowGasWaterSaltprecVapwatMain(argc_, argv_, outputCout_, outputFiles_);
611 }
612 else {
613 return flowGasWaterBrineMain(argc_, argv_, outputCout_, outputFiles_);
614 }
615 }
616 }
617 else if (eclipseState_->getSimulationConfig().hasPRECSALT()) {
618 if (eclipseState_->getSimulationConfig().hasVAPWAT()) {
619 //case with water vaporization into gas phase and salt precipitation
620 return flowBrinePrecsaltVapwatMain(argc_, argv_, outputCout_, outputFiles_);
621 }
622 else {
623 return flowBrineSaltPrecipitationMain(argc_, argv_, outputCout_, outputFiles_);
624 }
625 }
626 else {
627 return flowBrineMain(argc_, argv_, outputCout_, outputFiles_);
628 }
629
630 return EXIT_FAILURE;
631 }
632
633 int runSolvent(const Phases& phases)
634 {
635 if (phases.active(Phase::FOAM)) {
636 return flowSolventFoamMain(argc_, argv_, outputCout_, outputFiles_);
637 }
638 // solvent + gas + water
639 if (!phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
640 return flowGasWaterSolventMain(argc_, argv_, outputCout_, outputFiles_);
641 }
642
643 // solvent + gas + water + oil
644 if (phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
645 return flowSolventMain(argc_, argv_, outputCout_, outputFiles_);
646 }
647
648 if (outputCout_)
649 std::cerr << "No valid configuration is found for solvent simulation, valid options include "
650 << "gas + water + solvent and gas + oil + water + solvent" << std::endl;
651
652 return EXIT_FAILURE;
653 }
654
655 int runExtendedBlackOil()
656 {
657 return flowExtboMain(argc_, argv_, outputCout_, outputFiles_);
658 }
659
660 int runThermal(const Phases& phases)
661 {
662 // oil-gas-thermal
663 if (!phases.active( Phase::WATER ) && phases.active( Phase::OIL ) && phases.active( Phase::GAS )) {
664 return flowGasOilEnergyMain(argc_, argv_, outputCout_, outputFiles_);
665 }
666
667 // water-gas-thermal
668 if (!phases.active( Phase::OIL ) && phases.active( Phase::WATER ) && phases.active( Phase::GAS )) {
669
670 if (phases.active(Phase::BRINE)){
671 return flowGasWaterSaltprecEnergyMain(argc_, argv_, outputCout_, outputFiles_);
672 }
673 return flowGasWaterEnergyMain(argc_, argv_, outputCout_, outputFiles_);
674 }
675
676 return flowEnergyMain(argc_, argv_, outputCout_, outputFiles_);
677 }
678
679 int runBlackOil()
680 {
681 const bool diffusive = eclipseState_->getSimulationConfig().isDiffusive();
682 if (diffusive) {
683 // Use the traditional linearizer, as the TpfaLinearizer does not
684 // support the diffusion module yet.
685 return flowBlackoilMain(argc_, argv_, outputCout_, outputFiles_);
686 } else {
687 return flowBlackoilTpfaMain(argc_, argv_, outputCout_, outputFiles_);
688 }
689 }
690
691 void readDeck(const std::string& deckFilename,
692 const std::string& outputDir,
693 const std::string& outputMode,
694 const bool init_from_restart_file,
695 const bool allRanksDbgPrtLog,
696 const std::string& parsingStrictness,
697 const std::string& inputSkipMode,
698 const std::size_t numThreads,
699 const int output_param,
700 const std::string& parameters,
701 std::string_view moduleVersion,
702 std::string_view compileTimestamp);
703
704 void setupVanguard();
705
706 template<class TypeTag>
707 static int getNumThreads()
708 {
709
710 int threads;
711
712#ifdef _OPENMP
713 // This function is called before the parallel OpenMP stuff gets initialized.
714 // That initialization happends after the deck is read and we want this message.
715 // Hence we duplicate the code of setupParallelism to get the number of threads.
716 if (std::getenv("OMP_NUM_THREADS")) {
717 threads = omp_get_max_threads();
718 }
719 else {
720 threads = 2;
721
722 const int input_threads = Parameters::get<TypeTag, Properties::ThreadsPerProcess>();
723
724 if (input_threads > 0)
725 threads = input_threads;
726 }
727#else
728 threads = 1;
729#endif
730
731 return threads;
732 }
733
734#if HAVE_DAMARIS
735 void setupDamaris(const std::string& outputDir);
736#endif
737
738 int argc_{0};
739 char** argv_{nullptr};
740 bool ownMPI_{true};
741 bool outputCout_{false};
742 bool outputFiles_{false};
743 double setupTime_{0.0};
744 std::string deckFilename_{};
745 std::string flowProgName_{};
746 char *saveArgs_[3]{nullptr};
747 std::unique_ptr<UDQState> udqState_{};
748 std::unique_ptr<Action::State> actionState_{};
749 std::unique_ptr<WellTestState> wtestState_{};
750
751 // These variables may be owned by both Python and the simulator
752 std::shared_ptr<EclipseState> eclipseState_{};
753 std::shared_ptr<Schedule> schedule_{};
754 std::shared_ptr<SummaryConfig> summaryConfig_{};
755 bool mpi_init_{true};
756 bool mpi_finalize_{true};
757
758 // To demonstrate run with non_world_comm
759 bool test_split_comm_ = false;
760 bool isSimulationRank_ = true;
761#if HAVE_DAMARIS
762 bool enableDamarisOutput_ = false;
763#endif
764};
765
766} // namespace Opm
767
768#endif // OPM_MAIN_HEADER_INCLUDED
static Parallel::Communication & comm()
Obtain global communicator.
Definition: FlowGenericVanguard.hpp:255
Definition: FlowMain.hpp:83
static int setupParameters_(int argc, char **argv, Parallel::Communication comm)
Definition: FlowMain.hpp:103
int execute()
Definition: FlowMain.hpp:269
Definition: Main.hpp:128
int justInitialize()
Used for test_outputdir.
Definition: Main.hpp:196
int runDynamic()
Definition: Main.hpp:150
std::unique_ptr< FlowMainType > initFlowBlackoil(int &exitCode)
Definition: Main.hpp:180
Main(int argc, char **argv, bool ownMPI=true)
Main(const std::string &filename, bool mpi_init=true, bool mpi_finalize=true)
int runStatic()
Definition: Main.hpp:163
void setArgvArgc_(const std::string &filename)
void initMPI()
Main(const std::string &filename, std::shared_ptr< EclipseState > eclipseState, std::shared_ptr< Schedule > schedule, std::shared_ptr< SummaryConfig > summaryConfig, bool mpi_init=true, bool mpi_finalize=true)
Definition: AluGridVanguard.hpp:57
Definition: BlackoilPhases.hpp:27
std::string moduleVersionName()
int flowMain(int argc, char **argv, bool outputCout, bool outputFiles)
Definition: Main.hpp:110
std::string compileTimestamp()
void printFlowBanner(int nprocs, int threads, std::string_view moduleVersionName)
std::string moduleVersion()
std::tuple< FlowProblem > InheritsFrom
Definition: Main.hpp:96