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;
            }
        }
Example #5
0
    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]);
        }
    }
Example #6
0
    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]);
        }
    }
Example #7
0
        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);
            }
        }
Example #8
0
    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]);
        }
    }
Example #9
0
        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];
            }
        }
Example #10
0
    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];
                }
            }
        }
    }
Example #12
0
 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);
 }
Example #13
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);

        }
Example #14
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);
 }