00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef OPM_FLOWMAIN_HEADER_INCLUDED
00024 #define OPM_FLOWMAIN_HEADER_INCLUDED
00025
00026 #include <opm/common/utility/platform_dependent/disable_warnings.h>
00027
00028
00029 #include <dune/common/version.hh>
00030 #include <dune/common/parallel/mpihelper.hh>
00031
00032 #include <opm/common/utility/platform_dependent/reenable_warnings.h>
00033
00034
00035 #include <opm/core/grid/GridManager.hpp>
00036 #include <opm/autodiff/GridHelpers.hpp>
00037 #include <opm/autodiff/createGlobalCellArray.hpp>
00038 #include <opm/autodiff/GridInit.hpp>
00039 #include <opm/simulators/ParallelFileMerger.hpp>
00040 #include <opm/simulators/ensureDirectoryExists.hpp>
00041
00042 #include <opm/core/wells.h>
00043 #include <opm/core/wells/WellsManager.hpp>
00044 #include <opm/common/ErrorMacros.hpp>
00045 #include <opm/core/simulator/initState.hpp>
00046 #include <opm/core/simulator/initStateEquil.hpp>
00047 #include <opm/core/simulator/SimulatorReport.hpp>
00048 #include <opm/simulators/timestepping/SimulatorTimer.hpp>
00049 #include <opm/core/utility/miscUtilities.hpp>
00050 #include <opm/core/utility/parameters/ParameterGroup.hpp>
00051 #include <opm/simulators/thresholdPressures.hpp>
00052
00053 #include <opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp>
00054 #include <opm/core/props/BlackoilPropertiesBasic.hpp>
00055 #include <opm/core/props/BlackoilPropertiesFromDeck.hpp>
00056 #include <opm/core/props/rock/RockCompressibility.hpp>
00057 #include <opm/core/props/satfunc/RelpermDiagnostics.hpp>
00058 #include <opm/core/linalg/LinearSolverFactory.hpp>
00059 #include <opm/autodiff/NewtonIterationBlackoilSimple.hpp>
00060 #include <opm/autodiff/NewtonIterationBlackoilCPR.hpp>
00061 #include <opm/autodiff/NewtonIterationBlackoilInterleaved.hpp>
00062
00063 #include <opm/autodiff/WellStateFullyImplicitBlackoil.hpp>
00064
00065 #include <opm/autodiff/BlackoilPropsAdFromDeck.hpp>
00066 #include <opm/autodiff/RedistributeDataHandles.hpp>
00067 #include <opm/autodiff/moduleVersion.hpp>
00068 #include <opm/autodiff/MissingFeatures.hpp>
00069
00070 #include <opm/core/utility/share_obj.hpp>
00071 #include <opm/core/utility/initHydroCarbonState.hpp>
00072 #include <opm/common/OpmLog/OpmLog.hpp>
00073 #include <opm/common/OpmLog/EclipsePRTLog.hpp>
00074 #include <opm/common/OpmLog/LogUtil.hpp>
00075 #include <opm/parser/eclipse/Deck/Deck.hpp>
00076 #include <opm/parser/eclipse/Parser/Parser.hpp>
00077 #include <opm/parser/eclipse/Parser/ParseContext.hpp>
00078 #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
00079 #include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
00080 #include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
00081 #include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
00082 #include <opm/common/ResetLocale.hpp>
00083
00084 #include <boost/filesystem.hpp>
00085 #include <boost/algorithm/string.hpp>
00086
00087
00088 #ifdef _OPENMP
00089 #include <omp.h>
00090 #endif
00091
00092 #include <memory>
00093 #include <algorithm>
00094 #include <cstdlib>
00095 #include <iostream>
00096 #include <vector>
00097 #include <numeric>
00098 #include <cstdlib>
00099 #include <stdexcept>
00100
00101
00102
00103
00104 namespace Opm
00105 {
00106
00107
00108 namespace detail
00109 {
00110 boost::filesystem::path simulationCaseName( const std::string& casename );
00111 int64_t convertMessageType(const Message::type& mtype);
00112 }
00113
00114
00115
00116
00117
00118
00121 template <class Implementation, class Grid, class Simulator>
00122 class FlowMainBase
00123 {
00124 public:
00125
00126
00132 int execute(int argc, char** argv)
00133 try {
00134
00135
00136 resetLocale();
00137
00138
00139 asImpl().setupParallelism(argc, argv);
00140 asImpl().printStartupMessage();
00141 const bool ok = asImpl().setupParameters(argc, argv);
00142 if (!ok) {
00143 return EXIT_FAILURE;
00144 }
00145 asImpl().readDeckInput();
00146 asImpl().setupOutput();
00147 asImpl().setupLogging();
00148 asImpl().extractMessages();
00149 asImpl().setupGridAndProps();
00150 asImpl().runDiagnostics();
00151 asImpl().setupState();
00152 asImpl().writeInit();
00153 asImpl().distributeData();
00154 asImpl().setupOutputWriter();
00155 asImpl().setupLinearSolver();
00156 asImpl().createSimulator();
00157
00158
00159 auto ret = asImpl().runSimulator();
00160
00161 asImpl().mergeParallelLogFiles();
00162
00163 return ret;
00164 }
00165 catch (const std::exception &e) {
00166 std::ostringstream message;
00167 message << "Program threw an exception: " << e.what();
00168
00169 if( output_cout_ )
00170 {
00171
00172
00173 if (OpmLog::hasBackend("STREAMLOG")) {
00174 OpmLog::error(message.str());
00175 }
00176 else {
00177 std::cout << message.str() << "\n";
00178 }
00179 }
00180
00181 return EXIT_FAILURE;
00182 }
00183
00184
00185
00186 protected:
00187
00188
00189
00190
00191
00192
00193
00194
00195 typedef BlackoilPropsAdFromDeck FluidProps;
00196 typedef FluidProps::MaterialLawManager MaterialLawManager;
00197 typedef typename Simulator::ReservoirState ReservoirState;
00198 typedef typename Simulator::OutputWriter OutputWriter;
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 int mpi_rank_ = 0;
00209 bool output_cout_ = false;
00210 bool must_distribute_ = false;
00211
00212 ParameterGroup param_;
00213
00214 bool output_to_files_ = false;
00215 std::string output_dir_ = std::string(".");
00216
00217 std::shared_ptr<Deck> deck_;
00218 std::shared_ptr<EclipseState> eclipse_state_;
00219
00220 std::unique_ptr<GridInit<Grid>> grid_init_;
00221 std::shared_ptr<MaterialLawManager> material_law_manager_;
00222 std::unique_ptr<FluidProps> fluidprops_;
00223 std::unique_ptr<RockCompressibility> rock_comp_;
00224 std::array<double, 3> gravity_;
00225 bool use_local_perm_ = true;
00226 std::unique_ptr<DerivedGeology> geoprops_;
00227
00228 std::unique_ptr<ReservoirState> state_;
00229
00230 std::vector<double> threshold_pressures_;
00231
00232 boost::any parallel_information_;
00233
00234 std::unique_ptr<EclipseIO> eclipse_writer_;
00235 std::unique_ptr<OutputWriter> output_writer_;
00236
00237 std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver_;
00238
00239 std::unique_ptr<Simulator> simulator_;
00240
00241 std::string logFile_;
00242
00243
00244 std::unordered_set<std::string> defunct_well_names_;
00245
00246
00247
00248
00249
00250
00251
00252 void setupParallelism(int argc, char** argv)
00253 {
00254
00255
00256
00257
00258 const Dune::MPIHelper& mpi_helper = Dune::MPIHelper::instance(argc, argv);
00259 mpi_rank_ = mpi_helper.rank();
00260 const int mpi_size = mpi_helper.size();
00261 output_cout_ = ( mpi_rank_ == 0 );
00262 must_distribute_ = ( mpi_size > 1 );
00263
00264 #ifdef _OPENMP
00265
00266 if (!getenv("OMP_NUM_THREADS")) {
00267
00268
00269 int num_cores = omp_get_num_procs();
00270 int num_threads = std::min(4, num_cores);
00271 omp_set_num_threads(num_threads);
00272 }
00273 #pragma omp parallel
00274 if (omp_get_thread_num() == 0) {
00275
00276 const int num_omp_threads = omp_get_num_threads();
00277 if (mpi_size == 1) {
00278 std::cout << "OpenMP using " << num_omp_threads << " threads." << std::endl;
00279 } else {
00280 std::cout << "OpenMP using " << num_omp_threads << " threads on MPI rank " << mpi_rank_ << "." << std::endl;
00281 }
00282 }
00283 #endif
00284 }
00285
00287 bool cartesianAdjacent(const Grid& grid, int g1, int g2) {
00288
00289 using namespace UgGridHelpers;
00290
00291 int diff = std::abs(g1 - g2);
00292
00293 const int * dimens = cartDims(grid);
00294 if (diff == 1)
00295 return true;
00296 if (diff == dimens[0])
00297 return true;
00298 if (diff == dimens[0] * dimens[1])
00299 return true;
00300
00301 return false;
00302 }
00303
00304
00305 void printStartupMessage()
00306 {
00307 if (output_cout_) {
00308 const std::string version = moduleVersionName();
00309 std::cout << "**********************************************************************\n";
00310 std::cout << "* *\n";
00311 std::cout << "* This is flow_legacy (version " << version << ")"
00312 << std::string(26 - version.size(), ' ') << "*\n";
00313 std::cout << "* *\n";
00314 std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow, *\n";
00315 std::cout << "* and is part of OPM. For more information see: *\n";
00316 std::cout << "* http://opm-project.org *\n";
00317 std::cout << "* *\n";
00318 std::cout << "**********************************************************************\n\n";
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327 bool setupParameters(int argc, char** argv)
00328 {
00329 param_ = ParameterGroup(argc, argv, false, output_cout_);
00330
00331
00332 if (!param_.unhandledArguments().empty()) {
00333 if (param_.unhandledArguments().size() != 1) {
00334 std::cerr << "You can only specify a single input deck on the command line.\n";
00335 return false;
00336 } else {
00337 const auto casename = detail::simulationCaseName( param_.unhandledArguments()[ 0 ] );
00338 param_.insertParameter("deck_filename", casename.string() );
00339 }
00340 }
00341
00342
00343 if (!param_.has("deck_filename")) {
00344 std::cerr << "This program must be run with an input deck.\n"
00345 "Specify the deck filename either\n"
00346 " a) as a command line argument by itself\n"
00347 " b) as a command line parameter with the syntax deck_filename=<path to your deck>, or\n"
00348 " c) as a parameter in a parameter file (.param or .xml) passed to the program.\n";
00349 return false;
00350 }
00351 return true;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void setupOutput()
00364 {
00365 output_to_files_ = output_cout_ && param_.getDefault("output", true);
00366
00367
00368 auto& ioConfig = eclipse_state_->getIOConfig();
00369
00370 const std::string default_output_dir = ioConfig.getOutputDir();
00371 output_dir_ = param_.getDefault("output_dir", default_output_dir);
00372
00373 ioConfig.setOutputDir(output_dir_);
00374
00375
00376 if (output_to_files_) {
00377
00378 ensureDirectoryExists(output_dir_);
00379
00380 param_.writeParam(output_dir_ + "/simulation.param");
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389 void setupLogging()
00390 {
00391 std::string deck_filename = param_.get<std::string>("deck_filename");
00392
00393 using boost::filesystem::path;
00394 path fpath(deck_filename);
00395 std::string baseName;
00396 std::ostringstream debugFileStream;
00397 std::ostringstream logFileStream;
00398
00399 if (boost::to_upper_copy(path(fpath.extension()).string()) == ".DATA") {
00400 baseName = path(fpath.stem()).string();
00401 } else {
00402 baseName = path(fpath.filename()).string();
00403 }
00404
00405 logFileStream << output_dir_ << "/" << baseName;
00406 debugFileStream << output_dir_ << "/" << "." << baseName;
00407
00408 if ( must_distribute_ && mpi_rank_ != 0 )
00409 {
00410
00411
00412 debugFileStream << "."<< mpi_rank_;
00413
00414 logFileStream << "." << mpi_rank_;
00415 }
00416 logFileStream << ".PRT";
00417 debugFileStream << ".DEBUG";
00418
00419 std::string debugFile = debugFileStream.str();
00420 logFile_ = logFileStream.str();
00421
00422 std::shared_ptr<EclipsePRTLog> prtLog = std::make_shared<EclipsePRTLog>(logFile_ , Log::NoDebugMessageTypes, false, output_cout_);
00423 const bool all_to_terminal = param_.getDefault("all_messages_to_terminal", false);
00424 const auto terminal_msg_types = all_to_terminal ? Log::DefaultMessageTypes : Log::StdoutMessageTypes;
00425 std::shared_ptr<StreamLog> streamLog = std::make_shared<StreamLog>(std::cout, terminal_msg_types);
00426 OpmLog::addBackend( "ECLIPSEPRTLOG" , prtLog );
00427 OpmLog::addBackend( "STREAMLOG", streamLog);
00428 std::shared_ptr<StreamLog> debugLog = std::make_shared<EclipsePRTLog>(debugFile, Log::DefaultMessageTypes, false, output_cout_);
00429 OpmLog::addBackend( "DEBUGLOG" , debugLog);
00430 const auto& msgLimits = eclipse_state_->getSchedule().getMessageLimits();
00431 const std::map<int64_t, int> limits = {{Log::MessageType::Note, msgLimits.getCommentPrintLimit(0)},
00432 {Log::MessageType::Info, msgLimits.getMessagePrintLimit(0)},
00433 {Log::MessageType::Warning, msgLimits.getWarningPrintLimit(0)},
00434 {Log::MessageType::Error, msgLimits.getErrorPrintLimit(0)},
00435 {Log::MessageType::Problem, msgLimits.getProblemPrintLimit(0)},
00436 {Log::MessageType::Bug, msgLimits.getBugPrintLimit(0)}};
00437 prtLog->setMessageLimiter(std::make_shared<MessageLimiter>());
00438 prtLog->setMessageFormatter(std::make_shared<SimpleMessageFormatter>(false));
00439 streamLog->setMessageLimiter(std::make_shared<MessageLimiter>(10, limits));
00440 streamLog->setMessageFormatter(std::make_shared<SimpleMessageFormatter>(true));
00441
00442
00443 if ( output_cout_ )
00444 {
00445 OpmLog::debug("\n--------------- Reading parameters ---------------\n");
00446 }
00447 }
00448
00449
00450
00451
00452
00453 void mergeParallelLogFiles()
00454 {
00455
00456 OpmLog::removeAllBackends();
00457
00458 if( mpi_rank_ != 0 || !must_distribute_ || !output_to_files_ )
00459 {
00460 return;
00461 }
00462
00463 namespace fs = boost::filesystem;
00464 fs::path output_path(".");
00465 if ( param_.has("output_dir") )
00466 {
00467 output_path = fs::path(output_dir_);
00468 }
00469
00470 fs::path deck_filename(param_.get<std::string>("deck_filename"));
00471
00472 std::for_each(fs::directory_iterator(output_path),
00473 fs::directory_iterator(),
00474 detail::ParallelFileMerger(output_path, deck_filename.stem().string()));
00475 }
00476
00477
00478
00479
00480
00481
00482 void readDeckInput()
00483 {
00484 std::string deck_filename = param_.get<std::string>("deck_filename");
00485
00486
00487 Parser parser;
00488
00489
00490 try {
00491 ParseContext parseContext({ { ParseContext::PARSE_RANDOM_SLASH , InputError::IGNORE },
00492 { ParseContext::PARSE_MISSING_DIMS_KEYWORD, InputError::WARN },
00493 { ParseContext::SUMMARY_UNKNOWN_WELL, InputError::WARN },
00494 { ParseContext::SUMMARY_UNKNOWN_GROUP, InputError::WARN }});
00495 deck_ = std::make_shared< Deck >( parser.parseFile(deck_filename, parseContext) );
00496 checkDeck(*deck_, parser);
00497
00498 if ( output_cout_)
00499 {
00500 MissingFeatures::checkKeywords(*deck_);
00501 }
00502
00503 eclipse_state_.reset(new EclipseState(*deck_, parseContext));
00504 }
00505 catch (const std::invalid_argument& e) {
00506 std::cerr << "Failed to create valid EclipseState object. See logfile: " << logFile_ << std::endl;
00507 std::cerr << "Exception caught: " << e.what() << std::endl;
00508 throw;
00509 }
00510
00511
00512 if (param_.has("output_interval")) {
00513 const int output_interval = param_.get<int>("output_interval");
00514 eclipse_state_->getRestartConfig().overrideRestartWriteInterval( size_t( output_interval ) );
00515 }
00516
00517
00518 if (param_.has("nosim")) {
00519 const bool nosim = param_.get<bool>("nosim");
00520 auto& ioConfig = eclipse_state_->getIOConfig();
00521 ioConfig.overrideNOSIM( nosim );
00522 }
00523 }
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 void setupGridAndProps()
00539 {
00540
00541 const std::vector<double>& porv =
00542 eclipse_state_->get3DProperties().getDoubleGridProperty("PORV").getData();
00543 grid_init_.reset(new GridInit<Grid>(*eclipse_state_, porv));
00544 const Grid& grid = grid_init_->grid();
00545
00546
00547 std::vector<int> compressedToCartesianIdx;
00548 Opm::createGlobalCellArray(grid, compressedToCartesianIdx);
00549 material_law_manager_.reset(new MaterialLawManager());
00550 material_law_manager_->initFromDeck(*deck_, *eclipse_state_, compressedToCartesianIdx);
00551
00552
00553 fluidprops_.reset(new BlackoilPropsAdFromDeck(*deck_, *eclipse_state_, material_law_manager_, grid));
00554
00555
00556 rock_comp_.reset(new RockCompressibility(*eclipse_state_, output_cout_));
00557
00558
00559 assert(UgGridHelpers::dimensions(grid) == 3);
00560 gravity_.fill(0.0);
00561 gravity_[2] = deck_->hasKeyword("NOGRAV")
00562 ? param_.getDefault("gravity", 0.0)
00563 : param_.getDefault("gravity", unit::gravity);
00564
00565
00566 use_local_perm_ = param_.getDefault("use_local_perm", use_local_perm_);
00567 geoprops_.reset(new DerivedGeology(grid, *fluidprops_, *eclipse_state_, use_local_perm_, gravity_.data()));
00568 }
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 void setupState()
00580 {
00581 const PhaseUsage pu = Opm::phaseUsageFromDeck(*deck_);
00582 const Grid& grid = grid_init_->grid();
00583
00584
00585 BlackoilPropertiesFromDeck props( *deck_, *eclipse_state_, material_law_manager_,
00586 Opm::UgGridHelpers::numCells(grid),
00587 Opm::UgGridHelpers::globalCell(grid),
00588 Opm::UgGridHelpers::cartDims(grid),
00589 param_);
00590
00591
00592
00593 if (param_.has("init_saturation")) {
00594 state_.reset( new ReservoirState( Opm::UgGridHelpers::numCells(grid),
00595 Opm::UgGridHelpers::numFaces(grid),
00596 props.numPhases() ));
00597
00598 initStateBasic(Opm::UgGridHelpers::numCells(grid),
00599 Opm::UgGridHelpers::globalCell(grid),
00600 Opm::UgGridHelpers::cartDims(grid),
00601 Opm::UgGridHelpers::numFaces(grid),
00602 Opm::UgGridHelpers::faceCells(grid),
00603 Opm::UgGridHelpers::beginFaceCentroids(grid),
00604 Opm::UgGridHelpers::beginCellCentroids(grid),
00605 Opm::UgGridHelpers::dimensions(grid),
00606 props, param_, gravity_[2], *state_);
00607
00608 initBlackoilSurfvol(Opm::UgGridHelpers::numCells(grid), props, *state_);
00609
00610 enum { Oil = BlackoilPhases::Liquid, Gas = BlackoilPhases::Vapour };
00611 if (pu.phase_used[Oil] && pu.phase_used[Gas]) {
00612 const int numPhases = props.numPhases();
00613 const int numCells = Opm::UgGridHelpers::numCells(grid);
00614
00615
00616 auto& gor = state_->getCellData( BlackoilState::GASOILRATIO );
00617 const auto& surface_vol = state_->getCellData( BlackoilState::SURFACEVOL );
00618 for (int c = 0; c < numCells; ++c) {
00619
00620 gor[c] = surface_vol[ c * numPhases + pu.phase_pos[Gas]] / surface_vol[ c * numPhases + pu.phase_pos[Oil]];
00621 }
00622 }
00623 } else if (deck_->hasKeyword("EQUIL")) {
00624
00625 state_.reset( new ReservoirState( Opm::UgGridHelpers::numCells(grid),
00626 Opm::UgGridHelpers::numFaces(grid),
00627 props.numPhases()));
00628
00629 initStateEquil(grid, props, *deck_, *eclipse_state_, gravity_[2], *state_);
00630
00631 } else {
00632 state_.reset( new ReservoirState( Opm::UgGridHelpers::numCells(grid),
00633 Opm::UgGridHelpers::numFaces(grid),
00634 props.numPhases()));
00635 initBlackoilStateFromDeck(Opm::UgGridHelpers::numCells(grid),
00636 Opm::UgGridHelpers::globalCell(grid),
00637 Opm::UgGridHelpers::numFaces(grid),
00638 Opm::UgGridHelpers::faceCells(grid),
00639 Opm::UgGridHelpers::beginFaceCentroids(grid),
00640 Opm::UgGridHelpers::beginCellCentroids(grid),
00641 Opm::UgGridHelpers::dimensions(grid),
00642 props, *deck_, gravity_[2], *state_);
00643 }
00644
00645
00646 std::map<std::pair<int, int>, double> maxDp;
00647 computeMaxDp(maxDp, *deck_, *eclipse_state_, grid_init_->grid(), *state_, props, gravity_[2]);
00648 threshold_pressures_ = thresholdPressures(*deck_, *eclipse_state_, grid, maxDp);
00649 std::vector<double> threshold_pressures_nnc = thresholdPressuresNNC(*eclipse_state_, geoprops_->nnc(), maxDp);
00650 threshold_pressures_.insert(threshold_pressures_.end(), threshold_pressures_nnc.begin(), threshold_pressures_nnc.end());
00651
00652
00653 if (deck_->hasKeyword("SWATINIT")) {
00654 const int numCells = Opm::UgGridHelpers::numCells(grid);
00655 std::vector<int> cells(numCells);
00656 for (int c = 0; c < numCells; ++c) { cells[c] = c; }
00657 std::vector<double> pc = state_->saturation();
00658 props.capPress(numCells, state_->saturation().data(), cells.data(), pc.data(), nullptr);
00659 fluidprops_->setSwatInitScaling(state_->saturation(), pc);
00660 }
00661 initHydroCarbonState(*state_, pu, Opm::UgGridHelpers::numCells(grid), deck_->hasKeyword("DISGAS"), deck_->hasKeyword("VAPOIL"));
00662
00663
00664 }
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 void distributeData()
00679 {
00680
00681
00682
00683 if (must_distribute_) {
00684 defunct_well_names_ =
00685 distributeGridAndData(grid_init_->grid(), *deck_, *eclipse_state_,
00686 *state_, *fluidprops_, *geoprops_,
00687 material_law_manager_, threshold_pressures_,
00688 parallel_information_, use_local_perm_);
00689 }
00690 }
00691
00692
00693
00694
00695
00696
00697
00698
00699 void extractMessages()
00700 {
00701 if ( !output_cout_ )
00702 {
00703 return;
00704 }
00705
00706 auto extractMessage = [](const Message& msg) {
00707 auto log_type = detail::convertMessageType(msg.mtype);
00708 const auto& location = msg.location;
00709 if (location) {
00710 OpmLog::addTaggedMessage(log_type, "Parser message", Log::fileMessage(location.filename, location.lineno, msg.message));
00711 } else {
00712 OpmLog::addTaggedMessage(log_type, "Parser message", msg.message);
00713 }
00714 };
00715
00716
00717 for(const auto& msg : deck_->getMessageContainer()) {
00718 extractMessage(msg);
00719 }
00720
00721
00722 for (const auto& msg : eclipse_state_->getMessageContainer()) {
00723 extractMessage(msg);
00724 }
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734 void runDiagnostics()
00735 {
00736 if( ! output_cout_ )
00737 {
00738 return;
00739 }
00740
00741
00742 RelpermDiagnostics diagnostic;
00743 diagnostic.diagnosis(*eclipse_state_, *deck_, grid_init_->grid());
00744 }
00745
00746
00747 void writeInit()
00748 {
00749 bool output = param_.getDefault("output", true);
00750 bool output_ecl = param_.getDefault("output_ecl", true);
00751 const Grid& grid = grid_init_->grid();
00752 if( output && output_ecl && output_cout_)
00753 {
00754 const EclipseGrid& inputGrid = eclipse_state_->getInputGrid();
00755 eclipse_writer_.reset(new EclipseIO(*eclipse_state_, UgGridHelpers::createEclipseGrid( grid , inputGrid )));
00756 eclipse_writer_->writeInitial(geoprops_->simProps(grid),
00757 geoprops_->nonCartesianConnections());
00758 }
00759 }
00760
00761
00762
00763
00764
00765 void setupOutputWriter()
00766 {
00767
00768
00769
00770 output_writer_.reset(new OutputWriter(grid_init_->grid(),
00771 param_,
00772 *eclipse_state_,
00773 std::move(eclipse_writer_),
00774 Opm::phaseUsageFromDeck(*deck_)));
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784 void setupLinearSolver()
00785 {
00786 const std::string cprSolver = "cpr";
00787 const std::string interleavedSolver = "interleaved";
00788 const std::string directSolver = "direct";
00789 std::string flowDefaultSolver = interleavedSolver;
00790
00791 if (!param_.has("solver_approach")) {
00792 if (eclipse_state_->getSimulationConfig().useCPR()) {
00793 flowDefaultSolver = cprSolver;
00794 }
00795 }
00796
00797 const std::string solver_approach = param_.getDefault("solver_approach", flowDefaultSolver);
00798
00799 if (solver_approach == cprSolver) {
00800 fis_solver_.reset(new NewtonIterationBlackoilCPR(param_, parallel_information_));
00801 } else if (solver_approach == interleavedSolver) {
00802 fis_solver_.reset(new NewtonIterationBlackoilInterleaved(param_, parallel_information_));
00803 } else if (solver_approach == directSolver) {
00804 fis_solver_.reset(new NewtonIterationBlackoilSimple(param_, parallel_information_));
00805 } else {
00806 OPM_THROW( std::runtime_error , "Internal error - solver approach " << solver_approach << " not recognized.");
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815
00816 int runSimulator()
00817 {
00818 const auto& schedule = eclipse_state_->getSchedule();
00819 const auto& timeMap = schedule.getTimeMap();
00820 auto& ioConfig = eclipse_state_->getIOConfig();
00821 SimulatorTimer simtimer;
00822
00823
00824 const auto& initConfig = eclipse_state_->getInitConfig();
00825 simtimer.init(timeMap, (size_t)initConfig.getRestartStep());
00826
00827 if (!ioConfig.initOnly()) {
00828 if (output_cout_) {
00829 std::string msg;
00830 msg = "\n\n================ Starting main simulation loop ===============\n";
00831 OpmLog::info(msg);
00832 }
00833
00834 SimulatorReport fullReport = simulator_->run(simtimer, *state_);
00835
00836 if (output_cout_) {
00837 std::ostringstream ss;
00838 ss << "\n\n================ End of simulation ===============\n\n";
00839 fullReport.reportFullyImplicit(ss);
00840 OpmLog::info(ss.str());
00841 if (param_.anyUnused()) {
00842
00843
00844 std::cout << "-------------------- Unused parameters: --------------------\n";
00845 param_.displayUsage();
00846 std::cout << "----------------------------------------------------------------" << std::endl;
00847 }
00848 }
00849
00850 if (output_to_files_) {
00851 std::string filename = output_dir_ + "/walltime.txt";
00852 std::fstream tot_os(filename.c_str(), std::fstream::trunc | std::fstream::out);
00853 fullReport.reportParam(tot_os);
00854 }
00855 } else {
00856 if (output_cout_) {
00857 std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;
00858 }
00859
00860 }
00861 return EXIT_SUCCESS;
00862 }
00863
00864
00865
00866
00867
00868
00869
00870 Implementation& asImpl()
00871 {
00872 return static_cast<Implementation&>(*this);
00873 }
00874
00875
00876 };
00877
00878
00879
00880
00881
00882
00883
00884 template <class Grid, class Simulator>
00885 class FlowMain : public FlowMainBase<FlowMain<Grid, Simulator>, Grid, Simulator>
00886 {
00887 protected:
00888 using Base = FlowMainBase<FlowMain<Grid, Simulator>, Grid, Simulator>;
00889 friend Base;
00890
00891
00892
00893
00894 void createSimulator()
00895 {
00896
00897 Base::simulator_.reset(new Simulator(Base::param_,
00898 Base::grid_init_->grid(),
00899 *Base::geoprops_,
00900 *Base::fluidprops_,
00901 Base::rock_comp_->isActive() ? Base::rock_comp_.get() : nullptr,
00902 *Base::fis_solver_,
00903 Base::gravity_.data(),
00904 Base::deck_->hasKeyword("DISGAS"),
00905 Base::deck_->hasKeyword("VAPOIL"),
00906 Base::eclipse_state_,
00907 *Base::output_writer_,
00908 Base::threshold_pressures_,
00909 Base::defunct_well_names_));
00910 }
00911 };
00912
00913
00914
00915
00916
00917
00918 namespace detail
00919 {
00920
00921 boost::filesystem::path simulationCaseName( const std::string& casename ) {
00922 namespace fs = boost::filesystem;
00923
00924 const auto exists = []( const fs::path& f ) -> bool {
00925 if( !fs::exists( f ) ) return false;
00926
00927 if( fs::is_regular_file( f ) ) return true;
00928
00929 return fs::is_symlink( f )
00930 && fs::is_regular_file( fs::read_symlink( f ) );
00931 };
00932
00933 auto simcase = fs::path( casename );
00934
00935 if( exists( simcase ) ) {
00936 return simcase;
00937 }
00938
00939 for( const auto& ext : { std::string("data"), std::string("DATA") } ) {
00940 if( exists( simcase.replace_extension( ext ) ) ) {
00941 return simcase;
00942 }
00943 }
00944
00945 throw std::invalid_argument( "Cannot find input case " + casename );
00946 }
00947
00948
00949
00950
00951
00952 int64_t convertMessageType(const Message::type& mtype)
00953 {
00954 switch (mtype) {
00955 case Message::type::Debug:
00956 return Log::MessageType::Debug;
00957 case Message::type::Info:
00958 return Log::MessageType::Info;
00959 case Message::type::Warning:
00960 return Log::MessageType::Warning;
00961 case Message::type::Error:
00962 return Log::MessageType::Error;
00963 case Message::type::Problem:
00964 return Log::MessageType::Problem;
00965 case Message::type::Bug:
00966 return Log::MessageType::Bug;
00967 case Message::type::Note:
00968 return Log::MessageType::Note;
00969 }
00970 throw std::logic_error("Invalid messages type!\n");
00971 }
00972
00973
00974 }
00975
00976
00977 }
00978
00979 #endif // OPM_FLOWMAIN_HEADER_INCLUDED