Пример #1
0
    /// Looks at presence of WATER, OIL and GAS keywords in state object
    /// to determine active phases.
    inline PhaseUsage phaseUsageFromDeck(const Opm::EclipseState& eclipseState)
    {
        PhaseUsage pu;
        std::fill(pu.phase_used, pu.phase_used + BlackoilPhases::MaxNumPhases, 0);

        const auto& phase = eclipseState.runspec().phases();
        // Discover phase usage.
        if (phase.active(Phase::WATER)) {
            pu.phase_used[BlackoilPhases::Aqua] = 1;
        }
        if (phase.active(Phase::OIL)) {
            pu.phase_used[BlackoilPhases::Liquid] = 1;
        }
        if (phase.active(Phase::GAS)) {
            pu.phase_used[BlackoilPhases::Vapour] = 1;
        }
        pu.num_phases = 0;
        for (int i = 0; i < BlackoilPhases::MaxNumPhases; ++i) {
            pu.phase_pos[i] = pu.num_phases;
            pu.num_phases += pu.phase_used[i];
        }

        // Only 2 or 3 phase systems handled.
        if (pu.num_phases < 2 || pu.num_phases > 3) {
            OPM_THROW(std::runtime_error, "Cannot handle cases with " << pu.num_phases << " phases.");
        }

        // We need oil systems, since we do not support the keywords needed for
        // water-gas systems.
        if (!pu.phase_used[BlackoilPhases::Liquid]) {
            OPM_THROW(std::runtime_error, "Cannot handle cases with no OIL, i.e. water-gas systems.");
        }

        return pu;
    }
Пример #2
0
void extractPvtTableIndex(std::vector<int> &pvtTableIdx,
                          const Opm::EclipseState& eclState,
                          size_t numCompressed,
                          const int *compressedToCartesianCellIdx)
{
    //Get the PVTNUM data
    const std::vector<int>& pvtnumData = eclState.get3DProperties().getIntGridProperty("PVTNUM").getData();
    // Convert this into an array of compressed cells
    // Eclipse uses Fortran-style indices which start at 1
    // instead of 0, we subtract 1.
    pvtTableIdx.resize(numCompressed);
    for (size_t cellIdx = 0; cellIdx < numCompressed; ++ cellIdx) {
        size_t cartesianCellIdx = compressedToCartesianCellIdx ? compressedToCartesianCellIdx[cellIdx]:cellIdx;
        assert(cartesianCellIdx < pvtnumData.size());
        pvtTableIdx[cellIdx] = pvtnumData[cartesianCellIdx] - 1;
    }
}
Пример #3
0
    void SimulatorFullyImplicitBlackoilPolymer<GridT>::
    computeRepRadiusPerfLength(const Opm::EclipseState&        eclipseState,
                               const size_t                    timeStep,
                               const GridT&                    grid,
                               std::vector<double>&            wells_rep_radius,
                               std::vector<double>&            wells_perf_length,
                               std::vector<double>&            wells_bore_diameter)
    {

        // TODO, the function does not work for parallel running
        // to be fixed later.
        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;
        }

        const size_t n_perf = wells_rep_radius.size();

        wells_rep_radius.clear();
        wells_perf_length.clear();
        wells_bore_diameter.clear();

        wells_rep_radius.reserve(n_perf);
        wells_perf_length.reserve(n_perf);
        wells_bore_diameter.reserve(n_perf);

        std::map<int,int> cartesian_to_compressed;

        setupCompressedToCartesian(global_cell, number_of_cells,
                                   cartesian_to_compressed);

        const auto& schedule = eclipseState.getSchedule();
        auto wells           = schedule.getWells(timeStep);

        int well_index = 0;

        for (auto wellIter= wells.begin(); wellIter != wells.end(); ++wellIter) {
             const auto* well = (*wellIter);

             if (well->getStatus(timeStep) == WellCommon::SHUT) {
                 continue;
             }
             {   // COMPDAT handling
                 const auto& completionSet = well->getCompletions(timeStep);
                 for (size_t c=0; c<completionSet.size(); c++) {
                     const auto& 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);
                             wells_bore_diameter.push_back(2. * radius);
                         }
                     } else {
                         if (completion.getState() != WellCompletion::SHUT) {
                             OPM_THROW(std::runtime_error, "Completion state: " << WellCompletion::StateEnum2String( completion.getState() ) << " not handled");
                         }
                     }

                 }
            }
            well_index++;
        }
    }
