コード例 #1
0
        CornerPointChopper(const std::string& file)
        {
            Opm::ParseMode parseMode;
            Opm::ParserPtr parser(new Opm::Parser());
            deck_ = parser->parseFile(file , parseMode);

            metricUnits_.reset(Opm::UnitSystem::newMETRIC());

            Opm::DeckRecordConstPtr specgridRecord = deck_->getKeyword("SPECGRID")->getRecord(0);
            dims_[0] = specgridRecord->getItem("NX")->getInt(0);
            dims_[1] = specgridRecord->getItem("NY")->getInt(0);
            dims_[2] = specgridRecord->getItem("NZ")->getInt(0);

            int layersz = 8*dims_[0]*dims_[1];
            const std::vector<double>& ZCORN = deck_->getKeyword("ZCORN")->getRawDoubleData();
            botmax_ = *std::max_element(ZCORN.begin(), ZCORN.begin() + layersz/2);
            topmin_ = *std::min_element(ZCORN.begin() + dims_[2]*layersz - layersz/2,
                                        ZCORN.begin() + dims_[2]*layersz);

            abszmax_ = *std::max_element(ZCORN.begin(), ZCORN.end());
            abszmin_ = *std::min_element(ZCORN.begin(), ZCORN.end());

            std::cout << "Parsed grdecl file with dimensions ("
                      << dims_[0] << ", " << dims_[1] << ", " << dims_[2] << ")" << std::endl;
        }
コード例 #2
0
ファイル: BlackoilPVT.cpp プロジェクト: jokva/opm-porsol
    void BlackoilPVT::init(Opm::DeckConstPtr deck)
    {
        Opm::ParseMode parseMode;
        const auto eclipseState = std::make_shared<EclipseState>(deck , parseMode);
	region_number_ = 0;

	// Surface densities. Accounting for different orders in eclipse and our code.
	if (deck->hasKeyword("DENSITY")) {
        Opm::DeckRecordConstPtr densityRecord =
            deck->getKeyword("DENSITY")->getRecord(/*regionIdx=*/0);
	    densities_[Aqua]   = densityRecord->getItem("WATER")->getSIDouble(0);
	    densities_[Vapour] = densityRecord->getItem("GAS")->getSIDouble(0);
	    densities_[Liquid] = densityRecord->getItem("OIL")->getSIDouble(0);
	} else {
	    OPM_THROW(std::runtime_error, "Input is missing DENSITY\n");
	}

        // Water PVT
        if (deck->hasKeyword("PVTW")) {
            water_props_.reset(new MiscibilityWater(deck->getKeyword("PVTW")));
        } else {
            water_props_.reset(new MiscibilityWater(0.5*Opm::prefix::centi*Opm::unit::Poise)); // Eclipse 100 default 
        }

        // Oil PVT
        const auto& tables     = eclipseState->getTableManager();
        const auto& pvdoTables = tables->getPvdoTables();
        const auto& pvtoTables = tables->getPvtoTables();
        if (!pvdoTables.empty()) {
            const auto& pvdoTable = pvdoTables.getTable<PvdoTable>(0);
            oil_props_.reset(new MiscibilityDead(pvdoTable));
        } else if (pvtoTables.empty()) {
            // PVTOTables is a std::vector<>
            const auto& pvtoTable = pvtoTables[0];
            oil_props_.reset(new MiscibilityLiveOil(pvtoTable));
        } else if (deck->hasKeyword("PVCDO")) {
            auto *misc_water = new MiscibilityWater(0);
            misc_water->initFromPvcdo(deck->getKeyword("PVCDO"));
            oil_props_.reset(misc_water);
        } else {
            OPM_THROW(std::runtime_error, "Input is missing PVDO and PVTO\n");
        }

	// Gas PVT
        const auto& pvdgTables = tables->getPvdgTables();
        const auto& pvtgTables = tables->getPvtgTables();
        if (!pvdgTables.empty()) {
            const auto& pvdgTable = pvdgTables.getTable<PvdgTable>(0);
            gas_props_.reset(new MiscibilityDead(pvdgTable));
        } else if (pvtgTables.empty()) {
            gas_props_.reset(new MiscibilityLiveGas(pvtgTables[0]));
        } else {
	    OPM_THROW(std::runtime_error, "Input is missing PVDG and PVTG\n");
        }
    }
