inline void BlackoilPropertiesFromDeck::init(Opm::DeckConstPtr deck,
                                                 Opm::EclipseStateConstPtr eclState,
                                                 int number_of_cells,
                                                 const int* global_cell,
                                                 const int* cart_dims,
                                                 const CentroidIterator& begin_cell_centroids,
                                                 int dimension,
                                                 bool init_rock)
    {
        // retrieve the cell specific PVT table index from the deck
        // and using the grid...
        extractPvtTableIndex(cellPvtRegionIdx_, deck, number_of_cells, global_cell);

        if (init_rock){
           rock_.init(eclState, number_of_cells, global_cell, cart_dims);
        }
        pvt_.init(deck, /*numSamples=*/0);
        SaturationPropsFromDeck<SatFuncSimpleNonuniform>* ptr
            = new SaturationPropsFromDeck<SatFuncSimpleNonuniform>();
        satprops_.reset(ptr);
        ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids, dimension,
                  /*numSamples=*/0);

        if (pvt_.numPhases() != satprops_->numPhases()) {
            OPM_THROW(std::runtime_error, "BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
                  << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
        }
    }
    inline void BlackoilPropertiesFromDeck::init(Opm::DeckConstPtr deck,
                                                 Opm::EclipseStateConstPtr eclState,
                                                 std::shared_ptr<MaterialLawManager> materialLawManager,
                                                 int number_of_cells,
                                                 const int* global_cell,
                                                 const int* cart_dims,
                                                 bool init_rock)
    {
        // retrieve the cell specific PVT table index from the deck
        // and using the grid...
        extractPvtTableIndex(cellPvtRegionIdx_, eclState, number_of_cells, global_cell);

        if (init_rock){
           rock_.init(eclState, number_of_cells, global_cell, cart_dims);
        }
        pvt_.init(deck, eclState, /*numSamples=*/0);
        SaturationPropsFromDeck* ptr
            = new SaturationPropsFromDeck();
        ptr->init(phaseUsageFromDeck(deck), materialLawManager);
        satprops_.reset(ptr);

        if (pvt_.numPhases() != satprops_->numPhases()) {
            OPM_THROW(std::runtime_error, "BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
                  << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
        }
    }
    inline void BlackoilPropertiesFromDeck::init(Opm::DeckConstPtr deck,
                                                 Opm::EclipseStateConstPtr eclState,
                                                 std::shared_ptr<MaterialLawManager> materialLawManager,
                                                 int number_of_cells,
                                                 const int* global_cell,
                                                 const int* cart_dims,
                                                 const parameter::ParameterGroup& param,
                                                 bool init_rock)
    {
        // retrieve the cell specific PVT table index from the deck
        // and using the grid...
        extractPvtTableIndex(cellPvtRegionIdx_, eclState, number_of_cells, global_cell);

        if(init_rock){
            rock_.init(eclState, number_of_cells, global_cell, cart_dims);
        }

        const int pvt_samples = param.getDefault("pvt_tab_size", -1);
        pvt_.init(deck, eclState, pvt_samples);

        // Unfortunate lack of pointer smartness here...
        std::string threephase_model = param.getDefault<std::string>("threephase_model", "gwseg");
        if (deck->hasKeyword("ENDSCALE") && threephase_model != "gwseg") {
            OPM_THROW(std::runtime_error, "Sorry, end point scaling currently available for the 'gwseg' model only.");
        }

        SaturationPropsFromDeck* ptr
            = new SaturationPropsFromDeck();
        ptr->init(phaseUsageFromDeck(deck), materialLawManager);
        satprops_.reset(ptr);

        if (pvt_.numPhases() != satprops_->numPhases()) {
            OPM_THROW(std::runtime_error, "BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
                  << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
        }
    }
    inline void BlackoilPropertiesFromDeck::init(Opm::DeckConstPtr deck,
                                                 Opm::EclipseStateConstPtr eclState,
                                                 int number_of_cells,
                                                 const int* global_cell,
                                                 const int* cart_dims,
                                                 const CentroidIterator& begin_cell_centroids,
                                                 int dimension,
                                                 const parameter::ParameterGroup& param,
                                                 bool init_rock)
    {
        // retrieve the cell specific PVT table index from the deck
        // and using the grid...
        extractPvtTableIndex(cellPvtRegionIdx_, deck, number_of_cells, global_cell);

        if(init_rock){
            rock_.init(eclState, number_of_cells, global_cell, cart_dims);
        }

        const int pvt_samples = param.getDefault("pvt_tab_size", 200);
        pvt_.init(deck, pvt_samples);

        // Unfortunate lack of pointer smartness here...
        const int sat_samples = param.getDefault("sat_tab_size", 200);
        std::string threephase_model = param.getDefault<std::string>("threephase_model", "simple");
        if (deck->hasKeyword("ENDSCALE") && threephase_model != "gwseg") {
            OPM_THROW(std::runtime_error, "Sorry, end point scaling currently available for the 'gwseg' model only.");
        }
        if (sat_samples > 1) {
            if (threephase_model == "stone2") {
                SaturationPropsFromDeck<SatFuncStone2Uniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncStone2Uniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else if (threephase_model == "simple") {
                SaturationPropsFromDeck<SatFuncSimpleUniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncSimpleUniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else if (threephase_model == "gwseg") {
                SaturationPropsFromDeck<SatFuncGwsegUniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncGwsegUniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else {
                OPM_THROW(std::runtime_error, "Unknown threephase_model: " << threephase_model);
            }
        } else {
            if (threephase_model == "stone2") {
                SaturationPropsFromDeck<SatFuncStone2Nonuniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncStone2Nonuniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else if (threephase_model == "simple") {
                SaturationPropsFromDeck<SatFuncSimpleNonuniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncSimpleNonuniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else if (threephase_model == "gwseg") {
                SaturationPropsFromDeck<SatFuncGwsegNonuniform>* ptr
                    = new SaturationPropsFromDeck<SatFuncGwsegNonuniform>();
                satprops_.reset(ptr);
                ptr->init(deck, number_of_cells, global_cell, begin_cell_centroids,
                          dimension, sat_samples);
            } else {
                OPM_THROW(std::runtime_error, "Unknown threephase_model: " << threephase_model);
            }
        }

        if (pvt_.numPhases() != satprops_->numPhases()) {
            OPM_THROW(std::runtime_error, "BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data ("
                  << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
        }
    }
    /// Constructor wrapping an opm-core black oil interface.
    BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const EclipseGridParser& deck,
                                                     const UnstructuredGrid& grid,
                                                     const bool init_rock)
    {
        if (init_rock){
            rock_.init(deck, grid);
        }
        const int samples = 0;
        const int region_number = 0;

        phase_usage_ = phaseUsageFromDeck(deck);

        // Surface densities. Accounting for different orders in eclipse and our code.
        if (deck.hasField("DENSITY")) {
            const std::vector<double>& d = deck.getDENSITY().densities_[region_number];
            enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 };
            if (phase_usage_.phase_used[Aqua]) {
                densities_[phase_usage_.phase_pos[Aqua]]   = d[ECL_water];
            }
            if (phase_usage_.phase_used[Vapour]) {
                densities_[phase_usage_.phase_pos[Vapour]] = d[ECL_gas];
            }
            if (phase_usage_.phase_used[Liquid]) {
                densities_[phase_usage_.phase_pos[Liquid]] = d[ECL_oil];
            }
        } else {
            OPM_THROW(std::runtime_error, "Input is missing DENSITY\n");
        }

        // Set the properties.
        props_.resize(phase_usage_.num_phases);
        // Water PVT
        if (phase_usage_.phase_used[Aqua]) {
            if (deck.hasField("PVTW")) {
                props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(deck.getPVTW().pvtw_));
            } else {
                // Eclipse 100 default.
                props_[phase_usage_.phase_pos[Aqua]].reset(new SinglePvtConstCompr(0.5*Opm::prefix::centi*Opm::unit::Poise));
            }
        }
        // Oil PVT
        if (phase_usage_.phase_used[Liquid]) {
            if (deck.hasField("PVDO")) {
                if (samples > 0) {
                    props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDeadSpline(deck.getPVDO().pvdo_, samples));
                } else {
                    props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtDead(deck.getPVDO().pvdo_));
                }
            } else if (deck.hasField("PVTO")) {

                props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtLiveOil(deck.getPVTO().pvto_));
            } else if (deck.hasField("PVCDO")) {
                props_[phase_usage_.phase_pos[Liquid]].reset(new SinglePvtConstCompr(deck.getPVCDO().pvcdo_));
            } else {
                OPM_THROW(std::runtime_error, "Input is missing PVDO or PVTO\n");
            }
        }
        // Gas PVT
        if (phase_usage_.phase_used[Vapour]) {
            if (deck.hasField("PVDG")) {
                if (samples > 0) {
                    props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDeadSpline(deck.getPVDG().pvdg_, samples));
                } else {
                    props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtDead(deck.getPVDG().pvdg_));
                }
            // } else if (deck.hasField("PVTG")) {
            //     props_[phase_usage_.phase_pos[Vapour]].reset(new SinglePvtLiveGas(deck.getPVTG().pvtg_));
            } else {
                OPM_THROW(std::runtime_error, "Input is missing PVDG or PVTG\n");
            }
        }

        SaturationPropsFromDeck<SatFuncGwsegNonuniform>* ptr
            = new SaturationPropsFromDeck<SatFuncGwsegNonuniform>();
        satprops_.reset(ptr);
        ptr->init(deck, grid, -1);

        if (phase_usage_.num_phases != satprops_->numPhases()) {
            OPM_THROW(std::runtime_error, "BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck() - "
                  "Inconsistent number of phases in pvt data (" << phase_usage_.num_phases
                  << ") and saturation-dependent function data (" << satprops_->numPhases() << ").");
        }
    }