mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
calculating the representative radius and perf length
for all well perforations, to be used in shear-thinning calculation. The calculation is approximated.
This commit is contained in:
parent
cf17dbea38
commit
8205ad3303
@ -80,6 +80,8 @@ namespace Opm {
|
|||||||
const bool has_vapoil,
|
const bool has_vapoil,
|
||||||
const bool has_polymer,
|
const bool has_polymer,
|
||||||
const bool has_plyshlog,
|
const bool has_plyshlog,
|
||||||
|
std::vector<double>& wells_rep_radius,
|
||||||
|
std::vector<double>& wells_perf_length,
|
||||||
const bool terminal_output);
|
const bool terminal_output);
|
||||||
|
|
||||||
/// Called once before each time step.
|
/// Called once before each time step.
|
||||||
@ -128,6 +130,11 @@ namespace Opm {
|
|||||||
const int poly_pos_;
|
const int poly_pos_;
|
||||||
V cmax_;
|
V cmax_;
|
||||||
|
|
||||||
|
// representative radius and perforation length of well perforations
|
||||||
|
// to be used in shear-thinning computation.
|
||||||
|
std::vector<double> wells_rep_radius_;
|
||||||
|
std::vector<double> wells_perf_length_;
|
||||||
|
|
||||||
// Need to declare Base members we want to use here.
|
// Need to declare Base members we want to use here.
|
||||||
using Base::grid_;
|
using Base::grid_;
|
||||||
using Base::fluid_;
|
using Base::fluid_;
|
||||||
@ -252,6 +259,9 @@ namespace Opm {
|
|||||||
std::vector<double>& maxNormWell,
|
std::vector<double>& maxNormWell,
|
||||||
int nc,
|
int nc,
|
||||||
int nw) const;
|
int nw) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,13 +86,17 @@ namespace Opm {
|
|||||||
const bool has_vapoil,
|
const bool has_vapoil,
|
||||||
const bool has_polymer,
|
const bool has_polymer,
|
||||||
const bool has_plyshlog,
|
const bool has_plyshlog,
|
||||||
|
std::vector<double>& wells_rep_radius,
|
||||||
|
std::vector<double>& wells_perf_length,
|
||||||
const bool terminal_output)
|
const bool terminal_output)
|
||||||
: Base(param, grid, fluid, geo, rock_comp_props, wells, linsolver,
|
: Base(param, grid, fluid, geo, rock_comp_props, wells, linsolver,
|
||||||
has_disgas, has_vapoil, terminal_output),
|
has_disgas, has_vapoil, terminal_output),
|
||||||
polymer_props_ad_(polymer_props_ad),
|
polymer_props_ad_(polymer_props_ad),
|
||||||
has_polymer_(has_polymer),
|
has_polymer_(has_polymer),
|
||||||
has_plyshlog_(has_plyshlog),
|
has_plyshlog_(has_plyshlog),
|
||||||
poly_pos_(detail::polymerPos(fluid.phaseUsage()))
|
poly_pos_(detail::polymerPos(fluid.phaseUsage())),
|
||||||
|
wells_rep_radius_(wells_rep_radius),
|
||||||
|
wells_perf_length_(wells_perf_length)
|
||||||
{
|
{
|
||||||
if (has_polymer_) {
|
if (has_polymer_) {
|
||||||
if (!active_[Water]) {
|
if (!active_[Water]) {
|
||||||
@ -576,10 +580,6 @@ namespace Opm {
|
|||||||
return converged;
|
return converged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class Grid>
|
template <class Grid>
|
||||||
ADB
|
ADB
|
||||||
BlackoilPolymerModel<Grid>::computeMc(const SolutionState& state) const
|
BlackoilPolymerModel<Grid>::computeMc(const SolutionState& state) const
|
||||||
@ -587,8 +587,6 @@ namespace Opm {
|
|||||||
return polymer_props_ad_.polymerWaterVelocityRatio(state.concentration);
|
return polymer_props_ad_.polymerWaterVelocityRatio(state.concentration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
#endif // OPM_BLACKOILPOLYMERMODEL_IMPL_HEADER_INCLUDED
|
#endif // OPM_BLACKOILPOLYMERMODEL_IMPL_HEADER_INCLUDED
|
||||||
|
@ -124,17 +124,37 @@ namespace Opm
|
|||||||
|
|
||||||
std::unique_ptr<Solver> createSolver(const Wells* wells);
|
std::unique_ptr<Solver> createSolver(const Wells* wells);
|
||||||
|
|
||||||
|
|
||||||
void handleAdditionalWellInflow(SimulatorTimer& timer,
|
void handleAdditionalWellInflow(SimulatorTimer& timer,
|
||||||
WellsManager& wells_manager,
|
WellsManager& wells_manager,
|
||||||
typename BaseType::WellState& well_state,
|
typename BaseType::WellState& well_state,
|
||||||
const Wells* wells);
|
const Wells* wells);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const PolymerPropsAd& polymer_props_;
|
const PolymerPropsAd& polymer_props_;
|
||||||
bool has_polymer_;
|
bool has_polymer_;
|
||||||
/// flag for PLYSHLOG keywords
|
// flag for PLYSHLOG keyword
|
||||||
bool has_plyshlog_;
|
bool has_plyshlog_;
|
||||||
DeckConstPtr deck_;
|
DeckConstPtr deck_;
|
||||||
|
|
||||||
|
std::vector<double> wells_rep_radius_;
|
||||||
|
std::vector<double> wells_perf_length_;
|
||||||
|
|
||||||
|
// generate the mapping from Cartesian grid cells to global compressed cells,
|
||||||
|
// copied from opm-core, to be used in function computeRepRadiusPerfLength()
|
||||||
|
static void
|
||||||
|
setupCompressedToCartesian(const int* global_cell, int number_of_cells, std::map<int,int>& cartesian_to_compressed);
|
||||||
|
|
||||||
|
// calculate the representative radius and length for for well peforations
|
||||||
|
// it will be used in the shear-thinning calcluation only.
|
||||||
|
void
|
||||||
|
computeRepRadiusPerfLength(const Opm::EclipseStateConstPtr eclipseState,
|
||||||
|
const size_t timeStep,
|
||||||
|
const GridT& grid,
|
||||||
|
std::vector<double>& wells_rep_radius,
|
||||||
|
std::vector<double>& wells_perf_length);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
@ -68,6 +68,7 @@ namespace Opm
|
|||||||
ModelParams modelParams( BaseType::param_ );
|
ModelParams modelParams( BaseType::param_ );
|
||||||
typedef NewtonSolver<Model> Solver;
|
typedef NewtonSolver<Model> Solver;
|
||||||
|
|
||||||
|
|
||||||
auto model = std::unique_ptr<Model>(new Model(modelParams,
|
auto model = std::unique_ptr<Model>(new Model(modelParams,
|
||||||
BaseType::grid_,
|
BaseType::grid_,
|
||||||
BaseType::props_,
|
BaseType::props_,
|
||||||
@ -80,6 +81,8 @@ namespace Opm
|
|||||||
BaseType::has_vapoil_,
|
BaseType::has_vapoil_,
|
||||||
has_polymer_,
|
has_polymer_,
|
||||||
has_plyshlog_,
|
has_plyshlog_,
|
||||||
|
wells_rep_radius_,
|
||||||
|
wells_perf_length_,
|
||||||
BaseType::terminal_output_));
|
BaseType::terminal_output_));
|
||||||
|
|
||||||
if (!BaseType::threshold_pressures_by_face_.empty()) {
|
if (!BaseType::threshold_pressures_by_face_.empty()) {
|
||||||
@ -91,6 +94,9 @@ namespace Opm
|
|||||||
return std::unique_ptr<Solver>(new Solver(solverParams, std::move(model)));
|
return std::unique_ptr<Solver>(new Solver(solverParams, std::move(model)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class GridT>
|
template <class GridT>
|
||||||
void SimulatorFullyImplicitBlackoilPolymer<GridT>::
|
void SimulatorFullyImplicitBlackoilPolymer<GridT>::
|
||||||
handleAdditionalWellInflow(SimulatorTimer& timer,
|
handleAdditionalWellInflow(SimulatorTimer& timer,
|
||||||
@ -115,6 +121,134 @@ namespace Opm
|
|||||||
timer.simulationTimeElapsed() + timer.currentStepLength(),
|
timer.simulationTimeElapsed() + timer.currentStepLength(),
|
||||||
polymer_inflow_c);
|
polymer_inflow_c);
|
||||||
well_state.polymerInflow() = polymer_inflow_c;
|
well_state.polymerInflow() = polymer_inflow_c;
|
||||||
|
|
||||||
|
computeRepRadiusPerfLength(BaseType::eclipse_state_, timer.currentStepNum(), BaseType::grid_, wells_rep_radius_, wells_perf_length_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class GridT>
|
||||||
|
void SimulatorFullyImplicitBlackoilPolymer<GridT>::
|
||||||
|
setupCompressedToCartesian(const int* global_cell, int number_of_cells,
|
||||||
|
std::map<int,int>& cartesian_to_compressed )
|
||||||
|
{
|
||||||
|
if (global_cell) {
|
||||||
|
for (int i = 0; i < number_of_cells; ++i) {
|
||||||
|
cartesian_to_compressed.insert(std::make_pair(global_cell[i], i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < number_of_cells; ++i) {
|
||||||
|
cartesian_to_compressed.insert(std::make_pair(i, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class GridT>
|
||||||
|
void SimulatorFullyImplicitBlackoilPolymer<GridT>::
|
||||||
|
computeRepRadiusPerfLength(const Opm::EclipseStateConstPtr eclipseState,
|
||||||
|
const size_t timeStep,
|
||||||
|
const GridT& grid,
|
||||||
|
std::vector<double>& wells_rep_radius,
|
||||||
|
std::vector<double>& wells_perf_length)
|
||||||
|
{
|
||||||
|
|
||||||
|
int number_of_cells = Opm::UgGridHelpers::numCells(grid);
|
||||||
|
const int* global_cell = Opm::UgGridHelpers::globalCell(grid);
|
||||||
|
const int* cart_dims = Opm::UgGridHelpers::cartDims(grid);
|
||||||
|
auto cell_to_faces = Opm::UgGridHelpers::cell2Faces(grid);
|
||||||
|
auto begin_face_centroids = Opm::UgGridHelpers::beginFaceCentroids(grid);
|
||||||
|
|
||||||
|
if (eclipseState->getSchedule()->numWells() == 0) {
|
||||||
|
OPM_MESSAGE("No wells specified in Schedule section, "
|
||||||
|
"initializing no wells");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wells_rep_radius.clear();
|
||||||
|
wells_perf_length.clear();
|
||||||
|
|
||||||
|
std::map<int,int> cartesian_to_compressed;
|
||||||
|
|
||||||
|
setupCompressedToCartesian(global_cell, number_of_cells,
|
||||||
|
cartesian_to_compressed);
|
||||||
|
|
||||||
|
ScheduleConstPtr schedule = eclipseState->getSchedule();
|
||||||
|
std::vector<WellConstPtr> wells = schedule->getWells(timeStep);
|
||||||
|
|
||||||
|
int well_index = 0;
|
||||||
|
|
||||||
|
for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
|
||||||
|
WellConstPtr well = (*wellIter);
|
||||||
|
|
||||||
|
if (well->getStatus(timeStep) == WellCommon::SHUT) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{ // COMPDAT handling
|
||||||
|
CompletionSetConstPtr completionSet = well->getCompletions(timeStep);
|
||||||
|
for (size_t c=0; c<completionSet->size(); c++) {
|
||||||
|
CompletionConstPtr completion = completionSet->get(c);
|
||||||
|
if (completion->getState() == WellCompletion::OPEN) {
|
||||||
|
int i = completion->getI();
|
||||||
|
int j = completion->getJ();
|
||||||
|
int k = completion->getK();
|
||||||
|
|
||||||
|
const int* cpgdim = cart_dims;
|
||||||
|
int cart_grid_indx = i + cpgdim[0]*(j + cpgdim[1]*k);
|
||||||
|
std::map<int, int>::const_iterator cgit = cartesian_to_compressed.find(cart_grid_indx);
|
||||||
|
if (cgit == cartesian_to_compressed.end()) {
|
||||||
|
OPM_THROW(std::runtime_error, "Cell with i,j,k indices " << i << ' ' << j << ' '
|
||||||
|
<< k << " not found in grid (well = " << well->name() << ')');
|
||||||
|
}
|
||||||
|
int cell = cgit->second;
|
||||||
|
|
||||||
|
{
|
||||||
|
double radius = 0.5*completion->getDiameter();
|
||||||
|
if (radius <= 0.0) {
|
||||||
|
radius = 0.5*unit::feet;
|
||||||
|
OPM_MESSAGE("**** Warning: Well bore internal radius set to " << radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::array<double, 3> cubical =
|
||||||
|
WellsManagerDetail::getCubeDim<3>(cell_to_faces, begin_face_centroids, cell);
|
||||||
|
|
||||||
|
WellCompletion::DirectionEnum direction = completion->getDirection();
|
||||||
|
|
||||||
|
double re; // area equivalent radius of the grid block
|
||||||
|
double perf_length; // the length of the well perforation
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case Opm::WellCompletion::DirectionEnum::X:
|
||||||
|
re = std::sqrt(cubical[1] * cubical[2] / M_PI);
|
||||||
|
perf_length = cubical[0];
|
||||||
|
break;
|
||||||
|
case Opm::WellCompletion::DirectionEnum::Y:
|
||||||
|
re = std::sqrt(cubical[0] * cubical[2] / M_PI);
|
||||||
|
perf_length = cubical[1];
|
||||||
|
break;
|
||||||
|
case Opm::WellCompletion::DirectionEnum::Z:
|
||||||
|
re = std::sqrt(cubical[0] * cubical[1] / M_PI);
|
||||||
|
perf_length = cubical[2];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
OPM_THROW(std::runtime_error, " Dirtecion of well is not supported ");
|
||||||
|
}
|
||||||
|
|
||||||
|
double repR = std::sqrt(re * radius);
|
||||||
|
wells_rep_radius.push_back(repR);
|
||||||
|
wells_perf_length.push_back(perf_length);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (completion->getState() != WellCompletion::SHUT) {
|
||||||
|
OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion->getState() ) << " not handled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
well_index++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
Loading…
Reference in New Issue
Block a user