コード例 #3
0
std::vector<double> getMapaxesValues(Opm::DeckConstPtr deck)
{
    Opm::DeckRecordConstPtr mapaxesRecord = deck->getKeyword("MAPAXES")->getRecord(0);
    std::vector<double> result;
    for (size_t itemIdx = 0; itemIdx < mapaxesRecord->size(); ++itemIdx) {
        Opm::DeckItemConstPtr curItem = mapaxesRecord->getItem(itemIdx);

        for (size_t dataItemIdx = 0; dataItemIdx < curItem->size(); ++dataItemIdx) {
            result.push_back(curItem->getRawDouble(dataItemIdx));
        }
    }
    return result;
}
コード例 #4
0
ファイル: GridManager.cpp プロジェクト: higgscc/opm-core
void GridManager::createGrdecl(Opm::DeckConstPtr deck, struct grdecl &grdecl)
{
    // Extract data from deck.
    const std::vector<double>& zcorn = deck->getKeyword("ZCORN")->getSIDoubleData();
    const std::vector<double>& coord = deck->getKeyword("COORD")->getSIDoubleData();
    const int* actnum = NULL;
    if (deck->hasKeyword("ACTNUM")) {
        actnum = &(deck->getKeyword("ACTNUM")->getIntData()[0]);
    }

    std::array<int, 3> dims;
    if (deck->hasKeyword("DIMENS")) {
        Opm::DeckKeywordConstPtr dimensKeyword = deck->getKeyword("DIMENS");
        dims[0] = dimensKeyword->getRecord(0)->getItem(0)->getInt(0);
        dims[1] = dimensKeyword->getRecord(0)->getItem(1)->getInt(0);
        dims[2] = dimensKeyword->getRecord(0)->getItem(2)->getInt(0);
    } else if (deck->hasKeyword("SPECGRID")) {
        Opm::DeckKeywordConstPtr specgridKeyword = deck->getKeyword("SPECGRID");
        dims[0] = specgridKeyword->getRecord(0)->getItem(0)->getInt(0);
        dims[1] = specgridKeyword->getRecord(0)->getItem(1)->getInt(0);
        dims[2] = specgridKeyword->getRecord(0)->getItem(2)->getInt(0);
    } else {
        OPM_THROW(std::runtime_error, "Deck must have either DIMENS or SPECGRID.");
    }

    // Collect in input struct for preprocessing.

    grdecl.zcorn = &zcorn[0];
    grdecl.coord = &coord[0];
    grdecl.actnum = actnum;
    grdecl.dims[0] = dims[0];
    grdecl.dims[1] = dims[1];
    grdecl.dims[2] = dims[2];

    if (deck->hasKeyword("MAPAXES")) {
        Opm::DeckKeywordConstPtr mapaxesKeyword = deck->getKeyword("MAPAXES");
        Opm::DeckRecordConstPtr mapaxesRecord = mapaxesKeyword->getRecord(0);

        // memleak alert: here we need to make sure that C code
        // can properly take ownership of the grdecl.mapaxes
        // object. if it is not freed, it will result in a
        // memleak...
        double *cWtfMapaxes = static_cast<double*>(malloc(sizeof(double)*mapaxesRecord->size()));
        for (unsigned i = 0; i < mapaxesRecord->size(); ++i)
            cWtfMapaxes[i] = mapaxesRecord->getItem(i)->getSIDouble(0);
        grdecl.mapaxes = cWtfMapaxes;
    } else
        grdecl.mapaxes = NULL;

}
コード例 #5
0
/// Mirror keyword SPECGRID in deck
void mirror_specgrid(Opm::DeckConstPtr deck, std::string direction, std::ofstream& out) {
    // We only need to multiply the dimension by 2 in the correct direction.
    Opm::DeckRecordConstPtr specgridRecord = deck->getKeyword("SPECGRID")->getRecord(0);
    std::vector<int> dimensions(3);
    dimensions[0] = specgridRecord->getItem("NX")->getInt(0);
    dimensions[1] = specgridRecord->getItem("NY")->getInt(0);
    dimensions[2] = specgridRecord->getItem("NZ")->getInt(0);
    if (direction == "x")      {dimensions[0] *= 2;}
    else if (direction == "y") {dimensions[1] *= 2;}
    else                       {std::cerr << "Direction should be either x or y" << std::endl; exit(1);}
    out << "SPECGRID" << std::endl << dimensions[0] << " " << dimensions[1] << " " << dimensions[2] << " "
        << specgridRecord->getItem("NUMRES")->getInt(0) << " "
        << specgridRecord->getItem("COORD_TYPE")->getString(0) << " "
        << std::endl << "/" << std::endl << std::endl;
}
コード例 #6
0
    IncompPropertiesSinglePhase::IncompPropertiesSinglePhase(Opm::DeckConstPtr deck,
                                                             Opm::EclipseStateConstPtr eclState,
                                                             const UnstructuredGrid& grid)
    {
        rock_.init(eclState, grid.number_of_cells, grid.global_cell, grid.cartdims);

        if (deck->hasKeyword("DENSITY")) {
            Opm::DeckRecordConstPtr densityRecord = deck->getKeyword("DENSITY")->getRecord(0);
            surface_density_ = densityRecord->getItem("OIL")->getSIDouble(0);
        } else {
            surface_density_ = 1000.0;
            OPM_MESSAGE("Input is missing DENSITY -- using a standard density of "
                        << surface_density_ << ".\n");
        }

        // This will be modified if we have a PVCDO specification.
        reservoir_density_ = surface_density_;

        if (deck->hasKeyword("PVCDO")) {
            Opm::DeckRecordConstPtr pvcdoRecord = deck->getKeyword("PVCDO")->getRecord(0);
            if (pvcdoRecord->getItem("OIL_COMPRESSIBILITY")->getSIDouble(0) != 0.0 ||
                pvcdoRecord->getItem("OIL_VISCOSIBILITY")->getSIDouble(0) != 0.0) {
                OPM_MESSAGE("Compressibility effects in PVCDO are ignored.");
            }
            reservoir_density_ /= pvcdoRecord->getItem("OIL_VOL_FACTOR")->getSIDouble(0);
            viscosity_ = pvcdoRecord->getItem("OIL_VISCOSITY")->getSIDouble(0);
        } else {
            viscosity_ = 1.0 * prefix::centi*unit::Poise;
            OPM_MESSAGE("Input is missing PVCDO -- using a standard viscosity of "
                        << viscosity_ << " and reservoir density equal to surface density.\n");
        }
    }
