virtual void dBdp(const int n, const int* pvtRegionIdx, const double* p, const double* T, const double* z, double* output_B, double* output_dBdp) const { if (watdentRefTemp_.empty()) { // isothermal case isothermalPvt_->dBdp(n, pvtRegionIdx, p, T, z, output_B, output_dBdp); return; } // This changes how the water density depends on pressure. This is awkward, // but it seems to be what Eclipse does. See the documentation for the // WATDENT keyword in the Eclipse RM for (int i = 0; i < n; ++i) { int tableIdx = getTableIndex_(pvtRegionIdx, i); double BwRef = pvtwRefB_[tableIdx]; double TRef = watdentRefTemp_[tableIdx]; double X = pvtwCompressibility_[tableIdx]*(p[i] - pvtwRefPress_[tableIdx]); double cT1 = watdentCT1_[tableIdx]; double cT2 = watdentCT2_[tableIdx]; double Y = T[i] - TRef; double Bw = BwRef*(1 - X)*(1 + cT1*Y + cT2*Y*Y); output_B[i] = Bw; } std::fill(output_dBdp, output_dBdp + n, 0.0); }
virtual void b(const int n, const int* pvtRegionIdx, const double* p, const double* T, const double* r, const PhasePresence* cond, double* output_b, double* output_dbdp, double* output_dbdr) const { if (watdentRefTemp_.empty()) { // isothermal case isothermalPvt_->b(n, pvtRegionIdx, p, T, r, cond, output_b, output_dbdp, output_dbdr); return; } // This changes pressure dependence of the water density, but it seems to be // what Eclipse does. See the documentation for the WATDENT keyword in the // Eclipse RM for (int i = 0; i < n; ++i) { int tableIdx = getTableIndex_(pvtRegionIdx, i); double BwRef = pvtwRefB_[tableIdx]; double TRef = watdentRefTemp_[tableIdx]; double X = pvtwCompressibility_[tableIdx]*(p[i] - pvtwRefPress_[tableIdx]); double cT1 = watdentCT1_[tableIdx]; double cT2 = watdentCT2_[tableIdx]; double Y = T[i] - TRef; double Bw = BwRef*(1 - X)*(1 + cT1*Y + cT2*Y*Y); output_b[i] = 1.0/Bw; } std::fill(output_dbdp, output_dbdp + n, 0.0); std::fill(output_dbdr, output_dbdr + n, 0.0); }
virtual void mu(const int n, const int* pvtRegionIdx, const double* p, const double* T, const double* r, double* output_mu, double* output_dmudp, double* output_dmudr) const { // compute the isothermal viscosity and its derivatives isothermalPvt_->mu(n, pvtRegionIdx, p, T, r, output_mu, output_dmudp, output_dmudr); if (!watvisctTables_) // isothermal case return; // temperature dependence for (int i = 0; i < n; ++i) { int tableIdx = getTableIndex_(pvtRegionIdx, i); // calculate the viscosity of the isothermal keyword for the reference // pressure given by the VISCREF keyword. double x = -pvtwViscosibility_[tableIdx]*(viscrefPress_[tableIdx] - pvtwRefPress_[tableIdx]); double muRef = pvtwViscosity_[tableIdx]/(1.0 + x + 0.5*x*x); // compute the viscosity deviation due to temperature double muWatvisct = (*watvisctTables_)[tableIdx].evaluate("Viscosity", T[i]); double alpha = muWatvisct/muRef; output_mu[i] *= alpha; output_dmudp[i] *= alpha; output_dmudr[i] *= alpha; // TODO (?): derivative of viscosity w.r.t. temperature. } }
virtual void B(const int n, const int* pvtRegionIdx, const double* p, const double* T, const double* z, double* output_B) const { if (watdentRefTemp_.empty()) { // isothermal case isothermalPvt_->B(n, pvtRegionIdx, p, T, z, output_B); return; } // This changes how the water density depends on pressure compared to what's // used for the PVTW keyword, but it seems to be what Eclipse does. For // details, see the documentation for the WATDENT keyword in the Eclipse RM. for (int i = 0; i < n; ++i) { int tableIdx = getTableIndex_(pvtRegionIdx, i); double BwRef = pvtwRefB_[tableIdx]; double TRef = watdentRefTemp_[tableIdx]; double X = pvtwCompressibility_[tableIdx]*(p[i] - pvtwRefPress_[tableIdx]); double cT1 = watdentCT1_[tableIdx]; double cT2 = watdentCT2_[tableIdx]; double Y = T[i] - TRef; double Bw = BwRef*(1 - X)*(1 + cT1*Y + cT2*Y*Y); output_B[i] = Bw; } }
void PvtDead::mu(const int n, const int* pvtTableIdx, const double* p, const double* /*z*/, double* output_mu) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { int regionIdx = getTableIndex_(pvtTableIdx, i); output_mu[i] = viscosity_[regionIdx](p[i]); } }
void PvtDead::B(const int n, const int* pvtTableIdx, const double* p, const double* /*z*/, double* output_B) const { // #pragma omp parallel for // B = 1/b for (int i = 0; i < n; ++i) { int regionIdx = getTableIndex_(pvtTableIdx, i); output_B[i] = 1.0/b_[regionIdx](p[i]); } }
virtual void B(const int n, const int* pvtRegionIdx, const double* p, const double* /*z*/, double* output_B) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { // Computing a polynomial approximation to the exponential. int tableIdx = getTableIndex_(pvtRegionIdx, i); double x = comp_[tableIdx]*(p[i] - ref_press_[tableIdx]); output_B[i] = ref_B_[tableIdx]/(1.0 + x + 0.5*x*x); } }
void PvtDead::dBdp(const int n, const int* pvtTableIdx, const double* p, const double* /*z*/, double* output_B, double* output_dBdp) const { B(n, pvtTableIdx, p, 0, output_B); // #pragma omp parallel for for (int i = 0; i < n; ++i) { int regionIdx = getTableIndex_(pvtTableIdx, i); double Bg = output_B[i]; output_dBdp[i] = -Bg*Bg*b_[regionIdx].derivative(p[i]); } }
virtual void dBdp(const int n, const int* pvtRegionIdx, const double* p, const double* /*z*/, double* output_B, double* output_dBdp) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { int tableIdx = getTableIndex_(pvtRegionIdx, i); double x = comp_[tableIdx]*(p[i] - ref_press_[tableIdx]); double d = (1.0 + x + 0.5*x*x); output_B[i] = ref_B_[tableIdx]/d; output_dBdp[i] = (-ref_B_[tableIdx]/(d*d))*(1 + x) * comp_[tableIdx]; } }
void PvtDead::mu(const int n, const int* pvtTableIdx, const double* p, const double* /*r*/, double* output_mu, double* output_dmudp, double* output_dmudr) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { int regionIdx = getTableIndex_(pvtTableIdx, i); output_mu[i] = viscosity_[regionIdx](p[i]); output_dmudp[i] = viscosity_[regionIdx].derivative(p[i]); } std::fill(output_dmudr, output_dmudr + n, 0.0); }
/// \param[in] n Number of data points. /// \param[in] A Array of nP^2 values, where the P^2 values for a cell give the /// matrix A = RB^{-1} which relates z to u by z = Au. The matrices /// are assumed to be in Fortran order, and are typically the result /// of a call to the method matrix(). /// \param[in] cells The index of the grid cell of each data point. /// \param[out] rho Array of nP density values, array must be valid before calling. void BlackoilPropertiesFromDeck::density(const int n, const double* A, const int* cells, double* rho) const { const int np = numPhases(); // #pragma omp parallel for for (int i = 0; i < n; ++i) { int cellIdx = cells?cells[i]:i; int pvtRegionIdx = getTableIndex_(cellPvtRegionIndex(), cellIdx); const double* sdens = pvt_.surfaceDensities(pvtRegionIdx); for (int phase = 0; phase < np; ++phase) { rho[np*i + phase] = 0.0; for (int comp = 0; comp < np; ++comp) { rho[np*i + phase] += A[i*np*np + np*phase + comp]*sdens[comp]; } } } }
virtual void mu(const int n, const int* pvtRegionIdx, const double* p, const double* /*r*/, double* output_mu, double* output_dmudp, double* output_dmudr) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { // Computing a polynomial approximation to the exponential. int tableIdx = getTableIndex_(pvtRegionIdx, i); double x = -visc_comp_[tableIdx]*(p[i] - ref_press_[tableIdx]); double d = (1.0 + x + 0.5*x*x); output_mu[i] = viscosity_[tableIdx]/d; output_dmudp[i] = (viscosity_[tableIdx]/(d*d))*(1+x) * visc_comp_[tableIdx]; } std::fill(output_dmudr, output_dmudr + n, 0.0); }
void PvtDead::b(const int n, const int* pvtTableIdx, const double* p, const double* /*r*/, const PhasePresence* /*cond*/, double* output_b, double* output_dbdp, double* output_dbdr) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { int regionIdx = getTableIndex_(pvtTableIdx, i); output_b[i] = b_[regionIdx](p[i]); output_dbdp[i] = b_[regionIdx].derivative(p[i]); } std::fill(output_dbdr, output_dbdr + n, 0.0); }
virtual void b(const int n, const int* pvtRegionIdx, const double* p, const double* /*r*/, const PhasePresence* /*cond*/, double* output_b, double* output_dbdp, double* output_dbdr) const { // #pragma omp parallel for for (int i = 0; i < n; ++i) { // Computing a polynomial approximation to the exponential. int tableIdx = getTableIndex_(pvtRegionIdx, i); double x = comp_[tableIdx]*(p[i] - ref_press_[tableIdx]); double d = (1.0 + x + 0.5*x*x); // b = 1/B = d/ref_B_[tableIdx]B; output_b[i] = d/ref_B_[tableIdx]; output_dbdp[i] = (1 + x) * comp_[tableIdx]/ref_B_[tableIdx]; } std::fill(output_dbdr, output_dbdr + n, 0.0); }
/// Densities of stock components at surface conditions. /// \return Array of P density values. const double* BlackoilPropertiesFromDeck::surfaceDensity(int cellIdx) const { int pvtRegionIdx = getTableIndex_(cellPvtRegionIndex(), cellIdx); return pvt_.surfaceDensities(pvtRegionIdx); }