Esempio n. 1
0
 void ParserKeyword::applyUnitsToDeck( Deck& deck, DeckKeyword& deckKeyword) const {
     for (size_t index = 0; index < deckKeyword.size(); index++) {
         const auto& parserRecord = this->getRecord( index );
         auto& deckRecord = deckKeyword.getRecord( index );
         parserRecord.applyUnitsToDeck( deck, deckRecord );
     }
 }
Esempio n. 2
0
    void TimeMap::addFromDATESKeyword( const DeckKeyword& DATESKeyword ) {
        if (DATESKeyword.name() != "DATES")
            throw std::invalid_argument("Method requires DATES keyword input.");

        for (size_t recordIndex = 0; recordIndex < DATESKeyword.size(); recordIndex++) {
            const auto& record = DATESKeyword.getRecord( recordIndex );
            boost::posix_time::ptime nextTime = TimeMap::timeFromEclipse( record );
            addTime( nextTime );
        }
    }
Esempio n. 3
0
    bool DeckKeyword::equal_data(const DeckKeyword& other, bool cmp_default, bool cmp_numeric) const {
        if (this->size() != other.size())
            return false;

        for (size_t index = 0; index < this->size(); index++) {
            const auto& this_record = this->getRecord( index );
            const auto& other_record = other.getRecord( index );
            if (!this_record.equal( other_record , cmp_default, cmp_numeric))
                return false;
        }
        return true;
    }
Esempio n. 4
0
 std::vector<std::pair<size_t , size_t> > PvtxTable::recordRanges( const DeckKeyword& keyword ) {
     std::vector<std::pair<size_t,size_t> > ranges;
     size_t startRecord = 0;
     size_t recordIndex = 0;
     while (recordIndex < keyword.size()) {
         const auto& item = keyword.getRecord(recordIndex).getItem(0);
         if (item.size( ) == 0) {
             ranges.push_back( std::make_pair( startRecord , recordIndex ) );
             startRecord = recordIndex + 1;
         }
         recordIndex++;
     }
     ranges.push_back( std::make_pair( startRecord , recordIndex ) );
     return ranges;
 }
Esempio n. 5
0
    std::map<std::string , std::vector< CompletionPtr> > Completion::completionsFromCOMPDATKeyword( const DeckKeyword& compdatKeyword ) {
        std::map<std::string , std::vector< CompletionPtr> > completionMapList;
        for (size_t recordIndex = 0; recordIndex < compdatKeyword.size(); recordIndex++) {
            std::pair<std::string , std::vector< CompletionPtr> > wellCompletionsPair = completionsFromCOMPDATRecord( compdatKeyword.getRecord( recordIndex ));
            std::string well = wellCompletionsPair.first;
            std::vector<CompletionPtr>& newCompletions = wellCompletionsPair.second;

            if (completionMapList.find(well) == completionMapList.end())
                 completionMapList[well] = std::vector<CompletionPtr>();

            {
                std::vector<CompletionPtr>& currentCompletions = completionMapList.find(well)->second;

                for (size_t ic = 0; ic < newCompletions.size(); ic++)
                    currentCompletions.push_back( newCompletions[ic] );
            }
        }
        return completionMapList;
    }