コード例 #7
0
void EclipseGridInspector::init_()
{
    if (!deck_->hasKeyword("COORD")) {
        OPM_THROW(std::runtime_error, "Needed field \"COORD\" is missing in file");
    }
    if (!deck_->hasKeyword("ZCORN")) {
        OPM_THROW(std::runtime_error, "Needed field \"ZCORN\" is missing in file");
    }

    if (deck_->hasKeyword("SPECGRID")) {
        Opm::DeckRecordConstPtr specgridRecord =
            deck_->getKeyword("SPECGRID")->getRecord(0);
        logical_gridsize_[0] = specgridRecord->getItem("NX")->getInt(0);
        logical_gridsize_[1] = specgridRecord->getItem("NY")->getInt(0);
        logical_gridsize_[2] = specgridRecord->getItem("NZ")->getInt(0);
    } else if (deck_->hasKeyword("DIMENS")) {
        Opm::DeckRecordConstPtr dimensRecord =
            deck_->getKeyword("DIMENS")->getRecord(0);
        logical_gridsize_[0] = dimensRecord->getItem("NX")->getInt(0);
        logical_gridsize_[1] = dimensRecord->getItem("NY")->getInt(0);
        logical_gridsize_[2] = dimensRecord->getItem("NZ")->getInt(0);
    } else {
        OPM_THROW(std::runtime_error, "Found neither SPECGRID nor DIMENS in file. At least one is needed.");
    }

}
コード例 #8
0
ファイル: PvtConstCompr.hpp プロジェクト: xavierr/opm-core
        void initFromOil(Opm::DeckKeywordConstPtr pvcdoKeyword)
        {
            int numRegions = pvcdoKeyword->size();

            ref_press_.resize(numRegions);
            ref_B_.resize(numRegions);
            comp_.resize(numRegions);
            viscosity_.resize(numRegions);
            visc_comp_.resize(numRegions);

            for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
                Opm::DeckRecordConstPtr pvcdoRecord = pvcdoKeyword->getRecord(regionIdx);

                ref_press_[regionIdx] = pvcdoRecord->getItem("P_REF")->getSIDouble(0);
                ref_B_[regionIdx]     = pvcdoRecord->getItem("OIL_VOL_FACTOR")->getSIDouble(0);
                comp_[regionIdx]      = pvcdoRecord->getItem("OIL_COMPRESSIBILITY")->getSIDouble(0);
                viscosity_[regionIdx] = pvcdoRecord->getItem("OIL_VISCOSITY")->getSIDouble(0);
                visc_comp_[regionIdx] = pvcdoRecord->getItem("OIL_VISCOSIBILITY")->getSIDouble(0);
            }
        }
