/// @brief Computes phase mobilities for a set of saturation values. /// @param[in] props rock and fluid properties /// @param[in] cells cells with which the saturation values are associated /// @param[in] p pressure (one value per cell) /// @param[in] z surface-volume values (for all P phases) /// @param[in] s saturation values (for all phases) /// @param[out] pmobc phase mobilities (for all phases). void computePhaseMobilities(const Opm::BlackoilPropertiesInterface& props, const std::vector<int>& cells, const std::vector<double>& p, const std::vector<double>& z, const std::vector<double>& s, std::vector<double>& pmobc) { const int nc = props.numCells(); const int np = props.numPhases(); assert(int(s.size()) == nc * np); std::vector<double> mu(nc*np); props.viscosity(nc, &p[0], &z[0], &cells[0], &mu[0], 0); pmobc.clear(); pmobc.resize(nc*np, 0.0); double* dpmobc = 0; props.relperm(nc, &s[0], &cells[0], &pmobc[0], dpmobc); std::transform(pmobc.begin(), pmobc.end(), mu.begin(), pmobc.begin(), std::divides<double>()); }
/// Computes the fractional flow for each cell in the cells argument /// @param[in] props rock and fluid properties /// @param[in] polyprops polymer properties /// @param[in] cells cells with which the saturation values are associated /// @param[in] p pressure (one value per cell) /// @param[in] z surface-volume values (for all P phases) /// @param[in] s saturation values (for all phases) /// @param[in] c concentration values /// @param[in] cmax max polymer concentration experienced by cell /// @param[out] fractional_flow the fractional flow for each phase for each cell. void computeFractionalFlow(const Opm::BlackoilPropertiesInterface& props, const Opm::PolymerProperties& polyprops, const std::vector<int>& cells, const std::vector<double>& p, const std::vector<double>& T, const std::vector<double>& z, const std::vector<double>& s, const std::vector<double>& c, const std::vector<double>& cmax, std::vector<double>& fractional_flows) { int num_cells = cells.size(); int num_phases = props.numPhases(); if (num_phases != 2) { OPM_THROW(std::runtime_error, "computeFractionalFlow() assumes 2 phases."); } fractional_flows.resize(num_cells*num_phases); assert(int(s.size()) == num_cells*num_phases); std::vector<double> kr(num_cells*num_phases); props.relperm(num_cells, &s[0], &cells[0], &kr[0], 0); std::vector<double> mu(num_cells*num_phases); props.viscosity(num_cells, &p[0], &T[0], &z[0], &cells[0], &mu[0], 0); double mob[2]; // here we assume num_phases=2 for (int cell = 0; cell < num_cells; ++cell) { double* kr_cell = &kr[2*cell]; double* mu_cell = &mu[2*cell]; polyprops.effectiveMobilities(c[cell], cmax[cell], mu_cell, kr_cell, mob); fractional_flows[2*cell] = mob[0] / (mob[0] + mob[1]); fractional_flows[2*cell + 1] = mob[1] / (mob[0] + mob[1]); } }
/// Set the first saturation to either its min or max value in /// the indicated cells. The second saturation value s2 is set /// to (1.0 - s1) for each cell. Any further saturation values /// are unchanged. void setFirstSat(const std::vector<int>& cells, const Opm::BlackoilPropertiesInterface& props, ExtremalSat es) { const int n = cells.size(); std::vector<double> smin(num_phases_*n); std::vector<double> smax(num_phases_*n); props.satRange(n, &cells[0], &smin[0], &smax[0]); const double* svals = (es == MinSat) ? &smin[0] : &smax[0]; for (int ci = 0; ci < n; ++ci) { const int cell = cells[ci]; sat_[num_phases_*cell] = svals[num_phases_*ci]; sat_[num_phases_*cell + 1] = 1.0 - sat_[num_phases_*cell]; } }
TransportSolverCompressibleTwophaseReorder::TransportSolverCompressibleTwophaseReorder( const UnstructuredGrid& grid, const Opm::BlackoilPropertiesInterface& props, const double tol, const int maxit) : grid_(grid), props_(props), tol_(tol), maxit_(maxit), darcyflux_(0), source_(0), dt_(0.0), saturation_(grid.number_of_cells, -1.0), fractionalflow_(grid.number_of_cells, -1.0), gravity_(0), mob_(2*grid.number_of_cells, -1.0), ia_upw_(grid.number_of_cells + 1, -1), ja_upw_(grid.number_of_faces, -1), ia_downw_(grid.number_of_cells + 1, -1), ja_downw_(grid.number_of_faces, -1) { if (props.numPhases() != 2) { OPM_THROW(std::runtime_error, "Property object must have 2 phases"); } int np = props.numPhases(); int num_cells = props.numCells(); visc_.resize(np*num_cells); A_.resize(np*np*num_cells); smin_.resize(np*num_cells); smax_.resize(np*num_cells); allcells_.resize(num_cells); for (int i = 0; i < num_cells; ++i) { allcells_[i] = i; } props.satRange(props.numCells(), &allcells_[0], &smin_[0], &smax_[0]); }
/// Computes the fractional flow for each cell in the cells argument /// @param[in] props rock and fluid properties /// @param[in] cells cells with which the saturation values are associated /// @param[in] p pressure (one value per cell) /// @param[in] z surface-volume values (for all P phases) /// @param[in] s saturation values (for all phases) /// @param[out] fractional_flow the fractional flow for each phase for each cell. void computeFractionalFlow(const Opm::BlackoilPropertiesInterface& props, const std::vector<int>& cells, const std::vector<double>& p, const std::vector<double>& z, const std::vector<double>& s, std::vector<double>& fractional_flows) { const int num_phases = props.numPhases(); computePhaseMobilities(props, cells, p, z, s, fractional_flows); for (std::vector<int>::size_type i = 0; i < cells.size(); ++i) { double phase_sum = 0.0; for (int phase = 0; phase < num_phases; ++phase) { phase_sum += fractional_flows[i * num_phases + phase]; } for (int phase = 0; phase < num_phases; ++phase) { fractional_flows[i * num_phases + phase] /= phase_sum; } } }
/// @brief Computes total mobility for a set of saturation values. /// @param[in] props rock and fluid properties /// @param[in] cells cells with which the saturation values are associated /// @param[in] p pressure (one value per cell) /// @param[in] z surface-volume values (for all P phases) /// @param[in] s saturation values (for all phases) /// @param[out] totmob total mobilities. void computeTotalMobility(const Opm::BlackoilPropertiesInterface& props, const std::vector<int>& cells, const std::vector<double>& press, const std::vector<double>& z, const std::vector<double>& s, std::vector<double>& totmob) { std::vector<double> pmobc; computePhaseMobilities(props, cells, press, z, s, pmobc); const std::size_t np = props.numPhases(); const std::vector<int>::size_type nc = cells.size(); totmob.clear(); totmob.resize(nc, 0.0); for (std::vector<int>::size_type c = 0; c < nc; ++c) { for (std::size_t p = 0; p < np; ++p) { totmob[ c ] += pmobc[c*np + p]; } } }