mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
introduced computeWellTemperature() to be called at each timestep
This commit is contained in:
@@ -108,6 +108,7 @@ namespace Opm {
|
|||||||
static const int solventSaturationIdx = Indices::solventSaturationIdx;
|
static const int solventSaturationIdx = Indices::solventSaturationIdx;
|
||||||
static constexpr bool has_solvent_ = getPropValue<TypeTag, Properties::EnableSolvent>();
|
static constexpr bool has_solvent_ = getPropValue<TypeTag, Properties::EnableSolvent>();
|
||||||
static constexpr bool has_polymer_ = getPropValue<TypeTag, Properties::EnablePolymer>();
|
static constexpr bool has_polymer_ = getPropValue<TypeTag, Properties::EnablePolymer>();
|
||||||
|
static constexpr bool has_energy_ = getPropValue<TypeTag, Properties::EnableEnergy>();
|
||||||
|
|
||||||
// TODO: where we should put these types, WellInterface or Well Model?
|
// TODO: where we should put these types, WellInterface or Well Model?
|
||||||
// or there is some other strategy, like TypeTag
|
// or there is some other strategy, like TypeTag
|
||||||
@@ -509,6 +510,8 @@ namespace Opm {
|
|||||||
void assignGroupGuideRates(const Group& group,
|
void assignGroupGuideRates(const Group& group,
|
||||||
const std::unordered_map<std::string, data::GroupGuideRates>& groupGuideRates,
|
const std::unordered_map<std::string, data::GroupGuideRates>& groupGuideRates,
|
||||||
data::GroupData& gdata) const;
|
data::GroupData& gdata) const;
|
||||||
|
|
||||||
|
void computeWellTemperature();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -540,6 +540,9 @@ namespace Opm {
|
|||||||
if (terminal_output_) {
|
if (terminal_output_) {
|
||||||
global_deferredLogger.logMessages();
|
global_deferredLogger.logMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//reporting output temperatures
|
||||||
|
this->computeWellTemperature();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -703,12 +706,6 @@ namespace Opm {
|
|||||||
const SummaryState& summaryState)
|
const SummaryState& summaryState)
|
||||||
{
|
{
|
||||||
std::vector<double> cellPressures(this->local_num_cells_, 0.0);
|
std::vector<double> cellPressures(this->local_num_cells_, 0.0);
|
||||||
std::vector<double> cellTemperatures(this->local_num_cells_, 0.0);
|
|
||||||
const int np = numPhases();
|
|
||||||
std::vector<std::vector<double>> cellInternalEnergy(this->local_num_cells_, std::vector<double>(np));
|
|
||||||
std::vector<std::vector<double>> cellBinv(this->local_num_cells_, std::vector<double>(np));
|
|
||||||
std::vector<std::vector<double>> cellDensity(this->local_num_cells_, std::vector<double>(np));
|
|
||||||
|
|
||||||
ElementContext elemCtx(ebosSimulator_);
|
ElementContext elemCtx(ebosSimulator_);
|
||||||
|
|
||||||
const auto& gridView = ebosSimulator_.vanguard().gridView();
|
const auto& gridView = ebosSimulator_.vanguard().gridView();
|
||||||
@@ -725,16 +722,6 @@ namespace Opm {
|
|||||||
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
|
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
|
||||||
|
|
||||||
const auto& fs = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0).fluidState();
|
const auto& fs = elemCtx.intensiveQuantities(/*spaceIdx=*/0, /*timeIdx=*/0).fluidState();
|
||||||
|
|
||||||
cellTemperatures[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)] = fs.temperature(/*phaseIdx*/0).value();
|
|
||||||
|
|
||||||
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx)
|
|
||||||
{
|
|
||||||
cellInternalEnergy[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)][phaseIdx] = fs.enthalpy(phaseIdx).value() - fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
|
|
||||||
cellBinv[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)][phaseIdx] = fs.invB(phaseIdx).value();
|
|
||||||
cellDensity[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)][phaseIdx] = fs.density(phaseIdx).value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy of get perfpressure in Standard well except for value
|
// copy of get perfpressure in Standard well except for value
|
||||||
double& perf_pressure = cellPressures[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)];
|
double& perf_pressure = cellPressures[elemCtx.globalSpaceIndex(/*spaceIdx=*/0, /*timeIdx=*/0)];
|
||||||
if (Indices::oilEnabled) {
|
if (Indices::oilEnabled) {
|
||||||
@@ -746,7 +733,7 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
well_state_.init(cellPressures, cellTemperatures, cellInternalEnergy, cellBinv, cellDensity, schedule(), wells_ecl_, local_parallel_well_info_, timeStepIdx,
|
well_state_.init(cellPressures, schedule(), wells_ecl_, local_parallel_well_info_, timeStepIdx,
|
||||||
&previous_well_state_, phase_usage_, well_perf_data_,
|
&previous_well_state_, phase_usage_, well_perf_data_,
|
||||||
summaryState, globalNumWells);
|
summaryState, globalNumWells);
|
||||||
}
|
}
|
||||||
@@ -3081,4 +3068,57 @@ namespace Opm {
|
|||||||
prod = xgr.production;
|
prod = xgr.production;
|
||||||
inj = xgr.injection;
|
inj = xgr.injection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TypeTag>
|
||||||
|
void
|
||||||
|
BlackoilWellModel<TypeTag>::
|
||||||
|
computeWellTemperature()
|
||||||
|
{
|
||||||
|
if (!has_energy_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int np = numPhases();
|
||||||
|
double cellInternalEnergy;
|
||||||
|
double cellBinv;
|
||||||
|
double cellDensity;
|
||||||
|
double perfPhaseRate;
|
||||||
|
const int nw = numLocalWells();
|
||||||
|
for (auto wellID = 0*nw; wellID < nw; ++wellID) {
|
||||||
|
const Well& well = wells_ecl_[wellID];
|
||||||
|
if (well.isInjector())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int connpos = 0;
|
||||||
|
for (int i = 0; i < wellID; ++i) {
|
||||||
|
connpos += well_perf_data_[i].size();
|
||||||
|
}
|
||||||
|
connpos *= np;
|
||||||
|
double weighted_temperature = 0.0;
|
||||||
|
double total_weight = 0.0;
|
||||||
|
|
||||||
|
auto& well_info = *local_parallel_well_info_[wellID];
|
||||||
|
const int num_perf_this_well = well_info.communication().sum(well_perf_data_[wellID].size());
|
||||||
|
|
||||||
|
for (int perf = 0; perf < num_perf_this_well; ++perf) {
|
||||||
|
const int cell_idx = well_perf_data_[wellID][perf].cell_index;
|
||||||
|
const auto& intQuants = *(ebosSimulator_.model().cachedIntensiveQuantities(cell_idx, /*timeIdx=*/0));
|
||||||
|
const auto& fs = intQuants.fluidState();
|
||||||
|
|
||||||
|
double cellTemperatures = fs.temperature(/*phaseIdx*/0).value();
|
||||||
|
double weight_factor = 0.0;
|
||||||
|
for (int phaseIdx = 0; phaseIdx < np; ++phaseIdx) {
|
||||||
|
cellInternalEnergy = fs.enthalpy(phaseIdx).value() - fs.pressure(phaseIdx).value() / fs.density(phaseIdx).value();
|
||||||
|
cellBinv = fs.invB(phaseIdx).value();
|
||||||
|
cellDensity = fs.density(phaseIdx).value();
|
||||||
|
perfPhaseRate = well_state_.perfPhaseRates()[connpos + perf*np + phaseIdx ];
|
||||||
|
weight_factor += cellDensity * perfPhaseRate/cellBinv * cellInternalEnergy/cellTemperatures;
|
||||||
|
}
|
||||||
|
total_weight += weight_factor;
|
||||||
|
weighted_temperature += weight_factor * cellTemperatures;
|
||||||
|
}
|
||||||
|
weighted_temperature = well_info.communication().sum(weighted_temperature);
|
||||||
|
total_weight = well_info.communication().sum(total_weight);
|
||||||
|
well_state_.temperature()[wellID] = weighted_temperature/total_weight;
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
namespace Opm
|
namespace Opm
|
||||||
{
|
{
|
||||||
/// The state of a set of wells.
|
/// The state of a set of wells.
|
||||||
class WellState
|
class WellState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::array< int, 3 > mapentry_t;
|
typedef std::array< int, 3 > mapentry_t;
|
||||||
@@ -51,11 +51,6 @@ namespace Opm
|
|||||||
/// perfRates() field is filled with zero, and perfPress()
|
/// perfRates() field is filled with zero, and perfPress()
|
||||||
/// with -1e100.
|
/// with -1e100.
|
||||||
void init(const std::vector<double>& cellPressures,
|
void init(const std::vector<double>& cellPressures,
|
||||||
const std::vector<double>& cellTemperatures,
|
|
||||||
const std::vector<std::vector<double>>& cellInternalEnergy,
|
|
||||||
const std::vector<std::vector<double>>& cellBinv,
|
|
||||||
const std::vector<std::vector<double>>& cellDensity,
|
|
||||||
const std::vector<double>& perforationRates,
|
|
||||||
const std::vector<Well>& wells_ecl,
|
const std::vector<Well>& wells_ecl,
|
||||||
const std::vector<ParallelWellInfo*>& parallel_well_info,
|
const std::vector<ParallelWellInfo*>& parallel_well_info,
|
||||||
const PhaseUsage& pu,
|
const PhaseUsage& pu,
|
||||||
@@ -78,13 +73,13 @@ namespace Opm
|
|||||||
bhp_.resize(nw, 0.0);
|
bhp_.resize(nw, 0.0);
|
||||||
thp_.resize(nw, 0.0);
|
thp_.resize(nw, 0.0);
|
||||||
temperature_.resize(nw, 273.15 + 15.56); // standard condition temperature
|
temperature_.resize(nw, 273.15 + 15.56); // standard condition temperature
|
||||||
wellrates_.resize(nw * np, 0.0);
|
wellrates_.resize(nw * np, 0.0);
|
||||||
int connpos = 0;
|
int connpos = 0;
|
||||||
for (int w = 0; w < nw; ++w) {
|
for (int w = 0; w < nw; ++w) {
|
||||||
const Well& well = wells_ecl[w];
|
const Well& well = wells_ecl[w];
|
||||||
|
|
||||||
// Initialize bhp(), thp(), wellRates(), temperature().
|
// Initialize bhp(), thp(), wellRates(), temperature().
|
||||||
initSingleWell(cellPressures, cellTemperatures, cellInternalEnergy, cellBinv, cellDensity, perforationRates, w, well, *parallel_well_info[w], pu, summary_state);
|
initSingleWell(cellPressures, w, well, *parallel_well_info[w], pu, summary_state);
|
||||||
|
|
||||||
// Setup wellname -> well index mapping.
|
// Setup wellname -> well index mapping.
|
||||||
const int num_perf_this_well = well_perf_data[w].size();
|
const int num_perf_this_well = well_perf_data[w].size();
|
||||||
@@ -358,11 +353,6 @@ namespace Opm
|
|||||||
sizes.data(), displ.data(), 0);
|
sizes.data(), displ.data(), 0);
|
||||||
}
|
}
|
||||||
void initSingleWell(const std::vector<double>& cellPressures,
|
void initSingleWell(const std::vector<double>& cellPressures,
|
||||||
const std::vector<double>& cellTemperatures,
|
|
||||||
const std::vector<std::vector<double>>& cellInternalEnergy,
|
|
||||||
const std::vector<std::vector<double>>& cellBinv,
|
|
||||||
const std::vector<std::vector<double>>& cellDensity,
|
|
||||||
const std::vector<double>& perforationRates,
|
|
||||||
const int w,
|
const int w,
|
||||||
const Well& well,
|
const Well& well,
|
||||||
const ParallelWellInfo& well_info,
|
const ParallelWellInfo& well_info,
|
||||||
@@ -383,32 +373,6 @@ namespace Opm
|
|||||||
}
|
}
|
||||||
|
|
||||||
const int num_perf_this_well = well_info.communication().sum(well_perf_data_[w].size());
|
const int num_perf_this_well = well_info.communication().sum(well_perf_data_[w].size());
|
||||||
if ( well.isProducer() ) {
|
|
||||||
int sz = perforationRates.size();
|
|
||||||
int connpos = 0;
|
|
||||||
for (int i = 0; i < w; ++i){
|
|
||||||
connpos += well_perf_data_[i].size();
|
|
||||||
}
|
|
||||||
connpos *= np;
|
|
||||||
double weighted_temperature = 0.0;
|
|
||||||
double total_weight = 0.0;
|
|
||||||
if (sz > 0){
|
|
||||||
for (int i = 0; i < num_perf_this_well; ++i){
|
|
||||||
int perf_cell_index = well_perf_data_[w][i].cell_index;
|
|
||||||
double weight_factor = 0.0;
|
|
||||||
for (int p = 0; p < np; ++p) {
|
|
||||||
weight_factor += cellDensity[perf_cell_index][p] * perforationRates[connpos + i*np + p]/cellBinv[perf_cell_index][p] * cellInternalEnergy[perf_cell_index][p]/cellTemperatures[perf_cell_index];
|
|
||||||
}
|
|
||||||
total_weight += weight_factor;
|
|
||||||
weighted_temperature += weight_factor * cellTemperatures[perf_cell_index];
|
|
||||||
}
|
|
||||||
temperature_[w] = weighted_temperature/total_weight;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
temperature_[w]=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( num_perf_this_well == 0 ) {
|
if ( num_perf_this_well == 0 ) {
|
||||||
// No perforations of the well. Initialize to zero.
|
// No perforations of the well. Initialize to zero.
|
||||||
bhp_[w] = 0.;
|
bhp_[w] = 0.;
|
||||||
@@ -525,7 +489,7 @@ namespace Opm
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<std::vector<PerforationData>> well_perf_data_;
|
std::vector<std::vector<PerforationData>> well_perf_data_;
|
||||||
std::vector<ParallelWellInfo*> parallel_well_info_;
|
std::vector<ParallelWellInfo*> parallel_well_info_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|||||||
@@ -70,10 +70,6 @@ namespace Opm
|
|||||||
/// to give useful initial values to the bhp(), wellRates()
|
/// to give useful initial values to the bhp(), wellRates()
|
||||||
/// and perfPhaseRates() fields, depending on controls
|
/// and perfPhaseRates() fields, depending on controls
|
||||||
void init(const std::vector<double>& cellPressures,
|
void init(const std::vector<double>& cellPressures,
|
||||||
const std::vector<double>& cellTemperatures,
|
|
||||||
const std::vector<std::vector<double>>& cellInternalEnergy,
|
|
||||||
const std::vector<std::vector<double>>& cellBinv,
|
|
||||||
const std::vector<std::vector<double>>& cellDensity,
|
|
||||||
const Schedule& schedule,
|
const Schedule& schedule,
|
||||||
const std::vector<Well>& wells_ecl,
|
const std::vector<Well>& wells_ecl,
|
||||||
const std::vector<ParallelWellInfo*>& parallel_well_info,
|
const std::vector<ParallelWellInfo*>& parallel_well_info,
|
||||||
@@ -84,10 +80,8 @@ namespace Opm
|
|||||||
const SummaryState& summary_state,
|
const SummaryState& summary_state,
|
||||||
const int globalNumberOfWells)
|
const int globalNumberOfWells)
|
||||||
{
|
{
|
||||||
std::vector<double> perforationRates;
|
|
||||||
perforationRates = prevState->perfphaserates_;
|
|
||||||
// call init on base class
|
// call init on base class
|
||||||
BaseType :: init(cellPressures, cellTemperatures, cellInternalEnergy, cellBinv, cellDensity, perforationRates, wells_ecl, parallel_well_info, pu, well_perf_data, summary_state);
|
BaseType :: init(cellPressures, wells_ecl, parallel_well_info, pu, well_perf_data, summary_state);
|
||||||
|
|
||||||
for (const auto& winfo: parallel_well_info)
|
for (const auto& winfo: parallel_well_info)
|
||||||
{
|
{
|
||||||
@@ -185,7 +179,6 @@ namespace Opm
|
|||||||
|
|
||||||
perfRateBrine_.clear();
|
perfRateBrine_.clear();
|
||||||
perfRateBrine_.resize(nperf, 0.0);
|
perfRateBrine_.resize(nperf, 0.0);
|
||||||
|
|
||||||
// intialize wells that have been there before
|
// intialize wells that have been there before
|
||||||
// order may change so the mapping is based on the well name
|
// order may change so the mapping is based on the well name
|
||||||
if (prevState && !prevState->wellMap().empty()) {
|
if (prevState && !prevState->wellMap().empty()) {
|
||||||
@@ -355,8 +348,7 @@ namespace Opm
|
|||||||
const int globalNumWells)
|
const int globalNumWells)
|
||||||
{
|
{
|
||||||
const std::vector<double> tmp(numCells, 0.0); // <- UGLY HACK to pass the size
|
const std::vector<double> tmp(numCells, 0.0); // <- UGLY HACK to pass the size
|
||||||
std::vector<std::vector<double>> tmp1(numCells, std::vector<double>( numPhases()));// <- UGLY HACK to pass the size
|
init(tmp, schedule, wells_ecl, parallel_well_info, 0, nullptr, pu, well_perf_data, summary_state, globalNumWells);
|
||||||
init(tmp, tmp, tmp1, tmp1, tmp1, schedule, wells_ecl, parallel_well_info, 0, nullptr, pu, well_perf_data, summary_state, globalNumWells);
|
|
||||||
|
|
||||||
if (handle_ms_well) {
|
if (handle_ms_well) {
|
||||||
initWellStateMSWell(wells_ecl, pu, nullptr);
|
initWellStateMSWell(wells_ecl, pu, nullptr);
|
||||||
|
|||||||
Reference in New Issue
Block a user