コード例 #9
0
void mirror_celldata(std::string keyword, Opm::DeckConstPtr deck, std::string direction, std::ofstream& out) {
    if ( ! deck->hasKeyword(keyword)) {
        std::cout << "Ignoring keyword " << keyword << " as it was not found." << std::endl;
        return;
    }
    // Get data from eclipse deck
    Opm::DeckRecordConstPtr specgridRecord = deck->getKeyword("SPECGRID")->getRecord(0);
    std::vector<int> dimensions(3);
    dimensions[0] = specgridRecord->getItem("NX")->getInt(0);
    dimensions[1] = specgridRecord->getItem("NY")->getInt(0);
    dimensions[2] = specgridRecord->getItem("NZ")->getInt(0);
    std::vector<T> values = getKeywordValues(keyword, deck, T(0.0));
    std::vector<T> values_mirrored(2*dimensions[0]*dimensions[1]*dimensions[2], 0.0);
    // Handle the two directions differently due to ordering of the pillars.
    if (direction == "x") {
        typename std::vector<T>::iterator it_orig = values.begin();
        typename std::vector<T>::iterator it_new = values_mirrored.begin();
        // Loop through each line and copy old cell data and add new (which are the old reversed)
        for ( ; it_orig != values.end(); it_orig += dimensions[0]) {
            // Copy old cell data
            copy(it_orig, it_orig + dimensions[0], it_new);
            it_new += dimensions[0];
            // Add new cell data
            std::vector<double> next_vec(it_orig, it_orig + dimensions[0]);
            std::vector<double> next_reversed = next_vec;
            reverse(next_reversed.begin(), next_reversed.end());
            copy(next_reversed.begin(), next_reversed.end(), it_new);
            it_new += dimensions[0];
        }
    }
    else if (direction =="y") {
        typename std::vector<T>::iterator it_orig = values.begin();
        typename std::vector<T>::iterator it_new = values_mirrored.begin();
        // Entries per layer
        const int entries_per_layer = dimensions[0]*dimensions[1];
        // Loop through each layer and copy old cell data and add new (which are the old reordered) 
        for ( ; it_orig != values.end(); it_orig += entries_per_layer) {
            // Copy old cell data
            copy(it_orig, it_orig + entries_per_layer, it_new);
            it_new += entries_per_layer;
            // Add new cell data
            std::vector<T> next_vec(it_orig, it_orig + entries_per_layer);
            std::vector<T> next_reordered(entries_per_layer, 0.0);
            typename std::vector<T>::iterator it_next = next_vec.end();
            typename std::vector<T>::iterator it_reordered = next_reordered.begin();
            // Reorder next entries
            for ( ; it_reordered != next_reordered.end(); it_reordered += dimensions[0]) {
                copy(it_next - dimensions[0], it_next, it_reordered);
                it_next -= dimensions[0];
            }
            copy(next_reordered.begin(), next_reordered.end(), it_new);
            it_new += entries_per_layer;
        }
    }
    else {
        std::cerr << "Direction should be either x or y" << std::endl;
        exit(1);
    }
    // Write new keyword values to output file
    printKeywordValues(out, keyword, values_mirrored, 8);
}
コード例 #10
0
/// Mirror keyword ZCORN in deck
void mirror_zcorn(Opm::DeckConstPtr deck, std::string direction, std::ofstream& out) {
    Opm::DeckRecordConstPtr specgridRecord = deck->getKeyword("SPECGRID")->getRecord(0);
    std::vector<int> dimensions(3);
    dimensions[0] = specgridRecord->getItem("NX")->getInt(0);
    dimensions[1] = specgridRecord->getItem("NY")->getInt(0);
    dimensions[2] = specgridRecord->getItem("NZ")->getInt(0);
    std::vector<double> zcorn = deck->getKeyword("ZCORN")->getRawDoubleData();
    std::vector<double> zcorn_mirrored;
    // Handle the two directions differently due to ordering of the pillars.
    if (direction == "x") {
        // Total entries in mirrored ZCORN. Eight corners per cell.
        const int entries = dimensions[0]*2*dimensions[1]*dimensions[2]*8;
        zcorn_mirrored.assign(entries, 0.0);
        // Entries per line in x-direction. Two for each cell.
        const int entries_per_line = dimensions[0]*2;
        std::vector<double>::iterator it_new = zcorn_mirrored.begin();
        std::vector<double>::iterator it_orig = zcorn.begin();
        // Loop through each line and copy old corner-points and add new (which are the old reversed)
        for ( ; it_orig != zcorn.end(); it_orig += entries_per_line) {
            std::vector<double> next_vec(it_orig, it_orig + entries_per_line);
            std::vector<double> next_reversed = next_vec;
            reverse(next_reversed.begin(), next_reversed.end());
            // Copy old corner-points
            copy(it_orig, it_orig + entries_per_line, it_new);
            it_new += entries_per_line;
            // Add new corner-points
            copy(next_reversed.begin(), next_reversed.end(), it_new);
            it_new += entries_per_line;
        }
    }
    else if (direction == "y") {
        // Total entries in mirrored ZCORN. Eight corners per cell.
        const int entries = dimensions[0]*dimensions[1]*2*dimensions[2]*8;
        zcorn_mirrored.assign(entries, 0.0);
        // Entries per line in x-direction. Two for each cell.
        const int entries_per_line_x = dimensions[0]*2;
        // Entries per layer of corner-points. Four for each cell
        const int entries_per_layer = dimensions[0]*dimensions[1]*4;
        std::vector<double>::iterator it_new = zcorn_mirrored.begin();
        std::vector<double>::iterator it_orig = zcorn.begin();
        // Loop through each layer and copy old corner-points and add new (which are the old reordered) 
        for ( ; it_orig != zcorn.end(); it_orig += entries_per_layer) {
            // Copy old corner-points
            copy(it_orig, it_orig + entries_per_layer, it_new);
            it_new += entries_per_layer;
            // Add new corner-points
            std::vector<double> next_vec(it_orig, it_orig + entries_per_layer);
            std::vector<double> next_reordered(entries_per_layer, 0.0);
            std::vector<double>::iterator it_next = next_vec.end();
            std::vector<double>::iterator it_reordered = next_reordered.begin();
            // Reorder next entries
            for ( ; it_reordered != next_reordered.end(); it_reordered += entries_per_line_x) {
                copy(it_next - entries_per_line_x, it_next, it_reordered);
                it_next -= entries_per_line_x;
            }
            copy(next_reordered.begin(), next_reordered.end(), it_new);
            it_new += entries_per_layer;
        }
    }
    else {
        std::cerr << "Direction should be either x or y" << std::endl;
        exit(1);
    }
    // Write new ZCORN values to output file
    printKeywordValues(out, "ZCORN", zcorn_mirrored, 8);
}
コード例 #11
0
/// Mirror keyword COORD in deck
void mirror_coord(Opm::DeckConstPtr deck, std::string direction, std::ofstream& out) {
    // We assume uniform spacing in x and y directions and parallel top and bottom faces
    Opm::DeckRecordConstPtr specgridRecord = deck->getKeyword("SPECGRID")->getRecord(0);
    std::vector<int> dimensions(3);
    dimensions[0] = specgridRecord->getItem("NX")->getInt(0);
    dimensions[1] = specgridRecord->getItem("NY")->getInt(0);
    dimensions[2] = specgridRecord->getItem("NZ")->getInt(0);
    std::vector<double> coord = deck->getKeyword("COORD")->getRawDoubleData();
    const int entries_per_pillar = 6;
    std::vector<double> coord_mirrored;
    // Handle the two directions differently due to ordering of the pillars.
    if (direction == "x") {
        // Total entries in mirrored ZCORN. Number of pillars times 6
        const int entries = (2*dimensions[0] + 1) * (dimensions[1] + 1) * entries_per_pillar;
        // Entries per line in x-direction. Number of pillars in x-direction times 6
        const int entries_per_line = entries_per_pillar*(dimensions[0] + 1);
        coord_mirrored.assign(entries, 0.0);
        // Distance between pillars in x-directiion
        const double spacing = coord[entries_per_pillar]-coord[0];
        std::vector<double>::iterator it_new = coord_mirrored.begin();
        std::vector<double>::iterator it_orig;
        // Loop through each pillar line in the x-direction
        for (it_orig = coord.begin(); it_orig != coord.end(); it_orig += entries_per_line) {
            // Copy old pillars
            copy(it_orig, it_orig + entries_per_line, it_new);
            // Add new pillars in between
            it_new += entries_per_line;
            std::vector<double> next_vec(it_orig + entries_per_line - entries_per_pillar, it_orig + entries_per_line);
            for (int r=0; r < dimensions[0]; ++r) {
                next_vec[0] += spacing;
                next_vec[3] += spacing;
                copy(next_vec.begin(), next_vec.end(), it_new);
                it_new += entries_per_pillar;
            }
        }
    }
    else if (direction == "y") {
        // Total entries in mirrored ZCORN. Number of pillars times 6
        const int entries = (dimensions[0] + 1) * (2*dimensions[1] + 1) * entries_per_pillar;
        // Entries per line in y-direction. Number of pillars in y-direction times 6
        const int entries_per_line = entries_per_pillar*(dimensions[0] + 1);
        coord_mirrored.assign(entries, 0.0);
        // Distance between pillars in y-directiion
        const double spacing = coord[entries_per_line + 1]-coord[1];
        std::vector<double>::iterator it_new = coord_mirrored.begin();
        // Copy old pillars
        copy(coord.begin(), coord.end(), it_new);
        // Add new pillars at the end
        it_new += coord.size();
        std::vector<double> next_vec(coord.end() - entries_per_line, coord.end());
        for ( ; it_new != coord_mirrored.end(); it_new += entries_per_line) {
            for (int i = 1; i < entries_per_line; i += 3) {
                next_vec[i] += spacing;
            }
            copy(next_vec.begin(), next_vec.end(), it_new);
        }
    }
    else {
        std::cerr << "Direction should be either x or y" << std::endl;
        exit(1);
    }
    // Write new COORD values to output file
    printKeywordValues(out, "COORD", coord_mirrored, 6);
}
コード例 #12
0
        /// set the tables which specify the temperature dependence of the water viscosity
        void initFromDeck(std::shared_ptr<const PvtInterface> isothermalPvt,
                          Opm::DeckConstPtr deck,
                          Opm::EclipseStateConstPtr eclipseState)
        {
            isothermalPvt_ = isothermalPvt;
            watvisctTables_ = 0;

            // stuff which we need to get from the PVTW keyword
            Opm::DeckKeywordConstPtr pvtwKeyword = deck->getKeyword("PVTW");
            int numRegions = pvtwKeyword->size();
            pvtwRefPress_.resize(numRegions);
            pvtwRefB_.resize(numRegions);
            pvtwCompressibility_.resize(numRegions);
            pvtwViscosity_.resize(numRegions);
            pvtwViscosibility_.resize(numRegions);
            for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
                Opm::DeckRecordConstPtr pvtwRecord = pvtwKeyword->getRecord(regionIdx);
                pvtwRefPress_[regionIdx] = pvtwRecord->getItem("P_REF")->getSIDouble(0);
                pvtwRefB_[regionIdx] = pvtwRecord->getItem("WATER_VOL_FACTOR")->getSIDouble(0);
                pvtwViscosity_[regionIdx] = pvtwRecord->getItem("WATER_VISCOSITY")->getSIDouble(0);
                pvtwViscosibility_[regionIdx] = pvtwRecord->getItem("WATER_VISCOSIBILITY")->getSIDouble(0);
            }

            // quantities required for the temperature dependence of the viscosity
            // (basically we expect well-behaved VISCREF and WATVISCT keywords.)
            if (deck->hasKeyword("VISCREF")) {
                watvisctTables_ = &eclipseState->getWatvisctTables();
                Opm::DeckKeywordConstPtr viscrefKeyword = deck->getKeyword("VISCREF");

                assert(int(watvisctTables_->size()) == numRegions);
                assert(int(viscrefKeyword->size()) == numRegions);

                viscrefPress_.resize(numRegions);
                for (int regionIdx = 0; regionIdx < numRegions; ++ regionIdx) {
                    Opm::DeckRecordConstPtr viscrefRecord = viscrefKeyword->getRecord(regionIdx);

                    viscrefPress_[regionIdx] = viscrefRecord->getItem("REFERENCE_PRESSURE")->getSIDouble(0);
                }
            }

            // quantities required for the temperature dependence of the density
            if (deck->hasKeyword("WATDENT")) {
                DeckKeywordConstPtr watdentKeyword = deck->getKeyword("WATDENT");

                assert(int(watdentKeyword->size()) == numRegions);

                watdentRefTemp_.resize(numRegions);
                watdentCT1_.resize(numRegions);
                watdentCT2_.resize(numRegions);
                for (int regionIdx = 0; regionIdx < numRegions; ++regionIdx) {
                    Opm::DeckRecordConstPtr watdentRecord = watdentKeyword->getRecord(regionIdx);

                    watdentRefTemp_[regionIdx] = watdentRecord->getItem("REFERENCE_TEMPERATURE")->getSIDouble(0);
                    watdentCT1_[regionIdx] = watdentRecord->getItem("EXPANSION_COEFF_LINEAR")->getSIDouble(0);
                    watdentCT2_[regionIdx] = watdentRecord->getItem("EXPANSION_COEFF_QUADRATIC")->getSIDouble(0);
                }
            }
        }