mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-11-25 02:30:18 -06:00
a0fa87e81f
This at least slightly improves the old design. In that design the subclass had no own constructor but inherited the one of the base class. That base class constructor called certain subclass functions (createGrids_, filterConnections_, updateOutputDir_, and finalizeInit_)that would initialize raw pointers of the subclass. Hence subclasses where not allowed to have non-pod members and those used later (e.g. deleted in the destructor) had to be initialized in these functions. The new (still ugly) design introduces constructors into the subclasses and skips inheriting constructors. Now one must call a base class function classImplementationInit which will still call the functions createGrids_, filterConnections_, updateOutputDir_, and finalizeInit_, but at least at this point the baseclass is fully constructed and the subclass is constructed as much as possible/needed (non-pod types will be initialized now.)
634 lines
23 KiB
C++
634 lines
23 KiB
C++
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
/*
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Consult the COPYING file in the top-level source directory of this
|
|
module for the precise wording of the license and the list of
|
|
copyright holders.
|
|
*/
|
|
/*!
|
|
* \file
|
|
* \copydoc Opm::EclBaseVanguard
|
|
*/
|
|
#ifndef EWOMS_ECL_BASE_VANGUARD_HH
|
|
#define EWOMS_ECL_BASE_VANGUARD_HH
|
|
|
|
#include <opm/models/io/basevanguard.hh>
|
|
#include <opm/models/utils/propertysystem.hh>
|
|
#include <opm/models/utils/parametersystem.hh>
|
|
|
|
#include <opm/grid/CpGrid.hpp>
|
|
#include <opm/grid/cpgrid/GridHelpers.hpp>
|
|
#include <opm/core/props/satfunc/RelpermDiagnostics.hpp>
|
|
|
|
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
|
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
|
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
|
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
|
|
|
|
|
#if HAVE_MPI
|
|
#include <mpi.h>
|
|
#endif // HAVE_MPI
|
|
|
|
#include <array>
|
|
#include <chrono>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
namespace Opm {
|
|
template <class TypeTag>
|
|
class EclBaseVanguard;
|
|
}
|
|
|
|
BEGIN_PROPERTIES
|
|
|
|
NEW_TYPE_TAG(EclBaseVanguard);
|
|
|
|
// declare the properties required by the for the ecl simulator vanguard
|
|
NEW_PROP_TAG(Grid);
|
|
NEW_PROP_TAG(EquilGrid);
|
|
NEW_PROP_TAG(Scalar);
|
|
NEW_PROP_TAG(EclDeckFileName);
|
|
NEW_PROP_TAG(OutputDir);
|
|
NEW_PROP_TAG(EnableOpmRstFile);
|
|
NEW_PROP_TAG(EclStrictParsing);
|
|
NEW_PROP_TAG(EclOutputInterval);
|
|
NEW_PROP_TAG(IgnoreKeywords);
|
|
NEW_PROP_TAG(EnableExperiments);
|
|
NEW_PROP_TAG(EdgeWeightsMethod);
|
|
|
|
SET_STRING_PROP(EclBaseVanguard, IgnoreKeywords, "");
|
|
SET_STRING_PROP(EclBaseVanguard, EclDeckFileName, "");
|
|
SET_INT_PROP(EclBaseVanguard, EclOutputInterval, -1); // use the deck-provided value
|
|
SET_BOOL_PROP(EclBaseVanguard, EnableOpmRstFile, false);
|
|
SET_BOOL_PROP(EclBaseVanguard, EclStrictParsing, false);
|
|
SET_INT_PROP(EclBaseVanguard, EdgeWeightsMethod, 1);
|
|
|
|
END_PROPERTIES
|
|
|
|
namespace Opm {
|
|
|
|
/*!
|
|
* \ingroup EclBlackOilSimulator
|
|
*
|
|
* \brief Helper class for grid instantiation of ECL file-format using problems.
|
|
*/
|
|
template <class TypeTag>
|
|
class EclBaseVanguard : public BaseVanguard<TypeTag>
|
|
{
|
|
typedef BaseVanguard<TypeTag> ParentType;
|
|
typedef typename GET_PROP_TYPE(TypeTag, Vanguard) Implementation;
|
|
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
|
|
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
|
|
|
|
enum { enableExperiments = GET_PROP_VALUE(TypeTag, EnableExperiments) };
|
|
|
|
public:
|
|
typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
|
|
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
|
|
|
|
protected:
|
|
static const int dimension = Grid::dimension;
|
|
|
|
public:
|
|
/*!
|
|
* \brief Register the common run-time parameters for all ECL simulator vanguards.
|
|
*/
|
|
static void registerParameters()
|
|
{
|
|
EWOMS_REGISTER_PARAM(TypeTag, std::string, EclDeckFileName,
|
|
"The name of the file which contains the ECL deck to be simulated");
|
|
EWOMS_REGISTER_PARAM(TypeTag, int, EclOutputInterval,
|
|
"The number of report steps that ought to be skipped between two writes of ECL results");
|
|
EWOMS_REGISTER_PARAM(TypeTag, bool, EnableOpmRstFile,
|
|
"Include OPM-specific keywords in the ECL restart file to enable restart of OPM simulators from these files");
|
|
EWOMS_REGISTER_PARAM(TypeTag, std::string, IgnoreKeywords,
|
|
"List of Eclipse keywords which should be ignored. As a ':' separated string.");
|
|
EWOMS_REGISTER_PARAM(TypeTag, bool, EclStrictParsing,
|
|
"Use strict mode for parsing - all errors are collected before the applicaton exists.");
|
|
EWOMS_REGISTER_PARAM(TypeTag, int, EdgeWeightsMethod,
|
|
"Choose edge-weighing strategy: 0=uniform, 1=trans, 2=log(trans).");
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns the canonical path to a deck file.
|
|
*
|
|
* The input can either be the canonical deck file name or the name of the case
|
|
* (i.e., without the .DATA extension)
|
|
*/
|
|
static boost::filesystem::path canonicalDeckPath(const std::string& caseName)
|
|
{
|
|
const auto fileExists = [](const boost::filesystem::path& f) -> bool
|
|
{
|
|
if (!boost::filesystem::exists(f))
|
|
return false;
|
|
|
|
if (boost::filesystem::is_regular_file(f))
|
|
return true;
|
|
|
|
return boost::filesystem::is_symlink(f) && boost::filesystem::is_regular_file(boost::filesystem::read_symlink(f));
|
|
};
|
|
|
|
auto simcase = boost::filesystem::path(caseName);
|
|
if (fileExists(simcase))
|
|
return simcase;
|
|
|
|
for (const auto& ext : { std::string("data"), std::string("DATA") }) {
|
|
if (fileExists(simcase.replace_extension(ext)))
|
|
return simcase;
|
|
}
|
|
|
|
throw std::invalid_argument("Cannot find input case '"+caseName+"'");
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates an Opm::parseContext object assuming that the parameters are ready.
|
|
*/
|
|
static std::unique_ptr<Opm::ParseContext> createParseContext()
|
|
{
|
|
typedef std::pair<std::string, Opm::InputError::Action> ParseModePair;
|
|
typedef std::vector<ParseModePair> ParseModePairs;
|
|
ParseModePairs tmp;
|
|
tmp.emplace_back(Opm::ParseContext::PARSE_RANDOM_SLASH, Opm::InputError::IGNORE);
|
|
tmp.emplace_back(Opm::ParseContext::PARSE_MISSING_DIMS_KEYWORD, Opm::InputError::WARN);
|
|
tmp.emplace_back(Opm::ParseContext::SUMMARY_UNKNOWN_WELL, Opm::InputError::WARN);
|
|
tmp.emplace_back(Opm::ParseContext::SUMMARY_UNKNOWN_GROUP, Opm::InputError::WARN);
|
|
tmp.emplace_back(Opm::ParseContext::PARSE_EXTRA_RECORDS, Opm::InputError::WARN);
|
|
|
|
std::unique_ptr<Opm::ParseContext> parseContext(new Opm::ParseContext(tmp));
|
|
|
|
const std::string ignoredKeywords = EWOMS_GET_PARAM(TypeTag, std::string, IgnoreKeywords);
|
|
if (ignoredKeywords.size() > 0) {
|
|
size_t pos;
|
|
size_t offset = 0;
|
|
while (true) {
|
|
pos = ignoredKeywords.find(':', offset);
|
|
if (pos == std::string::npos) {
|
|
parseContext->ignoreKeyword(ignoredKeywords.substr(offset));
|
|
break;
|
|
}
|
|
parseContext->ignoreKeyword(ignoredKeywords.substr(offset, pos - offset));
|
|
offset = pos + 1;
|
|
}
|
|
}
|
|
|
|
if (EWOMS_GET_PARAM(TypeTag, bool, EclStrictParsing))
|
|
parseContext->update(Opm::InputError::DELAYED_EXIT1);
|
|
|
|
return parseContext;
|
|
}
|
|
|
|
/*!
|
|
* \brief Set the wall time which was spend externally to set up the external data structures
|
|
*
|
|
* i.e., the objects specified via the other setExternal*() methods.
|
|
*/
|
|
static void setExternalSetupTime(Scalar t)
|
|
{ externalSetupTime_ = t; }
|
|
|
|
/*!
|
|
* \brief Returns the wall time required to set up the simulator before it was born.
|
|
*/
|
|
static Scalar externalSetupTime()
|
|
{ return externalSetupTime_; }
|
|
|
|
/*!
|
|
* \brief Set the Opm::ParseContext object which ought to be used for parsing the deck and creating the Opm::EclipseState object.
|
|
*/
|
|
static void setExternalParseContext(Opm::ParseContext* parseContext)
|
|
{ externalParseContext_ = parseContext; }
|
|
|
|
/*!
|
|
* \brief Set the Opm::ErrorGuard object which ought to be used for parsing the deck and creating the Opm::EclipseState object.
|
|
*/
|
|
static void setExternalErrorGuard(Opm::ErrorGuard* errorGuard)
|
|
{ externalErrorGuard_ = errorGuard; }
|
|
|
|
/*!
|
|
* \brief Set the Opm::Deck object which ought to be used when the simulator vanguard
|
|
* is instantiated.
|
|
*
|
|
* This is basically an optimization: In cases where the ECL input deck must be
|
|
* examined to decide which simulator ought to be used, this avoids having to parse
|
|
* the input twice. When this method is used, the caller is responsible for lifetime
|
|
* management of these two objects, i.e., they are not allowed to be deleted as long
|
|
* as the simulator vanguard object is alive.
|
|
*/
|
|
static void setExternalDeck(Opm::Deck* deck)
|
|
{ externalDeck_ = deck; }
|
|
|
|
/*!
|
|
* \brief Set the Opm::EclipseState object which ought to be used when the simulator
|
|
* vanguard is instantiated.
|
|
*/
|
|
static void setExternalEclState(Opm::EclipseState* eclState)
|
|
{ externalEclState_ = eclState; }
|
|
|
|
/*!
|
|
* \brief Create the grid for problem data files which use the ECL file format.
|
|
*
|
|
* This is the file format used by the commercial ECLiPSE simulator. Usually it uses
|
|
* a cornerpoint description of the grid.
|
|
*/
|
|
EclBaseVanguard(Simulator& simulator)
|
|
: ParentType(simulator)
|
|
{
|
|
int myRank = 0;
|
|
#if HAVE_MPI
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
|
|
#endif
|
|
|
|
std::string fileName = EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName);
|
|
edgeWeightsMethod_ = Dune::EdgeWeightMethod(EWOMS_GET_PARAM(TypeTag, int, EdgeWeightsMethod));
|
|
|
|
if (fileName == "")
|
|
throw std::runtime_error("No input deck file has been specified as a command line argument,"
|
|
" or via '--ecl-deck-file-name=CASE.DATA'");
|
|
|
|
fileName = canonicalDeckPath(fileName).string();
|
|
|
|
// compute the base name of the input file name
|
|
const char directorySeparator = '/';
|
|
long int i;
|
|
for (i = fileName.size(); i >= 0; -- i)
|
|
if (fileName[i] == directorySeparator)
|
|
break;
|
|
std::string baseName = fileName.substr(i + 1, fileName.size());
|
|
|
|
// remove the extension from the input file
|
|
for (i = baseName.size(); i >= 0; -- i)
|
|
if (baseName[i] == '.')
|
|
break;
|
|
std::string rawCaseName;
|
|
if (i < 0)
|
|
rawCaseName = baseName;
|
|
else
|
|
rawCaseName = baseName.substr(0, i);
|
|
|
|
// transform the result to ALL_UPPERCASE
|
|
caseName_ = rawCaseName;
|
|
std::transform(caseName_.begin(), caseName_.end(), caseName_.begin(), ::toupper);
|
|
|
|
// create the parser objects for the deck or use their externally specified
|
|
// versions (if desired)
|
|
if (!externalParseContext_) {
|
|
internalParseContext_ = createParseContext();
|
|
parseContext_ = internalParseContext_.get();
|
|
}
|
|
else
|
|
parseContext_ = externalParseContext_;
|
|
|
|
if (!externalParseContext_) {
|
|
internalErrorGuard_.reset(new Opm::ErrorGuard);
|
|
errorGuard_ = internalErrorGuard_.get();
|
|
}
|
|
else
|
|
errorGuard_ = externalErrorGuard_;
|
|
|
|
if (!externalDeck_) {
|
|
if (myRank == 0)
|
|
std::cout << "Reading the deck file '" << fileName << "'" << std::endl;
|
|
|
|
Opm::Parser parser;
|
|
internalDeck_.reset(new Opm::Deck(parser.parseFile(fileName, *parseContext_, *errorGuard_)));
|
|
deck_ = internalDeck_.get();
|
|
|
|
if (enableExperiments && myRank == 0)
|
|
Opm::checkDeck(*deck_, parser, *parseContext_, *errorGuard_);
|
|
}
|
|
else {
|
|
assert(externalDeck_);
|
|
|
|
deck_ = externalDeck_;
|
|
}
|
|
|
|
if (!externalEclState_) {
|
|
internalEclState_.reset(new Opm::EclipseState(*deck_, *parseContext_, *errorGuard_));
|
|
eclState_ = internalEclState_.get();
|
|
}
|
|
else {
|
|
assert(externalDeck_);
|
|
assert(externalEclState_);
|
|
|
|
deck_ = externalDeck_;
|
|
eclState_ = externalEclState_;
|
|
}
|
|
|
|
if (!externalEclSchedule_) {
|
|
// create the schedule object. Note that if eclState is supposed to represent
|
|
// the internalized version of the deck, this constitutes a layering
|
|
// violation.
|
|
internalEclSchedule_.reset(new Opm::Schedule(*deck_, *eclState_, *parseContext_, *errorGuard_));
|
|
eclSchedule_ = internalEclSchedule_.get();
|
|
}
|
|
else
|
|
eclSchedule_ = externalEclSchedule_;
|
|
this->summaryState_.reset( new Opm::SummaryState( std::chrono::system_clock::from_time_t(this->eclSchedule_->getStartTime() )));
|
|
|
|
if (!externalEclSummaryConfig_) {
|
|
// create the schedule object. Note that if eclState is supposed to represent
|
|
// the internalized version of the deck, this constitutes a layering
|
|
// violation.
|
|
internalEclSummaryConfig_.reset(new Opm::SummaryConfig(*deck_,
|
|
*eclSchedule_,
|
|
eclState_->getTableManager(),
|
|
*parseContext_,
|
|
*errorGuard_));
|
|
|
|
eclSummaryConfig_ = internalEclSummaryConfig_.get();
|
|
}
|
|
else
|
|
eclSummaryConfig_ = externalEclSummaryConfig_;
|
|
|
|
if (*errorGuard_) {
|
|
errorGuard_->dump();
|
|
errorGuard_->clear();
|
|
|
|
throw std::runtime_error("Unrecoverable errors were encountered while loading input.");
|
|
}
|
|
|
|
// Possibly override IOConfig setting for how often RESTART files should get
|
|
// written to disk (every N report step)
|
|
int outputInterval = EWOMS_GET_PARAM(TypeTag, int, EclOutputInterval);
|
|
if (outputInterval >= 0)
|
|
eclState_->getRestartConfig().overrideRestartWriteInterval(outputInterval);
|
|
}
|
|
|
|
/*!
|
|
* \brief Return a reference to the parsed ECL deck.
|
|
*/
|
|
const Opm::Deck& deck() const
|
|
{ return *deck_; }
|
|
|
|
Opm::Deck& deck()
|
|
{ return *deck_; }
|
|
|
|
/*!
|
|
* \brief Return a reference to the internalized ECL deck.
|
|
*/
|
|
const Opm::EclipseState& eclState() const
|
|
{ return *eclState_; }
|
|
|
|
Opm::EclipseState& eclState()
|
|
{ return *eclState_; }
|
|
|
|
/*!
|
|
* \brief Return a reference to the object that managages the ECL schedule.
|
|
*/
|
|
const Opm::Schedule& schedule() const
|
|
{ return *eclSchedule_; }
|
|
|
|
Opm::Schedule& schedule()
|
|
{ return *eclSchedule_; }
|
|
|
|
/*!
|
|
* \brief Set the schedule object.
|
|
*
|
|
* The lifetime of this object is not managed by the vanguard, i.e., the object must
|
|
* stay valid until after the vanguard gets destroyed.
|
|
*/
|
|
static void setExternalSchedule(Opm::Schedule* schedule)
|
|
{ externalEclSchedule_ = schedule; }
|
|
|
|
/*!
|
|
* \brief Return a reference to the object that determines which quantities ought to
|
|
* be put into the ECL summary output.
|
|
*/
|
|
const Opm::SummaryConfig& summaryConfig() const
|
|
{ return *eclSummaryConfig_; }
|
|
|
|
/*!
|
|
* \brief Set the summary configuration object.
|
|
*
|
|
* The lifetime of this object is not managed by the vanguard, i.e., the object must
|
|
* stay valid until after the vanguard gets destroyed.
|
|
*/
|
|
static void setExternalSummaryConfig(Opm::SummaryConfig* summaryConfig)
|
|
{ externalEclSummaryConfig_ = summaryConfig; }
|
|
|
|
|
|
/*!
|
|
* \brief Returns the summary state
|
|
*
|
|
* The summary state is a small container object for
|
|
* computed, ready to use summary values. The values will typically be used by
|
|
* the UDQ, WTEST and ACTIONX calculations.
|
|
*/
|
|
Opm::SummaryState& summaryState()
|
|
{ return *summaryState_; }
|
|
|
|
const Opm::SummaryState& summaryState() const
|
|
{ return *summaryState_; }
|
|
|
|
/*!
|
|
* \brief Parameter deciding the edge-weight strategy of the load balancer.
|
|
*/
|
|
Dune::EdgeWeightMethod edgeWeightsMethod() const
|
|
{ return edgeWeightsMethod_; }
|
|
/*!
|
|
* \brief Returns the name of the case.
|
|
*
|
|
* i.e., the all-uppercase version of the file name from which the
|
|
* deck is loaded with the ".DATA" suffix removed.
|
|
*/
|
|
const std::string& caseName() const
|
|
{ return caseName_; }
|
|
|
|
/*!
|
|
* \brief Returns the number of logically Cartesian cells in each direction
|
|
*/
|
|
const std::array<int, dimension>& cartesianDimensions() const
|
|
{ return asImp_().cartesianIndexMapper().cartesianDimensions(); }
|
|
|
|
/*!
|
|
* \brief Returns the overall number of cells of the logically Cartesian grid
|
|
*/
|
|
int cartesianSize() const
|
|
{ return asImp_().cartesianIndexMapper().cartesianSize(); }
|
|
|
|
/*!
|
|
* \brief Returns the overall number of cells of the logically EquilCartesian grid
|
|
*/
|
|
int equilCartesianSize() const
|
|
{ return asImp_().equilCartesianIndexMapper().cartesianSize(); }
|
|
|
|
/*!
|
|
* \brief Returns the Cartesian cell id for identifaction with ECL data
|
|
*/
|
|
unsigned cartesianIndex(unsigned compressedCellIdx) const
|
|
{ return asImp_().cartesianIndexMapper().cartesianIndex(compressedCellIdx); }
|
|
|
|
/*!
|
|
* \brief Return the index of the cells in the logical Cartesian grid
|
|
*/
|
|
unsigned cartesianIndex(const std::array<int,dimension>& coords) const
|
|
{
|
|
unsigned cartIndex = coords[0];
|
|
int factor = cartesianDimensions()[0];
|
|
for (unsigned i = 1; i < dimension; ++i) {
|
|
cartIndex += coords[i]*factor;
|
|
factor *= cartesianDimensions()[i];
|
|
}
|
|
|
|
return cartIndex;
|
|
}
|
|
|
|
/*!
|
|
* \brief Extract Cartesian index triplet (i,j,k) of an active cell.
|
|
*
|
|
* \param [in] cellIdx Active cell index.
|
|
* \param [out] ijk Cartesian index triplet
|
|
*/
|
|
void cartesianCoordinate(unsigned cellIdx, std::array<int,3>& ijk) const
|
|
{ return asImp_().cartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); }
|
|
|
|
/*!
|
|
* \brief Returns the Cartesian cell id given an element index for the grid used for equilibration
|
|
*/
|
|
unsigned equilCartesianIndex(unsigned compressedEquilCellIdx) const
|
|
{ return asImp_().equilCartesianIndexMapper().cartesianIndex(compressedEquilCellIdx); }
|
|
|
|
/*!
|
|
* \brief Extract Cartesian index triplet (i,j,k) of an active cell of the grid used for EQUIL.
|
|
*
|
|
* \param [in] cellIdx Active cell index.
|
|
* \param [out] ijk Cartesian index triplet
|
|
*/
|
|
void equilCartesianCoordinate(unsigned cellIdx, std::array<int,3>& ijk) const
|
|
{ return asImp_().equilCartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); }
|
|
|
|
/*!
|
|
* \brief Return the names of the wells which do not penetrate any cells on the local
|
|
* process.
|
|
*
|
|
* This is a kludge around the fact that for distributed grids, not all wells are
|
|
* seen by all proccesses.
|
|
*/
|
|
std::unordered_set<std::string> defunctWellNames() const
|
|
{ return std::unordered_set<std::string>(); }
|
|
|
|
protected:
|
|
void callImplementationInit()
|
|
{
|
|
asImp_().createGrids_();
|
|
asImp_().filterConnections_();
|
|
asImp_().updateOutputDir_();
|
|
asImp_().finalizeInit_();
|
|
|
|
if (enableExperiments) {
|
|
Opm::RelpermDiagnostics relpermDiagnostics;
|
|
relpermDiagnostics.diagnosis(*eclState_, *deck_, asImp_().grid());
|
|
}
|
|
}
|
|
private:
|
|
void updateOutputDir_()
|
|
{
|
|
// update the location for output
|
|
std::string outputDir = EWOMS_GET_PARAM(TypeTag, std::string, OutputDir);
|
|
auto& ioConfig = eclState_->getIOConfig();
|
|
if (outputDir == "")
|
|
// If no output directory parameter is specified, use the output directory
|
|
// which Opm::IOConfig thinks that should be used. Normally this is the
|
|
// directory in which the input files are located.
|
|
outputDir = ioConfig.getOutputDir();
|
|
|
|
// ensure that the output directory exists and that it is a directory
|
|
if (!boost::filesystem::is_directory(outputDir)) {
|
|
try {
|
|
boost::filesystem::create_directories(outputDir);
|
|
}
|
|
catch (...) {
|
|
throw std::runtime_error("Creation of output directory '"+outputDir+"' failed\n");
|
|
}
|
|
}
|
|
|
|
// specify the directory output. This is not a very nice mechanism because
|
|
// the eclState is supposed to be immutable here, IMO.
|
|
ioConfig.setOutputDir(outputDir);
|
|
|
|
ioConfig.setEclCompatibleRST(!EWOMS_GET_PARAM(TypeTag, bool, EnableOpmRstFile));
|
|
}
|
|
|
|
Implementation& asImp_()
|
|
{ return *static_cast<Implementation*>(this); }
|
|
|
|
const Implementation& asImp_() const
|
|
{ return *static_cast<const Implementation*>(this); }
|
|
|
|
std::string caseName_;
|
|
|
|
static Scalar externalSetupTime_;
|
|
|
|
static Opm::ParseContext* externalParseContext_;
|
|
static Opm::ErrorGuard* externalErrorGuard_;
|
|
static Opm::Deck* externalDeck_;
|
|
static Opm::EclipseState* externalEclState_;
|
|
static Opm::Schedule* externalEclSchedule_;
|
|
static Opm::SummaryConfig* externalEclSummaryConfig_;
|
|
|
|
std::unique_ptr<Opm::ParseContext> internalParseContext_;
|
|
std::unique_ptr<Opm::ErrorGuard> internalErrorGuard_;
|
|
std::unique_ptr<Opm::Deck> internalDeck_;
|
|
std::unique_ptr<Opm::EclipseState> internalEclState_;
|
|
std::unique_ptr<Opm::Schedule> internalEclSchedule_;
|
|
std::unique_ptr<Opm::SummaryConfig> internalEclSummaryConfig_;
|
|
std::unique_ptr<Opm::SummaryState> summaryState_;
|
|
|
|
// these attributes point either to the internal or to the external version of the
|
|
// parser objects.
|
|
Opm::ParseContext* parseContext_;
|
|
Opm::ErrorGuard* errorGuard_;
|
|
Opm::Deck* deck_;
|
|
Opm::EclipseState* eclState_;
|
|
Opm::Schedule* eclSchedule_;
|
|
Opm::SummaryConfig* eclSummaryConfig_;
|
|
|
|
Dune::EdgeWeightMethod edgeWeightsMethod_;
|
|
};
|
|
|
|
template <class TypeTag>
|
|
typename EclBaseVanguard<TypeTag>::Scalar EclBaseVanguard<TypeTag>::externalSetupTime_ = 0.0;
|
|
|
|
template <class TypeTag>
|
|
Opm::ParseContext* EclBaseVanguard<TypeTag>::externalParseContext_ = nullptr;
|
|
|
|
template <class TypeTag>
|
|
Opm::ErrorGuard* EclBaseVanguard<TypeTag>::externalErrorGuard_ = nullptr;
|
|
|
|
template <class TypeTag>
|
|
Opm::Deck* EclBaseVanguard<TypeTag>::externalDeck_ = nullptr;
|
|
|
|
template <class TypeTag>
|
|
Opm::EclipseState* EclBaseVanguard<TypeTag>::externalEclState_;
|
|
|
|
template <class TypeTag>
|
|
Opm::Schedule* EclBaseVanguard<TypeTag>::externalEclSchedule_ = nullptr;
|
|
|
|
template <class TypeTag>
|
|
Opm::SummaryConfig* EclBaseVanguard<TypeTag>::externalEclSummaryConfig_ = nullptr;
|
|
|
|
} // namespace Opm
|
|
|
|
#endif
|