Esempio n. 6
0
    std::vector< Compsegs > Compsegs::compsegsFromCOMPSEGSKeyword( const DeckKeyword& compsegsKeyword ) {

        // only handle the second record here
        // The first record here only contains the well name
        std::vector< Compsegs > compsegs;

        for (size_t recordIndex = 1; recordIndex < compsegsKeyword.size(); ++recordIndex) {
            const auto& record = compsegsKeyword.getRecord(recordIndex);
            // following the coordinate rule for completions
            const int I = record.getItem<ParserKeywords::COMPSEGS::I>().get< int >(0) - 1;
            const int J = record.getItem<ParserKeywords::COMPSEGS::J>().get< int >(0) - 1;
            const int K = record.getItem<ParserKeywords::COMPSEGS::K>().get< int >(0) - 1;
            const int branch = record.getItem<ParserKeywords::COMPSEGS::BRANCH>().get< int >(0);

            double distance_start;
            double distance_end;
            if (record.getItem<ParserKeywords::COMPSEGS::DISTANCE_START>().hasValue(0)) {
                distance_start = record.getItem<ParserKeywords::COMPSEGS::DISTANCE_START>().getSIDouble(0);
            } else if (recordIndex == 1) {
                distance_start = 0.;
            } else {
                // TODO: the end of the previous connection or range
                // 'previous' should be in term of the input order
                // since basically no specific order for the completions
                throw std::runtime_error("this way to obtain DISTANCE_START not implemented yet!");
            }
            if (record.getItem<ParserKeywords::COMPSEGS::DISTANCE_END>().hasValue(0)) {
                distance_end = record.getItem<ParserKeywords::COMPSEGS::DISTANCE_END>().getSIDouble(0);
            } else {
                // TODO: the distance_start plus the thickness of the grid block
                throw std::runtime_error("this way to obtain DISTANCE_END not implemented yet!");
            }

            if( !record.getItem< ParserKeywords::COMPSEGS::DIRECTION >().hasValue( 0 ) &&
                !record.getItem< ParserKeywords::COMPSEGS::DISTANCE_END >().hasValue( 0 ) ) {
                throw std::runtime_error("the direction has to be specified when DISTANCE_END in the record is not specified");
            }

            if( record.getItem< ParserKeywords::COMPSEGS::END_IJK >().hasValue( 0 ) &&
               !record.getItem< ParserKeywords::COMPSEGS::DIRECTION >().hasValue( 0 ) ) {
                throw std::runtime_error("the direction has to be specified when END_IJK in the record is specified");
            }

            /*
             * Defaulted well completion. Must be non-defaulted if DISTANCE_END
             * is set or a range is specified. If not this is effectively ignored.
             */
            WellCompletion::DirectionEnum direction = WellCompletion::X;
            if( record.getItem< ParserKeywords::COMPSEGS::DIRECTION >().hasValue( 0 ) ) {
                direction = WellCompletion::DirectionEnumFromString(record.getItem<ParserKeywords::COMPSEGS::DIRECTION>().get< std::string >(0));
            }

            double center_depth;
            if (!record.getItem<ParserKeywords::COMPSEGS::CENTER_DEPTH>().defaultApplied(0)) {
                center_depth = record.getItem<ParserKeywords::COMPSEGS::CENTER_DEPTH>().getSIDouble(0);
            } else {
                // 0.0 is also the defaulted value
                // which is used to indicate to obtain the final value through related segment
                center_depth = 0.;
            }

            if (center_depth < 0.) {
                //TODO: get the depth from COMPDAT data.
                throw std::runtime_error("this way to obtain CENTER_DISTANCE not implemented yet either!");
            }

            int segment_number;
            if (record.getItem<ParserKeywords::COMPSEGS::SEGMENT_NUMBER>().hasValue(0)) {
                segment_number = record.getItem<ParserKeywords::COMPSEGS::SEGMENT_NUMBER>().get< int >(0);
            } else {
                segment_number = 0;
                // will decide the segment number based on the distance in a process later.
            }

            if (!record.getItem<ParserKeywords::COMPSEGS::END_IJK>().hasValue(0)) { // only one compsegs
                compsegs.emplace_back( I, J, K,
                                       branch,
                                       distance_start, distance_end,
                                       direction,
                                       center_depth,
                                       segment_number );
            } else { // a range is defined. genrate a range of Compsegs
                throw std::runtime_error("entering COMPSEGS entries with a range is not supported yet!");
            }
        }

        return compsegs;
    }
