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_FLOW_MAIN_EBOS_HEADER_INCLUDED
00024 #define OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED
00025
00026
00027 #include <sys/utsname.h>
00028
00029
00030 #include <opm/simulators/ParallelFileMerger.hpp>
00031 #include <opm/simulators/ensureDirectoryExists.hpp>
00032
00033 #include <opm/autodiff/BlackoilModelEbos.hpp>
00034 #include <opm/autodiff/NewtonIterationBlackoilSimple.hpp>
00035 #include <opm/autodiff/NewtonIterationBlackoilCPR.hpp>
00036 #include <opm/autodiff/NewtonIterationBlackoilInterleaved.hpp>
00037 #include <opm/autodiff/MissingFeatures.hpp>
00038 #include <opm/autodiff/moduleVersion.hpp>
00039 #include <opm/autodiff/ExtractParallelGridInformationToISTL.hpp>
00040 #include <opm/autodiff/RedistributeDataHandles.hpp>
00041 #include <opm/autodiff/SimulatorFullyImplicitBlackoilEbos.hpp>
00042
00043 #include <opm/core/props/satfunc/RelpermDiagnostics.hpp>
00044
00045 #include <opm/common/OpmLog/OpmLog.hpp>
00046 #include <opm/common/OpmLog/EclipsePRTLog.hpp>
00047 #include <opm/common/OpmLog/LogUtil.hpp>
00048
00049 #include <opm/parser/eclipse/Deck/Deck.hpp>
00050 #include <opm/parser/eclipse/Parser/Parser.hpp>
00051 #include <opm/parser/eclipse/Parser/ParseContext.hpp>
00052 #include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
00053 #include <opm/parser/eclipse/EclipseState/IOConfig/IOConfig.hpp>
00054 #include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
00055 #include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
00056
00057 #if HAVE_DUNE_FEM
00058 #include <dune/fem/misc/mpimanager.hh>
00059 #else
00060 #include <dune/common/parallel/mpihelper.hh>
00061 #endif
00062
00063 namespace Opm
00064 {
00065
00066 template <class TypeTag>
00067 class FlowMainEbos
00068 {
00069 enum FileOutputValue{
00071 OUTPUT_NONE = 0,
00073 OUTPUT_LOG_ONLY = 1,
00075 OUTPUT_ALL = 3
00076 };
00077
00078 public:
00079 typedef typename GET_PROP(TypeTag, MaterialLaw)::EclMaterialLawManager MaterialLawManager;
00080 typedef typename GET_PROP_TYPE(TypeTag, Simulator) EbosSimulator;
00081 typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
00082 typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
00083 typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
00084 typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
00085 typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
00086
00087 typedef Opm::SimulatorFullyImplicitBlackoilEbos<TypeTag> Simulator;
00088 typedef typename Simulator::ReservoirState ReservoirState;
00089 typedef typename Simulator::OutputWriter OutputWriter;
00090
00096 int execute(int argc, char** argv)
00097 {
00098 try {
00099 setupParallelism();
00100 printStartupMessage();
00101 const bool ok = setupParameters(argc, argv);
00102 if (!ok) {
00103 return EXIT_FAILURE;
00104 }
00105
00106 setupEbosSimulator();
00107 setupOutput();
00108 setupLogging();
00109 printPRTHeader();
00110 extractMessages();
00111 runDiagnostics();
00112 setupState();
00113 writeInit();
00114 setupOutputWriter();
00115 setupLinearSolver();
00116 createSimulator();
00117
00118
00119 auto ret = runSimulator();
00120
00121 mergeParallelLogFiles();
00122
00123 return ret;
00124 }
00125 catch (const std::exception &e) {
00126 std::ostringstream message;
00127 message << "Program threw an exception: " << e.what();
00128
00129 if( output_cout_ )
00130 {
00131
00132
00133 if (OpmLog::hasBackend("STREAMLOG")) {
00134 OpmLog::error(message.str());
00135 }
00136 else {
00137 std::cout << message.str() << "\n";
00138 }
00139 }
00140
00141 return EXIT_FAILURE;
00142 }
00143 }
00144
00145 protected:
00146 void setupParallelism()
00147 {
00148
00149
00150 #if HAVE_MPI
00151 MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank_);
00152 int mpi_size;
00153 MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
00154 #else
00155 mpi_rank_ = 0;
00156 const int mpi_size = 1;
00157 #endif
00158 output_cout_ = ( mpi_rank_ == 0 );
00159 must_distribute_ = ( mpi_size > 1 );
00160
00161 #ifdef _OPENMP
00162
00163 if (!getenv("OMP_NUM_THREADS")) {
00164
00165
00166 int num_cores = omp_get_num_procs();
00167 int num_threads = std::min(4, num_cores);
00168 omp_set_num_threads(num_threads);
00169 }
00170 #pragma omp parallel
00171 if (omp_get_thread_num() == 0) {
00172
00173 const int num_omp_threads = omp_get_num_threads();
00174 if (mpi_size == 1) {
00175 std::cout << "OpenMP using " << num_omp_threads << " threads." << std::endl;
00176 } else {
00177 std::cout << "OpenMP using " << num_omp_threads << " threads on MPI rank " << mpi_rank_ << "." << std::endl;
00178 }
00179 }
00180 #endif
00181 }
00182
00183
00184 void printStartupMessage()
00185 {
00186
00187 if (output_cout_) {
00188 const int lineLen = 70;
00189 const std::string version = moduleVersionName();
00190 const std::string banner = "This is flow "+version;
00191 const int bannerPreLen = (lineLen - 2 - banner.size())/2;
00192 const int bannerPostLen = bannerPreLen + (lineLen - 2 - banner.size())%2;
00193 std::cout << "**********************************************************************\n";
00194 std::cout << "* *\n";
00195 std::cout << "*" << std::string(bannerPreLen, ' ') << banner << std::string(bannerPostLen, ' ') << "*\n";
00196 std::cout << "* *\n";
00197 std::cout << "* Flow is a simulator for fully implicit three-phase black-oil flow, *\n";
00198 std::cout << "* including solvent and polymer capabilities. *\n";
00199 std::cout << "* For more information, see http://opm-project.org *\n";
00200 std::cout << "* *\n";
00201 std::cout << "**********************************************************************\n\n";
00202 }
00203 }
00204
00205
00206
00207
00208
00209
00210 bool setupParameters(int argc, char** argv)
00211 {
00212 param_ = ParameterGroup(argc, argv, false, output_cout_);
00213
00214
00215 if (!param_.unhandledArguments().empty()) {
00216 if (param_.unhandledArguments().size() != 1) {
00217 std::cerr << "You can only specify a single input deck on the command line.\n";
00218 return false;
00219 } else {
00220 const auto casename = this->simulationCaseName( param_.unhandledArguments()[ 0 ] );
00221 param_.insertParameter("deck_filename", casename.string() );
00222 }
00223 }
00224
00225
00226 if (!param_.has("deck_filename")) {
00227 std::cerr << "This program must be run with an input deck.\n"
00228 "Specify the deck filename either\n"
00229 " a) as a command line argument by itself\n"
00230 " b) as a command line parameter with the syntax deck_filename=<path to your deck>, or\n"
00231 " c) as a parameter in a parameter file (.param or .xml) passed to the program.\n";
00232 return false;
00233 }
00234 return true;
00235 }
00236
00237
00238
00239
00240
00241
00242 void setupOutput()
00243 {
00244 const std::string output = param_.getDefault("output", std::string("all"));
00245 static std::map<std::string, FileOutputValue> string2OutputEnum =
00246 { {"none", OUTPUT_NONE },
00247 {"false", OUTPUT_LOG_ONLY },
00248 {"log", OUTPUT_LOG_ONLY },
00249 {"all" , OUTPUT_ALL },
00250 {"true" , OUTPUT_ALL }};
00251 auto converted = string2OutputEnum.find(output);
00252 if ( converted != string2OutputEnum.end() )
00253 {
00254 output_ = string2OutputEnum[output];
00255 }
00256 else
00257 {
00258 std::cerr << "Value " << output <<
00259 " passed to option output was invalid. Using \"all\" instead."
00260 << std::endl;
00261 }
00262
00263 output_to_files_ = output_cout_ && output_ > OUTPUT_NONE;
00264
00265
00266 auto& ioConfig = eclState().getIOConfig();
00267
00268 const std::string default_output_dir = ioConfig.getOutputDir();
00269 output_dir_ = param_.getDefault("output_dir", default_output_dir);
00270
00271 ioConfig.setOutputDir(output_dir_);
00272
00273
00274 if (output_to_files_) {
00275
00276 ensureDirectoryExists(output_dir_);
00277
00278 param_.writeParam(output_dir_ + "/simulation.param");
00279 }
00280 }
00281
00282
00283 void setupLogging()
00284 {
00285 std::string deck_filename = param_.get<std::string>("deck_filename");
00286
00287 using boost::filesystem::path;
00288 path fpath(deck_filename);
00289 std::string baseName;
00290 std::ostringstream debugFileStream;
00291 std::ostringstream logFileStream;
00292
00293 if (boost::to_upper_copy(path(fpath.extension()).string()) == ".DATA") {
00294 baseName = path(fpath.stem()).string();
00295 } else {
00296 baseName = path(fpath.filename()).string();
00297 }
00298
00299 logFileStream << output_dir_ << "/" << baseName;
00300 debugFileStream << output_dir_ << "/" << "." << baseName;
00301
00302 if ( must_distribute_ && mpi_rank_ != 0 )
00303 {
00304
00305
00306 debugFileStream << "."<< mpi_rank_;
00307
00308 logFileStream << "." << mpi_rank_;
00309 }
00310 logFileStream << ".PRT";
00311 debugFileStream << ".DEBUG";
00312
00313 logFile_ = logFileStream.str();
00314
00315 if( output_ > OUTPUT_NONE)
00316 {
00317 std::shared_ptr<EclipsePRTLog> prtLog = std::make_shared<EclipsePRTLog>(logFile_ , Log::NoDebugMessageTypes, false, output_cout_);
00318 OpmLog::addBackend( "ECLIPSEPRTLOG" , prtLog );
00319 prtLog->setMessageLimiter(std::make_shared<MessageLimiter>());
00320 prtLog->setMessageFormatter(std::make_shared<SimpleMessageFormatter>(false));
00321 }
00322
00323 if( output_ >= OUTPUT_LOG_ONLY && !param_.getDefault("no_debug_log", false) )
00324 {
00325 std::string debugFile = debugFileStream.str();
00326 std::shared_ptr<StreamLog> debugLog = std::make_shared<EclipsePRTLog>(debugFile, Log::DefaultMessageTypes, false, output_cout_);
00327 OpmLog::addBackend( "DEBUGLOG" , debugLog);
00328 }
00329
00330 std::shared_ptr<StreamLog> streamLog = std::make_shared<StreamLog>(std::cout, Log::StdoutMessageTypes);
00331 OpmLog::addBackend( "STREAMLOG", streamLog);
00332 const auto& msgLimits = eclState().getSchedule().getMessageLimits();
00333 const std::map<int64_t, int> limits = {{Log::MessageType::Note, msgLimits.getCommentPrintLimit(0)},
00334 {Log::MessageType::Info, msgLimits.getMessagePrintLimit(0)},
00335 {Log::MessageType::Warning, msgLimits.getWarningPrintLimit(0)},
00336 {Log::MessageType::Error, msgLimits.getErrorPrintLimit(0)},
00337 {Log::MessageType::Problem, msgLimits.getProblemPrintLimit(0)},
00338 {Log::MessageType::Bug, msgLimits.getBugPrintLimit(0)}};
00339 streamLog->setMessageLimiter(std::make_shared<MessageLimiter>(10, limits));
00340 streamLog->setMessageFormatter(std::make_shared<SimpleMessageFormatter>(true));
00341
00342 if ( output_cout_ )
00343 {
00344
00345 OpmLog::debug("\n--------------- Reading parameters ---------------\n");
00346 }
00347 }
00348
00349 void printPRTHeader()
00350 {
00351
00352 if ( output_cout_ ) {
00353 const std::string version = moduleVersionName();
00354 const double megabyte = 1024 * 1024;
00355 unsigned num_cpu = std::thread::hardware_concurrency();
00356 struct utsname arch;
00357 const char* user = getlogin();
00358 time_t now = std::time(0);
00359 struct tm tstruct;
00360 char tmstr[80];
00361 tstruct = *localtime(&now);
00362 strftime(tmstr, sizeof(tmstr), "%d-%m-%Y at %X", &tstruct);
00363 const double mem_size = getTotalSystemMemory() / megabyte;
00364 std::ostringstream ss;
00365 ss << "\n\n\n ######## # ###### # #\n";
00366 ss << " # # # # # # \n";
00367 ss << " ##### # # # # # # \n";
00368 ss << " # # # # # # # # \n";
00369 ss << " # ####### ###### # # \n\n";
00370 ss << "Flow is a simulator for fully implicit three-phase black-oil flow,";
00371 ss << " and is part of OPM.\nFor more information visit: http://opm-project.org \n\n";
00372 ss << "Flow Version = " + version + "\n";
00373 if (uname(&arch) == 0) {
00374 ss << "System = " << arch.nodename << " (Number of cores: " << num_cpu;
00375 ss << ", RAM: " << std::fixed << std::setprecision (2) << mem_size << " MB) \n";
00376 ss << "Architecture = " << arch.sysname << " " << arch.machine << " (Release: " << arch.release;
00377 ss << ", Version: " << arch.version << " )\n";
00378 }
00379 if (user) {
00380 ss << "User = " << user << std::endl;
00381 }
00382 ss << "Simulation started on " << tmstr << " hrs\n";
00383 OpmLog::note(ss.str());
00384 }
00385 }
00386
00387 void mergeParallelLogFiles()
00388 {
00389
00390 OpmLog::removeAllBackends();
00391
00392 if( mpi_rank_ != 0 || !must_distribute_ || !output_to_files_ )
00393 {
00394 return;
00395 }
00396
00397 namespace fs = boost::filesystem;
00398 fs::path output_path(".");
00399 if ( param_.has("output_dir") )
00400 {
00401 output_path = fs::path(output_dir_);
00402 }
00403
00404 fs::path deck_filename(param_.get<std::string>("deck_filename"));
00405
00406 std::for_each(fs::directory_iterator(output_path),
00407 fs::directory_iterator(),
00408 detail::ParallelFileMerger(output_path, deck_filename.stem().string()));
00409 }
00410
00411 void setupEbosSimulator()
00412 {
00413 std::string progName("flow_ebos");
00414 std::string deckFile("--ecl-deck-file-name=");
00415 deckFile += param_.get<std::string>("deck_filename");
00416 char* ptr[2];
00417 ptr[ 0 ] = const_cast< char * > (progName.c_str());
00418 ptr[ 1 ] = const_cast< char * > (deckFile.c_str());
00419 EbosSimulator::registerParameters();
00420 Ewoms::setupParameters_< TypeTag > ( 2, ptr );
00421 ebosSimulator_.reset(new EbosSimulator(false));
00422 ebosSimulator_->model().applyInitialSolution();
00423
00424
00425 globalGrid_.reset(new Grid(grid()));
00426 globalGrid_->switchToGlobalView();
00427
00428 try {
00429 if (output_cout_) {
00430 MissingFeatures::checkKeywords(deck());
00431 }
00432
00433
00434 if (param_.has("nosim")) {
00435 const bool nosim = param_.get<bool>("nosim");
00436 auto& ioConfig = eclState().getIOConfig();
00437 ioConfig.overrideNOSIM( nosim );
00438 }
00439 }
00440 catch (const std::invalid_argument& e) {
00441 std::cerr << "Failed to create valid EclipseState object. See logfile: " << logFile_ << std::endl;
00442 std::cerr << "Exception caught: " << e.what() << std::endl;
00443 throw;
00444 }
00445
00446
00447 if (param_.has("output_interval")) {
00448 const int output_interval = param_.get<int>("output_interval");
00449 eclState().getRestartConfig().overrideRestartWriteInterval( size_t( output_interval ) );
00450 }
00451 }
00452
00453 const Deck& deck() const
00454 { return ebosSimulator_->gridManager().deck(); }
00455
00456 Deck& deck()
00457 { return ebosSimulator_->gridManager().deck(); }
00458
00459 const EclipseState& eclState() const
00460 { return ebosSimulator_->gridManager().eclState(); }
00461
00462 EclipseState& eclState()
00463 { return ebosSimulator_->gridManager().eclState(); }
00464
00465
00466
00467
00468
00469 void setupState()
00470 {
00471 const PhaseUsage pu = Opm::phaseUsageFromDeck(deck());
00472 const Grid& grid = this->grid();
00473
00474
00475 BlackoilPropertiesFromDeck props(deck(),
00476 eclState(),
00477 materialLawManager(),
00478 grid.size(0),
00479 grid.globalCell().data(),
00480 grid.logicalCartesianSize().data(),
00481 param_);
00482
00483
00484
00485 if (param_.has("init_saturation")) {
00486 state_.reset(new ReservoirState(grid.size(0),
00487 grid.numFaces(),
00488 props.numPhases()));
00489
00490 initStateBasic(grid.size(0),
00491 grid.globalCell().data(),
00492 grid.logicalCartesianSize().data(),
00493 grid.numFaces(),
00494 Opm::UgGridHelpers::faceCells(grid),
00495 Opm::UgGridHelpers::beginFaceCentroids(grid),
00496 Opm::UgGridHelpers::beginCellCentroids(grid),
00497 Grid::dimension,
00498 props, param_, gravity(), *state_);
00499
00500 initBlackoilSurfvol(Opm::UgGridHelpers::numCells(grid), props, *state_);
00501
00502 enum { Oil = BlackoilPhases::Liquid, Gas = BlackoilPhases::Vapour };
00503 if (pu.phase_used[Oil] && pu.phase_used[Gas]) {
00504 const int numPhases = props.numPhases();
00505 const int numCells = Opm::UgGridHelpers::numCells(grid);
00506
00507
00508 auto& gor = state_->getCellData( BlackoilState::GASOILRATIO );
00509 const auto& surface_vol = state_->getCellData( BlackoilState::SURFACEVOL );
00510 for (int c = 0; c < numCells; ++c) {
00511
00512 gor[c] = surface_vol[ c * numPhases + pu.phase_pos[Gas]] / surface_vol[ c * numPhases + pu.phase_pos[Oil]];
00513 }
00514 }
00515 } else if (deck().hasKeyword("EQUIL")) {
00516
00517 state_.reset( new ReservoirState( Opm::UgGridHelpers::numCells(grid),
00518 Opm::UgGridHelpers::numFaces(grid),
00519 props.numPhases()));
00520
00521 initStateEquil(grid, props, deck(), eclState(), gravity(), *state_);
00522
00523 } else {
00524 state_.reset( new ReservoirState( Opm::UgGridHelpers::numCells(grid),
00525 Opm::UgGridHelpers::numFaces(grid),
00526 props.numPhases()));
00527 initBlackoilStateFromDeck(Opm::UgGridHelpers::numCells(grid),
00528 Opm::UgGridHelpers::globalCell(grid),
00529 Opm::UgGridHelpers::numFaces(grid),
00530 Opm::UgGridHelpers::faceCells(grid),
00531 Opm::UgGridHelpers::beginFaceCentroids(grid),
00532 Opm::UgGridHelpers::beginCellCentroids(grid),
00533 Opm::UgGridHelpers::dimensions(grid),
00534 props, deck(), gravity(), *state_);
00535 }
00536
00537 initHydroCarbonState(*state_, pu, Opm::UgGridHelpers::numCells(grid), deck().hasKeyword("DISGAS"), deck().hasKeyword("VAPOIL"));
00538
00539
00540 if (GET_PROP_VALUE(TypeTag, EnablePolymer)) {
00541 auto& cpolymer = state_->getCellData( state_->POLYMER );
00542 const int numCells = Opm::UgGridHelpers::numCells(grid);
00543 for (int c = 0; c < numCells; ++c) {
00544 cpolymer[c] = ebosProblem().polymerConcentration(c);
00545 }
00546 }
00547
00548 if (GET_PROP_VALUE(TypeTag, EnableSolvent)) {
00549 auto& solvent = state_->getCellData( state_->SSOL );
00550 auto& sat = state_->saturation();
00551 const int np = props.numPhases();
00552 const int numCells = Opm::UgGridHelpers::numCells(grid);
00553 for (int c = 0; c < numCells; ++c) {
00554 solvent[c] = ebosProblem().solventSaturation(c);
00555 sat[c * np + pu.phase_pos[Water]];
00556 }
00557 }
00558
00559 }
00560
00561
00562
00563
00564 void extractMessages()
00565 {
00566 if ( !output_cout_ )
00567 {
00568 return;
00569 }
00570
00571 auto extractMessage = [this](const Message& msg) {
00572 auto log_type = this->convertMessageType(msg.mtype);
00573 const auto& location = msg.location;
00574 if (location) {
00575 OpmLog::addMessage(log_type, Log::fileMessage(location.filename, location.lineno, msg.message));
00576 } else {
00577 OpmLog::addMessage(log_type, msg.message);
00578 }
00579 };
00580
00581
00582 for(const auto& msg : deck().getMessageContainer()) {
00583 extractMessage(msg);
00584 }
00585
00586
00587 for (const auto& msg : eclState().getMessageContainer()) {
00588 extractMessage(msg);
00589 }
00590 }
00591
00592
00593
00594
00595 void runDiagnostics()
00596 {
00597 if( ! output_cout_ )
00598 {
00599 return;
00600 }
00601
00602
00603 RelpermDiagnostics diagnostic;
00604 diagnostic.diagnosis(eclState(), deck(), this->grid());
00605 }
00606
00607 void writeInit()
00608 {
00609 bool output = ( output_ > OUTPUT_LOG_ONLY );
00610 bool output_ecl = param_.getDefault("output_ecl", true);
00611 if( output && output_ecl && grid().comm().rank() == 0 )
00612 {
00613 exportNncStructure_();
00614
00615 const EclipseGrid& inputGrid = eclState().getInputGrid();
00616 eclIO_.reset(new EclipseIO(eclState(), UgGridHelpers::createEclipseGrid( this->globalGrid() , inputGrid )));
00617 eclIO_->writeInitial(computeLegacySimProps_(), nnc_);
00618 }
00619 }
00620
00621
00622
00623
00624 void setupOutputWriter()
00625 {
00626
00627
00628
00629 output_writer_.reset(new OutputWriter(grid(),
00630 param_,
00631 eclState(),
00632 std::move(eclIO_),
00633 Opm::phaseUsageFromDeck(deck())) );
00634 }
00635
00636
00637
00638 int runSimulator()
00639 {
00640 const auto& schedule = eclState().getSchedule();
00641 const auto& timeMap = schedule.getTimeMap();
00642 auto& ioConfig = eclState().getIOConfig();
00643 SimulatorTimer simtimer;
00644
00645
00646 const auto& initConfig = eclState().getInitConfig();
00647 simtimer.init(timeMap, (size_t)initConfig.getRestartStep());
00648
00649 if (!ioConfig.initOnly()) {
00650 if (output_cout_) {
00651 std::string msg;
00652 msg = "\n\n================ Starting main simulation loop ===============\n";
00653 OpmLog::info(msg);
00654 }
00655
00656 SimulatorReport successReport = simulator_->run(simtimer, *state_);
00657 SimulatorReport failureReport = simulator_->failureReport();
00658
00659 if (output_cout_) {
00660 std::ostringstream ss;
00661 ss << "\n\n================ End of simulation ===============\n\n";
00662 successReport.reportFullyImplicit(ss, &failureReport);
00663 OpmLog::info(ss.str());
00664 if (param_.anyUnused()) {
00665
00666
00667 std::cout << "-------------------- Unused parameters: --------------------\n";
00668 param_.displayUsage();
00669 std::cout << "----------------------------------------------------------------" << std::endl;
00670 }
00671 }
00672
00673 if (output_to_files_) {
00674 std::string filename = output_dir_ + "/walltime.txt";
00675 std::fstream tot_os(filename.c_str(), std::fstream::trunc | std::fstream::out);
00676 successReport.reportParam(tot_os);
00677 }
00678 } else {
00679 if (output_cout_) {
00680 std::cout << "\n\n================ Simulation turned off ===============\n" << std::flush;
00681 }
00682
00683 }
00684 return EXIT_SUCCESS;
00685 }
00686
00687
00688
00689
00690 void setupLinearSolver()
00691 {
00692 typedef typename BlackoilModelEbos<TypeTag> :: ISTLSolverType ISTLSolverType;
00693
00694 extractParallelGridInformationToISTL(grid(), parallel_information_);
00695 fis_solver_.reset( new ISTLSolverType( param_, parallel_information_ ) );
00696 }
00697
00699
00700
00701
00702 void createSimulator()
00703 {
00704
00705 simulator_.reset(new Simulator(*ebosSimulator_,
00706 param_,
00707 *fis_solver_,
00708 FluidSystem::enableDissolvedGas(),
00709 FluidSystem::enableVaporizedOil(),
00710 eclState(),
00711 *output_writer_,
00712 defunctWellNames()));
00713 }
00714
00715 private:
00716 boost::filesystem::path simulationCaseName( const std::string& casename ) {
00717 namespace fs = boost::filesystem;
00718
00719 const auto exists = []( const fs::path& f ) -> bool {
00720 if( !fs::exists( f ) ) return false;
00721
00722 if( fs::is_regular_file( f ) ) return true;
00723
00724 return fs::is_symlink( f )
00725 && fs::is_regular_file( fs::read_symlink( f ) );
00726 };
00727
00728 auto simcase = fs::path( casename );
00729
00730 if( exists( simcase ) ) {
00731 return simcase;
00732 }
00733
00734 for( const auto& ext : { std::string("data"), std::string("DATA") } ) {
00735 if( exists( simcase.replace_extension( ext ) ) ) {
00736 return simcase;
00737 }
00738 }
00739
00740 throw std::invalid_argument( "Cannot find input case " + casename );
00741 }
00742
00743 unsigned long long getTotalSystemMemory()
00744 {
00745 long pages = sysconf(_SC_PHYS_PAGES);
00746 long page_size = sysconf(_SC_PAGE_SIZE);
00747 return pages * page_size;
00748 }
00749
00750 int64_t convertMessageType(const Message::type& mtype)
00751 {
00752 switch (mtype) {
00753 case Message::type::Debug:
00754 return Log::MessageType::Debug;
00755 case Message::type::Info:
00756 return Log::MessageType::Info;
00757 case Message::type::Warning:
00758 return Log::MessageType::Warning;
00759 case Message::type::Error:
00760 return Log::MessageType::Error;
00761 case Message::type::Problem:
00762 return Log::MessageType::Problem;
00763 case Message::type::Bug:
00764 return Log::MessageType::Bug;
00765 case Message::type::Note:
00766 return Log::MessageType::Note;
00767 }
00768 throw std::logic_error("Invalid messages type!\n");
00769 }
00770
00771 Grid& grid()
00772 { return ebosSimulator_->gridManager().grid(); }
00773
00774 const Grid& globalGrid()
00775 { return *globalGrid_; }
00776
00777 Problem& ebosProblem()
00778 { return ebosSimulator_->problem(); }
00779
00780 const Problem& ebosProblem() const
00781 { return ebosSimulator_->problem(); }
00782
00783 std::shared_ptr<MaterialLawManager> materialLawManager()
00784 { return ebosProblem().materialLawManager(); }
00785
00786 Scalar gravity() const
00787 { return ebosProblem().gravity()[2]; }
00788
00789 std::unordered_set<std::string> defunctWellNames() const
00790 { return ebosSimulator_->gridManager().defunctWellNames(); }
00791
00792 data::Solution computeLegacySimProps_()
00793 {
00794 const int* dims = UgGridHelpers::cartDims(grid());
00795 const int globalSize = dims[0]*dims[1]*dims[2];
00796
00797 data::CellData tranx = {UnitSystem::measure::transmissibility, std::vector<double>( globalSize ), data::TargetType::INIT};
00798 data::CellData trany = {UnitSystem::measure::transmissibility, std::vector<double>( globalSize ), data::TargetType::INIT};
00799 data::CellData tranz = {UnitSystem::measure::transmissibility, std::vector<double>( globalSize ), data::TargetType::INIT};
00800
00801 for (size_t i = 0; i < tranx.data.size(); ++i) {
00802 tranx.data[0] = 0.0;
00803 trany.data[0] = 0.0;
00804 tranz.data[0] = 0.0;
00805 }
00806
00807 const Grid& globalGrid = this->globalGrid();
00808 const auto& globalGridView = globalGrid.leafGridView();
00809 typedef typename Grid::LeafGridView GridView;
00810 typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGElementLayout> ElementMapper;
00811 ElementMapper globalElemMapper(globalGridView);
00812 const auto& cartesianCellIdx = globalGrid.globalCell();
00813
00814 const auto* globalTrans = &(ebosSimulator_->gridManager().globalTransmissibility());
00815 if (grid().comm().size() < 2) {
00816
00817
00818
00819
00820
00821
00822 globalTrans = &ebosSimulator_->problem().eclTransmissibilities();
00823 }
00824
00825 auto elemIt = globalGridView.template begin<0>();
00826 const auto& elemEndIt = globalGridView.template end<0>();
00827 for (; elemIt != elemEndIt; ++ elemIt) {
00828 const auto& elem = *elemIt;
00829
00830 auto isIt = globalGridView.ibegin(elem);
00831 const auto& isEndIt = globalGridView.iend(elem);
00832 for (; isIt != isEndIt; ++ isIt) {
00833 const auto& is = *isIt;
00834
00835 if (!is.neighbor())
00836 {
00837 continue;
00838 }
00839
00840 unsigned c1 = globalElemMapper.index(is.inside());
00841 unsigned c2 = globalElemMapper.index(is.outside());
00842
00843 if (c1 > c2)
00844 {
00845 continue;
00846 }
00847
00848
00849 int gc1 = std::min(cartesianCellIdx[c1], cartesianCellIdx[c2]);
00850 int gc2 = std::max(cartesianCellIdx[c1], cartesianCellIdx[c2]);
00851 if (gc2 - gc1 == 1) {
00852 tranx.data[gc1] = globalTrans->transmissibility(c1, c2);
00853 }
00854
00855 if (gc2 - gc1 == dims[0]) {
00856 trany.data[gc1] = globalTrans->transmissibility(c1, c2);
00857 }
00858
00859 if (gc2 - gc1 == dims[0]*dims[1]) {
00860 tranz.data[gc1] = globalTrans->transmissibility(c1, c2);
00861 }
00862 }
00863 }
00864
00865 return {{"TRANX" , tranx},
00866 {"TRANY" , trany} ,
00867 {"TRANZ" , tranz}};
00868 }
00869
00870 void exportNncStructure_()
00871 {
00872 nnc_ = eclState().getInputNNC();
00873 int nx = eclState().getInputGrid().getNX();
00874 int ny = eclState().getInputGrid().getNY();
00875
00876
00877 const Grid& globalGrid = this->globalGrid();
00878 const auto& globalGridView = globalGrid.leafGridView();
00879 typedef typename Grid::LeafGridView GridView;
00880 typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGElementLayout> ElementMapper;
00881 ElementMapper globalElemMapper(globalGridView);
00882
00883 const auto* globalTrans = &(ebosSimulator_->gridManager().globalTransmissibility());
00884 if (grid().comm().size() < 2) {
00885
00886
00887
00888
00889
00890
00891 globalTrans = &ebosSimulator_->problem().eclTransmissibilities();
00892 }
00893
00894 auto elemIt = globalGridView.template begin<0>();
00895 const auto& elemEndIt = globalGridView.template end<0>();
00896 for (; elemIt != elemEndIt; ++ elemIt) {
00897 const auto& elem = *elemIt;
00898
00899 auto isIt = globalGridView.ibegin(elem);
00900 const auto& isEndIt = globalGridView.iend(elem);
00901 for (; isIt != isEndIt; ++ isIt) {
00902 const auto& is = *isIt;
00903
00904 if (!is.neighbor())
00905 {
00906 continue;
00907 }
00908
00909 unsigned c1 = globalElemMapper.index(is.inside());
00910 unsigned c2 = globalElemMapper.index(is.outside());
00911
00912 if (c1 > c2)
00913 {
00914 continue;
00915 }
00916
00917
00918
00919
00920 int cc1 = globalGrid.globalCell()[c1];
00921 int cc2 = globalGrid.globalCell()[c2];
00922
00923 if (std::abs(cc1 - cc2) != 1 &&
00924 std::abs(cc1 - cc2) != nx &&
00925 std::abs(cc1 - cc2) != nx*ny)
00926 {
00927 nnc_.addNNC(cc1, cc2, globalTrans->transmissibility(c1, c2));
00928 }
00929 }
00930 }
00931 }
00932
00933 std::unique_ptr<EbosSimulator> ebosSimulator_;
00934 int mpi_rank_ = 0;
00935 bool output_cout_ = false;
00936 FileOutputValue output_ = OUTPUT_ALL;
00937 bool must_distribute_ = false;
00938 ParameterGroup param_;
00939 bool output_to_files_ = false;
00940 std::string output_dir_ = std::string(".");
00941 std::unique_ptr<ReservoirState> state_;
00942 NNC nnc_;
00943 std::unique_ptr<EclipseIO> eclIO_;
00944 std::unique_ptr<OutputWriter> output_writer_;
00945 boost::any parallel_information_;
00946 std::unique_ptr<NewtonIterationBlackoilInterface> fis_solver_;
00947 std::unique_ptr<Simulator> simulator_;
00948 std::string logFile_;
00949
00950 std::shared_ptr<Grid> globalGrid_;
00951 };
00952 }
00953
00954 #endif // OPM_FLOW_MAIN_EBOS_HEADER_INCLUDED