From fe50050e0eb50b95b83f64ac7cf5f4947ceb7266 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Tue, 3 Nov 2015 15:34:10 +0100 Subject: [PATCH] adding the structure Compsegs limitations for now: 1. The input with a range is not supported yet. 2. More than one completion for a segment is not supported yet. 3. Calculating distance based on thickness of grid block is not supported yet. 4. Calculting completion depth based on COMPDAT is not supported yet. --- opm/parser/eclipse/CMakeLists.txt | 2 + .../EclipseState/Schedule/Compsegs.cpp | 140 ++++++++++++++++++ .../EclipseState/Schedule/Compsegs.hpp | 61 ++++++++ 3 files changed, 203 insertions(+) create mode 100644 opm/parser/eclipse/EclipseState/Schedule/Compsegs.cpp create mode 100644 opm/parser/eclipse/EclipseState/Schedule/Compsegs.hpp diff --git a/opm/parser/eclipse/CMakeLists.txt b/opm/parser/eclipse/CMakeLists.txt index 04af26651..0c7c9c516 100644 --- a/opm/parser/eclipse/CMakeLists.txt +++ b/opm/parser/eclipse/CMakeLists.txt @@ -96,6 +96,7 @@ EclipseState/Schedule/WellInjectionProperties.cpp EclipseState/Schedule/WellPolymerProperties.cpp EclipseState/Schedule/Segment.cpp EclipseState/Schedule/SegmentSet.cpp +EclipseState/Schedule/Compsegs.cpp EclipseState/Schedule/WellSet.cpp EclipseState/Schedule/Group.cpp EclipseState/Schedule/Completion.cpp @@ -191,6 +192,7 @@ EclipseState/Schedule/WellInjectionProperties.hpp EclipseState/Schedule/WellPolymerProperties.hpp EclipseState/Schedule/Segment.hpp EclipseState/Schedule/SegmentSet.hpp +EclipseState/Schedule/Compsegs.hpp EclipseState/Schedule/WellSet.hpp EclipseState/Schedule/Group.hpp EclipseState/Schedule/DynamicState.hpp diff --git a/opm/parser/eclipse/EclipseState/Schedule/Compsegs.cpp b/opm/parser/eclipse/EclipseState/Schedule/Compsegs.cpp new file mode 100644 index 000000000..e6e0e15c6 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/Compsegs.cpp @@ -0,0 +1,140 @@ +/* + Copyright 2015 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#include +#include +#include + +namespace Opm { + + + Compsegs::Compsegs(int i_in, int j_in, int k_in, int branch_number_in, double distance_start_in, double distance_end_in, + WellCompletion::DirectionEnum dir_in, double center_depth_in, double thermal_length_in, int segment_number_in) + : m_i(i_in), + m_j(j_in), + m_k(k_in), + m_branch_number(branch_number_in), + m_distance_start(distance_start_in), + m_distance_end(distance_end_in), + m_dir(dir_in), + m_center_depth(center_depth_in), + m_thermal_length(thermal_length_in), + m_segment_number(segment_number_in) + { + } + + std::vector> Compsegs::compsegsFromCOMPSEGSKeyword(DeckKeywordConstPtr compsegsKeyword, + EclipseGridConstPtr grid) { + // the thickness of grid cells will be required in the future for more complete support. + // Silence warning about unused argument + static_cast(grid); + + // only handle the second record here + // The first record here only contains the well name + std::vector> compsegs; + + for (size_t recordIndex = 1; recordIndex < compsegsKeyword->size(); ++recordIndex) { + DeckRecordConstPtr record = compsegsKeyword->getRecord(recordIndex); + // following the coordinate rule for completions + const int I = record->getItem("I")->getInt(0) - 1; + const int J = record->getItem("J")->getInt(0) - 1; + const int K = record->getItem("K")->getInt(0) - 1; + const int branch = record->getItem("BRANCH")->getInt(0); + + double distance_start; + double distance_end; + if (record->getItem("DISTANCE_START")->hasValue(0)) { + distance_start = record->getItem("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("DISTANCE_END")->hasValue(0)) { + distance_end = record->getItem("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!"); + } + + WellCompletion::DirectionEnum direction; + if (record->getItem("DIRECTION")->hasValue(0)) { + direction = WellCompletion::DirectionEnumFromString(record->getItem("DIRECTION")->getString(0)); + } else if (!record->getItem("DISTANCE_END")->hasValue(0)) { + throw std::runtime_error("the direction has to be specified when DISTANCE_END in the record is not specified"); + } + + int end_IJK; + if (record->getItem("END_IJK")->hasValue(0)) { + // following the coordinate rule for completions + end_IJK = record->getItem("END_IJK")->getInt(0) - 1; + if (!record->getItem("DIRECTION")->hasValue(0)) { + throw std::runtime_error("the direction has to be specified when END_IJK in the record is specified"); + } + } else { + // only one completion is specified here + end_IJK = -1; + } + + double center_depth; + if (!record->getItem("CENTER_DEPTH")->defaultApplied(0)) { + center_depth = record->getItem("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!"); + } + + double thermal_length; + if (!record->getItem("THERMAL_LENGTH")->defaultApplied(0)) { + thermal_length = record->getItem("THERMAL_LENGTH")->getSIDouble(0); + } else { + //TODO: get the thickness of the grid block in the direction of penetration + throw std::runtime_error("this way to obtain THERMAL_LENGTH not implemented yet!"); + } + + int segment_number; + if (record->getItem("SEGMENT_NUMBER")->hasValue(0)) { + segment_number = record->getItem("SEGMENT_NUMBER")->getInt(0); + } else { + segment_number = 0; + // will decide the segment number based on the distance in a process later. + } + + if (end_IJK < 0) { // only one compsegs + CompsegsPtr new_compsegs = std::make_shared(I, J, K, branch, distance_start, distance_end, + direction, center_depth, thermal_length, segment_number); + compsegs.push_back(new_compsegs); + } 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; + } + +} diff --git a/opm/parser/eclipse/EclipseState/Schedule/Compsegs.hpp b/opm/parser/eclipse/EclipseState/Schedule/Compsegs.hpp new file mode 100644 index 000000000..49952ebd7 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/Compsegs.hpp @@ -0,0 +1,61 @@ +/* + Copyright 2015 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + + +#ifndef COMPSEGS_HPP_ +#define COMPSEGS_HPP_ + +#include +#include + +#include +#include +#include +#include + +namespace Opm { + + struct Compsegs { + int m_i; + int m_j; + int m_k; + int m_branch_number; + double m_distance_start; + double m_distance_end; + + WellCompletion::DirectionEnum m_dir; + double m_center_depth; + double m_thermal_length; + int m_segment_number; + + Compsegs(int i_in, int j_in, int k_in, int branch_number_in, double distance_start_in, double distance_end_in, + WellCompletion::DirectionEnum dir_in, double center_depth_in, double thermal_length_in, int segment_number_in); + + static std::vector> compsegsFromCOMPSEGSKeyword(DeckKeywordConstPtr compsegsKeyword, + EclipseGridConstPtr grid); + + }; + + typedef std::shared_ptr CompsegsPtr; + typedef std::shared_ptr CompsegsConstPtr; +} + + + +#endif /* COMPSEGS_HPP_ */