Esempio n. 7
0
VFPProdTable::VFPProdTable( const DeckKeyword& table, const UnitSystem& deck_unit_system) {
    using ParserKeywords::VFPPROD;

    //Check that the table has enough records
    if (table.size() < 7) {
        throw std::invalid_argument("VFPPROD table does not appear to have enough records to be valid");
    }

    //Get record 1, the metadata for the table
    const auto& header = table.getRecord(0);

    //Get the different header items
    m_table_num   = header.getItem<VFPPROD::TABLE>().get< int >(0);
    m_datum_depth = header.getItem<VFPPROD::DATUM_DEPTH>().getSIDouble(0);

    m_flo_type = Opm::getFloType(header.getItem<VFPPROD::RATE_TYPE>());
    m_wfr_type = Opm::getWFRType(header.getItem<VFPPROD::WFR>());
    m_gfr_type = Opm::getGFRType(header.getItem<VFPPROD::GFR>());

    //Not used, but check that PRESSURE_DEF is indeed THP
    std::string quantity_string = header.getItem<VFPPROD::PRESSURE_DEF>().get< std::string >(0);
    if (quantity_string != "THP") {
        throw std::invalid_argument("PRESSURE_DEF is required to be THP");
    }

    m_alq_type = Opm::getALQType(header.getItem<VFPPROD::ALQ_DEF>());

    //Check units used for this table
    std::string units_string = "";
    if (header.getItem<VFPPROD::UNITS>().hasValue(0)) {
        units_string = header.getItem<VFPPROD::UNITS>().get< std::string >(0);
    }
    else {
        //If units does not exist in record, the default value is the
        //unit system of the deck itself: do nothing...
    }

    if (units_string != "") {
        UnitSystem::UnitType table_unit_type;

        //FIXME: Only metric and field supported at the moment.
        //Need to change all of the convertToSI functions to support LAB/PVT-M

        if (units_string == "METRIC") {
            table_unit_type = UnitSystem::UnitType::UNIT_TYPE_METRIC;
        }
        else if (units_string == "FIELD") {
            table_unit_type = UnitSystem::UnitType::UNIT_TYPE_FIELD;
        }
        else if (units_string == "LAB") {
            table_unit_type = UnitSystem::UnitType::UNIT_TYPE_LAB;
        }
        else if (units_string == "PVT-M") {
            throw std::invalid_argument("Unsupported UNITS string: 'PVT-M'");
        }
        else {
            throw std::invalid_argument("Invalid UNITS string");
        }

        //Sanity check
        if(table_unit_type != deck_unit_system.getType()) {
            throw std::invalid_argument("Deck units are not equal VFPPROD table units.");
        }
    }

    //Quantity in the body of the table
    std::string body_string = header.getItem<VFPPROD::BODY_DEF>().get< std::string >(0);
    if (body_string == "TEMP") {
        throw std::invalid_argument("Invalid BODY_DEF string: TEMP not supported");
    }
    else if (body_string == "BHP") {

    }
    else {
        throw std::invalid_argument("Invalid BODY_DEF string");
    }


    //Get actual rate / flow values
    m_flo_data = table.getRecord(1).getItem<VFPPROD::FLOW_VALUES>().getData< double >();
    convertFloToSI(m_flo_type, m_flo_data, deck_unit_system);

    //Get actual tubing head pressure values
    m_thp_data = table.getRecord(2).getItem<VFPPROD::THP_VALUES>().getData< double >();
    convertTHPToSI(m_thp_data, deck_unit_system);

    //Get actual water fraction values
    m_wfr_data = table.getRecord(3).getItem<VFPPROD::WFR_VALUES>().getData< double >();
    convertWFRToSI(m_wfr_type, m_wfr_data, deck_unit_system);

    //Get actual gas fraction values
    m_gfr_data = table.getRecord(4).getItem<VFPPROD::GFR_VALUES>().getData< double >();
    convertGFRToSI(m_gfr_type, m_gfr_data, deck_unit_system);

    //Get actual gas fraction values
    m_alq_data = table.getRecord(5).getItem<VFPPROD::ALQ_VALUES>().getData< double >();

    //Finally, read the actual table itself.
    size_t nt = m_thp_data.size();
    size_t nw = m_wfr_data.size();
    size_t ng = m_gfr_data.size();
    size_t na = m_alq_data.size();
    size_t nf = m_flo_data.size();
    extents shape;
    shape[0] = nt;
    shape[1] = nw;
    shape[2] = ng;
    shape[3] = na;
    shape[4] = nf;
    m_data.resize(shape);
    std::fill_n(m_data.data(), m_data.num_elements(), std::nan("0"));

    //Check that size of table matches size of axis:
    if (table.size() != nt*nw*ng*na + 6) {
        throw std::invalid_argument("VFPPROD table does not contain enough records.");
    }

    //FIXME: Unit for TEMP=Tubing head temperature is not Pressure, see BODY_DEF
    const double table_scaling_factor = deck_unit_system.parse("Pressure").getSIScaling();
    for (size_t i=6; i<table.size(); ++i) {
        const auto& record = table.getRecord(i);
        //Get indices (subtract 1 to get 0-based index)
        int t = record.getItem<VFPPROD::THP_INDEX>().get< int >(0) - 1;
        int w = record.getItem<VFPPROD::WFR_INDEX>().get< int >(0) - 1;
        int g = record.getItem<VFPPROD::GFR_INDEX>().get< int >(0) - 1;
        int a = record.getItem<VFPPROD::ALQ_INDEX>().get< int >(0) - 1;

        //Rest of values (bottom hole pressure or tubing head temperature) have index of flo value
        const std::vector<double>& bhp_tht = record.getItem<VFPPROD::VALUES>().getData< double >();

        if (bhp_tht.size() != nf) {
            throw std::invalid_argument("VFPPROD table does not contain enough FLO values.");
        }

        for (size_t f=0; f<bhp_tht.size(); ++f) {
            //Check that all data is within reasonable ranges, defined to be up-to 1.0e10...
            if (bhp_tht[f] > 1.0e10) {
                //TODO: Replace with proper log message
                std::cerr << "VFPPROD element ["
                        << t << "," << w << "," << g << "," << a << "," << f
                        << "]=" << bhp_tht[f] << " too large" << std::endl;
            }
            m_data[t][w][g][a][f] = table_scaling_factor*bhp_tht[f];
        }
    }

    check(table, table_scaling_factor);
}