Пример #4
0
    /// Looks at presence of WATER, OIL and GAS keywords in state object
    /// to determine active phases.
    inline PhaseUsage phaseUsageFromDeck(const Opm::EclipseState& eclipseState)
    {
        const auto& phases = eclipseState.runspec().phases();

        return phaseUsage(phases);
    }
        /// set the tables which specify the temperature dependence of the oil viscosity
        void initFromDeck(std::shared_ptr<const PvtInterface> isothermalPvt,
                          const Opm::Deck& deck,
                          const Opm::EclipseState& eclipseState)
        {
            isothermalPvt_ = isothermalPvt;

            int numRegions;
            auto tables = eclipseState->getTableManager();

            if (deck->hasKeyword("PVTO"))
                numRegions = tables->getPvtoTables().size();
            else if (deck->hasKeyword("PVDO"))
                numRegions = tables->getPvdoTables().size();
            else if (deck->hasKeyword("PVCDO"))
                numRegions = deck->getKeyword("PVCDO").size();
            else
                OPM_THROW(std::runtime_error, "Oil phase was not initialized using a known way");

            // viscosity
            if (deck->hasKeyword("VISCREF")) {
                oilvisctTables_ = &tables->getOilvisctTables();
                const auto& viscrefKeyword = deck->getKeyword("VISCREF");

                assert(int(oilvisctTables_->size()) == numRegions);
                assert(int(viscrefKeyword.size()) == numRegions);

                viscrefPress_.resize(numRegions);
                viscrefRs_.resize(numRegions);
                muRef_.resize(numRegions);
                for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) {
                    const auto& viscrefRecord = viscrefKeyword.getRecord(regionIdx);
                    viscrefPress_[regionIdx] = viscrefRecord.getItem("REFERENCE_PRESSURE").getSIDouble(0);
                    viscrefRs_[regionIdx] = viscrefRecord.getItem("REFERENCE_RS").getSIDouble(0);

                    // temperature used to calculate the reference viscosity [K]. the
                    // value does not really matter if the underlying PVT object really
                    // is isothermal...
                    double Tref = 273.15 + 20;

                    // compute the reference viscosity using the isothermal PVT object.
                    double tmp1, tmp2;
                    isothermalPvt_->mu(1,
                                       &regionIdx,
                                       &viscrefPress_[regionIdx],
                                       &Tref,
                                       &viscrefRs_[regionIdx],
                                       &muRef_[regionIdx],
                                       &tmp1,
                                       &tmp2);
                }
            }

            // quantities required for density. note that we just always use the values
            // for the first EOS. (since EOS != PVT region.)
            tref_ = 0.0;
            if (deck->hasKeyword("THERMEX1")) {
                oilCompIdx_ = deck->getKeyword("OCOMPIDX").getRecord(0).getItem("OIL_COMPONENT_INDEX").get< int >(0) - 1;

                // always use the values of the first EOS
                tref_ = deck->getKeyword("TREF").getRecord(0).getItem("TEMPERATURE").getSIDouble(oilCompIdx_);
                pref_ = deck->getKeyword("PREF").getRecord(0).getItem("PRESSURE").getSIDouble(oilCompIdx_);
                cref_ = deck->getKeyword("CREF").getRecord(0).getItem("COMPRESSIBILITY").getSIDouble(oilCompIdx_);
                thermex1_ = deck->getKeyword("THERMEX1").getRecord(0).getItem("EXPANSION_COEFF").getSIDouble(oilCompIdx_);
            }
        }