mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
eclbasevanguard: split in template and non-template parts
This commit is contained in:
parent
5aa1b43e41
commit
3397cd6252
@ -24,6 +24,7 @@
|
||||
# find opm -name '*.c*' -printf '\t%p\n' | sort
|
||||
list (APPEND MAIN_SOURCE_FILES
|
||||
ebos/collecttoiorank.cc
|
||||
ebos/eclgenericvanguard.cc
|
||||
opm/core/props/phaseUsageFromDeck.cpp
|
||||
opm/core/props/satfunc/RelpermDiagnostics.cpp
|
||||
opm/simulators/timestepping/SimulatorReport.cpp
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "ebos.hh"
|
||||
#include "startEbos.hh"
|
||||
#include <opm/models/blackoil/blackoiltwophaseindices.hh>
|
||||
|
||||
namespace Opm::Properties {
|
||||
|
||||
|
@ -27,39 +27,21 @@
|
||||
#ifndef EWOMS_ECL_BASE_VANGUARD_HH
|
||||
#define EWOMS_ECL_BASE_VANGUARD_HH
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
|
||||
#include <opm/models/io/basevanguard.hh>
|
||||
#include <opm/models/utils/propertysystem.hh>
|
||||
#include <opm/models/utils/parametersystem.hh>
|
||||
#include <opm/models/discretization/common/fvbaseproperties.hh>
|
||||
#include <ebos/eclgenericvanguard.hh>
|
||||
|
||||
#include <opm/grid/CpGrid.hpp>
|
||||
#include <opm/grid/cpgrid/GridHelpers.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Python/Python.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>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/State.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
|
||||
|
||||
#include <opm/simulators/utils/readDeck.hpp>
|
||||
|
||||
#if HAVE_MPI
|
||||
#include <mpi.h>
|
||||
#endif // HAVE_MPI
|
||||
#include <opm/grid/common/GridEnums.hpp>
|
||||
#include <opm/grid/common/CartesianIndexMapper.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
@ -192,7 +174,8 @@ namespace Opm {
|
||||
* \brief Helper class for grid instantiation of ECL file-format using problems.
|
||||
*/
|
||||
template <class TypeTag>
|
||||
class EclBaseVanguard : public BaseVanguard<TypeTag>
|
||||
class EclBaseVanguard : public BaseVanguard<TypeTag>,
|
||||
public EclGenericVanguard
|
||||
{
|
||||
using ParentType = BaseVanguard<TypeTag>;
|
||||
using Implementation = GetPropType<TypeTag, Properties::Vanguard>;
|
||||
@ -245,119 +228,6 @@ public:
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
* \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 std::string canonicalDeckPath(const std::string& caseName)
|
||||
{
|
||||
const auto fileExists = [](const filesystem::path& f) -> bool
|
||||
{
|
||||
if (!filesystem::exists(f))
|
||||
return false;
|
||||
|
||||
if (filesystem::is_regular_file(f))
|
||||
return true;
|
||||
|
||||
return filesystem::is_symlink(f) && filesystem::is_regular_file(filesystem::read_symlink(f));
|
||||
};
|
||||
|
||||
auto simcase = filesystem::path(caseName);
|
||||
if (fileExists(simcase))
|
||||
return simcase.string();
|
||||
|
||||
for (const auto& ext : { std::string("data"), std::string("DATA") }) {
|
||||
if (fileExists(simcase.replace_extension(ext)))
|
||||
return simcase.string();
|
||||
}
|
||||
|
||||
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<ParseContext> createParseContext(const std::string& ignoredKeywords,
|
||||
bool eclStrictParsing)
|
||||
{
|
||||
typedef std::pair<std::string, InputError::Action> ParseModePair;
|
||||
typedef std::vector<ParseModePair> ParseModePairs;
|
||||
ParseModePairs tmp;
|
||||
tmp.emplace_back(ParseContext::PARSE_RANDOM_SLASH, InputError::IGNORE);
|
||||
tmp.emplace_back(ParseContext::PARSE_MISSING_DIMS_KEYWORD, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::SUMMARY_UNKNOWN_WELL, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::SUMMARY_UNKNOWN_GROUP, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::PARSE_EXTRA_RECORDS, InputError::WARN);
|
||||
|
||||
auto parseContext = std::make_unique<ParseContext>(tmp);
|
||||
|
||||
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 (eclStrictParsing)
|
||||
parseContext->update(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(std::unique_ptr<ParseContext> parseContext)
|
||||
{ externalParseContext_ = std::move(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(std::unique_ptr<ErrorGuard> errorGuard)
|
||||
{ externalErrorGuard_ = std::move(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(std::unique_ptr<Deck> deck)
|
||||
{ externalDeck_ = std::move(deck); externalDeckSet_ = true; }
|
||||
/*!
|
||||
* \brief Set the Opm::EclipseState object which ought to be used when the simulator
|
||||
* vanguard is instantiated.
|
||||
*/
|
||||
static void setExternalEclState(std::unique_ptr<EclipseState> eclState)
|
||||
{ externalEclState_ = std::move(eclState); }
|
||||
|
||||
/*!
|
||||
* \brief Create the grid for problem data files which use the ECL file format.
|
||||
*
|
||||
@ -367,277 +237,23 @@ public:
|
||||
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);
|
||||
fileName_ = EWOMS_GET_PARAM(TypeTag, std::string, EclDeckFileName);
|
||||
edgeWeightsMethod_ = Dune::EdgeWeightMethod(EWOMS_GET_PARAM(TypeTag, int, EdgeWeightsMethod));
|
||||
ownersFirst_ = EWOMS_GET_PARAM(TypeTag, bool, OwnerCellsFirst);
|
||||
serialPartitioning_ = EWOMS_GET_PARAM(TypeTag, bool, SerialPartitioning);
|
||||
zoltanImbalanceTol_ = EWOMS_GET_PARAM(TypeTag, double, ZoltanImbalanceTol);
|
||||
enableDistributedWells_ = EWOMS_GET_PARAM(TypeTag, bool, AllowDistributedWells);
|
||||
|
||||
// Make proper case name.
|
||||
{
|
||||
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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
std::unique_ptr<ErrorGuard> errorGuard = nullptr;
|
||||
|
||||
// Check that we are in one of the known configurations for external variables
|
||||
// and move them to internal
|
||||
if (externalDeck_)
|
||||
{
|
||||
deck_ = std::move(externalDeck_);
|
||||
|
||||
if (externalParseContext_ && externalErrorGuard_ )
|
||||
{
|
||||
parseContext_ = std::move(externalParseContext_);
|
||||
errorGuard = std::move(externalErrorGuard_);
|
||||
}
|
||||
else if(externalEclState_ && externalEclSchedule_ && externalEclSummaryConfig_)
|
||||
{
|
||||
eclState_ = std::move(externalEclState_);
|
||||
eclSchedule_ = std::move(externalEclSchedule_);
|
||||
eclSummaryConfig_ = std::move(externalEclSummaryConfig_);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Either parse context and error guard or ECL state, schedule, and summary config need to be"
|
||||
<< " set externally.");
|
||||
}
|
||||
}
|
||||
else if (externalParseContext_)
|
||||
{
|
||||
parseContext_ = std::move(externalParseContext_);
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string ignoredKeywords = EWOMS_GET_PARAM(TypeTag, std::string, IgnoreKeywords);
|
||||
bool eclStrictParsing = EWOMS_GET_PARAM(TypeTag, bool, EclStrictParsing);
|
||||
parseContext_ = createParseContext(ignoredKeywords, eclStrictParsing);
|
||||
}
|
||||
|
||||
std::optional<int> outputInterval;
|
||||
ignoredKeywords_ = EWOMS_GET_PARAM(TypeTag, std::string, IgnoreKeywords);
|
||||
eclStrictParsing_ = EWOMS_GET_PARAM(TypeTag, bool, EclStrictParsing);
|
||||
int output_param = EWOMS_GET_PARAM(TypeTag, int, EclOutputInterval);
|
||||
if (output_param >= 0)
|
||||
outputInterval = output_param;
|
||||
outputInterval_ = output_param;
|
||||
useMultisegmentWell_ = EWOMS_GET_PARAM(TypeTag, bool, UseMultisegmentWell);
|
||||
enableExperiments_ = enableExperiments;
|
||||
|
||||
readDeck(myRank, fileName, deck_, eclState_, eclSchedule_,
|
||||
eclSummaryConfig_, std::move(errorGuard), python,
|
||||
std::move(parseContext_), /* initFromRestart = */ false,
|
||||
/* checkDeck = */ enableExperiments, outputInterval);
|
||||
|
||||
this->summaryState_ = std::make_unique<SummaryState>( TimeService::from_time_t(this->eclSchedule_->getStartTime() ));
|
||||
this->udqState_ = std::make_unique<UDQState>( this->eclSchedule_->getUDQConfig(0).params().undefinedValue() );
|
||||
this->actionState_ = std::make_unique<Action::State>() ;
|
||||
|
||||
// Initialize parallelWells with all local wells
|
||||
const auto& schedule_wells = schedule().getWellsatEnd();
|
||||
parallelWells_.reserve(schedule_wells.size());
|
||||
|
||||
for (const auto& well: schedule_wells)
|
||||
{
|
||||
parallelWells_.emplace_back(well.name(), true);
|
||||
}
|
||||
std::sort(parallelWells_.begin(), parallelWells_.end());
|
||||
|
||||
// Check whether allowing distribute wells makes sense
|
||||
if (enableDistributedWells() )
|
||||
{
|
||||
int hasMsWell = false;
|
||||
|
||||
if (EWOMS_GET_PARAM(TypeTag, bool, UseMultisegmentWell))
|
||||
{
|
||||
if (myRank == 0)
|
||||
{
|
||||
const auto& wells = this->schedule().getWellsatEnd();
|
||||
for ( const auto& well: wells)
|
||||
{
|
||||
hasMsWell = hasMsWell || well.isMultiSegment();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 7)
|
||||
const auto& comm = Dune::MPIHelper::getCommunication();
|
||||
#else
|
||||
const auto& comm = Dune::MPIHelper::getCollectiveCommunication();
|
||||
#endif
|
||||
hasMsWell = comm.max(hasMsWell);
|
||||
|
||||
if (hasMsWell)
|
||||
{
|
||||
if (myRank == 0)
|
||||
{
|
||||
std::string message =
|
||||
std::string("Option --allow-distributed-wells=true is only allowed if model\n")
|
||||
+ "only has only standard wells. You need to provide option \n"
|
||||
+ " with --enable-multisegement-wells=false to treat existing \n"
|
||||
+ "multisegment wells as standard wells.";
|
||||
OpmLog::error(message);
|
||||
}
|
||||
comm.barrier();
|
||||
OPM_THROW(std::invalid_argument, "All wells need to be standard wells!");
|
||||
}
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the parsed ECL deck.
|
||||
*/
|
||||
const Deck& deck() const
|
||||
{ return *deck_; }
|
||||
|
||||
Deck& deck()
|
||||
{ return *deck_; }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the internalized ECL deck.
|
||||
*/
|
||||
const EclipseState& eclState() const
|
||||
{ return *eclState_; }
|
||||
|
||||
EclipseState& eclState()
|
||||
{ return *eclState_; }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the object that managages the ECL schedule.
|
||||
*/
|
||||
const Schedule& schedule() const
|
||||
{ return *eclSchedule_; }
|
||||
|
||||
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(std::unique_ptr<Schedule> schedule)
|
||||
{ externalEclSchedule_ = std::move(schedule); }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the object that determines which quantities ought to
|
||||
* be put into the ECL summary output.
|
||||
*/
|
||||
const 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(std::unique_ptr<SummaryConfig> summaryConfig)
|
||||
{ externalEclSummaryConfig_ = std::move(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.
|
||||
*/
|
||||
SummaryState& summaryState()
|
||||
{ return *summaryState_; }
|
||||
|
||||
const SummaryState& summaryState() const
|
||||
{ return *summaryState_; }
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Returns the action state
|
||||
*
|
||||
* The ActionState keeps track of how many times the various actions have run.
|
||||
*/
|
||||
Action::State& actionState()
|
||||
{ return *actionState_; }
|
||||
|
||||
const Action::State& actionState() const
|
||||
{ return *actionState_; }
|
||||
|
||||
/*!
|
||||
* \brief Returns the udq state
|
||||
*
|
||||
* The UDQState keeps track of the result of UDQ evaluations.
|
||||
*/
|
||||
UDQState& udqState()
|
||||
{ return *udqState_; }
|
||||
|
||||
const UDQState& udqState() const
|
||||
{ return *udqState_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter deciding the edge-weight strategy of the load balancer.
|
||||
*/
|
||||
Dune::EdgeWeightMethod edgeWeightsMethod() const
|
||||
{ return edgeWeightsMethod_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that decide if cells owned by rank are ordered before ghost cells.
|
||||
*/
|
||||
bool ownersFirst() const
|
||||
{ return ownersFirst_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that decides if partitioning for parallel runs
|
||||
* should be performed on a single process only.
|
||||
*/
|
||||
bool serialPartitioning() const
|
||||
{ return serialPartitioning_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that sets the zoltan imbalance tolarance.
|
||||
*/
|
||||
double zoltanImbalanceTol() const
|
||||
{ return zoltanImbalanceTol_; }
|
||||
|
||||
/*!
|
||||
* \brief Whether perforations of a well might be distributed.
|
||||
*/
|
||||
bool enableDistributedWells() const
|
||||
{ return enableDistributedWells_; }
|
||||
|
||||
/*!
|
||||
* \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_; }
|
||||
|
||||
const CartesianIndexMapper& cartesianMapper() const
|
||||
{ return asImp_().cartesianIndexMapper(); }
|
||||
@ -716,15 +332,6 @@ public:
|
||||
{ return asImp_().equilCartesianIndexMapper().cartesianCoordinate(cellIdx, ijk); }
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Returns vector with name and whether the has local perforated cells
|
||||
* for all wells.
|
||||
*
|
||||
* Will only have usable values for CpGrid.
|
||||
*/
|
||||
const std::vector<std::pair<std::string,bool>>& parallelWells() const
|
||||
{ return parallelWells_; }
|
||||
|
||||
/*!
|
||||
* \brief Get the cell centroids for a distributed grid.
|
||||
*
|
||||
@ -789,6 +396,7 @@ protected:
|
||||
asImp_().updateOutputDir_(outputDir, enableEclCompatFile);
|
||||
asImp_().finalizeInit_();
|
||||
}
|
||||
|
||||
void updateCartesianToCompressedMapping_()
|
||||
{
|
||||
size_t num_cells = asImp_().grid().leafGridView().size(0);
|
||||
@ -808,7 +416,7 @@ protected:
|
||||
auto elemIt = this->gridView().template begin</*codim=*/0>();
|
||||
const auto& elemEndIt = this->gridView().template end</*codim=*/0>();
|
||||
|
||||
const auto num_aqu_cells = this->eclState_->aquifer().numericalAquifers().allAquiferCells();
|
||||
const auto num_aqu_cells = this->allAquiferCells();
|
||||
|
||||
for (; elemIt != elemEndIt; ++elemIt) {
|
||||
const Element& element = *elemIt;
|
||||
@ -827,17 +435,7 @@ protected:
|
||||
}
|
||||
void updateCellThickness_()
|
||||
{
|
||||
bool drsdtcon = false;
|
||||
auto schIt = this->schedule().begin();
|
||||
const auto& schEndIt = this->schedule().end();
|
||||
for(; schIt != schEndIt; ++schIt) {
|
||||
const auto& oilVaporizationControl = schIt->oilvap();
|
||||
if(oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::DRSDTCON) {
|
||||
drsdtcon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!drsdtcon)
|
||||
if (!this->drsdtconEnabled())
|
||||
return;
|
||||
|
||||
ElementMapper elemMapper(this->gridView(), Dune::mcmgElementLayout());
|
||||
@ -859,35 +457,6 @@ protected:
|
||||
|
||||
|
||||
private:
|
||||
void updateOutputDir_(std::string outputDir,
|
||||
bool enableEclCompatFile)
|
||||
{
|
||||
// update the location for output
|
||||
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 (!filesystem::is_directory(outputDir)) {
|
||||
try {
|
||||
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(enableEclCompatFile);
|
||||
}
|
||||
|
||||
|
||||
// computed from averaging cell corner depths
|
||||
Scalar cellCenterDepth(const Element& element) const
|
||||
{
|
||||
@ -909,38 +478,6 @@ private:
|
||||
const Implementation& asImp_() const
|
||||
{ return *static_cast<const Implementation*>(this); }
|
||||
|
||||
std::string caseName_;
|
||||
|
||||
static double externalSetupTime_;
|
||||
|
||||
static std::unique_ptr<ParseContext> externalParseContext_;
|
||||
static std::unique_ptr<ErrorGuard> externalErrorGuard_;
|
||||
static std::unique_ptr<Deck> externalDeck_;
|
||||
static bool externalDeckSet_;
|
||||
static std::unique_ptr<EclipseState> externalEclState_;
|
||||
static std::unique_ptr<Schedule> externalEclSchedule_;
|
||||
static std::unique_ptr<SummaryConfig> externalEclSummaryConfig_;
|
||||
|
||||
std::unique_ptr<SummaryState> summaryState_;
|
||||
std::unique_ptr<Action::State> actionState_;
|
||||
std::unique_ptr<UDQState> udqState_;
|
||||
|
||||
// these attributes point either to the internal or to the external version of the
|
||||
// parser objects.
|
||||
std::unique_ptr<ParseContext> parseContext_;
|
||||
std::unique_ptr<ErrorGuard> errorGuard_;
|
||||
std::unique_ptr<Deck> deck_;
|
||||
std::unique_ptr<EclipseState> eclState_;
|
||||
std::unique_ptr<Schedule> eclSchedule_;
|
||||
std::unique_ptr<SummaryConfig> eclSummaryConfig_;
|
||||
std::shared_ptr<Python> python = std::make_shared<Python>();
|
||||
|
||||
Dune::EdgeWeightMethod edgeWeightsMethod_;
|
||||
bool ownersFirst_;
|
||||
bool serialPartitioning_;
|
||||
double zoltanImbalanceTol_;
|
||||
bool enableDistributedWells_;
|
||||
|
||||
protected:
|
||||
/*! \brief The cell centroids after loadbalance was called.
|
||||
* Empty otherwise. Used by EclTransmissibilty.
|
||||
@ -956,44 +493,11 @@ protected:
|
||||
*/
|
||||
std::vector<Scalar> cellCenterDepth_;
|
||||
|
||||
/*! \brief Cell thichness
|
||||
/*! \brief Cell thickness
|
||||
*/
|
||||
std::vector<Scalar> cellThickness_;
|
||||
|
||||
/*! \brief information about wells in parallel
|
||||
*
|
||||
* For each well in the model there is an entry with its name
|
||||
* and a boolean indicating whether it perforates local cells.
|
||||
*/
|
||||
std::vector<std::pair<std::string,bool>> parallelWells_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
template <class TypeTag>
|
||||
double EclBaseVanguard<TypeTag>::externalSetupTime_ = 0.0;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<ParseContext> EclBaseVanguard<TypeTag>::externalParseContext_ = nullptr;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<ErrorGuard> EclBaseVanguard<TypeTag>::externalErrorGuard_ = nullptr;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<Deck> EclBaseVanguard<TypeTag>::externalDeck_ = nullptr;
|
||||
|
||||
template <class TypeTag>
|
||||
bool EclBaseVanguard<TypeTag>::externalDeckSet_ = false;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<EclipseState> EclBaseVanguard<TypeTag>::externalEclState_;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<Schedule> EclBaseVanguard<TypeTag>::externalEclSchedule_ = nullptr;
|
||||
|
||||
template <class TypeTag>
|
||||
std::unique_ptr<SummaryConfig> EclBaseVanguard<TypeTag>::externalEclSummaryConfig_ = nullptr;
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
||||
|
336
ebos/eclgenericvanguard.cc
Normal file
336
ebos/eclgenericvanguard.cc
Normal file
@ -0,0 +1,336 @@
|
||||
// -*- 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <ebos/eclgenericvanguard.hh>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <opm/common/utility/FileSystem.hpp>
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Aquifer/NumericalAquifer/NumericalAquiferCell.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/State.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Python/Python.hpp>
|
||||
#include <opm/simulators/utils/readDeck.hpp>
|
||||
|
||||
#include <dune/common/version.hh>
|
||||
#include <dune/common/parallel/mpihelper.hh>
|
||||
|
||||
#if HAVE_MPI
|
||||
#include <mpi.h>
|
||||
#endif // HAVE_MPI
|
||||
|
||||
namespace Opm {
|
||||
|
||||
double EclGenericVanguard::externalSetupTime_ = 0.0;
|
||||
std::unique_ptr<ParseContext> EclGenericVanguard::externalParseContext_ = nullptr;
|
||||
std::unique_ptr<ErrorGuard> EclGenericVanguard::externalErrorGuard_ = nullptr;
|
||||
std::unique_ptr<Deck> EclGenericVanguard::externalDeck_;
|
||||
bool EclGenericVanguard::externalDeckSet_ = false;
|
||||
std::unique_ptr<EclipseState> EclGenericVanguard::externalEclState_;
|
||||
std::unique_ptr<Schedule> EclGenericVanguard::externalEclSchedule_ = nullptr;
|
||||
std::unique_ptr<SummaryConfig> EclGenericVanguard::externalEclSummaryConfig_ = nullptr;
|
||||
|
||||
EclGenericVanguard::EclGenericVanguard()
|
||||
: python(std::make_shared<Python>())
|
||||
{
|
||||
}
|
||||
|
||||
EclGenericVanguard::~EclGenericVanguard() = default;
|
||||
|
||||
void EclGenericVanguard::setExternalParseContext(std::unique_ptr<ParseContext> parseContext)
|
||||
{
|
||||
externalParseContext_ = std::move(parseContext);
|
||||
}
|
||||
|
||||
void EclGenericVanguard::setExternalErrorGuard(std::unique_ptr<ErrorGuard> errorGuard)
|
||||
{
|
||||
externalErrorGuard_ = std::move(errorGuard);
|
||||
}
|
||||
|
||||
void EclGenericVanguard::setExternalSchedule(std::unique_ptr<Schedule> schedule)
|
||||
{
|
||||
externalEclSchedule_ = std::move(schedule);
|
||||
}
|
||||
|
||||
void EclGenericVanguard::setExternalSummaryConfig(std::unique_ptr<SummaryConfig> summaryConfig)
|
||||
{
|
||||
externalEclSummaryConfig_ = std::move(summaryConfig);
|
||||
}
|
||||
|
||||
void EclGenericVanguard::setExternalDeck(std::unique_ptr<Deck> deck)
|
||||
{
|
||||
externalDeck_ = std::move(deck);
|
||||
externalDeckSet_ = true;
|
||||
}
|
||||
|
||||
void EclGenericVanguard::setExternalEclState(std::unique_ptr<EclipseState> eclState)
|
||||
{
|
||||
externalEclState_ = std::move(eclState);
|
||||
}
|
||||
|
||||
std::string EclGenericVanguard::canonicalDeckPath(const std::string& caseName)
|
||||
{
|
||||
const auto fileExists = [](const filesystem::path& f) -> bool
|
||||
{
|
||||
if (!filesystem::exists(f))
|
||||
return false;
|
||||
|
||||
if (filesystem::is_regular_file(f))
|
||||
return true;
|
||||
|
||||
return filesystem::is_symlink(f) && filesystem::is_regular_file(filesystem::read_symlink(f));
|
||||
};
|
||||
|
||||
auto simcase = filesystem::path(caseName);
|
||||
if (fileExists(simcase))
|
||||
return simcase.string();
|
||||
|
||||
for (const auto& ext : { std::string("data"), std::string("DATA") }) {
|
||||
if (fileExists(simcase.replace_extension(ext)))
|
||||
return simcase.string();
|
||||
}
|
||||
|
||||
throw std::invalid_argument("Cannot find input case '"+caseName+"'");
|
||||
}
|
||||
|
||||
std::unique_ptr<ParseContext> EclGenericVanguard::createParseContext(const std::string& ignoredKeywords,
|
||||
bool eclStrictParsing)
|
||||
{
|
||||
typedef std::pair<std::string, InputError::Action> ParseModePair;
|
||||
typedef std::vector<ParseModePair> ParseModePairs;
|
||||
ParseModePairs tmp;
|
||||
tmp.emplace_back(ParseContext::PARSE_RANDOM_SLASH, InputError::IGNORE);
|
||||
tmp.emplace_back(ParseContext::PARSE_MISSING_DIMS_KEYWORD, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::SUMMARY_UNKNOWN_WELL, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::SUMMARY_UNKNOWN_GROUP, InputError::WARN);
|
||||
tmp.emplace_back(ParseContext::PARSE_EXTRA_RECORDS, InputError::WARN);
|
||||
|
||||
auto parseContext = std::make_unique<ParseContext>(tmp);
|
||||
|
||||
if (!ignoredKeywords.empty()) {
|
||||
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 (eclStrictParsing)
|
||||
parseContext->update(InputError::DELAYED_EXIT1);
|
||||
|
||||
return parseContext;
|
||||
}
|
||||
|
||||
void EclGenericVanguard::updateOutputDir_(std::string outputDir,
|
||||
bool enableEclCompatFile)
|
||||
{
|
||||
// update the location for output
|
||||
auto& ioConfig = eclState_->getIOConfig();
|
||||
if (outputDir.empty())
|
||||
// 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 (!filesystem::is_directory(outputDir)) {
|
||||
try {
|
||||
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(enableEclCompatFile);
|
||||
}
|
||||
|
||||
void EclGenericVanguard::init()
|
||||
{
|
||||
int myRank = 0;
|
||||
|
||||
#if HAVE_MPI
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
|
||||
#endif
|
||||
|
||||
// Make proper case name.
|
||||
{
|
||||
if (fileName_.empty())
|
||||
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_);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
std::unique_ptr<ErrorGuard> errorGuard = nullptr;
|
||||
|
||||
// Check that we are in one of the known configurations for external variables
|
||||
// and move them to internal
|
||||
if (externalDeck_)
|
||||
{
|
||||
deck_ = std::move(externalDeck_);
|
||||
|
||||
if (externalParseContext_ && externalErrorGuard_ )
|
||||
{
|
||||
parseContext_ = std::move(externalParseContext_);
|
||||
errorGuard = std::move(externalErrorGuard_);
|
||||
}
|
||||
else if(externalEclState_ && externalEclSchedule_ && externalEclSummaryConfig_)
|
||||
{
|
||||
eclState_ = std::move(externalEclState_);
|
||||
eclSchedule_ = std::move(externalEclSchedule_);
|
||||
eclSummaryConfig_ = std::move(externalEclSummaryConfig_);
|
||||
}
|
||||
else
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Either parse context and error guard or ECL state, schedule, and summary config need to be"
|
||||
<< " set externally.");
|
||||
}
|
||||
}
|
||||
else if (externalParseContext_)
|
||||
{
|
||||
parseContext_ = std::move(externalParseContext_);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseContext_ = createParseContext(ignoredKeywords_, eclStrictParsing_);
|
||||
}
|
||||
|
||||
readDeck(myRank, fileName_, deck_, eclState_, eclSchedule_,
|
||||
eclSummaryConfig_, std::move(errorGuard), python,
|
||||
std::move(parseContext_), /* initFromRestart = */ false,
|
||||
/* checkDeck = */ enableExperiments_, outputInterval_);
|
||||
|
||||
this->summaryState_ = std::make_unique<SummaryState>( TimeService::from_time_t(this->eclSchedule_->getStartTime() ));
|
||||
this->udqState_ = std::make_unique<UDQState>( this->eclSchedule_->getUDQConfig(0).params().undefinedValue() );
|
||||
this->actionState_ = std::make_unique<Action::State>() ;
|
||||
|
||||
// Initialize parallelWells with all local wells
|
||||
const auto& schedule_wells = schedule().getWellsatEnd();
|
||||
parallelWells_.reserve(schedule_wells.size());
|
||||
|
||||
for (const auto& well: schedule_wells)
|
||||
{
|
||||
parallelWells_.emplace_back(well.name(), true);
|
||||
}
|
||||
std::sort(parallelWells_.begin(), parallelWells_.end());
|
||||
|
||||
// Check whether allowing distribute wells makes sense
|
||||
if (enableDistributedWells() )
|
||||
{
|
||||
int hasMsWell = false;
|
||||
|
||||
if (useMultisegmentWell_)
|
||||
{
|
||||
if (myRank == 0)
|
||||
{
|
||||
const auto& wells = this->schedule().getWellsatEnd();
|
||||
for ( const auto& well: wells)
|
||||
{
|
||||
hasMsWell = hasMsWell || well.isMultiSegment();
|
||||
}
|
||||
}
|
||||
}
|
||||
#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 7)
|
||||
const auto& comm = Dune::MPIHelper::getCommunication();
|
||||
#else
|
||||
const auto& comm = Dune::MPIHelper::getCollectiveCommunication();
|
||||
#endif
|
||||
hasMsWell = comm.max(hasMsWell);
|
||||
|
||||
if (hasMsWell)
|
||||
{
|
||||
if (myRank == 0)
|
||||
{
|
||||
std::string message =
|
||||
std::string("Option --allow-distributed-wells=true is only allowed if model\n")
|
||||
+ "only has only standard wells. You need to provide option \n"
|
||||
+ " with --enable-multisegement-wells=false to treat existing \n"
|
||||
+ "multisegment wells as standard wells.";
|
||||
OpmLog::error(message);
|
||||
}
|
||||
comm.barrier();
|
||||
OPM_THROW(std::invalid_argument, "All wells need to be standard wells!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EclGenericVanguard::drsdtconEnabled() const
|
||||
{
|
||||
for (const auto& schIt : this->schedule()) {
|
||||
const auto& oilVaporizationControl = schIt.oilvap();
|
||||
if (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::DRSDTCON) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unordered_map<size_t, const NumericalAquiferCell*> EclGenericVanguard::allAquiferCells() const
|
||||
{
|
||||
return this->eclState_->aquifer().numericalAquifers().allAquiferCells();
|
||||
}
|
||||
|
||||
} // namespace Opm
|
318
ebos/eclgenericvanguard.hh
Normal file
318
ebos/eclgenericvanguard.hh
Normal file
@ -0,0 +1,318 @@
|
||||
// -*- 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_GENERIC_VANGUARD_HH
|
||||
#define EWOMS_ECL_GENERIC_VANGUARD_HH
|
||||
|
||||
#include <opm/grid/common/GridEnums.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace Action { class State; }
|
||||
class Deck;
|
||||
class EclipseState;
|
||||
class ErrorGuard;
|
||||
class NumericalAquiferCell;
|
||||
class ParseContext;
|
||||
class Schedule;
|
||||
class Python;
|
||||
class SummaryConfig;
|
||||
class SummaryState;
|
||||
class UDQState;
|
||||
|
||||
class EclGenericVanguard {
|
||||
public:
|
||||
using ParallelWellStruct = std::vector<std::pair<std::string,bool>>;
|
||||
|
||||
/*!
|
||||
* \brief Constructor.
|
||||
* \details Needs to be in compile unit.
|
||||
*/
|
||||
EclGenericVanguard();
|
||||
|
||||
/*!
|
||||
* \brief Destructor.
|
||||
* \details Empty, but needs to be in compile unit.
|
||||
*/
|
||||
~EclGenericVanguard();
|
||||
|
||||
/*!
|
||||
* \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 std::string canonicalDeckPath(const std::string& caseName);
|
||||
|
||||
/*!
|
||||
* \brief Creates an Opm::parseContext object assuming that the parameters are ready.
|
||||
*/
|
||||
static std::unique_ptr<ParseContext> createParseContext(const std::string& ignoredKeywords,
|
||||
bool eclStrictParsing);
|
||||
|
||||
/*!
|
||||
* \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(double t)
|
||||
{ externalSetupTime_ = t; }
|
||||
|
||||
/*!
|
||||
* \brief Returns the wall time required to set up the simulator before it was born.
|
||||
*/
|
||||
static double 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(std::unique_ptr<ParseContext> 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(std::unique_ptr<ErrorGuard> 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(std::unique_ptr<Deck> deck);
|
||||
|
||||
/*!
|
||||
* \brief Set the Opm::EclipseState object which ought to be used when the simulator
|
||||
* vanguard is instantiated.
|
||||
*/
|
||||
static void setExternalEclState(std::unique_ptr<EclipseState> eclState);
|
||||
|
||||
/*!
|
||||
* \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(std::unique_ptr<Schedule> schedule);
|
||||
|
||||
/*!
|
||||
* \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(std::unique_ptr<SummaryConfig> summaryConfig);
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the parsed ECL deck.
|
||||
*/
|
||||
const Deck& deck() const
|
||||
{ return *deck_; }
|
||||
|
||||
Deck& deck()
|
||||
{ return *deck_; }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the internalized ECL deck.
|
||||
*/
|
||||
const EclipseState& eclState() const
|
||||
{ return *eclState_; }
|
||||
|
||||
EclipseState& eclState()
|
||||
{ return *eclState_; }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the object that managages the ECL schedule.
|
||||
*/
|
||||
const Schedule& schedule() const
|
||||
{ return *eclSchedule_; }
|
||||
|
||||
Schedule& schedule()
|
||||
{ return *eclSchedule_; }
|
||||
|
||||
/*!
|
||||
* \brief Return a reference to the object that determines which quantities ought to
|
||||
* be put into the ECL summary output.
|
||||
*/
|
||||
const SummaryConfig& summaryConfig() const
|
||||
{ return *eclSummaryConfig_; }
|
||||
|
||||
/*!
|
||||
* \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.
|
||||
*/
|
||||
SummaryState& summaryState()
|
||||
{ return *summaryState_; }
|
||||
|
||||
const SummaryState& summaryState() const
|
||||
{ return *summaryState_; }
|
||||
|
||||
/*!
|
||||
* \brief Returns the action state
|
||||
*
|
||||
* The ActionState keeps track of how many times the various actions have run.
|
||||
*/
|
||||
Action::State& actionState()
|
||||
{ return *actionState_; }
|
||||
|
||||
const Action::State& actionState() const
|
||||
{ return *actionState_; }
|
||||
|
||||
/*!
|
||||
* \brief Returns the udq state
|
||||
*
|
||||
* The UDQState keeps track of the result of UDQ evaluations.
|
||||
*/
|
||||
UDQState& udqState()
|
||||
{ return *udqState_; }
|
||||
|
||||
const UDQState& udqState() const
|
||||
{ return *udqState_; }
|
||||
|
||||
/*!
|
||||
* \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 Parameter deciding the edge-weight strategy of the load balancer.
|
||||
*/
|
||||
Dune::EdgeWeightMethod edgeWeightsMethod() const
|
||||
{ return edgeWeightsMethod_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that decide if cells owned by rank are ordered before ghost cells.
|
||||
*/
|
||||
bool ownersFirst() const
|
||||
{ return ownersFirst_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that decides if partitioning for parallel runs
|
||||
* should be performed on a single process only.
|
||||
*/
|
||||
bool serialPartitioning() const
|
||||
{ return serialPartitioning_; }
|
||||
|
||||
/*!
|
||||
* \brief Parameter that sets the zoltan imbalance tolarance.
|
||||
*/
|
||||
double zoltanImbalanceTol() const
|
||||
{ return zoltanImbalanceTol_; }
|
||||
|
||||
/*!
|
||||
* \brief Whether perforations of a well might be distributed.
|
||||
*/
|
||||
bool enableDistributedWells() const
|
||||
{ return enableDistributedWells_; }
|
||||
|
||||
/*!
|
||||
* \brief Returns vector with name and whether the has local perforated cells
|
||||
* for all wells.
|
||||
*
|
||||
* Will only have usable values for CpGrid.
|
||||
*/
|
||||
const std::vector<std::pair<std::string,bool>>& parallelWells() const
|
||||
{ return parallelWells_; }
|
||||
|
||||
protected:
|
||||
void updateOutputDir_(std::string outputDir,
|
||||
bool enableEclCompatFile);
|
||||
|
||||
bool drsdtconEnabled() const;
|
||||
|
||||
std::unordered_map<std::size_t, const NumericalAquiferCell*> allAquiferCells() const;
|
||||
|
||||
void init();
|
||||
|
||||
static double externalSetupTime_;
|
||||
static std::unique_ptr<ParseContext> externalParseContext_;
|
||||
static std::unique_ptr<ErrorGuard> externalErrorGuard_;
|
||||
static std::unique_ptr<Deck> externalDeck_;
|
||||
static bool externalDeckSet_;
|
||||
static std::unique_ptr<EclipseState> externalEclState_;
|
||||
static std::unique_ptr<Schedule> externalEclSchedule_;
|
||||
static std::unique_ptr<SummaryConfig> externalEclSummaryConfig_;
|
||||
|
||||
std::string caseName_;
|
||||
std::string fileName_;
|
||||
Dune::EdgeWeightMethod edgeWeightsMethod_;
|
||||
bool ownersFirst_;
|
||||
bool serialPartitioning_;
|
||||
double zoltanImbalanceTol_;
|
||||
bool enableDistributedWells_;
|
||||
std::string ignoredKeywords_;
|
||||
bool eclStrictParsing_;
|
||||
std::optional<int> outputInterval_;
|
||||
bool useMultisegmentWell_;
|
||||
bool enableExperiments_;
|
||||
|
||||
std::unique_ptr<SummaryState> summaryState_;
|
||||
std::unique_ptr<Action::State> actionState_;
|
||||
std::unique_ptr<UDQState> udqState_;
|
||||
|
||||
// these attributes point either to the internal or to the external version of the
|
||||
// parser objects.
|
||||
std::unique_ptr<ParseContext> parseContext_;
|
||||
std::unique_ptr<ErrorGuard> errorGuard_;
|
||||
std::unique_ptr<Deck> deck_;
|
||||
std::unique_ptr<EclipseState> eclState_;
|
||||
std::unique_ptr<Schedule> eclSchedule_;
|
||||
std::unique_ptr<SummaryConfig> eclSummaryConfig_;
|
||||
std::shared_ptr<Python> python;
|
||||
|
||||
/*! \brief Information about wells in parallel
|
||||
*
|
||||
* For each well in the model there is an entry with its name
|
||||
* and a boolean indicating whether it perforates local cells.
|
||||
*/
|
||||
ParallelWellStruct parallelWells_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif
|
@ -40,6 +40,7 @@
|
||||
#include <opm/material/common/Valgrind.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/output/data/Cells.hpp>
|
||||
#include <opm/output/eclipse/EclipseIO.hpp>
|
||||
|
@ -40,7 +40,9 @@
|
||||
# endif
|
||||
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/checkDeck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ArrayDimChecker.hpp>
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/parser/eclipse/Python/Python.hpp>
|
||||
|
Loading…
Reference in New Issue
Block a user