Compare commits
306 Commits
testing/20
...
release/su
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b900441ac6 | ||
|
|
76f709aa70 | ||
|
|
57d19c9cdb | ||
|
|
e9756c3ee5 | ||
|
|
19c81fad9c | ||
|
|
ecca175ccd | ||
|
|
2caf82baff | ||
|
|
d82be29745 | ||
|
|
8eb10b33ce | ||
|
|
42d08db25b | ||
|
|
d7d3d2538a | ||
|
|
e0fad15f0a | ||
|
|
4c2105f85c | ||
|
|
981e6c9b22 | ||
|
|
4e83b63a0d | ||
|
|
4c1333fb4f | ||
|
|
6db8a45d88 | ||
|
|
c33f69fd1b | ||
|
|
bb5b2f4232 | ||
|
|
ebe2f28c67 | ||
|
|
414661b898 | ||
|
|
4e00897117 | ||
|
|
98133f44fc | ||
|
|
1574d7714d | ||
|
|
3c41d4c17a | ||
|
|
ef606711f2 | ||
|
|
ed9827bfcf | ||
|
|
fcadc69e49 | ||
|
|
27eaeb2ec9 | ||
|
|
420b66822b | ||
|
|
9913cb8600 | ||
|
|
c874c8b6ea | ||
|
|
6ca6f27640 | ||
|
|
bd4e872230 | ||
|
|
3a9bab6285 | ||
|
|
30e2577f31 | ||
|
|
959502e8cd | ||
|
|
4a3c6b2058 | ||
|
|
29db657757 | ||
|
|
91734f13c4 | ||
|
|
b4c86e73af | ||
|
|
f3a82ddd70 | ||
|
|
4174602da2 | ||
|
|
749353a4b0 | ||
|
|
a8db1f155c | ||
|
|
59b4ca4b20 | ||
|
|
261f7c3c03 | ||
|
|
a1214ba49e | ||
|
|
d9585d6585 | ||
|
|
a668248aa1 | ||
|
|
d40177dacb | ||
|
|
67acaaa637 | ||
|
|
33c5b79d98 | ||
|
|
7790fe743e | ||
|
|
40a2e848cb | ||
|
|
7f6fd34fd3 | ||
|
|
586f296de0 | ||
|
|
8a2c2304e7 | ||
|
|
9df659370c | ||
|
|
66650a20fb | ||
|
|
eae4a080cd | ||
|
|
eb5454aeaf | ||
|
|
dc0ccc010a | ||
|
|
aa63d772d7 | ||
|
|
91afb0b656 | ||
|
|
666cc9210b | ||
|
|
bdd82445d2 | ||
|
|
bf9a142b6d | ||
|
|
9bbacfe710 | ||
|
|
982b221753 | ||
|
|
a4d0bb685b | ||
|
|
3429db8fc1 | ||
|
|
fc0e61518b | ||
|
|
b7eefe8b18 | ||
|
|
0d5b3a5285 | ||
|
|
3eef43b904 | ||
|
|
db90ecd88c | ||
|
|
68769e5b1d | ||
|
|
85949d44ac | ||
|
|
690e00a079 | ||
|
|
cf42146d84 | ||
|
|
23cbe9035b | ||
|
|
2cd6fa2f49 | ||
|
|
1b1f7b807d | ||
|
|
bf52e6d123 | ||
|
|
c6bbe5d24b | ||
|
|
ad001df804 | ||
|
|
69e921b33a | ||
|
|
875626b738 | ||
|
|
7e05d51e6f | ||
|
|
0dc80689c0 | ||
|
|
ae8b81c7ae | ||
|
|
ba0675997a | ||
|
|
15c473e3bb | ||
|
|
6465b5b23c | ||
|
|
9e93dc5af2 | ||
|
|
481123ed25 | ||
|
|
4968c35ad8 | ||
|
|
f6136e69fe | ||
|
|
6832788eef | ||
|
|
4c0776e3d2 | ||
|
|
00d1607347 | ||
|
|
142c0a12c3 | ||
|
|
25fbff2632 | ||
|
|
1833ee2c43 | ||
|
|
f5851bcb92 | ||
|
|
5632fc6662 | ||
|
|
8375516c82 | ||
|
|
bf6732559f | ||
|
|
3b951985ec | ||
|
|
9c98b5ceb4 | ||
|
|
161f555bc0 | ||
|
|
39a6871b1d | ||
|
|
175da3d436 | ||
|
|
cf61068ad1 | ||
|
|
bf7b2697ee | ||
|
|
9098316775 | ||
|
|
1249ef0dd2 | ||
|
|
2b2d4901d1 | ||
|
|
d4740ae249 | ||
|
|
49eda9fc72 | ||
|
|
3ea522d7ba | ||
|
|
70172f5771 | ||
|
|
91306c12f4 | ||
|
|
67f96f4996 | ||
|
|
39bb94c2c8 | ||
|
|
7955805dd5 | ||
|
|
74c06ea703 | ||
|
|
71b0c2883f | ||
|
|
334dbe4e1f | ||
|
|
53252e6694 | ||
|
|
e27df951f6 | ||
|
|
1062fb836b | ||
|
|
343d060118 | ||
|
|
b15fab221b | ||
|
|
88b16f981c | ||
|
|
dc3f1cbf40 | ||
|
|
01e3aa377c | ||
|
|
44102f83a0 | ||
|
|
2c13cdfa18 | ||
|
|
1d22e3b0ed | ||
|
|
2add79d122 | ||
|
|
0cfbfb9957 | ||
|
|
92f65b7958 | ||
|
|
79037f93b2 | ||
|
|
633a5883f7 | ||
|
|
63590f95b0 | ||
|
|
e783eaafc0 | ||
|
|
e341bd1c08 | ||
|
|
f9ce82547c | ||
|
|
b349b3b217 | ||
|
|
983ed5fcb8 | ||
|
|
f414f5b8ad | ||
|
|
7c52f6f5a8 | ||
|
|
188eb23911 | ||
|
|
72ad2eaa7f | ||
|
|
92870dc1e9 | ||
|
|
2d43ccaf8f | ||
|
|
b2e0eb2507 | ||
|
|
5085fb35c0 | ||
|
|
8d33ec55bd | ||
|
|
d70b86484d | ||
|
|
0089fa9287 | ||
|
|
6b80dd10e6 | ||
|
|
f4a9298cf4 | ||
|
|
7de217b8fb | ||
|
|
039fdb70de | ||
|
|
2f7a0bc532 | ||
|
|
fda1719eab | ||
|
|
c0e9b71eec | ||
|
|
d93bd35b8e | ||
|
|
afab0103e3 | ||
|
|
62f39dacce | ||
|
|
1d7a12442e | ||
|
|
d69bf47a28 | ||
|
|
7064b96260 | ||
|
|
e0d5711f8e | ||
|
|
3677f470fb | ||
|
|
44409c7a30 | ||
|
|
7c1e868973 | ||
|
|
0768c5a8b3 | ||
|
|
ea7cb8d2c6 | ||
|
|
6858bd4578 | ||
|
|
1b8680df7d | ||
|
|
316324a78e | ||
|
|
2bf33c30d8 | ||
|
|
862b3450d3 | ||
|
|
082476f840 | ||
|
|
49655b464c | ||
|
|
1432367e07 | ||
|
|
e4912d4fcf | ||
|
|
d0e5f8f470 | ||
|
|
65ef90f471 | ||
|
|
bcb852e8f2 | ||
|
|
927bf09688 | ||
|
|
6921801eec | ||
|
|
f21e2035c4 | ||
|
|
c1ffeeef53 | ||
|
|
e27abdd1a0 | ||
|
|
8b8285ae2b | ||
|
|
bdcb227a53 | ||
|
|
88f043645a | ||
|
|
ad55655a08 | ||
|
|
6af3194c6c | ||
|
|
bb96eb9b70 | ||
|
|
baae4a3faf | ||
|
|
36c3080f85 | ||
|
|
c35832b155 | ||
|
|
ca9da29c53 | ||
|
|
1ba51534ae | ||
|
|
01abada947 | ||
|
|
212a1fde5f | ||
|
|
0b8adcbee3 | ||
|
|
1d755859a6 | ||
|
|
5d3125c532 | ||
|
|
971d300243 | ||
|
|
199b7d710a | ||
|
|
d60787188e | ||
|
|
819ad1bf9e | ||
|
|
3cbc40bd4d | ||
|
|
8e92a84c09 | ||
|
|
ff8ab1c1dc | ||
|
|
9d45632628 | ||
|
|
089b58f101 | ||
|
|
967e3ad3af | ||
|
|
e2d748906e | ||
|
|
95179f393c | ||
|
|
6fee172f16 | ||
|
|
a241a1bd07 | ||
|
|
4348438044 | ||
|
|
8e801a1fae | ||
|
|
2d5d0953ee | ||
|
|
9df3bea857 | ||
|
|
056d6bccb4 | ||
|
|
68e6926355 | ||
|
|
2df9779a62 | ||
|
|
60fb68d3fc | ||
|
|
ae9d5e97c7 | ||
|
|
d958da6542 | ||
|
|
b8c5d8c129 | ||
|
|
e7660b0613 | ||
|
|
7ebadbb055 | ||
|
|
0f485c7801 | ||
|
|
a6ec18cd4e | ||
|
|
af8f8c6bfd | ||
|
|
258bcbc186 | ||
|
|
2260efaad9 | ||
|
|
624dec542a | ||
|
|
7ca8b46167 | ||
|
|
8fbb93497a | ||
|
|
ef5465dcfc | ||
|
|
f9eb32a235 | ||
|
|
f275fd6089 | ||
|
|
decd0b10a9 | ||
|
|
10c9da1a36 | ||
|
|
47141dfabf | ||
|
|
613aafe4ae | ||
|
|
f867d7f82c | ||
|
|
fe060c7f48 | ||
|
|
80154e8f5f | ||
|
|
ae0cb3e5ad | ||
|
|
133f89198f | ||
|
|
03bb4da004 | ||
|
|
e356a16ab2 | ||
|
|
eea23abedd | ||
|
|
5f620f7451 | ||
|
|
c76ee877aa | ||
|
|
fd36bf88fb | ||
|
|
24bd410313 | ||
|
|
984a308e24 | ||
|
|
6ea7a1796d | ||
|
|
ee0d256a12 | ||
|
|
42d7587e1b | ||
|
|
c75a50796b | ||
|
|
1190260d7d | ||
|
|
5b8882d6f0 | ||
|
|
f8e711246f | ||
|
|
5283611695 | ||
|
|
ca8e2f279b | ||
|
|
c49b51ab23 | ||
|
|
7c65850894 | ||
|
|
7279fd5ea8 | ||
|
|
f279c7e374 | ||
|
|
7b1595d0b2 | ||
|
|
8c8290f614 | ||
|
|
3819910396 | ||
|
|
72b39e513a | ||
|
|
04a9e710d5 | ||
|
|
1c771a66fc | ||
|
|
c938765224 | ||
|
|
a37625b2cf | ||
|
|
83331033b5 | ||
|
|
58a5a4e371 | ||
|
|
3655213c40 | ||
|
|
2844aa4468 | ||
|
|
c81e5027c9 | ||
|
|
23950403f1 | ||
|
|
33372a3337 | ||
|
|
c067e48276 | ||
|
|
5d398565c2 | ||
|
|
a9a82e3814 | ||
|
|
3f94b580a2 | ||
|
|
cfc1b29c08 | ||
|
|
264d451d56 | ||
|
|
21eddfbdf2 | ||
|
|
22b38f1031 |
@@ -7,6 +7,7 @@ set(OPM_MACROS_ROOT ${PROJECT_SOURCE_DIR})
|
||||
|
||||
option(ENABLE_ECL_INPUT "Enable eclipse input support?" ON)
|
||||
option(ENABLE_ECL_OUTPUT "Enable eclipse output support?" ON)
|
||||
option(ENABLE_MOCKSIM "Build the mock simulator for io testing" ON)
|
||||
|
||||
# Output implies input
|
||||
if(ENABLE_ECL_OUTPUT)
|
||||
@@ -18,6 +19,7 @@ if(NOT ENABLE_ECL_INPUT)
|
||||
set(ENABLE_ECL_OUTPUT OFF)
|
||||
endif()
|
||||
|
||||
|
||||
# not the same location as most of the other projects; this hook overrides
|
||||
macro (dir_hook)
|
||||
endmacro (dir_hook)
|
||||
@@ -130,6 +132,30 @@ endmacro (install_hook)
|
||||
# all setup common to the OPM library modules is done here
|
||||
include (OpmLibMain)
|
||||
|
||||
if (ENABLE_MOCKSIM)
|
||||
add_library(mocksim
|
||||
msim/src/msim.cpp)
|
||||
target_link_libraries(mocksim opmcommon)
|
||||
target_include_directories(mocksim PUBLIC msim/include)
|
||||
add_executable(msim examples/msim.cpp)
|
||||
target_link_libraries(msim mocksim)
|
||||
|
||||
set(_libs mocksim opmcommon
|
||||
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
|
||||
|
||||
foreach( test test_msim test_msim_ACTIONX )
|
||||
add_executable(${test} "tests/msim/${test}")
|
||||
target_link_libraries(${test} ${_libs})
|
||||
add_test(NAME ${test} COMMAND ${test})
|
||||
set_tests_properties(${test} PROPERTIES WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/tests)
|
||||
|
||||
if(HAVE_DYNAMIC_BOOST_TEST)
|
||||
set_target_properties(${test} PROPERTIES
|
||||
COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Build the compare utilities
|
||||
if(ENABLE_ECL_INPUT)
|
||||
add_library(testutil STATIC
|
||||
|
||||
@@ -46,12 +46,14 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/Deck/DeckOutput.cpp
|
||||
src/opm/parser/eclipse/Deck/Section.cpp
|
||||
src/opm/parser/eclipse/EclipseState/AquiferCT.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Aquifetp.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Aquancon.cpp
|
||||
src/opm/parser/eclipse/EclipseState/checkDeck.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Eclipse3DProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/EclipseConfig.cpp
|
||||
src/opm/parser/eclipse/EclipseState/EclipseState.cpp
|
||||
src/opm/parser/eclipse/EclipseState/EndpointScaling.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Edit/EDITNNC.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/Box.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/BoxManager.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Grid/EclipseGrid.cpp
|
||||
@@ -73,7 +75,13 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/EclipseState/IOConfig/IOConfig.cpp
|
||||
src/opm/parser/eclipse/EclipseState/IOConfig/RestartConfig.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Runspec.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/ActionX.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionAST.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionContext.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/Actions.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionParser.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ActionValue.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Action/ASTNode.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Connection.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellConnections.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Events.cpp
|
||||
@@ -87,12 +95,16 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/SummaryState.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/TimeMap.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Tuning.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/Well.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WList.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WListManager.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellInjectionProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellTestConfig.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/WellTestState.cpp
|
||||
@@ -103,17 +115,19 @@ if(ENABLE_ECL_INPUT)
|
||||
src/opm/parser/eclipse/EclipseState/Tables/JFunc.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/PvtxTable.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/SimpleTable.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/PolyInjTables.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/TableColumn.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/TableContainer.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/TableIndex.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/TableManager.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/TableSchema.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Tables/Tables.cpp
|
||||
src/opm/parser/eclipse/EclipseState/UDQConfig.cpp
|
||||
src/opm/parser/eclipse/EclipseState/UDQParams.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/UDQ.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/UDQExpression.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.cpp
|
||||
src/opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.cpp
|
||||
src/opm/parser/eclipse/Parser/ErrorGuard.cpp
|
||||
src/opm/parser/eclipse/Parser/ParseContext.cpp
|
||||
src/opm/parser/eclipse/Parser/Parser.cpp
|
||||
src/opm/parser/eclipse/Parser/ParserEnums.cpp
|
||||
@@ -153,7 +167,6 @@ if(ENABLE_ECL_OUTPUT)
|
||||
src/opm/output/eclipse/LogiHEAD.cpp
|
||||
src/opm/output/eclipse/RestartIO.cpp
|
||||
src/opm/output/eclipse/Summary.cpp
|
||||
src/opm/output/eclipse/SummaryState.cpp
|
||||
src/opm/output/eclipse/Tables.cpp
|
||||
src/opm/output/eclipse/RegionCache.cpp
|
||||
src/opm/output/eclipse/RestartValue.cpp
|
||||
@@ -178,6 +191,7 @@ if(ENABLE_ECL_INPUT)
|
||||
tests/parser/ACTIONX.cpp
|
||||
tests/parser/ADDREGTests.cpp
|
||||
tests/parser/AquiferCTTests.cpp
|
||||
tests/parser/AquifetpTests.cpp
|
||||
tests/parser/AqudimsTests.cpp
|
||||
tests/parser/AquanconTests.cpp
|
||||
tests/parser/BoxTests.cpp
|
||||
@@ -206,6 +220,7 @@ if(ENABLE_ECL_INPUT)
|
||||
tests/parser/MULTREGTScannerTests.cpp
|
||||
tests/parser/OrderedMapTests.cpp
|
||||
tests/parser/ParseContextTests.cpp
|
||||
tests/parser/ParseContext_EXIT1.cpp
|
||||
tests/parser/PORVTests.cpp
|
||||
tests/parser/RawKeywordTests.cpp
|
||||
tests/parser/RestartConfigTests.cpp
|
||||
@@ -231,12 +246,16 @@ if(ENABLE_ECL_INPUT)
|
||||
tests/parser/UnitTests.cpp
|
||||
tests/parser/ValueTests.cpp
|
||||
tests/parser/WellSolventTests.cpp
|
||||
tests/parser/WellTracerTests.cpp
|
||||
tests/parser/WellTests.cpp
|
||||
tests/parser/WLIST.cpp
|
||||
tests/parser/WTEST.cpp)
|
||||
endif()
|
||||
if(ENABLE_ECL_OUTPUT)
|
||||
list (APPEND TEST_SOURCE_FILES
|
||||
tests/test_AggregateWellData.cpp
|
||||
#The unit tests are not finished yet, will be added in a separate pullrequest soon
|
||||
#tests/test_AggregateMSWData.cpp
|
||||
tests/test_CharArrayNullTerm.cpp
|
||||
tests/test_EclipseIO.cpp
|
||||
tests/test_DoubHEAD.cpp
|
||||
@@ -273,6 +292,7 @@ if(ENABLE_ECL_OUTPUT)
|
||||
tests/SUMMARY_EFF_FAC.DATA
|
||||
tests/SPE1CASE1.DATA
|
||||
tests/SPE9_CP_PACKED.DATA
|
||||
tests/SOFR_TEST.DATA
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -342,6 +362,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/Units/UnitSystem.hpp
|
||||
opm/parser/eclipse/Units/Units.hpp
|
||||
opm/parser/eclipse/Units/Dimension.hpp
|
||||
opm/parser/eclipse/Parser/ErrorGuard.hpp
|
||||
opm/parser/eclipse/Parser/ParserItem.hpp
|
||||
opm/parser/eclipse/Parser/Parser.hpp
|
||||
opm/parser/eclipse/Parser/ParserRecord.hpp
|
||||
@@ -355,6 +376,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Util/Value.hpp
|
||||
opm/parser/eclipse/EclipseState/Util/OrderedMap.hpp
|
||||
opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp
|
||||
opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/GridDims.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/TransMult.hpp
|
||||
opm/parser/eclipse/EclipseState/Grid/GridProperties.hpp
|
||||
@@ -374,6 +396,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp
|
||||
opm/parser/eclipse/EclipseState/EndpointScaling.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SimpleTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PdvdTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/TlpmixpaTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PvdgTable.hpp
|
||||
@@ -383,8 +406,11 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/Tables/Eqldims.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SpecrockTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PlydhflfTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PlymwinjTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/PlyshlogTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/RsvdTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SkprwatTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SkprpolyTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SpecheatTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/SgcwmisTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Tables/Sof2Table.hpp
|
||||
@@ -434,16 +460,24 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/EclipseConfig.hpp
|
||||
opm/parser/eclipse/EclipseState/Aquancon.hpp
|
||||
opm/parser/eclipse/EclipseState/AquiferCT.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/ActionX.hpp
|
||||
opm/parser/eclipse/EclipseState/Aquifetp.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Action/ActionAST.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Action/ActionContext.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Well.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WellInjectionProperties.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WList.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WListManager.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/DynamicVector.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/Group.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/MessageLimits.hpp
|
||||
@@ -467,7 +501,7 @@ if(ENABLE_ECL_INPUT)
|
||||
opm/parser/eclipse/EclipseState/checkDeck.hpp
|
||||
opm/parser/eclipse/EclipseState/Runspec.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/UDQ.hpp
|
||||
opm/parser/eclipse/EclipseState/UDQConfig.hpp
|
||||
opm/parser/eclipse/EclipseState/UDQParams.hpp
|
||||
opm/parser/eclipse/EclipseState/Schedule/UDQExpression.hpp
|
||||
opm/parser/eclipse/Deck/DeckItem.hpp
|
||||
opm/parser/eclipse/Deck/Deck.hpp
|
||||
@@ -506,7 +540,6 @@ if(ENABLE_ECL_OUTPUT)
|
||||
opm/output/eclipse/RestartIO.hpp
|
||||
opm/output/eclipse/RestartValue.hpp
|
||||
opm/output/eclipse/Summary.hpp
|
||||
opm/output/eclipse/SummaryState.hpp
|
||||
opm/output/eclipse/Tables.hpp
|
||||
opm/output/eclipse/WindowedArray.hpp
|
||||
opm/output/eclipse/WriteRestartHelpers.hpp
|
||||
|
||||
@@ -49,6 +49,7 @@ list(APPEND EXTRA_TESTS EclipseStateTests)
|
||||
foreach (test BoxTest
|
||||
CheckDeckValidity
|
||||
EclipseGridCreateFromDeck
|
||||
EDITNNCTests
|
||||
IncludeTest
|
||||
IntegrationTests
|
||||
IOConfigIntegrationTest
|
||||
|
||||
@@ -7,6 +7,7 @@ set(genkw_SOURCES src/opm/json/JsonObject.cpp
|
||||
src/opm/parser/eclipse/Deck/DeckOutput.cpp
|
||||
src/opm/parser/eclipse/Generator/KeywordGenerator.cpp
|
||||
src/opm/parser/eclipse/Generator/KeywordLoader.cpp
|
||||
src/opm/parser/eclipse/Parser/ErrorGuard.cpp
|
||||
src/opm/parser/eclipse/Parser/ParseContext.cpp
|
||||
src/opm/parser/eclipse/Parser/ParserEnums.cpp
|
||||
src/opm/parser/eclipse/Parser/ParserItem.cpp
|
||||
|
||||
46
cmake/Modules/FindAlberta.cmake
Normal file
46
cmake/Modules/FindAlberta.cmake
Normal file
@@ -0,0 +1,46 @@
|
||||
find_library(ALBERTA_LTDL_LIB
|
||||
NAMES ltdl
|
||||
PATH_SUFFIXES lib lib32 lib64
|
||||
)
|
||||
find_path(ALBERTA_INCLUDE_DIR
|
||||
NAMES alberta/alberta.h
|
||||
PATHS ${ALBERTA_ROOT}
|
||||
PATH_SUFFIXES alberta include NO_DEFAULT_PATH
|
||||
DOC "Include path of Alberta")
|
||||
find_path(ALBERTA_INCLUDE_DIR
|
||||
NAMES
|
||||
alberta/alberta.h
|
||||
PATHS /usr/local /opt
|
||||
PATH_SUFFIXES alberta)
|
||||
#look for libraries
|
||||
find_library(ALBERTA_UTIL_LIB
|
||||
NAMES alberta_util alberta_utilities
|
||||
PATHS ${ALBERTA_ROOT}
|
||||
PATH_SUFFIXES lib lib32 lib64
|
||||
NO_DEFAULT_PATH)
|
||||
find_library(ALBERTA_UTIL_LIB
|
||||
NAMES alberta_util alberta_utilities
|
||||
PATH_SUFFIXES lib lib32 lib64)
|
||||
|
||||
foreach(dim RANGE 1 9)
|
||||
find_library(ALBERTA_${dim}D_LIB alberta_${dim}d
|
||||
PATHS ${ALBERTA_ROOT}
|
||||
PATH_SUFFIXES lib lib32 lib64
|
||||
Cache FILEPATH DOC "Alberta lib for ${dim}D" NO_DEFAULT_PATH)
|
||||
find_library(ALBERTA_${dim}D_LIB alberta_${dim}d PATH_SUFFIXES lib lib32 lib64)
|
||||
if(ALBERTA_${dim}D_LIB)
|
||||
set(ALBERTA_LIBRARIES ${ALBERTA_LIBRARIES} ${ALBERTA_${dim}D_LIB})
|
||||
endif()
|
||||
endforeach(dim RANGE 1 9)
|
||||
|
||||
if(ALBERTA_LIBRARIES AND ALBERTA_INCLUDE_DIR)
|
||||
set(ALBERTA_INCLUDE_DIRS ${ALBERTA_INCLUDE_DIR})
|
||||
set(ALBERTA_LIBRARIES ${ALBERTA_LIBRARIES} ${ALBERTA_UTIL_LIB} ${ALBERTA_LTDL_LIB})
|
||||
set(ALBERTA_FOUND ON)
|
||||
set(Alberta_FOUND ON)
|
||||
set(HAVE_ALBERTA 1)
|
||||
set(DUNE_ALBERTA_VERSION 0x300)
|
||||
else()
|
||||
set(ALBERTA_FOUND OFF)
|
||||
set(Alberta_FOUND OFF)
|
||||
endif()
|
||||
@@ -27,7 +27,8 @@ find_opm_package (
|
||||
dune-geometry REQUIRED;
|
||||
dune-uggrid;
|
||||
MPI;
|
||||
UG
|
||||
UG;
|
||||
Alberta
|
||||
"
|
||||
# header to search for
|
||||
"dune/grid/onedgrid.hh"
|
||||
@@ -55,7 +56,8 @@ int main (void) {
|
||||
HAVE_AMIRAMESH;
|
||||
HAVE_ALBERTA;
|
||||
HAVE_STDINT_H;
|
||||
DUNE_GRID_EXPERIMENTAL_GRID_EXTENSIONS
|
||||
DUNE_GRID_EXPERIMENTAL_GRID_EXTENSIONS;
|
||||
DUNE_ALBERTA_VERSION
|
||||
")
|
||||
|
||||
#debug_find_vars ("dune-grid")
|
||||
|
||||
@@ -65,7 +65,7 @@ macro (opm_compile_satellites opm satellite excl_all test_regexp)
|
||||
set_target_properties (${_sat_NAME} PROPERTIES
|
||||
LINK_FLAGS "${${opm}_LINKER_FLAGS_STR}"
|
||||
)
|
||||
if(HAVE_DYNAMIC_BOOST_TEST AND NOT (${opm} STREQUAL "opm-parser" AND NOT BUILD_SHARED_LIBS))
|
||||
if(HAVE_DYNAMIC_BOOST_TEST)
|
||||
set_target_properties (${_sat_NAME} PROPERTIES
|
||||
COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK
|
||||
)
|
||||
@@ -316,6 +316,11 @@ macro(opm_add_test TestName)
|
||||
# run-only case occurs if the binary is already compiled by an
|
||||
# earlier test.)
|
||||
add_executable("${CURTEST_EXE_NAME}" ${CURTEST_EXCLUDE_FROM_ALL} ${CURTEST_SOURCES})
|
||||
if(HAVE_DYNAMIC_BOOST_TEST)
|
||||
set_target_properties (${CURTEST_EXE_NAME} PROPERTIES
|
||||
COMPILE_DEFINITIONS BOOST_TEST_DYN_LINK
|
||||
)
|
||||
endif()
|
||||
target_link_libraries (${CURTEST_EXE_NAME} ${CURTEST_LIBRARIES})
|
||||
|
||||
if(CURTEST_DEPENDS)
|
||||
@@ -344,12 +349,12 @@ macro(opm_add_test TestName)
|
||||
|
||||
# specify the dependencies between the tests
|
||||
if (CURTEST_TEST_DEPENDS)
|
||||
set_tests_properties(${TestName} PROPERTIES DEPENDS "${CURTEST_TEST_DEPENDS}")
|
||||
set_tests_properties(${_FANCY} PROPERTIES DEPENDS "${CURTEST_TEST_DEPENDS}")
|
||||
endif()
|
||||
|
||||
# tell ctest how many cores it should reserve to run the test
|
||||
if (CURTEST_PROCESSORS)
|
||||
set_tests_properties(${TestName} PROPERTIES PROCESSORS "${CURTEST_PROCESSORS}")
|
||||
set_tests_properties(${_FANCY} PROPERTIES PROCESSORS "${CURTEST_PROCESSORS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
2
debian/changelog
vendored
2
debian/changelog
vendored
@@ -1,4 +1,4 @@
|
||||
opm-common (2015.10-1~trusty) trusty; urgency=medium
|
||||
opm-common (2019.04-pre~xenial) xenial; urgency=medium
|
||||
|
||||
* New release
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
Module: opm-common
|
||||
Description: Open Porous Media Initiative shared infrastructure
|
||||
Version: 2018.10-pre
|
||||
Label: 2018.10-pre
|
||||
Version: 2019.04-pre
|
||||
Label: 2019.04-pre
|
||||
Maintainer: opm@opm-project.org
|
||||
MaintainerName: OPM community
|
||||
Url: http://opm-project.org
|
||||
|
||||
53
examples/msim.cpp
Normal file
53
examples/msim.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Copyright 2013 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <opm/output/eclipse/EclipseIO.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
|
||||
#include <opm/msim/msim.hpp>
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
std::string deck_file = argv[1];
|
||||
Opm::Parser parser;
|
||||
Opm::ParseContext parse_context;
|
||||
Opm::ErrorGuard error_guard;
|
||||
|
||||
Opm::Deck deck = parser.parseFile(deck_file, parse_context, error_guard);
|
||||
Opm::EclipseState state(deck, parse_context, error_guard);
|
||||
Opm::Schedule schedule(deck, state.getInputGrid(), state.get3DProperties(), state.runspec(), parse_context, error_guard);
|
||||
Opm::SummaryConfig summary_config(deck, schedule, state.getTableManager(), parse_context, error_guard);
|
||||
|
||||
if (error_guard) {
|
||||
error_guard.dump();
|
||||
error_guard.terminate();
|
||||
}
|
||||
|
||||
Opm::msim msim(state);
|
||||
Opm::EclipseIO io(state, state.getInputGrid(), schedule, summary_config);
|
||||
msim.run(schedule, io);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
@@ -30,16 +31,16 @@
|
||||
|
||||
inline void loadDeck( const char * deck_file) {
|
||||
Opm::ParseContext parseContext;
|
||||
Opm::ErrorGuard errors;
|
||||
Opm::Parser parser;
|
||||
|
||||
std::cout << "Loading deck: " << deck_file << " ..... "; std::cout.flush();
|
||||
auto deck = parser.parseFile(deck_file, parseContext);
|
||||
auto deck = parser.parseFile(deck_file, parseContext, errors);
|
||||
std::cout << "parse complete - creating EclipseState .... "; std::cout.flush();
|
||||
Opm::EclipseState state( deck, parseContext );
|
||||
Opm::Schedule schedule( deck, state.getInputGrid(), state.get3DProperties(), state.runspec().phases(), parseContext);
|
||||
Opm::SummaryConfig summary( deck, schedule, state.getTableManager( ), parseContext );
|
||||
Opm::EclipseState state( deck, parseContext, errors );
|
||||
Opm::Schedule schedule( deck, state.getInputGrid(), state.get3DProperties(), state.runspec(), parseContext, errors);
|
||||
Opm::SummaryConfig summary( deck, schedule, state.getTableManager( ), parseContext, errors );
|
||||
std::cout << "complete." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/InputErrorAction.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
@@ -29,9 +30,10 @@
|
||||
|
||||
inline void pack_deck( const char * deck_file, std::ostream& os) {
|
||||
Opm::ParseContext parseContext(Opm::InputError::WARN);
|
||||
Opm::ErrorGuard errors;
|
||||
Opm::Parser parser;
|
||||
|
||||
auto deck = parser.parseFile(deck_file, parseContext);
|
||||
auto deck = parser.parseFile(deck_file, parseContext, errors);
|
||||
os << deck;
|
||||
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class ECLRegressionTest: public ECLFilesComparator {
|
||||
// Accept extra keywords: If this switch is set to true the comparison
|
||||
// of restart files will ignore extra keywords which are only present
|
||||
// in the new simulation.
|
||||
void setAcceptExtraKeywords(bool acceptExtraKeywords) { this->acceptExtraKeywords = acceptExtraKeywords; }
|
||||
void setAcceptExtraKeywords(bool acceptExtraKeywordsArg) { this->acceptExtraKeywords = acceptExtraKeywordsArg; }
|
||||
|
||||
//! \brief Compares grid properties of the two cases.
|
||||
// gridCompare() checks if both the number of active and global cells in the two cases are the same. If they are, and volumecheck is true, all cells are looped over to calculate the cell volume deviation for the two cases. If the both the relative and absolute deviation exceeds the tolerances, an exception is thrown.
|
||||
|
||||
@@ -281,6 +281,7 @@ int main(int argc, char** argv) {
|
||||
compare.doAnalysis(analysis);
|
||||
compare.setPrintKeywords(printKeywords);
|
||||
compare.setIsRestartFile(restartFile);
|
||||
compare.setAllowDifferentNumberOfKeywords(acceptExtraKeywords);
|
||||
if(specificKeyword){
|
||||
compare.getRegressionTest(keyword);
|
||||
}
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "summaryRegressionTest.hpp"
|
||||
#include "summaryIntegrationTest.hpp"
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <getopt.h>
|
||||
|
||||
void printHelp(){
|
||||
std::cout << "\n\nThe program can handle both unified and non-unified summary files."<< std::endl;
|
||||
std::cout <<"In the case of non-unified summary files all the files must be located in the same directory. Only the basename (full path without extension) is needed as input." << std::endl << std::endl;
|
||||
std::cout << "\nThe program takes four arguments" << std::endl;
|
||||
std::cout << "1) <path to file1>/<base_name>, basename without extension" << std::endl;
|
||||
std::cout << "2) <path to file2>/<base_name>, basename without extension" << std::endl;
|
||||
std::cout << "3) absolute tolerance" << std::endl;
|
||||
std::cout << "4) relative tolerance (between 0 and 1)" << std::endl;
|
||||
std::cout << "The program will only throw an exception when both the absolute and relative tolerance are exceeded." << std::endl;
|
||||
std::cout << "The program is capable of performing both a regression test and an integration test, \nhowever only one type of test at a time. ";
|
||||
std::cout << "By default the program will run a regression test."<< std::endl;
|
||||
std::cout << "\nThe program have command line options:" << std::endl;
|
||||
std::cout << "-a \tRun a full analysis of errors." << std::endl;
|
||||
std::cout << "-h \t\tPrint help message." << std::endl << std::endl;
|
||||
std::cout << "For the regression test: " << std::endl;
|
||||
std::cout << "-r \t\tChoosing regression test (this is default)."<< std::endl;
|
||||
std::cout << "-k keyword \tSpecify a specific keyword to compare, for example - k WOPR:PRODU1."<< std::endl;
|
||||
std::cout << "-p \t\tWill print the keywords of the files." << std::endl;
|
||||
std::cout << "-R \t\tWill allow comparison between a restarted simulation and a normal simulation. The files must end at the same time." << std::endl << std::endl;
|
||||
std::cout << "For the integration test:"<< std::endl;
|
||||
std::cout << "-i \t\tChoosing integration test." << std::endl;
|
||||
std::cout << "-d \t\tThe program will not throw an exception when the volume error ratio exceeds the limit." << std::endl;
|
||||
std::cout << "-g \t\tWill print the vector with the greatest error ratio." << std::endl;
|
||||
std::cout << "-k keyword \tSpecify a specific keyword to compare, for example - k WOPR:PRODU1."<< std::endl;
|
||||
std::cout << "-K \t\tWill not allow different amount of keywords in the two files. Throws an exception if the amount are different." << std::endl;
|
||||
std::cout << "-m mainVar \tWill calculate the error ratio for one main variable. Valid input is WOPR, WWPR, WGPR or WBHP." << std::endl;
|
||||
std::cout << "-n \tDo not throw on errors." << std::endl;
|
||||
std::cout << "-p \t\tWill print the keywords of the files." << std::endl;
|
||||
std::cout << "-P keyword \tWill print the summary vectors of a specified kewyord, for example -P WOPR:B-3H." << std::endl;
|
||||
std::cout << "-s int \t\tSets the number of spikes that are allowed for each keyword, for example: -s 5." << std::endl;
|
||||
std::cout << "-v \t\tFor the rate keywords WOPR, WGPR, WWPR and WBHP. Calculates the error volume of \n\t\tthe two summary files. This is printed to screen." << std::endl;
|
||||
std::cout << "-V keyword \tWill calculate the error rate for a specific keyword." << std::endl << std::endl;
|
||||
std::cout << "Suggested combination of command line options:"<< std::endl;
|
||||
std::cout << " -i -g -m mainVariable, will print the vector which have the greatest error ratio of the main variable of interest.\n"<< std::endl;
|
||||
}
|
||||
|
||||
//---------------------------------------------------
|
||||
|
||||
|
||||
int main (int argc, char ** argv){
|
||||
|
||||
//------------------------------------------------
|
||||
//Defines some constants
|
||||
bool specificKeyword = false;
|
||||
bool allowSpikes = false;
|
||||
bool findVolumeError = false;
|
||||
bool integrationTest = false;
|
||||
bool regressionTest = true;
|
||||
bool allowDifferentAmountOfKeywords = true;
|
||||
bool printKeywords = false;
|
||||
bool printSpecificKeyword = false;
|
||||
bool findVectorWithGreatestErrorRatio = false;
|
||||
bool oneOfTheMainVariables = false;
|
||||
bool throwExceptionForTooGreatErrorRatio = true;
|
||||
bool isRestartFile = false;
|
||||
bool throwOnError = true;
|
||||
bool analysis = false;
|
||||
const char* keyword = nullptr;
|
||||
const char* mainVariable = nullptr;
|
||||
int c = 0;
|
||||
int limit = -1;
|
||||
//------------------------------------------------
|
||||
|
||||
//------------------------------------------------
|
||||
//For setting the options selected
|
||||
while ((c = getopt(argc, argv, "dghik:Km:napP:rRs:vV:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
analysis = true;
|
||||
break;
|
||||
case 'd':
|
||||
throwExceptionForTooGreatErrorRatio = false;
|
||||
break;
|
||||
case 'g':
|
||||
findVectorWithGreatestErrorRatio = true;
|
||||
throwExceptionForTooGreatErrorRatio = false;
|
||||
break;
|
||||
case 'h':
|
||||
printHelp();
|
||||
return 0;
|
||||
case 'i':
|
||||
integrationTest = true;
|
||||
regressionTest = false;
|
||||
break;
|
||||
case 'k':
|
||||
specificKeyword = true;
|
||||
keyword = optarg;
|
||||
break;
|
||||
case 'K':
|
||||
allowDifferentAmountOfKeywords = false;
|
||||
break;
|
||||
case 'm':
|
||||
oneOfTheMainVariables = true;
|
||||
mainVariable = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
throwOnError = false;
|
||||
break;
|
||||
case 'p':
|
||||
printKeywords = true;
|
||||
break;
|
||||
case 'P':
|
||||
specificKeyword = true;
|
||||
printSpecificKeyword = true;
|
||||
keyword = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
integrationTest = false;
|
||||
regressionTest = true;
|
||||
break;
|
||||
case 'R':
|
||||
isRestartFile = true;
|
||||
break;
|
||||
case 's':
|
||||
allowSpikes = true;
|
||||
limit = atof(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
findVolumeError = true;
|
||||
break;
|
||||
case 'V':
|
||||
findVolumeError = true;
|
||||
specificKeyword = true;
|
||||
keyword = optarg;
|
||||
break;
|
||||
case '?':
|
||||
if (optopt == 'k' || optopt == 'm' || optopt == 'P'
|
||||
|| optopt == 's' || optopt == 'V') {
|
||||
std::cout << "Option -"<<optopt<<" requires an keyword." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
std::cout << "Unknown option." << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
default:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------
|
||||
|
||||
int argOffset = optind;
|
||||
if (argc != argOffset + 4) {
|
||||
printHelp();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
const char * basename1 = argv[argOffset];
|
||||
const char * basename2 = argv[argOffset+1];
|
||||
double absoluteTolerance = strtod(argv[argOffset+2], nullptr);
|
||||
double relativeTolerance = strtod(argv[argOffset+3], nullptr);
|
||||
|
||||
std::cout << "Comparing '" << basename1 << "' to '" << basename2 << "'." << std::endl;
|
||||
|
||||
try {
|
||||
if(regressionTest){
|
||||
SummaryRegressionTest compare(basename1,basename2, absoluteTolerance, relativeTolerance);
|
||||
compare.throwOnErrors(throwOnError);
|
||||
compare.doAnalysis(analysis);
|
||||
if(printKeywords){compare.setPrintKeywords(true);}
|
||||
if(isRestartFile){compare.setIsRestartFile(true);}
|
||||
if(specificKeyword){
|
||||
compare.getRegressionTest(keyword);
|
||||
}
|
||||
else{
|
||||
if(printKeywords){compare.setPrintKeywords(true);}
|
||||
compare.getRegressionTest();
|
||||
}
|
||||
}
|
||||
if(integrationTest){
|
||||
SummaryIntegrationTest compare(basename1,basename2, absoluteTolerance, relativeTolerance);
|
||||
compare.throwOnErrors(throwOnError);
|
||||
if(findVectorWithGreatestErrorRatio){compare.setFindVectorWithGreatestErrorRatio(true);}
|
||||
if(allowSpikes){compare.setAllowSpikes(true);}
|
||||
if(oneOfTheMainVariables){
|
||||
compare.setOneOfTheMainVariables(true);
|
||||
std::string str(mainVariable);
|
||||
std::transform(str.begin(), str.end(),str.begin(), ::toupper);
|
||||
if(str == "WOPR" ||str=="WWPR" ||str=="WGPR" || str == "WBHP"){
|
||||
compare.setMainVariable(str);
|
||||
}else{
|
||||
throw std::invalid_argument("The input is not a main variable. -m option requires a valid main variable.");
|
||||
}
|
||||
}
|
||||
if(findVolumeError){compare.setFindVolumeError(true);}
|
||||
if(limit != -1){compare.setSpikeLimit(limit);}
|
||||
if(!allowDifferentAmountOfKeywords){compare.setAllowDifferentAmountOfKeywords(false);}
|
||||
if(printKeywords){compare.setPrintKeywords(true);}
|
||||
if(!throwExceptionForTooGreatErrorRatio){compare.setThrowExceptionForTooGreatErrorRatio(false);}
|
||||
if(specificKeyword){
|
||||
if(printSpecificKeyword){compare.setPrintSpecificKeyword(true);}
|
||||
compare.getIntegrationTest(keyword);
|
||||
return 0;
|
||||
}
|
||||
compare.getIntegrationTest();
|
||||
}
|
||||
}
|
||||
catch(const std::exception& e) {
|
||||
std::cerr << "Program threw an exception: " << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -17,10 +17,10 @@
|
||||
*/
|
||||
|
||||
#include "summaryComparator.hpp"
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
#include <ert/util/stringlist.h>
|
||||
#include <ert/util/int_vector.h>
|
||||
#include <ert/util/bool_vector.h>
|
||||
#include <ert/ecl/ecl_sum.hpp>
|
||||
#include <ert/util/stringlist.hpp>
|
||||
#include <ert/util/int_vector.hpp>
|
||||
#include <ert/util/bool_vector.hpp>
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "summaryIntegrationTest.hpp"
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
#include <ert/util/stringlist.h>
|
||||
#include <ert/ecl/ecl_sum.hpp>
|
||||
#include <ert/util/stringlist.hpp>
|
||||
#include <cmath>
|
||||
|
||||
|
||||
@@ -155,13 +155,10 @@ void SummaryIntegrationTest::findGreatestErrorRatio(const WellProductionVolume&
|
||||
|
||||
|
||||
void SummaryIntegrationTest::volumeErrorCheck(const char* keyword){
|
||||
const smspec_node_type * node = ecl_sum_get_general_var_node (ecl_sum_fileShort ,keyword);//doesn't matter which ecl_sum_file one uses, the kewyord SHOULD be equal in terms of smspec data.
|
||||
bool hist = smspec_node_is_historical(node);
|
||||
/* returns true if the keyword corresponds to a summary vector "history".
|
||||
E.g. WOPRH, where the last character, 'H', indicates that it is a HISTORY vector.*/
|
||||
if(hist){
|
||||
return;//To make sure we do not include history vectors.
|
||||
}
|
||||
const ecl::smspec_node * node = ecl_sum_get_general_var_node (ecl_sum_fileShort ,keyword);//doesn't matter which ecl_sum_file one uses, the kewyord SHOULD be equal in terms of smspec data.
|
||||
if (node->is_historical())
|
||||
return;
|
||||
|
||||
if (!mainVariable.empty()){
|
||||
std::string keywordString(keyword);
|
||||
std::string firstFour = keywordString.substr(0,4);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "summaryRegressionTest.hpp"
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
#include <ert/ecl/ecl_sum.hpp>
|
||||
#include <ert/util/stringlist.h>
|
||||
#include <string>
|
||||
|
||||
@@ -28,7 +28,9 @@ void SummaryRegressionTest::getRegressionTest(){
|
||||
setDataSets(timeVec1, timeVec2); //Figures which dataset that contains more/less values pr keyword vector.
|
||||
std::cout << "Comparing " << timeVec1.size() << " steps." << std::endl;
|
||||
int ivar = 0;
|
||||
if(stringlist_get_size(keysShort) != stringlist_get_size(keysLong)){
|
||||
if((! this->allowDifferentNumberOfKeywords) &&
|
||||
(stringlist_get_size(keysShort) != stringlist_get_size(keysLong)))
|
||||
{
|
||||
int missing_count = 0;
|
||||
std::cout << "Keywords missing from one case: " << std::endl;
|
||||
|
||||
@@ -169,3 +171,8 @@ bool SummaryRegressionTest::startTest(const char* keyword){
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SummaryRegressionTest::setAllowDifferentNumberOfKeywords(const bool allow)
|
||||
{
|
||||
this->allowDifferentNumberOfKeywords = allow;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,12 @@ class SummaryRegressionTest: public SummaryComparator {
|
||||
bool checkDeviation(Deviation deviation, const char* keyword, int refIndex, int checkIndex);
|
||||
|
||||
bool isRestartFile = false; //!< Private member variable, when true the files that are being compared is a restart file vs a normal file
|
||||
|
||||
/// Whether or not to require that the two files have the same
|
||||
/// number of keywords. Throw exception if not.
|
||||
/// Default value: false (don't allow different number of keywords).
|
||||
bool allowDifferentNumberOfKeywords = false;
|
||||
|
||||
public:
|
||||
//! \brief Constructor, creates an object of RefressionTest class.
|
||||
//! \param[in] basename1 Path to file1 without extension.
|
||||
@@ -69,6 +75,13 @@ class SummaryRegressionTest: public SummaryComparator {
|
||||
//! \brief This function sets the private member variable isRestartFiles
|
||||
//! \param[in] boolean Boolean value
|
||||
void setIsRestartFile(bool boolean){this->isRestartFile = boolean;}
|
||||
|
||||
/// \brief Dynamically control whether or not to require equal
|
||||
/// number of keywords (vectors) in the two result sets.
|
||||
///
|
||||
/// \param[in] allow Whether or not to allow different number of
|
||||
/// summary keywords in the two result sets.
|
||||
void setAllowDifferentNumberOfKeywords(const bool allow);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,10 +79,26 @@ function printHeader {
|
||||
# $2 = 0 to build and install module, 1 to build and test module
|
||||
# $3 = Source root of module to build
|
||||
function build_module {
|
||||
cmake $3 -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=$2 -DCMAKE_TOOLCHAIN_FILE=${configurations[$configuration]} $1
|
||||
CMAKE_PARAMS="$1"
|
||||
DO_TEST_FLAG="$2"
|
||||
MOD_SRC_DIR="$3"
|
||||
cmake "$MOD_SRC_DIR" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=$DO_TEST_FLAG -DCMAKE_TOOLCHAIN_FILE=${configurations[$configuration]} $CMAKE_PARAMS
|
||||
test $? -eq 0 || exit 1
|
||||
if test $2 -eq 1
|
||||
if test $DO_TEST_FLAG -eq 1
|
||||
then
|
||||
|
||||
pushd "$CWD"
|
||||
cd "$MOD_SRC_DIR"
|
||||
if test -x "./jenkins/pre-build.sh"; then
|
||||
echo "Running pre-build script"
|
||||
if ! "./jenkins/pre-build.sh"; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "No pre-build script detected"
|
||||
fi
|
||||
popd
|
||||
|
||||
if [ ! -z $BUILDTHREADS ]
|
||||
then
|
||||
cmake --build . -- -j$BUILDTHREADS
|
||||
|
||||
52
msim/include/opm/msim/msim.hpp
Normal file
52
msim/include/opm/msim/msim.hpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef ISIM_MAIN_HPP
|
||||
#define ISIM_MAIN_HPP
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
|
||||
#include <opm/output/data/Solution.hpp>
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class EclipseIO;
|
||||
class ParseContext;
|
||||
class Parser;
|
||||
|
||||
class msim {
|
||||
|
||||
public:
|
||||
using well_rate_function = double(const EclipseState&, const Schedule&, const data::Solution&, size_t report_step, double seconds_elapsed);
|
||||
using solution_function = void(const EclipseState&, const Schedule&, data::Solution&, size_t report_step, double seconds_elapsed);
|
||||
|
||||
msim(const EclipseState& state);
|
||||
|
||||
void well_rate(const std::string& well, data::Rates::opt rate, std::function<well_rate_function> func);
|
||||
void solution(const std::string& field, std::function<solution_function> func);
|
||||
void run(Schedule& schedule, EclipseIO& io);
|
||||
void post_step(Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, EclipseIO& io) const;
|
||||
private:
|
||||
|
||||
void run_step(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, EclipseIO& io) const;
|
||||
void run_step(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, double dt, EclipseIO& io) const;
|
||||
void output(size_t report_step, bool substep, double seconds_elapsed, const data::Solution& sol, const data::Wells& well_data, EclipseIO& io) const;
|
||||
void simulate(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, double seconds_elapsed, double time_step) const;
|
||||
|
||||
EclipseState state;
|
||||
|
||||
std::map<std::string, std::map<data::Rates::opt, std::function<well_rate_function>>> well_rates;
|
||||
std::map<std::string, std::function<solution_function>> solutions;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
148
msim/src/msim.cpp
Normal file
148
msim/src/msim.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright 2018 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <opm/output/eclipse/EclipseIO.hpp>
|
||||
#include <opm/output/eclipse/RestartValue.hpp>
|
||||
#include <opm/output/data/Solution.hpp>
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/msim/msim.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
msim::msim(const EclipseState& state) :
|
||||
state(state)
|
||||
{}
|
||||
|
||||
void msim::run(Schedule& schedule, EclipseIO& io) {
|
||||
const double week = 7 * 86400;
|
||||
data::Solution sol;
|
||||
data::Wells well_data;
|
||||
|
||||
io.writeInitial();
|
||||
for (size_t report_step = 1; report_step < schedule.size(); report_step++) {
|
||||
double time_step = std::min(week, 0.5*schedule.stepLength(report_step - 1));
|
||||
run_step(schedule, sol, well_data, report_step, time_step, io);
|
||||
post_step(schedule, sol, well_data, report_step, io);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void msim::post_step(Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, EclipseIO& io) const {
|
||||
const auto& actions = schedule.actions();
|
||||
if (actions.empty())
|
||||
return;
|
||||
|
||||
const SummaryState& summary_state = io.summaryState();
|
||||
ActionContext context( summary_state );
|
||||
std::vector<std::string> matching_wells;
|
||||
|
||||
auto sim_time = schedule.simTime(report_step);
|
||||
for (const auto& action : actions.pending(sim_time)) {
|
||||
if (action->eval(sim_time, context, matching_wells))
|
||||
schedule.applyAction(report_step, *action, matching_wells);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void msim::run_step(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, EclipseIO& io) const {
|
||||
this->run_step(schedule, sol, well_data, report_step, schedule.stepLength(report_step - 1), io);
|
||||
}
|
||||
|
||||
|
||||
void msim::run_step(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, double dt, EclipseIO& io) const {
|
||||
double start_time = schedule.seconds(report_step - 1);
|
||||
double end_time = schedule.seconds(report_step);
|
||||
double seconds_elapsed = start_time;
|
||||
|
||||
while (seconds_elapsed < end_time) {
|
||||
double time_step = dt;
|
||||
if ((seconds_elapsed + time_step) > end_time)
|
||||
time_step = end_time - seconds_elapsed;
|
||||
|
||||
this->simulate(schedule, sol, well_data, report_step, seconds_elapsed, time_step);
|
||||
|
||||
seconds_elapsed += time_step;
|
||||
this->output(report_step,
|
||||
(seconds_elapsed < end_time),
|
||||
seconds_elapsed,
|
||||
sol,
|
||||
well_data,
|
||||
io);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void msim::output(size_t report_step, bool substep, double seconds_elapsed, const data::Solution& sol, const data::Wells& well_data, EclipseIO& io) const {
|
||||
RestartValue value(sol, well_data);
|
||||
io.writeTimeStep(report_step,
|
||||
false,
|
||||
seconds_elapsed,
|
||||
value,
|
||||
{},
|
||||
{},
|
||||
{});
|
||||
}
|
||||
|
||||
|
||||
void msim::simulate(const Schedule& schedule, data::Solution& sol, data::Wells& well_data, size_t report_step, double seconds_elapsed, double time_step) const {
|
||||
for (const auto& sol_pair : this->solutions) {
|
||||
auto func = sol_pair.second;
|
||||
func(this->state, schedule, sol, report_step, seconds_elapsed + time_step);
|
||||
}
|
||||
|
||||
for (const auto& well_pair : this->well_rates) {
|
||||
const std::string& well_name = well_pair.first;
|
||||
data::Well& well = well_data[well_name];
|
||||
for (const auto& rate_pair : well_pair.second) {
|
||||
auto rate = rate_pair.first;
|
||||
auto func = rate_pair.second;
|
||||
|
||||
well.rates.set(rate, func(this->state, schedule, sol, report_step, seconds_elapsed + time_step));
|
||||
}
|
||||
|
||||
// This is complete bogus; a temporary fix to pass an assert() in the
|
||||
// the restart output.
|
||||
well.connections.resize(100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void msim::well_rate(const std::string& well, data::Rates::opt rate, std::function<well_rate_function> func) {
|
||||
this->well_rates[well][rate] = func;
|
||||
}
|
||||
|
||||
|
||||
void msim::solution(const std::string& field, std::function<solution_function> func) {
|
||||
this->solutions[field] = func;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
#ifndef OPM_OUTPUT_WELLS_HPP
|
||||
#define OPM_OUTPUT_WELLS_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
@@ -56,6 +58,12 @@ namespace Opm {
|
||||
reservoir_water = (1 << 8),
|
||||
reservoir_oil = (1 << 9),
|
||||
reservoir_gas = (1 << 10),
|
||||
productivity_index_water = (1 << 11),
|
||||
productivity_index_oil = (1 << 12),
|
||||
productivity_index_gas = (1 << 13),
|
||||
well_potential_water = (1 << 14),
|
||||
well_potential_oil = (1 << 15),
|
||||
well_potential_gas = (1 << 16),
|
||||
};
|
||||
|
||||
using enum_size = std::underlying_type< opt >::type;
|
||||
@@ -99,6 +107,12 @@ namespace Opm {
|
||||
double reservoir_water = 0.0;
|
||||
double reservoir_oil = 0.0;
|
||||
double reservoir_gas = 0.0;
|
||||
double productivity_index_water = 0.0;
|
||||
double productivity_index_oil = 0.0;
|
||||
double productivity_index_gas = 0.0;
|
||||
double well_potential_water = 0.0;
|
||||
double well_potential_oil = 0.0;
|
||||
double well_potential_gas = 0.0;
|
||||
};
|
||||
|
||||
struct Connection {
|
||||
@@ -120,6 +134,18 @@ namespace Opm {
|
||||
void read(MessageBufferType& buffer);
|
||||
};
|
||||
|
||||
struct Segment {
|
||||
Rates rates;
|
||||
double pressure;
|
||||
std::size_t segNumber;
|
||||
|
||||
template <class MessageBufferType>
|
||||
void write(MessageBufferType& buffer) const;
|
||||
|
||||
template <class MessageBufferType>
|
||||
void read(MessageBufferType& buffer);
|
||||
};
|
||||
|
||||
struct Well {
|
||||
Rates rates;
|
||||
double bhp;
|
||||
@@ -127,7 +153,7 @@ namespace Opm {
|
||||
double temperature;
|
||||
int control;
|
||||
std::vector< Connection > connections;
|
||||
|
||||
std::unordered_map<std::size_t, Segment> segments;
|
||||
inline bool flowing() const noexcept;
|
||||
template <class MessageBufferType>
|
||||
void write(MessageBufferType& buffer) const;
|
||||
@@ -249,6 +275,12 @@ namespace Opm {
|
||||
case opt::reservoir_water: return this->reservoir_water;
|
||||
case opt::reservoir_oil: return this->reservoir_oil;
|
||||
case opt::reservoir_gas: return this->reservoir_gas;
|
||||
case opt::productivity_index_water: return this->productivity_index_water;
|
||||
case opt::productivity_index_oil: return this->productivity_index_oil;
|
||||
case opt::productivity_index_gas: return this->productivity_index_gas;
|
||||
case opt::well_potential_water: return this->well_potential_water;
|
||||
case opt::well_potential_oil: return this->well_potential_oil;
|
||||
case opt::well_potential_gas: return this->well_potential_gas;
|
||||
}
|
||||
|
||||
throw std::invalid_argument(
|
||||
@@ -286,6 +318,12 @@ namespace Opm {
|
||||
buffer.write(this->reservoir_water);
|
||||
buffer.write(this->reservoir_oil);
|
||||
buffer.write(this->reservoir_gas);
|
||||
buffer.write(this->productivity_index_water);
|
||||
buffer.write(this->productivity_index_oil);
|
||||
buffer.write(this->productivity_index_gas);
|
||||
buffer.write(this->well_potential_water);
|
||||
buffer.write(this->well_potential_oil);
|
||||
buffer.write(this->well_potential_gas);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
@@ -300,6 +338,13 @@ namespace Opm {
|
||||
buffer.write(this->effective_Kh);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void Segment::write(MessageBufferType& buffer) const {
|
||||
buffer.write(this->segNumber);
|
||||
this->rates.write(buffer);
|
||||
buffer.write(this->pressure);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void Well::write(MessageBufferType& buffer) const {
|
||||
this->rates.write(buffer);
|
||||
@@ -311,6 +356,16 @@ namespace Opm {
|
||||
buffer.write(size);
|
||||
for (const Connection& comp : this->connections)
|
||||
comp.write(buffer);
|
||||
|
||||
{
|
||||
const auto nSeg =
|
||||
static_cast<unsigned int>(this->segments.size());
|
||||
buffer.write(nSeg);
|
||||
|
||||
for (const auto& seg : this->segments) {
|
||||
seg.second.write(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
@@ -327,6 +382,12 @@ namespace Opm {
|
||||
buffer.read(this->reservoir_water);
|
||||
buffer.read(this->reservoir_oil);
|
||||
buffer.read(this->reservoir_gas);
|
||||
buffer.read(this->productivity_index_water);
|
||||
buffer.read(this->productivity_index_oil);
|
||||
buffer.read(this->productivity_index_gas);
|
||||
buffer.read(this->well_potential_water);
|
||||
buffer.read(this->well_potential_oil);
|
||||
buffer.read(this->well_potential_gas);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
@@ -341,6 +402,13 @@ namespace Opm {
|
||||
buffer.read(this->effective_Kh);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void Segment::read(MessageBufferType& buffer) {
|
||||
buffer.read(this->segNumber);
|
||||
this->rates.read(buffer);
|
||||
buffer.read(this->pressure);
|
||||
}
|
||||
|
||||
template <class MessageBufferType>
|
||||
void Well::read(MessageBufferType& buffer) {
|
||||
this->rates.read(buffer);
|
||||
@@ -348,6 +416,8 @@ namespace Opm {
|
||||
buffer.read(this->thp);
|
||||
buffer.read(this->temperature);
|
||||
buffer.read(this->control);
|
||||
|
||||
// Connection information
|
||||
unsigned int size = 0.0; //this->connections.size();
|
||||
buffer.read(size);
|
||||
this->connections.resize(size);
|
||||
@@ -356,9 +426,25 @@ namespace Opm {
|
||||
auto& comp = this->connections[ i ];
|
||||
comp.read(buffer);
|
||||
}
|
||||
|
||||
// Segment information (if applicable)
|
||||
const auto nSeg = [&buffer]() -> unsigned int
|
||||
{
|
||||
auto n = 0u;
|
||||
buffer.read(n);
|
||||
|
||||
return n;
|
||||
}();
|
||||
|
||||
for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
|
||||
auto seg = Segment{};
|
||||
seg.read(buffer);
|
||||
|
||||
const auto segNumber = seg.segNumber;
|
||||
this->segments.emplace(segNumber, std::move(seg));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}} // Opm::data
|
||||
|
||||
#endif //OPM_OUTPUT_WELLS_HPP
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Opm {
|
||||
class Schedule;
|
||||
class EclipseGrid;
|
||||
class UnitSystem;
|
||||
class SummaryState;
|
||||
} // Opm
|
||||
|
||||
namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
@@ -44,16 +45,31 @@ namespace Opm { namespace RestartIO { namespace Helpers {
|
||||
int branch;
|
||||
};
|
||||
|
||||
struct SegmentSetSourceSinkTerms {
|
||||
std::vector<double> qosc;
|
||||
std::vector<double> qwsc;
|
||||
std::vector<double> qgsc;
|
||||
};
|
||||
|
||||
struct SegmentSetFlowRates {
|
||||
std::vector<double> sofr;
|
||||
std::vector<double> swfr;
|
||||
std::vector<double> sgfr;
|
||||
};
|
||||
|
||||
class AggregateMSWData
|
||||
{
|
||||
public:
|
||||
explicit AggregateMSWData(const std::vector<int>& inteHead);
|
||||
|
||||
|
||||
void captureDeclaredMSWData(const Opm::Schedule& sched,
|
||||
const std::size_t rptStep,
|
||||
const Opm::UnitSystem& units,
|
||||
const std::vector<int>& inteHead,
|
||||
const Opm::EclipseGrid& grid);
|
||||
const Opm::EclipseGrid& grid,
|
||||
const Opm::SummaryState& smry,
|
||||
const Opm::data::WellRates& wr
|
||||
);
|
||||
|
||||
/// Retrieve Integer Multisegment well data Array.
|
||||
const std::vector<int>& getISeg() const
|
||||
|
||||
@@ -55,7 +55,8 @@ namespace Opm { namespace RestartIO {
|
||||
DoubHEAD& timeStamp(const TimeStamp& ts);
|
||||
|
||||
DoubHEAD& drsdt(const Schedule& sched,
|
||||
const std::size_t lookup_step);
|
||||
const std::size_t lookup_step,
|
||||
const double cnvT);
|
||||
|
||||
const std::vector<double>& data() const
|
||||
{
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
#include <opm/output/data/Solution.hpp>
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/eclipse/RestartValue.hpp>
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class EclipseState;
|
||||
class SummaryConfig;
|
||||
class Schedule;
|
||||
class SummaryState;
|
||||
|
||||
/*!
|
||||
* \brief A class to write the reservoir state and the well state of a
|
||||
@@ -225,6 +225,8 @@ public:
|
||||
EclipseIO( const EclipseIO& ) = delete;
|
||||
~EclipseIO();
|
||||
|
||||
const SummaryState& summaryState() const;
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr< Impl > impl;
|
||||
|
||||
@@ -38,7 +38,9 @@ namespace Opm { namespace RestartIO {
|
||||
|
||||
LogiHEAD& variousParam(const bool e300_radial,
|
||||
const bool e100_radial,
|
||||
const int nswlmx);
|
||||
const int nswlmx,
|
||||
const bool enableHyster
|
||||
);
|
||||
|
||||
const std::vector<bool>& data() const
|
||||
{
|
||||
|
||||
@@ -20,15 +20,15 @@
|
||||
#ifndef OPM_OUTPUT_SUMMARY_HPP
|
||||
#define OPM_OUTPUT_SUMMARY_HPP
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ert/ecl/ecl_sum.h>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/eclipse/RegionCache.hpp>
|
||||
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SUMMARY_STATE_H
|
||||
#define SUMMARY_STATE_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace Opm{
|
||||
|
||||
|
||||
/*
|
||||
The purpose of this class is to serve as a small container object for
|
||||
computed, ready to use summary values. The values will typically be used by
|
||||
the UDQ, WTEST and ACTIONX calculations. Observe that all value *have been
|
||||
converted to the correct output units*.
|
||||
*/
|
||||
class SummaryState {
|
||||
public:
|
||||
typedef std::unordered_map<std::string, double>::const_iterator const_iterator;
|
||||
|
||||
void add(const std::string& key, double value);
|
||||
double get(const std::string&) const;
|
||||
bool has(const std::string& key) const;
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
private:
|
||||
std::unordered_map<std::string,double> values;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -41,6 +41,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
||||
VFPTab = 11, // ID (one-based) of well's current VFP table
|
||||
|
||||
item18 = 17, // Unknown
|
||||
XFlow = 22,
|
||||
item25 = 24, // Unknown
|
||||
item32 = 31, // Unknown
|
||||
item48 = 47, // Unknown
|
||||
@@ -115,6 +116,10 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
|
||||
BHPTarget = 6, // Well's bottom hole pressure target
|
||||
|
||||
DatumDepth = 9, // Well's reference depth for BHP
|
||||
LiqRateTarget_2 = 33, //Well's liquid rate target/limit for a well on WCONINJH control or for a producer
|
||||
GasRateTarget_2 = 54, //Well's gas rate target/limit for a well on WCONINJH control or for producer
|
||||
BHPTarget_2 = 55, //Well's bottom hole pressure target/limit
|
||||
|
||||
};
|
||||
} // SWell
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ namespace Opm {
|
||||
const std::string& getInputPath() const;
|
||||
const std::string& getDataFile() const;
|
||||
void setDataFile(const std::string& dataFile);
|
||||
std::string makeDeckPath(const std::string& path) const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
@@ -44,9 +44,10 @@ namespace Opm {
|
||||
struct AquanconOutput{
|
||||
int aquiferID;
|
||||
std::vector<size_t> global_index;
|
||||
std::vector<double> influx_coeff; // Size = size(global_index)
|
||||
std::vector<std::shared_ptr<double>> influx_coeff; // Size = size(global_index)
|
||||
std::vector<double> influx_multiplier; // Size = size(global_index)
|
||||
std::vector<int> reservoir_face_dir; // Size = size(global_index)
|
||||
std::vector<int> record_index;
|
||||
};
|
||||
|
||||
Aquancon(const EclipseGrid& grid, const Deck& deck);
|
||||
@@ -55,7 +56,7 @@ namespace Opm {
|
||||
|
||||
private:
|
||||
|
||||
void logic_application(std::vector<Aquancon::AquanconOutput>& output_vector);
|
||||
std::vector<Aquancon::AquanconOutput> logic_application(const std::vector<Aquancon::AquanconOutput> original_vector);
|
||||
|
||||
void collate_function(std::vector<Aquancon::AquanconOutput>& output_vector,
|
||||
std::vector<Opm::AquanconRecord>& m_aqurecord,
|
||||
|
||||
@@ -58,10 +58,10 @@ namespace Opm {
|
||||
k_a , //aquifer permeability
|
||||
c1, // 0.008527 (METRIC, PVT-M); 0.006328 (FIELD); 3.6 (LAB)
|
||||
h , //aquifer thickness
|
||||
p0, //Initial aquifer pressure at datum depth, d0
|
||||
theta , //angle subtended by the aquifer boundary
|
||||
c2 ; //6.283 (METRIC, PVT-M); 1.1191 (FIELD); 6.283 (LAB).
|
||||
|
||||
|
||||
std::shared_ptr<double> p0; //Initial aquifer pressure at datum depth, d0
|
||||
std::vector<double> td, pi;
|
||||
};
|
||||
|
||||
|
||||
74
opm/parser/eclipse/EclipseState/Aquifetp.hpp
Executable file
74
opm/parser/eclipse/EclipseState/Aquifetp.hpp
Executable file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (C) 2017 TNO
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_AQUIFERFETP_HPP
|
||||
#define OPM_AQUIFERFETP_HPP
|
||||
|
||||
/*
|
||||
The Aquiferfetp which stands for AquiferFetkovich is a data container object meant to hold the data for the fetkovich aquifer model.
|
||||
This includes the logic for parsing as well as the associated tables. It is meant to be used by opm-grid and opm-simulators in order to
|
||||
implement the Fetkovich analytical aquifer model in OPM Flow.
|
||||
*/
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParserKeywords/A.hpp>
|
||||
#include <opm/parser/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Aqudims.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableContainer.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class Aquifetp {
|
||||
public:
|
||||
|
||||
struct AQUFETP_data{
|
||||
|
||||
// Aquifer ID
|
||||
int aquiferID;
|
||||
// Table IDs
|
||||
int inftableID, pvttableID;
|
||||
std::vector<int> cell_id;
|
||||
// Variables constants
|
||||
double J, // Specified Productivity Index
|
||||
rho, // water density in the aquifer
|
||||
C_t, // total rock compressibility
|
||||
V0, // initial volume of water in aquifer
|
||||
d0; // aquifer datum depth
|
||||
std::shared_ptr<double> p0; //Initial aquifer pressure at datum depth d0 - nullptr if the pressure has been defaulted.
|
||||
};
|
||||
|
||||
Aquifetp(const Deck& deck);
|
||||
|
||||
const std::vector<Aquifetp::AQUFETP_data>& getAquifers() const;
|
||||
int getAqPvtTabID(size_t aquiferIndex);
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Aquifetp::AQUFETP_data> m_aqufetp;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -93,6 +93,7 @@ namespace Opm {
|
||||
void handleEQUALREGKeyword(const DeckKeyword& deckKeyword );
|
||||
void handleMULTIREGKeyword(const DeckKeyword& deckKeyword );
|
||||
void handleOPERATEKeyword( const DeckKeyword& deckKeyword, BoxManager& boxManager);
|
||||
void handleOPERATERKeyword( const DeckKeyword& deckKeyword);
|
||||
|
||||
void loadGridPropertyFromDeckKeyword(const Box& inputBox,
|
||||
const DeckKeyword& deckKeyword);
|
||||
|
||||
@@ -29,11 +29,13 @@
|
||||
namespace Opm {
|
||||
|
||||
class Deck;
|
||||
class ParseContext;
|
||||
class ErrorGuard;
|
||||
|
||||
class EclipseConfig
|
||||
{
|
||||
public:
|
||||
EclipseConfig(const Deck& deck);
|
||||
EclipseConfig(const Deck& deck, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
|
||||
const InitConfig& init() const;
|
||||
const IOConfig& io() const;
|
||||
|
||||
@@ -23,15 +23,17 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/parser/eclipse/Parser/ErrorGuard.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/FaultCollection.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/TransMult.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/parser/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SimulationConfig/SimulationConfig.hpp>
|
||||
|
||||
namespace Opm {
|
||||
@@ -64,9 +66,11 @@ namespace Opm {
|
||||
AllProperties = IntProperties | DoubleProperties
|
||||
};
|
||||
|
||||
EclipseState(const Deck& deck , ParseContext parseContext = ParseContext());
|
||||
template<typename T>
|
||||
EclipseState(const Deck& deck , const ParseContext& parseContext, T&& errors);
|
||||
EclipseState(const Deck& deck , const ParseContext& parseContext, ErrorGuard& errors);
|
||||
EclipseState(const Deck& deck);
|
||||
|
||||
const ParseContext& getParseContext() const;
|
||||
const IOConfig& getIOConfig() const;
|
||||
IOConfig& getIOConfig();
|
||||
|
||||
@@ -85,6 +89,11 @@ namespace Opm {
|
||||
const NNC& getInputNNC() const;
|
||||
bool hasInputNNC() const;
|
||||
|
||||
/// editing non-neighboring connections
|
||||
/// the non-standard adjacencies as specified in input deck
|
||||
const EDITNNC& getInputEDITNNC() const;
|
||||
bool hasInputEDITNNC() const;
|
||||
|
||||
const Eclipse3DProperties& get3DProperties() const;
|
||||
const TableManager& getTableManager() const;
|
||||
const EclipseConfig& getEclipseConfig() const;
|
||||
@@ -112,12 +121,12 @@ namespace Opm {
|
||||
void complainAboutAmbiguousKeyword(const Deck& deck,
|
||||
const std::string& keywordName);
|
||||
|
||||
ParseContext m_parseContext;
|
||||
const TableManager m_tables;
|
||||
Runspec m_runspec;
|
||||
EclipseConfig m_eclipseConfig;
|
||||
UnitSystem m_deckUnitSystem;
|
||||
NNC m_inputNnc;
|
||||
EDITNNC m_inputEditNnc;
|
||||
EclipseGrid m_inputGrid;
|
||||
Eclipse3DProperties m_eclipseProperties;
|
||||
const SimulationConfig m_simulationConfig;
|
||||
|
||||
48
opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp
Normal file
48
opm/parser/eclipse/EclipseState/Edit/EDITNNC.hpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2018 Equinor AS
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef OPM_COMMON_EDITNNC_HPP
|
||||
#define OPM_COMMON_EDITNNC_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
/// Represents edit information for non-neighboring connections (NNCs, faults, etc.)
|
||||
class EDITNNC
|
||||
{
|
||||
public:
|
||||
EDITNNC() = default;
|
||||
|
||||
/// Construct from input deck
|
||||
explicit EDITNNC(const Deck& deck);
|
||||
/// \brief Get an ordered set of EDITNNC
|
||||
const std::vector<NNCdata>& data() const
|
||||
{
|
||||
return m_editnnc;
|
||||
}
|
||||
/// \brief Get the number of entries
|
||||
size_t size() const;
|
||||
/// \brief Whether EDITNNC was empty.
|
||||
bool empty() const;
|
||||
|
||||
private:
|
||||
std::vector<NNCdata> m_editnnc;
|
||||
};
|
||||
}
|
||||
#endif // OPM_COMMON_EDITNNC_HPP
|
||||
@@ -38,6 +38,7 @@ namespace Opm {
|
||||
|
||||
class Deck;
|
||||
class ZcornMapper;
|
||||
class NNC;
|
||||
|
||||
/**
|
||||
About cell information and dimension: The actual grid
|
||||
@@ -76,6 +77,8 @@ namespace Opm {
|
||||
/// explicitly. If a null pointer is passed, every cell is active.
|
||||
EclipseGrid(const Deck& deck, const int * actnum = nullptr);
|
||||
|
||||
|
||||
static bool hasGDFILE(const Deck& deck);
|
||||
static bool hasCylindricalKeywords(const Deck& deck);
|
||||
static bool hasCornerPointKeywords(const Deck&);
|
||||
static bool hasCartesianKeywords(const Deck&);
|
||||
@@ -85,6 +88,8 @@ namespace Opm {
|
||||
size_t activeIndex(size_t i, size_t j, size_t k) const;
|
||||
size_t activeIndex(size_t globalIndex) const;
|
||||
|
||||
void save(const std::string& filename, UnitSystem::UnitType output_units) const;
|
||||
void addNNC(const NNC& nnc);
|
||||
/*
|
||||
Observe that the there is a getGlobalIndex(i,j,k)
|
||||
implementation in the base class. This method - translating
|
||||
@@ -107,7 +112,7 @@ namespace Opm {
|
||||
PinchMode::ModeEnum getMultzOption( ) const;
|
||||
|
||||
MinpvMode::ModeEnum getMinpvMode() const;
|
||||
double getMinpvValue( ) const;
|
||||
const std::vector<double>& getMinpvVector( ) const;
|
||||
|
||||
|
||||
/*
|
||||
@@ -176,7 +181,7 @@ namespace Opm {
|
||||
const ecl_grid_type * c_ptr() const;
|
||||
|
||||
private:
|
||||
double m_minpvValue;
|
||||
std::vector<double> m_minpvVector;
|
||||
MinpvMode::ModeEnum m_minpvMode;
|
||||
Value<double> m_pinch;
|
||||
PinchMode::ModeEnum m_pinchoutMode;
|
||||
@@ -200,6 +205,7 @@ namespace Opm {
|
||||
ert_ptr( ecl_grid_alloc_copy( src.get() ) ) {}
|
||||
};
|
||||
grid_ptr m_grid;
|
||||
void initBinaryGrid(const Deck& deck);
|
||||
|
||||
void initCornerPointGrid(const std::array<int,3>& dims ,
|
||||
const std::vector<double>& coord ,
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace Opm {
|
||||
|
||||
private:
|
||||
void init(const DeckKeyword& keyword);
|
||||
void binary_init(const Deck& deck);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -141,12 +141,13 @@ namespace Opm {
|
||||
void handleMULTIPLYRecord( const DeckRecord& record, BoxManager& boxManager);
|
||||
void handleCOPYRecord( const DeckRecord& record, BoxManager& boxManager);
|
||||
void handleEQUALSRecord( const DeckRecord& record, BoxManager& boxManager);
|
||||
void handleOPERATERecord( const DeckRecord& record , BoxManager& boxManager);
|
||||
|
||||
void handleEQUALREGRecord( const DeckRecord& record, const GridProperty<int>& regionProperty );
|
||||
void handleADDREGRecord( const DeckRecord& record, const GridProperty<int>& regionProperty );
|
||||
void handleMULTIREGRecord( const DeckRecord& record, const GridProperty<int>& regionProperty );
|
||||
void handleCOPYREGRecord( const DeckRecord& record, const GridProperty<int>& regionProperty );
|
||||
void handleOPERATERecord( const DeckRecord& record , BoxManager& boxManager);
|
||||
void handleOPERATERRecord( const DeckRecord& record , const GridProperty<int>& regionProperty );
|
||||
/*
|
||||
Iterators over initialized properties. The overloaded
|
||||
operator*() opens the pair which comes natively from the
|
||||
@@ -184,6 +185,11 @@ namespace Opm {
|
||||
const std::string& dimString,
|
||||
const bool defaultInitializable );
|
||||
|
||||
void postAddKeyword(const std::string& name,
|
||||
std::function< std::vector< T >(size_t) > initProcessor,
|
||||
const std::string& dimString);
|
||||
|
||||
|
||||
GridProperty<T>& getKeyword(const std::string& keyword);
|
||||
bool addAutoGeneratedKeyword_(const std::string& keywordName) const;
|
||||
void insertKeyword(const SupportedKeywordInfo& supportedKeyword) const;
|
||||
|
||||
@@ -177,13 +177,91 @@ public:
|
||||
grid and call the cellsEqual( T , std::vector<int>&) overload,
|
||||
otherwise it will return indexEqual( value );
|
||||
*/
|
||||
std::vector<size_t> cellsEqual(T value, const EclipseGrid& grid, bool active = true) const;
|
||||
|
||||
std::vector<size_t> cellsEqual(T value, const EclipseGrid& grid, bool active = true) const;
|
||||
/*
|
||||
Will return a std::vector<T> of the data in the active cells.
|
||||
*/
|
||||
std::vector<T> compressedCopy( const EclipseGrid& grid) const;
|
||||
|
||||
|
||||
/*
|
||||
The grid properties like PORO and SATNUM can be created in essentially two
|
||||
ways; either they can be explicitly assigned in the deck as:
|
||||
|
||||
PORO
|
||||
1000*0.15 /
|
||||
|
||||
or they can be created indirectly through various mathematical operations
|
||||
like:
|
||||
|
||||
MULTIPLY
|
||||
TRANX 0.20 /
|
||||
/
|
||||
|
||||
The deckAssigned() property is used so that we can differentiate between
|
||||
properties which have been explicitly assigned/loaded from the deck, and
|
||||
those where the default construction has been invoked. This functionality
|
||||
is implemented purely to support the TRAN? keywords. The transmissibility
|
||||
is be default calculated by the simulator code, but the TRAN keywords can
|
||||
be used in the deck to manipulate this calculation in two different ways:
|
||||
|
||||
1. TRAN explicitly assigned in GRID section
|
||||
===========================================
|
||||
...
|
||||
TRANX
|
||||
1000*0.026 /
|
||||
|
||||
COPY
|
||||
'TRANX' 'TRANY' /
|
||||
/
|
||||
|
||||
In this case the simulator should detect that the input deck has TRANX
|
||||
specified and just use the input values from the deck. This is the
|
||||
normal handling of keywords, and agrees with e.g. PERMX and PORO. This
|
||||
also applies when the COPY keyword has been used, as in the case of
|
||||
'TRANY' above.
|
||||
|
||||
|
||||
2. TRAN modifier present in EDIT section
|
||||
========================================
|
||||
The scenario here is that there is no mention of TRANX in the GRID
|
||||
section, however the EDIT section contains modifiers like this:
|
||||
|
||||
MULTIPLY
|
||||
TRANX 0.25 /
|
||||
|
||||
I.e. we request the TRANX values to be reduced with a factor of 0.25. In
|
||||
this case the simulator should still calculate transmissibility according
|
||||
to it's normal algorithm, and then subsequently scale that result with a
|
||||
factor of 0.25.
|
||||
|
||||
In this case the input layer needs to autocreate a TRANX keyword,
|
||||
defaulted to 1.0 and then scale that to 0.25.
|
||||
|
||||
|
||||
Now - the important point is that when doing transmissibility calculations
|
||||
the simulator must be able to distinguish between cases 1 and 2,
|
||||
specifically whether the TRANX keyword should be interpreted as absolute
|
||||
values(case 1) or as a multiplier(case 2). That is the purpose of the
|
||||
deckAssigned() property. Pseudo code for the transmissibility calculations
|
||||
in the simulator could be:
|
||||
|
||||
|
||||
const auto& input_tranx = properties.getKeyword("TRANX");
|
||||
if (input_tranx.deckAssigned()) {
|
||||
// set simulator internal transmissibilities to values from input_tranx
|
||||
tranx = input_tranx;
|
||||
} else {
|
||||
// Calculate transmissibilities according to normal simulator algorithm
|
||||
...
|
||||
...
|
||||
// Scale transmissibilities with scale factor from input_tranx
|
||||
tranx *= input_tranx;
|
||||
}
|
||||
|
||||
*/
|
||||
bool deckAssigned() const;
|
||||
|
||||
private:
|
||||
const DeckItem& getDeckItem( const DeckKeyword& );
|
||||
void setDataPoint(size_t sourceIdx, size_t targetIdx, const DeckItem& deckItem);
|
||||
@@ -192,6 +270,7 @@ private:
|
||||
SupportedKeywordInfo m_kwInfo;
|
||||
std::vector<T> m_data;
|
||||
bool m_hasRunPostProcessor = false;
|
||||
bool assigned = false;
|
||||
};
|
||||
|
||||
// initialize the TEMPI grid property using the temperature vs depth
|
||||
|
||||
@@ -50,14 +50,11 @@ namespace Opm {
|
||||
|
||||
|
||||
|
||||
class MULTREGTRecord {
|
||||
public:
|
||||
MULTREGTRecord(int src, int target, double trans_mult, int directions, MULTREGT::NNCBehaviourEnum nnc_behaviour, const std::string& region_name);
|
||||
|
||||
struct MULTREGTRecord {
|
||||
int src_value;
|
||||
int target_value;
|
||||
int directions;
|
||||
double trans_mult;
|
||||
int directions;
|
||||
MULTREGT::NNCBehaviourEnum nnc_behaviour;
|
||||
std::string region_name;
|
||||
};
|
||||
|
||||
@@ -28,6 +28,10 @@ namespace Opm
|
||||
{
|
||||
|
||||
struct NNCdata {
|
||||
NNCdata(size_t c1, size_t c2, double t)
|
||||
: cell1(c1), cell2(c2), trans(t)
|
||||
{}
|
||||
NNCdata() = default;
|
||||
size_t cell1;
|
||||
size_t cell2;
|
||||
double trans;
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Opm {
|
||||
void setOutputDir(const std::string& outputDir);
|
||||
|
||||
const std::string& getBaseName() const;
|
||||
void setBaseName(std::string baseName);
|
||||
void setBaseName(const std::string& baseName);
|
||||
|
||||
/// Return a string consisting of outputpath and basename;
|
||||
/// i.e. /path/to/sim/CASE
|
||||
@@ -199,8 +199,8 @@ namespace Opm {
|
||||
std::string m_deck_filename;
|
||||
bool m_output_enabled = true;
|
||||
std::string m_output_dir;
|
||||
std::string m_base_name;
|
||||
bool m_nosim;
|
||||
std::string m_base_name;
|
||||
bool ecl_compatible_rst = true;
|
||||
|
||||
IOConfig( const GRIDSection&,
|
||||
|
||||
@@ -200,7 +200,8 @@ namespace Opm {
|
||||
class SOLUTIONSection;
|
||||
class TimeMap;
|
||||
class Schedule;
|
||||
|
||||
class ParseContext;
|
||||
class ErrorGuard;
|
||||
|
||||
/*The IOConfig class holds data about input / ouput configurations
|
||||
|
||||
@@ -317,19 +318,27 @@ namespace Opm {
|
||||
public:
|
||||
|
||||
RestartConfig();
|
||||
explicit RestartConfig( const Deck& );
|
||||
|
||||
template<typename T>
|
||||
RestartConfig( const Deck&, const ParseContext& parseContext, T&& errors );
|
||||
|
||||
RestartConfig( const Deck&, const ParseContext& parseContext, ErrorGuard& errors );
|
||||
RestartConfig( const Deck& );
|
||||
|
||||
RestartConfig( const SCHEDULESection& schedule,
|
||||
const SOLUTIONSection& solution,
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors,
|
||||
TimeMap timemap );
|
||||
|
||||
|
||||
int getFirstRestartStep() const;
|
||||
bool getWriteRestartFile(size_t timestep) const;
|
||||
bool getWriteRestartFile(size_t timestep, bool log=true) const;
|
||||
const std::map< std::string, int >& getRestartKeywords( size_t timestep ) const;
|
||||
int getKeyword( const std::string& keyword, size_t timeStep) const;
|
||||
|
||||
void overrideRestartWriteInterval(size_t interval);
|
||||
void handleSolutionSection(const SOLUTIONSection& solutionSection);
|
||||
void handleSolutionSection(const SOLUTIONSection& solutionSection, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void setWriteInitialRestartFile(bool writeInitialRestartFile);
|
||||
|
||||
RestartSchedule getNode( size_t timestep ) const;
|
||||
@@ -356,7 +365,7 @@ namespace Opm {
|
||||
int m_first_restart_step;
|
||||
bool m_write_initial_RST_file = false;
|
||||
|
||||
void handleScheduleSection( const SCHEDULESection& schedule);
|
||||
void handleScheduleSection( const SCHEDULESection& schedule, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void update( size_t step, const RestartSchedule& rs);
|
||||
static RestartSchedule rptsched( const DeckKeyword& );
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Tabdims.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EndpointScaling.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/UDQConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/UDQParams.hpp>
|
||||
|
||||
namespace Opm {
|
||||
class Deck;
|
||||
@@ -112,17 +112,61 @@ private:
|
||||
int nLatBranchMax;
|
||||
};
|
||||
|
||||
class EclHysterConfig
|
||||
{
|
||||
public:
|
||||
explicit EclHysterConfig(const Deck& deck);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Specify whether hysteresis is enabled or not.
|
||||
*/
|
||||
//void setActive(bool yesno);
|
||||
|
||||
/*!
|
||||
* \brief Returns whether hysteresis is enabled (active).
|
||||
*/
|
||||
bool active() const;
|
||||
|
||||
/*!
|
||||
* \brief Return the type of the hysteresis model which is used for capillary pressure.
|
||||
*
|
||||
* -1: capillary pressure hysteresis is disabled
|
||||
* 0: use the Killough model for capillary pressure hysteresis
|
||||
*/
|
||||
int pcHysteresisModel() const;
|
||||
|
||||
/*!
|
||||
* \brief Return the type of the hysteresis model which is used for relative permeability.
|
||||
*
|
||||
* -1: relperm hysteresis is disabled
|
||||
* 0: use the Carlson model for relative permeability hysteresis
|
||||
*/
|
||||
int krHysteresisModel() const;
|
||||
|
||||
private:
|
||||
// enable hysteresis at all
|
||||
bool activeHyst { false };
|
||||
|
||||
// the capillary pressure and the relperm hysteresis models to be used
|
||||
int pcHystMod { 0 };
|
||||
int krHystMod { 0 };
|
||||
};
|
||||
|
||||
|
||||
|
||||
class Runspec {
|
||||
public:
|
||||
explicit Runspec( const Deck& );
|
||||
|
||||
const UDQConfig& udqConfig() const noexcept;
|
||||
const UDQParams& udqParams() const noexcept;
|
||||
const Phases& phases() const noexcept;
|
||||
const Tabdims& tabdims() const noexcept;
|
||||
const EndpointScaling& endpointScaling() const noexcept;
|
||||
const Welldims& wellDimensions() const noexcept;
|
||||
const WellSegmentDims& wellSegmentDimensions() const noexcept;
|
||||
int eclPhaseMask( ) const noexcept;
|
||||
const EclHysterConfig& hysterPar() const noexcept;
|
||||
|
||||
private:
|
||||
Phases active_phases;
|
||||
@@ -130,9 +174,11 @@ class Runspec {
|
||||
EndpointScaling endscale;
|
||||
Welldims welldims;
|
||||
WellSegmentDims wsegdims;
|
||||
UDQConfig udq_config;
|
||||
UDQParams udq_params;
|
||||
EclHysterConfig hystpar;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // OPM_RUNSPEC_HPP
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright 2018 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ActionAST_HPP
|
||||
#define ActionAST_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class ActionContext;
|
||||
class ASTNode;
|
||||
|
||||
|
||||
|
||||
class ActionAST{
|
||||
public:
|
||||
ActionAST() = default;
|
||||
explicit ActionAST(const std::vector<std::string>& tokens);
|
||||
bool eval(const ActionContext& context, std::vector<std::string>& matching_wells) const;
|
||||
private:
|
||||
/*
|
||||
The use of a pointer here is to be able to create this class with only a
|
||||
forward declaration of the ASTNode class. Would have prefered to use a
|
||||
unique_ptr, but that requires writing custom destructors - the use of a
|
||||
shared_ptr does not imply any shared ownership.
|
||||
*/
|
||||
std::shared_ptr<ASTNode> condition;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2018 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ActionContext_HPP
|
||||
#define ActionContext_HPP
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class ActionContext {
|
||||
public:
|
||||
/*
|
||||
Observe that the ActionContext takes a copy of the SummaryState object.
|
||||
*/
|
||||
explicit ActionContext(const SummaryState& summary_state);
|
||||
|
||||
/*
|
||||
The get methods will first check the internal storage in the 'values' map
|
||||
and then subsequently query the SummaryState member.
|
||||
*/
|
||||
double get(const std::string& func, const std::string& arg) const;
|
||||
void add(const std::string& func, const std::string& arg, double value);
|
||||
|
||||
double get(const std::string& func) const;
|
||||
void add(const std::string& func, double value);
|
||||
|
||||
std::vector<std::string> wells(const std::string& func) const;
|
||||
|
||||
private:
|
||||
SummaryState summary_state;
|
||||
std::map<std::string, double> values;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -22,6 +22,11 @@
|
||||
#define ActionX_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ctime>
|
||||
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionAST.hpp>
|
||||
|
||||
namespace Opm {
|
||||
/*
|
||||
@@ -49,21 +54,36 @@ namespace Opm {
|
||||
*/
|
||||
|
||||
class DeckKeyword;
|
||||
class ActionContext;
|
||||
|
||||
class ActionX {
|
||||
public:
|
||||
ActionX(const std::string& name, size_t max_run, double max_wait);
|
||||
explicit ActionX(const DeckKeyword& kw);
|
||||
ActionX(const std::string& name, size_t max_run, double max_wait, std::time_t start_time);
|
||||
ActionX(const DeckKeyword& kw, std::time_t start_time);
|
||||
ActionX(const DeckRecord& record, std::time_t start_time);
|
||||
|
||||
void addKeyword(const DeckKeyword& kw);
|
||||
bool ready(std::time_t sim_time) const;
|
||||
bool eval(std::time_t sim_time, const ActionContext& context, std::vector<std::string>& wells) const;
|
||||
|
||||
const std::string& name() const;
|
||||
|
||||
std::string name() const { return this->m_name; }
|
||||
size_t max_run() const { return this->m_max_run; }
|
||||
double min_wait() const { return this->m_min_wait; }
|
||||
std::time_t start_time() const { return this->m_start_time; }
|
||||
std::vector<DeckKeyword>::const_iterator begin() const;
|
||||
std::vector<DeckKeyword>::const_iterator end() const;
|
||||
static bool valid_keyword(const std::string& keyword);
|
||||
private:
|
||||
std::string m_name;
|
||||
size_t max_run;
|
||||
double max_wait;
|
||||
size_t m_max_run = 0;
|
||||
double m_min_wait = 0.0;
|
||||
std::time_t m_start_time;
|
||||
|
||||
std::vector<DeckKeyword> keywords;
|
||||
ActionAST condition;
|
||||
mutable size_t run_count = 0;
|
||||
mutable std::time_t last_run = 0;
|
||||
};
|
||||
|
||||
}
|
||||
45
opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp
Normal file
45
opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2018 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ActionCOnfig_HPP
|
||||
#define ActionCOnfig_HPP
|
||||
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class Actions {
|
||||
public:
|
||||
Actions() = default;
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
void add(const ActionX& action);
|
||||
bool ready(std::time_t sim_time) const;
|
||||
ActionX& at(const std::string& name);
|
||||
std::vector<const ActionX *> pending(std::time_t sim_time) const;
|
||||
private:
|
||||
std::map<std::string, ActionX> actions;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -46,6 +46,8 @@ namespace Opm {
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
double r0,
|
||||
double skin_factor,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction,
|
||||
const std::size_t seqIndex,
|
||||
@@ -69,6 +71,8 @@ namespace Opm {
|
||||
double CF() const;
|
||||
double Kh() const;
|
||||
double rw() const;
|
||||
double r0() const;
|
||||
double skinFactor() const;
|
||||
double wellPi() const;
|
||||
|
||||
void setState(WellCompletion::StateEnum state);
|
||||
@@ -96,6 +100,8 @@ namespace Opm {
|
||||
double m_CF;
|
||||
double m_Kh;
|
||||
double m_rw;
|
||||
double m_r0;
|
||||
double m_skin_factor;
|
||||
|
||||
std::array<int,3> ijk;
|
||||
std::size_t m_seqIndex;
|
||||
|
||||
@@ -114,6 +114,35 @@ class DynamicState {
|
||||
this->m_data[index] = value;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Will assign all currently equal values starting at index with the new
|
||||
value. Purpose of the method is to support manipulations of an existing
|
||||
Schedule object, if e.g. a well is initially closed in the interval
|
||||
[T1,T2] and then opened at time T1 < Tx < T2 then the open should be
|
||||
applied for all times in the range [Tx,T2].
|
||||
*/
|
||||
void update_equal(size_t index, const T& value) {
|
||||
if (this->m_data.size() <= index)
|
||||
throw std::out_of_range("Invalid index for update_equal()");
|
||||
|
||||
const T prev_value = this->m_data[index];
|
||||
if (prev_value == value)
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
if (this->m_data[index] != prev_value)
|
||||
break;
|
||||
|
||||
this->m_data[index] = value;
|
||||
|
||||
index++;
|
||||
if (index == this->m_data.size())
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// Will return the index of the first occurence of @value, or
|
||||
/// -1 if @value is not found.
|
||||
int find(const T& value) const {
|
||||
|
||||
@@ -34,8 +34,8 @@ class GroupTree {
|
||||
bool exists( const std::string& group ) const;
|
||||
const std::string& parent( const std::string& name ) const;
|
||||
std::vector< std::string > children( const std::string& parent ) const;
|
||||
const std::map<const std::string , size_t>& nameSeqIndMap() const;
|
||||
const std::map<size_t, const std::string >& seqIndNameMap() const;
|
||||
const std::map<std::string , size_t>& nameSeqIndMap() const;
|
||||
const std::map<size_t, std::string >& seqIndNameMap() const;
|
||||
size_t groupTreeSize();
|
||||
bool operator==( const GroupTree& ) const;
|
||||
bool operator!=( const GroupTree& ) const;
|
||||
@@ -57,8 +57,8 @@ class GroupTree {
|
||||
std::vector< group > groups = { group { "FIELD", "" } };
|
||||
friend bool operator<( const std::string&, const group& );
|
||||
std::vector< group >::iterator find( const std::string& );
|
||||
std::map<const std::string , size_t> m_nameSeqIndMap;
|
||||
std::map<size_t, const std::string > m_seqIndNameMap;
|
||||
std::map<std::string , size_t> m_nameSeqIndMap;
|
||||
std::map<size_t, std::string > m_seqIndNameMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
|
||||
@@ -28,24 +29,27 @@ namespace Opm
|
||||
{
|
||||
/*
|
||||
* The OilVaporizationProperties class
|
||||
* This classe is used to store the values from {VAPPARS, DRSDT, DRVDT} the behavior of the keywords are mutal exclusive.
|
||||
* Any one of the three keywords {VAPPARS, DRSDT, DRVDT} will cancel previous settings of the other keywords.
|
||||
* This classe is used to store the values from {VAPPARS, DRSDT, DRVDT}
|
||||
* The VAPPARS and {DRSDT, DRVDT} are mutal exclusive and will cancel previous settings of the other keywords.
|
||||
* Ask for type first and the ask for the correct values for this type, asking for values not valid for the current type will throw a logic exception.
|
||||
*/
|
||||
class OilVaporizationProperties {
|
||||
public:
|
||||
OilVaporizationProperties() = default;
|
||||
static OilVaporizationProperties createDRSDT(double maxDRSDT, const std::string& option);
|
||||
static OilVaporizationProperties createDRVDT(double maxDRVDT);
|
||||
static OilVaporizationProperties createVAPPARS(double vap1, double vap2);
|
||||
explicit OilVaporizationProperties(const size_t numPvtReginIdx);
|
||||
static void updateDRSDT(Opm::OilVaporizationProperties& ovp, const std::vector<double>& maxDRSDT, const std::vector<std::string>& option);
|
||||
static void updateDRVDT(Opm::OilVaporizationProperties& ovp, const std::vector<double>& maxDRVDT);
|
||||
static void updateVAPPARS(Opm::OilVaporizationProperties& ovp, const std::vector<double>& vap1, const std::vector<double>& vap2);
|
||||
|
||||
Opm::OilVaporizationEnum getType() const;
|
||||
double getVap1() const;
|
||||
double getVap2() const;
|
||||
double getMaxDRSDT() const;
|
||||
double getMaxDRVDT() const;
|
||||
bool getOption() const;
|
||||
double getVap1(const size_t pvtRegionIdx) const;
|
||||
double getVap2(const size_t pvtRegionIdx) const;
|
||||
double getMaxDRSDT(const size_t pvtRegionIdx) const;
|
||||
double getMaxDRVDT(const size_t pvtRegionIdx) const;
|
||||
bool getOption(const size_t pvtRegionIdx) const;
|
||||
bool drsdtActive() const;
|
||||
bool drvdtActive() const;
|
||||
bool defined() const;
|
||||
size_t numPvtRegions() const {return m_maxDRSDT.size();}
|
||||
|
||||
/*
|
||||
* if either argument was default constructed == will always be false
|
||||
@@ -56,11 +60,11 @@ namespace Opm
|
||||
|
||||
private:
|
||||
Opm::OilVaporizationEnum m_type = OilVaporizationEnum::UNDEF;
|
||||
double m_vap1;
|
||||
double m_vap2;
|
||||
double m_maxDRSDT;
|
||||
double m_maxDRVDT;
|
||||
bool m_maxDRSDT_allCells;
|
||||
std::vector<double> m_vap1;
|
||||
std::vector<double> m_vap2;
|
||||
std::vector<double> m_maxDRSDT;
|
||||
std::vector<bool> m_maxDRSDT_allCells;
|
||||
std::vector<double> m_maxDRVDT;
|
||||
};
|
||||
}
|
||||
#endif // DRSDT_H
|
||||
|
||||
@@ -40,31 +40,62 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellTestConfig.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
class Actions;
|
||||
class Deck;
|
||||
class DeckKeyword;
|
||||
class DeckRecord;
|
||||
class EclipseGrid;
|
||||
class Eclipse3DProperties;
|
||||
class EclipseState;
|
||||
class Runspec;
|
||||
class SCHEDULESection;
|
||||
class SummaryState;
|
||||
class TimeMap;
|
||||
class UnitSystem;
|
||||
class EclipseState;
|
||||
class ErrorGuard;
|
||||
class WListManager;
|
||||
class UDQ;
|
||||
|
||||
class Schedule {
|
||||
public:
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseGrid& grid,
|
||||
const Eclipse3DProperties& eclipseProperties,
|
||||
const Phases &phases,
|
||||
const ParseContext& parseContext = ParseContext());
|
||||
const Runspec &runspec,
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors);
|
||||
|
||||
template<typename T>
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseGrid& grid,
|
||||
const Eclipse3DProperties& eclipseProperties,
|
||||
const Runspec &runspec,
|
||||
const ParseContext& parseContext,
|
||||
T&& errors);
|
||||
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseGrid& grid,
|
||||
const Eclipse3DProperties& eclipseProperties,
|
||||
const Runspec &runspec);
|
||||
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseState& es,
|
||||
const ParseContext& parseContext = ParseContext());
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors);
|
||||
|
||||
template <typename T>
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseState& es,
|
||||
const ParseContext& parseContext,
|
||||
T&& errors);
|
||||
|
||||
Schedule(const Deck& deck,
|
||||
const EclipseState& es);
|
||||
|
||||
/*
|
||||
* If the input deck does not specify a start time, Eclipse's 1. Jan
|
||||
@@ -73,7 +104,9 @@ namespace Opm
|
||||
time_t getStartTime() const;
|
||||
time_t posixStartTime() const;
|
||||
time_t posixEndTime() const;
|
||||
|
||||
time_t simTime(size_t timeStep) const;
|
||||
double seconds(size_t timeStep) const;
|
||||
double stepLength(size_t timeStep) const;
|
||||
|
||||
const TimeMap& getTimeMap() const;
|
||||
|
||||
@@ -94,26 +127,30 @@ namespace Opm
|
||||
|
||||
is an inefficient way to get all the wells defined at time
|
||||
't'.
|
||||
*/
|
||||
//std::vector< const Group& > getChildGroups(const std::string& group_name, size_t timeStep) const;
|
||||
*/
|
||||
//std::vector< const Group& > getChildGroups(const std::string& group_name, size_t timeStep) const;
|
||||
std::vector< const Group* > getChildGroups(const std::string& group_name, size_t timeStep) const;
|
||||
std::vector< const Well* > getWells(const std::string& group, size_t timeStep) const;
|
||||
std::vector< const Well* > getChildWells(const std::string& group_name, size_t timeStep) const;
|
||||
std::vector< const Well* > getChildWells(const std::string& group_name, size_t timeStep) const;
|
||||
std::vector< const Well* > getWellsMatching( const std::string& ) const;
|
||||
const OilVaporizationProperties& getOilVaporizationProperties(size_t timestep) const;
|
||||
|
||||
const WellTestConfig& wtestConfig(size_t timestep) const;
|
||||
const WListManager& getWListManager(size_t timeStep) const;
|
||||
const UDQ& getUDQConfig(size_t timeStep) const;
|
||||
const Actions& actions() const;
|
||||
void evalAction(const SummaryState& summary_state, size_t timeStep);
|
||||
|
||||
const GroupTree& getGroupTree(size_t t) const;
|
||||
size_t numGroups() const;
|
||||
size_t numGroups(size_t timeStep) const;
|
||||
size_t numGroups(size_t timeStep) const;
|
||||
bool hasGroup(const std::string& groupName) const;
|
||||
const Group& getGroup(const std::string& groupName) const;
|
||||
std::vector< const Group* > getGroups() const;
|
||||
std::vector< const Group* > getGroups(size_t timeStep) const;
|
||||
std::vector< const Group* > getGroups(size_t timeStep) const;
|
||||
const Tuning& getTuning() const;
|
||||
const MessageLimits& getMessageLimits() const;
|
||||
void invalidNamePattern (const std::string& namePattern, const ParseContext& parseContext, const DeckKeyword& keyword) const;
|
||||
void invalidNamePattern (const std::string& namePattern, const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& keyword) const;
|
||||
|
||||
const Events& getEvents() const;
|
||||
const Deck& getModifierDeck(size_t timeStep) const;
|
||||
@@ -127,7 +164,9 @@ namespace Opm
|
||||
active. Will scan through all wells and all timesteps.
|
||||
*/
|
||||
void filterConnections(const EclipseGrid& grid);
|
||||
size_t size() const;
|
||||
|
||||
void applyAction(size_t reportStep, const ActionX& action, const std::vector<std::string>& matching_wells);
|
||||
private:
|
||||
TimeMap m_timeMap;
|
||||
OrderedMap< Well > m_wells;
|
||||
@@ -138,57 +177,67 @@ namespace Opm
|
||||
DynamicVector< Deck > m_modifierDeck;
|
||||
Tuning m_tuning;
|
||||
MessageLimits m_messageLimits;
|
||||
Phases m_phases;
|
||||
Runspec m_runspec;
|
||||
std::map<int, DynamicState<std::shared_ptr<VFPProdTable>>> vfpprod_tables;
|
||||
std::map<int, DynamicState<std::shared_ptr<VFPInjTable>>> vfpinj_tables;
|
||||
DynamicState<std::shared_ptr<WellTestConfig>> wtest_config;
|
||||
DynamicState<std::shared_ptr<WListManager>> wlist_manager;
|
||||
DynamicState<std::shared_ptr<UDQ>> udq_config;
|
||||
|
||||
WellProducer::ControlModeEnum m_controlModeWHISTCTL;
|
||||
Actions m_actions;
|
||||
|
||||
std::vector< Well* > getWells(const std::string& wellNamePattern);
|
||||
std::vector< Well* > getWells(const std::string& wellNamePattern, const std::vector<std::string>& matching_wells = {});
|
||||
std::vector< Group* > getGroups(const std::string& groupNamePattern);
|
||||
|
||||
void updateWellStatus( Well& well, size_t reportStep , WellCommon::StatusEnum status);
|
||||
void addWellToGroup( Group& newGroup , Well& well , size_t timeStep);
|
||||
void iterateScheduleSection(const ParseContext& parseContext , const SCHEDULESection& , const EclipseGrid& grid,
|
||||
void iterateScheduleSection(const ParseContext& parseContext , ErrorGuard& errors, const SCHEDULESection& , const EclipseGrid& grid,
|
||||
const Eclipse3DProperties& eclipseProperties);
|
||||
bool handleGroupFromWELSPECS(const std::string& groupName, GroupTree& newTree) const;
|
||||
void addGroup(const std::string& groupName , size_t timeStep);
|
||||
void addWell(const std::string& wellName, const DeckRecord& record, size_t timeStep, WellCompletion::CompletionOrderEnum wellCompletionOrder);
|
||||
void handleCOMPORD(const ParseContext& parseContext, const DeckKeyword& compordKeyword, size_t currentStep);
|
||||
void handleUDQ(const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWLIST(const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleCOMPORD(const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& compordKeyword, size_t currentStep);
|
||||
void handleWELSPECS( const SCHEDULESection&, size_t, size_t );
|
||||
void handleWCONProducer( const DeckKeyword& keyword, size_t currentStep, bool isPredictionMode, const ParseContext& parseContext);
|
||||
void handleWCONHIST( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWCONPROD( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWCONProducer( const DeckKeyword& keyword, size_t currentStep, bool isPredictionMode, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWCONHIST( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWCONPROD( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWGRUPCON( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const ParseContext& parseContext);
|
||||
void handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleCOMPLUMP( const DeckKeyword& keyword, size_t currentStep );
|
||||
void handleWELSEGS( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleCOMPSEGS( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid);
|
||||
void handleWCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWPOLYMER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWSOLVENT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWINJTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWCONINJH( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWELOPEN( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext );
|
||||
void handleWELTARG( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleGCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleGCONPROD( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleGEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWPOLYMER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWSOLVENT( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWTRACER( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWPMITAB( const DeckKeyword& keyword, const size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWSKPTAB( const DeckKeyword& keyword, const size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWINJTEMP( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWCONINJH( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWELOPEN( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors, const std::vector<std::string>& matching_wells = {});
|
||||
void handleWELTARG( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleGCONINJE( const SCHEDULESection&, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleGCONPROD( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleGEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWEFAC( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleTUNING( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleGRUPTREE( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleGRUPNET( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWRFT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWTEST( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWTEST( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWRFTPLT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWPIMULT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleDRSDT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleDRVDT( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleDRSDTR( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleDRVDTR( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleVAPPARS( const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleWECON( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext);
|
||||
void handleWHISTCTL(const ParseContext& parseContext, const DeckKeyword& keyword);
|
||||
void handleWECON( const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
void handleWHISTCTL(const ParseContext& parseContext, ErrorGuard& errors, const DeckKeyword& keyword);
|
||||
void handleMESSAGES(const DeckKeyword& keyword, size_t currentStep);
|
||||
void handleVFPPROD(const DeckKeyword& vfpprodKeyword, const UnitSystem& unit_system, size_t currentStep);
|
||||
void handleVFPINJ(const DeckKeyword& vfpprodKeyword, const UnitSystem& unit_system, size_t currentStep);
|
||||
@@ -198,7 +247,7 @@ namespace Opm
|
||||
const SCHEDULESection& section,
|
||||
size_t keywordIdx,
|
||||
const DeckKeyword& keyword,
|
||||
const ParseContext& parseContext,
|
||||
const ParseContext& parseContext, ErrorGuard& errors,
|
||||
const EclipseGrid& grid,
|
||||
const Eclipse3DProperties& eclipseProperties,
|
||||
const UnitSystem& unit_system,
|
||||
|
||||
@@ -230,8 +230,7 @@ namespace Opm {
|
||||
enum OilVaporizationEnum{
|
||||
UNDEF = 0,
|
||||
VAPPARS = 1,
|
||||
DRSDT = 2,
|
||||
DRVDT = 3
|
||||
DRDT = 2 // DRSDT or DRVDT
|
||||
};
|
||||
|
||||
|
||||
|
||||
88
opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp
Normal file
88
opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SUMMARY_STATE_H
|
||||
#define SUMMARY_STATE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ert/ecl/smspec_node.hpp>
|
||||
|
||||
namespace Opm{
|
||||
|
||||
|
||||
/*
|
||||
The purpose of this class is to serve as a small container object for
|
||||
computed, ready to use summary values. The values will typically be used by
|
||||
the UDQ, WTEST and ACTIONX calculations. Observe that all value *have been
|
||||
converted to the correct output units*.
|
||||
|
||||
The main key used to access the content of this container is the eclipse style
|
||||
colon separated string - i.e. 'WWCT:OPX' to get the watercut in well 'OPX'.
|
||||
The main usage of the SummaryState class is a temporary holding ground while
|
||||
assembling data for the summary output, but it is also used as a context
|
||||
object when evaulating the condition in ACTIONX keywords. For that reason some
|
||||
of the data is duplicated both in the general structure and a specialized
|
||||
structure:
|
||||
|
||||
SummaryState st;
|
||||
|
||||
st.add_well_var("OPX", "WWCT", 0.75);
|
||||
st.add("WGOR:OPY", 120);
|
||||
|
||||
// The WWCT:OPX key has been added with the specialized add_well_var()
|
||||
// method and this data is available both with the general
|
||||
// st.has("WWCT:OPX") and the specialized st.has_well_var("OPX", "WWCT");
|
||||
st.has("WWCT:OPX") => True
|
||||
st.has_well_var("OPX", "WWCT") => True
|
||||
|
||||
|
||||
// The WGOR:OPY key is added with the general add("WGOR:OPY") and is *not*
|
||||
// accessible through the specialized st.has_well_var("OPY", "WGOR").
|
||||
st.has("WGOR:OPY") => True
|
||||
st.has_well_var("OPY", "WGOR") => False
|
||||
*/
|
||||
|
||||
class SummaryState {
|
||||
public:
|
||||
typedef std::unordered_map<std::string, double>::const_iterator const_iterator;
|
||||
|
||||
double get(const std::string&) const;
|
||||
bool has(const std::string& key) const;
|
||||
void add(const std::string& key, double value);
|
||||
void add(const ecl::smspec_node& node, double value);
|
||||
|
||||
void add_well_var(const std::string& well, const std::string& var, double value);
|
||||
bool has_well_var(const std::string& well, const std::string& var) const;
|
||||
double get_well_var(const std::string& well, const std::string& var) const;
|
||||
|
||||
std::vector<std::string> wells(const std::string& var) const;
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
private:
|
||||
std::unordered_map<std::string,double> values;
|
||||
|
||||
// The first key is the variable and the second key is the well.
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, double>> well_values;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -44,6 +44,7 @@ namespace Opm {
|
||||
size_t last() const;
|
||||
size_t numTimesteps() const;
|
||||
double getTotalTime() const;
|
||||
double seconds(size_t timeStep) const;
|
||||
|
||||
std::time_t operator[] (size_t index) const;
|
||||
/// Return the date and time where a given time step starts.
|
||||
@@ -65,8 +66,8 @@ namespace Opm {
|
||||
static std::time_t forward(std::time_t t0, int64_t seconds);
|
||||
static std::time_t mkdate(int year, int month, int day);
|
||||
static std::time_t mkdatetime(int year, int month, int day, int hour, int minute, int second);
|
||||
private:
|
||||
static const std::map<std::string, int>& eclipseMonthIndices();
|
||||
private:
|
||||
|
||||
std::vector<std::time_t> m_timeList;
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@
|
||||
#ifndef UDQState_HPP_
|
||||
#define UDQState_HPP_
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/UDQConfig.hpp>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/UDQExpression.hpp>
|
||||
|
||||
|
||||
@@ -29,10 +31,13 @@ namespace Opm {
|
||||
|
||||
class UDQ{
|
||||
public:
|
||||
UDQ(const UDQConfig& config, const Deck& deck);
|
||||
void add_record(const DeckRecord& record);
|
||||
const std::vector<UDQExpression>& expressions() const noexcept;
|
||||
const std::string& unit(const std::string& key) const;
|
||||
void assign_unit(const std::string& keyword, const std::string& unit);
|
||||
private:
|
||||
std::vector<UDQExpression> m_expressions;
|
||||
std::unordered_map<std::string, std::string> units;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,12 @@ namespace Opm {
|
||||
UDQExpression(const std::string& action, const std::string& keyword, const std::vector<std::string>& data);
|
||||
explicit UDQExpression(const DeckRecord& expression);
|
||||
const std::vector<std::string>& tokens() const;
|
||||
UDQAction action() const;
|
||||
const std::string& keyword() const;
|
||||
static UDQAction actionString2Enum(const std::string& action_string);
|
||||
private:
|
||||
UDQAction action;
|
||||
std::string keyword;
|
||||
UDQAction m_action;
|
||||
std::string m_keyword;
|
||||
std::vector<std::string> data;
|
||||
};
|
||||
}
|
||||
|
||||
41
opm/parser/eclipse/EclipseState/Schedule/WList.hpp
Normal file
41
opm/parser/eclipse/EclipseState/Schedule/WList.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class WList {
|
||||
public:
|
||||
using storage = std::unordered_set<std::string>;
|
||||
std::size_t size() const;
|
||||
void add(const std::string& well);
|
||||
void del(const std::string& well);
|
||||
bool has(const std::string& well) const;
|
||||
|
||||
std::vector<std::string> wells() const;
|
||||
storage::const_iterator begin() const;
|
||||
storage::const_iterator end() const;
|
||||
private:
|
||||
storage well_list;
|
||||
};
|
||||
|
||||
}
|
||||
39
opm/parser/eclipse/EclipseState/Schedule/WListManager.hpp
Normal file
39
opm/parser/eclipse/EclipseState/Schedule/WListManager.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2019 Equinor ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class WList;
|
||||
|
||||
class WListManager {
|
||||
public:
|
||||
bool hasList(const std::string&) const;
|
||||
WList& getList(const std::string& name);
|
||||
const WList& getList(const std::string& name) const;
|
||||
WList& newList(const std::string& name);
|
||||
void delWell(const std::string& well);
|
||||
private:
|
||||
std::map<std::string, WList> wlists;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellEconProductionLimits.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellInjectionProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellPolymerProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellTracerProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
@@ -51,14 +52,14 @@ namespace Opm {
|
||||
class Well {
|
||||
public:
|
||||
Well(const std::string& name, const size_t& seqIndex, int headI,
|
||||
int headJ, double refDepth, Phase preferredPhase,
|
||||
int headJ, double refDepth, double drainageRadius, Phase preferredPhase,
|
||||
const TimeMap& timeMap, size_t creationTimeStep,
|
||||
WellCompletion::CompletionOrderEnum completionOrdering = WellCompletion::TRACK,
|
||||
bool allowCrossFlow = true, bool automaticShutIn = true);
|
||||
const std::string& name() const;
|
||||
const size_t& seqIndex() const;
|
||||
const std::size_t getTotNoConn() const;
|
||||
void setTotNoConn(std::size_t noConn);
|
||||
std::size_t getTotNoConn() const;
|
||||
void setTotNoConn(std::size_t noConn);
|
||||
bool hasBeenDefined(size_t timeStep) const;
|
||||
const std::string getGroupName(size_t timeStep) const;
|
||||
void setGroupName(size_t timeStep , const std::string& groupName);
|
||||
@@ -76,6 +77,9 @@ namespace Opm {
|
||||
double getRefDepth() const;
|
||||
double getRefDepth( size_t timestep ) const;
|
||||
void setRefDepth( size_t timestep, double );
|
||||
double getDrainageRadius( size_t timestep ) const;
|
||||
void setDrainageRadius( size_t timestep, double );
|
||||
|
||||
Phase getPreferredPhase() const;
|
||||
|
||||
bool isAvailableForGroupControl(size_t timeStep) const;
|
||||
@@ -147,6 +151,9 @@ namespace Opm {
|
||||
WellPolymerProperties getPolymerPropertiesCopy(size_t timeStep) const;
|
||||
const WellPolymerProperties& getPolymerProperties(size_t timeStep) const;
|
||||
|
||||
bool setTracerProperties(size_t timeStep , const WellTracerProperties& properties);
|
||||
const WellTracerProperties& getTracerProperties(size_t timeStep) const;
|
||||
|
||||
bool setSolventFraction(size_t timeStep , const double fraction);
|
||||
const double& getSolventFraction(size_t timeStep) const;
|
||||
|
||||
@@ -219,6 +226,7 @@ namespace Opm {
|
||||
DynamicState< WellPolymerProperties > m_polymerProperties;
|
||||
DynamicState< WellEconProductionLimits > m_econproductionlimits;
|
||||
DynamicState< double > m_solventFraction;
|
||||
DynamicState< WellTracerProperties > m_tracerProperties;
|
||||
DynamicState< std::string > m_groupName;
|
||||
DynamicState< int > m_rft;
|
||||
DynamicState< int > m_plt;
|
||||
@@ -226,6 +234,7 @@ namespace Opm {
|
||||
DynamicState< int > m_headI;
|
||||
DynamicState< int > m_headJ;
|
||||
DynamicState< double > m_refDepth;
|
||||
DynamicState< double > m_drainageRadius;
|
||||
Phase m_preferredPhase;
|
||||
|
||||
WellCompletion::CompletionOrderEnum m_comporder;
|
||||
|
||||
@@ -38,12 +38,14 @@ namespace Opm {
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
double r0,
|
||||
double skin_factor,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z,
|
||||
const std::size_t seqIndex = 0,
|
||||
const double segDistStart= 0.0,
|
||||
const double segDistEnd= 0.0,
|
||||
const bool defaultSatTabId = true);
|
||||
const std::size_t seqIndex = 0,
|
||||
const double segDistStart= 0.0,
|
||||
const double segDistEnd= 0.0,
|
||||
const bool defaultSatTabId = true);
|
||||
void loadCOMPDAT(const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, std::size_t& totNC);
|
||||
|
||||
using const_iterator = std::vector< Connection >::const_iterator;
|
||||
@@ -87,16 +89,19 @@ namespace Opm {
|
||||
double CF,
|
||||
double Kh,
|
||||
double rw,
|
||||
double r0,
|
||||
double skin_factor,
|
||||
const int satTableId,
|
||||
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z,
|
||||
const std::size_t seqIndex = 0,
|
||||
const double segDistStart= 0.0,
|
||||
const double segDistEnd= 0.0,
|
||||
const bool defaultSatTabId = true);
|
||||
const std::size_t seqIndex = 0,
|
||||
const double segDistStart= 0.0,
|
||||
const double segDistEnd= 0.0,
|
||||
const bool defaultSatTabId = true);
|
||||
|
||||
std::vector< Connection > m_connections;
|
||||
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
||||
|
||||
int headI, headJ;
|
||||
std::vector< Connection > m_connections;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,10 @@ namespace Opm {
|
||||
if ((injectionControls & controlModeArg) == 0)
|
||||
injectionControls += controlModeArg;
|
||||
}
|
||||
|
||||
void resetDefaultHistoricalBHPLimit();
|
||||
|
||||
void setBHPLimit(const double limit);
|
||||
};
|
||||
|
||||
std::ostream& operator<<( std::ostream&, const WellInjectionProperties& );
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Opm {
|
||||
struct WellPolymerProperties {
|
||||
double m_polymerConcentration;
|
||||
double m_saltConcentration;
|
||||
int m_plymwinjtable;
|
||||
int m_skprwattable;
|
||||
int m_skprpolytable;
|
||||
|
||||
bool operator==(const WellPolymerProperties& other) const;
|
||||
bool operator!=(const WellPolymerProperties& other) const;
|
||||
|
||||
@@ -57,7 +57,8 @@ namespace Opm {
|
||||
|
||||
static WellProductionProperties history(const WellProductionProperties& prevProperties,
|
||||
const DeckRecord& record,
|
||||
const WellProducer::ControlModeEnum controlModeWHISTCL);
|
||||
const WellProducer::ControlModeEnum controlModeWHISTCL,
|
||||
const bool switching_from_injector);
|
||||
|
||||
static WellProductionProperties prediction( const DeckRecord& record, bool addGroupProductionControl );
|
||||
|
||||
@@ -82,6 +83,12 @@ namespace Opm {
|
||||
int m_productionControls = 0;
|
||||
|
||||
WellProductionProperties(const DeckRecord& record);
|
||||
|
||||
void resetDefaultBHPLimit();
|
||||
|
||||
void setBHPLimit(const double limit);
|
||||
|
||||
double getBHPLimit() const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<( std::ostream&, const WellProductionProperties& );
|
||||
|
||||
@@ -105,6 +105,11 @@ public:
|
||||
size_t sizeWells() const;
|
||||
size_t sizeCompletions() const;
|
||||
|
||||
/*
|
||||
Return the last tested time for the well, or throw if no such well.
|
||||
*/
|
||||
double lastTestTime(const std::string& well_name) const;
|
||||
|
||||
private:
|
||||
std::vector<ClosedWell> wells;
|
||||
std::vector<ClosedCompletion> completions;
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2018 NORCE.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WELLTRACERPROPERTIES_HPP_HEADER_INCLUDED
|
||||
#define WELLTRACERPROPERTIES_HPP_HEADER_INCLUDED
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class WellTracerProperties {
|
||||
|
||||
public:
|
||||
WellTracerProperties();
|
||||
|
||||
void setConcentration(const std::string& name, const double& concentration);
|
||||
double getConcentration(const std::string& name) const;
|
||||
|
||||
bool operator==(const WellTracerProperties& other) const;
|
||||
bool operator!=(const WellTracerProperties& other) const;
|
||||
|
||||
private:
|
||||
std::map< std::string, double > m_tracerConcentrations;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -40,12 +40,14 @@ namespace Opm {
|
||||
bool useCPR() const;
|
||||
bool hasDISGAS() const;
|
||||
bool hasVAPOIL() const;
|
||||
bool isThermal() const;
|
||||
|
||||
private:
|
||||
ThresholdPressure m_ThresholdPressure;
|
||||
bool m_useCPR;
|
||||
bool m_DISGAS;
|
||||
bool m_VAPOIL;
|
||||
bool m_isThermal;
|
||||
};
|
||||
|
||||
} //namespace Opm
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
#include <ert/ecl/smspec_node.h>
|
||||
#include <ert/ecl/smspec_node.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -36,44 +36,61 @@ namespace Opm {
|
||||
|
||||
class SummaryNode {
|
||||
public:
|
||||
SummaryNode(smspec_node_type * c_ptr) :
|
||||
ptr(c_ptr)
|
||||
SummaryNode(const std::string& keyword) :
|
||||
ecl_node(0, keyword.c_str(), "UNIT", 0.0)
|
||||
{}
|
||||
|
||||
SummaryNode(const SummaryNode& other) :
|
||||
ptr( smspec_node_alloc_copy(other.get()))
|
||||
|
||||
SummaryNode(const std::string& keyword, const std::string& wgname) :
|
||||
ecl_node(0, keyword.c_str(), wgname.c_str(), "UNIT", 0.0, ":")
|
||||
{}
|
||||
|
||||
const smspec_node_type * get() const {
|
||||
return this->ptr;
|
||||
}
|
||||
SummaryNode(const std::string& keyword, const std::string& wgname, int num) :
|
||||
ecl_node(0, keyword.c_str(), wgname.c_str(), num, "UNIT", 0.0, ":")
|
||||
{}
|
||||
|
||||
SummaryNode(const std::string& keyword, int num) :
|
||||
ecl_node(0, keyword.c_str(), num, "UNIT", 0, ":")
|
||||
{}
|
||||
|
||||
SummaryNode(const std::string& keyword, int num, const int grid_dims[3]) :
|
||||
ecl_node(0, keyword.c_str(), num, "UNIT", grid_dims, 0, ":")
|
||||
{}
|
||||
|
||||
SummaryNode(const std::string& keyword, const std::string& wgname, int num, const int grid_dims[3]) :
|
||||
ecl_node(0, keyword.c_str(), wgname.c_str(), num, "UNIT", grid_dims, 0, ":")
|
||||
{}
|
||||
|
||||
std::string wgname() const {
|
||||
return smspec_node_get_wgname(this->ptr);
|
||||
const char * c_ptr = this->ecl_node.get_wgname();
|
||||
if (c_ptr)
|
||||
return std::string(c_ptr);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string keyword() const {
|
||||
return smspec_node_get_keyword(this->ptr);
|
||||
return this->ecl_node.get_keyword();
|
||||
}
|
||||
|
||||
std::string gen_key() const {
|
||||
return this->ecl_node.get_gen_key1();
|
||||
}
|
||||
|
||||
int num() const {
|
||||
return smspec_node_get_num(this->ptr);
|
||||
return this->ecl_node.get_num();
|
||||
}
|
||||
|
||||
ecl_smspec_var_type type() const {
|
||||
return smspec_node_get_var_type(this->ptr);
|
||||
return this->ecl_node.get_var_type();
|
||||
}
|
||||
|
||||
SummaryNode& operator=(const SummaryNode &other) {
|
||||
this->ptr = smspec_node_alloc_copy(other.ptr);
|
||||
return *this;
|
||||
int cmp(const SummaryNode& other) const {
|
||||
return this->ecl_node.cmp( other.ecl_node );
|
||||
}
|
||||
|
||||
~SummaryNode() {
|
||||
smspec_node_free(this->ptr);
|
||||
}
|
||||
private:
|
||||
smspec_node_type * ptr;
|
||||
ecl::smspec_node ecl_node;
|
||||
};
|
||||
|
||||
|
||||
@@ -82,6 +99,7 @@ namespace Opm {
|
||||
class EclipseState;
|
||||
class ParserKeyword;
|
||||
class Schedule;
|
||||
class ErrorGuard;
|
||||
class ParseContext;
|
||||
class GridDims;
|
||||
|
||||
@@ -91,8 +109,24 @@ namespace Opm {
|
||||
typedef std::vector< keyword_type > keyword_list;
|
||||
typedef keyword_list::const_iterator const_iterator;
|
||||
|
||||
SummaryConfig( const Deck&, const Schedule&,
|
||||
const TableManager&, const ParseContext&);
|
||||
SummaryConfig( const Deck&,
|
||||
const Schedule&,
|
||||
const TableManager&,
|
||||
const ParseContext&,
|
||||
ErrorGuard&);
|
||||
|
||||
template <typename T>
|
||||
SummaryConfig( const Deck&,
|
||||
const Schedule&,
|
||||
const TableManager&,
|
||||
const ParseContext&,
|
||||
T&&);
|
||||
|
||||
SummaryConfig( const Deck&,
|
||||
const Schedule&,
|
||||
const TableManager&);
|
||||
|
||||
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
@@ -124,6 +158,7 @@ namespace Opm {
|
||||
const Schedule& schedule,
|
||||
const TableManager& tables,
|
||||
const ParseContext& parseContext,
|
||||
ErrorGuard& errors,
|
||||
const GridDims& dims);
|
||||
|
||||
/*
|
||||
|
||||
38
opm/parser/eclipse/EclipseState/Tables/PlymwinjTable.hpp
Normal file
38
opm/parser/eclipse/EclipseState/Tables/PlymwinjTable.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright (C) 2018 Statoil ASA
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_PARSER_PLYMWINJ_TABLE_HPP
|
||||
#define OPM_PARSER_PLYMWINJ_TABLE_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp>
|
||||
namespace Opm {
|
||||
|
||||
class DeckKeyword;
|
||||
|
||||
class PlymwinjTable : public PolyInjTable {
|
||||
public:
|
||||
|
||||
explicit PlymwinjTable(const DeckKeyword& table);
|
||||
|
||||
const std::vector<std::vector<double>>& getMoleWeights() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_PARSER_PLYMWINJ_TABLE_HPP
|
||||
67
opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp
Normal file
67
opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright (C) 2018 Statoil ASA
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_PARSER_POLY_INJ_TABLE_HPP
|
||||
#define OPM_PARSER_POLY_INJ_TABLE_HPP
|
||||
|
||||
|
||||
/* This class is introduced for the following keywords related to polymer injectivity study.
|
||||
* PLYMWINJ, SKPRWAT, SKPRPOLY .
|
||||
* These keywords share very similar structure with small difference.
|
||||
*
|
||||
* KEYWORD
|
||||
* 1 / --table number
|
||||
* 0 20 30 / -- water throughputs
|
||||
* 0 0.1 0.2 0.3 / -- water velocities
|
||||
* -- the rest is the table data,
|
||||
* -- each row corresponds to one value in throughputs
|
||||
* -- each column corresponds to one value in water velocities
|
||||
* 20 19 18 17 /
|
||||
* 20 18 17 16 /
|
||||
* 20 17 16 15 /
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class PolyInjTable {
|
||||
public:
|
||||
|
||||
int getTableNumber() const;
|
||||
|
||||
const std::vector<double>& getThroughputs() const;
|
||||
const std::vector<double>& getVelocities() const;
|
||||
const std::vector<std::vector<double>>& getTableData() const;
|
||||
|
||||
protected:
|
||||
std::vector<double> m_throughputs;
|
||||
std::vector<double> m_velocities;
|
||||
|
||||
// TODO: maybe not needed, since this is also stored in the std::map
|
||||
int m_table_number;
|
||||
|
||||
// each vector corresponds to the values corresponds to one value related to one x sampling point
|
||||
// as a result, the number of the vector should be equal to be the size of m_x_points,
|
||||
// the size of each vector should be equal to the size of m_y_points
|
||||
std::vector<std::vector<double> > m_data;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPM_PARSER_POLY_INJ_TABLE_HPP
|
||||
44
opm/parser/eclipse/EclipseState/Tables/SkprpolyTable.hpp
Normal file
44
opm/parser/eclipse/EclipseState/Tables/SkprpolyTable.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright (C) 2018 Statoil ASA
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_PARSER_SKPRPOLY_TABLE_HPP
|
||||
#define OPM_PARSER_SKPRPOLY_TABLE_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp>
|
||||
namespace Opm {
|
||||
|
||||
class DeckKeyword;
|
||||
|
||||
class SkprpolyTable : public PolyInjTable {
|
||||
public:
|
||||
|
||||
explicit SkprpolyTable(const DeckKeyword& table);
|
||||
|
||||
double referenceConcentration() const;
|
||||
|
||||
const std::vector<std::vector<double>>& getSkinPressures() const;
|
||||
|
||||
private:
|
||||
double m_ref_polymer_concentration;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_PARSER_SKPRPOLY_TABLE_HPP
|
||||
39
opm/parser/eclipse/EclipseState/Tables/SkprwatTable.hpp
Normal file
39
opm/parser/eclipse/EclipseState/Tables/SkprwatTable.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (C) 2018 Statoil ASA
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_PARSER_SKPRWAT_TABLE_HPP
|
||||
#define OPM_PARSER_SKPRWAT_TABLE_HPP
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PolyInjTable.hpp>
|
||||
namespace Opm {
|
||||
|
||||
class DeckKeyword;
|
||||
|
||||
class SkprwatTable : public PolyInjTable {
|
||||
public:
|
||||
|
||||
explicit SkprwatTable(const DeckKeyword& table);
|
||||
|
||||
const std::vector<std::vector<double>>& getSkinPressures() const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //OPM_PARSER_SKPRWAT_TABLE_HPP
|
||||
@@ -45,6 +45,9 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Tabdims.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/TableContainer.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Aqudims.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/PlymwinjTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SkprwatTable.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/SkprpolyTable.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -121,6 +124,9 @@ namespace Opm {
|
||||
const RockTable& getRockTable() const;
|
||||
const ViscrefTable& getViscrefTable() const;
|
||||
const WatdentTable& getWatdentTable() const;
|
||||
const std::map<int, PlymwinjTable>& getPlymwinjTables() const;
|
||||
const std::map<int, SkprwatTable>& getSkprwatTables() const;
|
||||
const std::map<int, SkprpolyTable>& getSkprpolyTables() const;
|
||||
|
||||
/// deck has keyword "IMPTVD" --- Imbition end-point versus depth tables
|
||||
bool useImptvd() const;
|
||||
@@ -151,6 +157,10 @@ namespace Opm {
|
||||
void initPlyrockTables(const Deck& deck);
|
||||
void initPlyshlogTables(const Deck& deck);
|
||||
|
||||
void initPlymwinjTables(const Deck& deck);
|
||||
void initSkprwatTables(const Deck& deck);
|
||||
void initSkprpolyTables(const Deck& deck);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -287,6 +297,9 @@ namespace Opm {
|
||||
RockTable m_rockTable;
|
||||
ViscrefTable m_viscrefTable;
|
||||
WatdentTable m_watdentTable;
|
||||
std::map<int, PlymwinjTable> m_plymwinjTables;
|
||||
std::map<int, SkprwatTable> m_skprwatTables;
|
||||
std::map<int, SkprpolyTable> m_skprpolyTables;
|
||||
|
||||
Tabdims m_tabdims;
|
||||
std::shared_ptr<Regdims> m_regdims;
|
||||
|
||||
@@ -17,19 +17,19 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_UDQ_CONFIG_HPP
|
||||
#define OPM_UDQ_CONFIG_HPP
|
||||
#ifndef OPM_UDQ_PARAMS_HPP
|
||||
#define OPM_UDQ_PARAMS_HPP
|
||||
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class Deck;
|
||||
|
||||
class UDQConfig
|
||||
class UDQParams
|
||||
{
|
||||
public:
|
||||
explicit UDQConfig(const Deck& deck);
|
||||
UDQConfig();
|
||||
explicit UDQParams(const Deck& deck);
|
||||
UDQParams();
|
||||
|
||||
bool reseedRNG() const noexcept;
|
||||
int randomSeed() const noexcept;
|
||||
54
opm/parser/eclipse/Parser/ErrorGuard.hpp
Normal file
54
opm/parser/eclipse/Parser/ErrorGuard.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2019 Joakim Hove/datagr
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ERROR_GUARD_HPP
|
||||
#define ERROR_GUARD_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class ErrorGuard {
|
||||
public:
|
||||
void addError(const std::string& errorKey, const std::string& msg);
|
||||
void addWarning(const std::string& errorKey, const std::string &msg);
|
||||
void clear();
|
||||
|
||||
explicit operator bool() const { return !this->error_list.empty(); }
|
||||
|
||||
/*
|
||||
Observe that this desctructor has a somewhat special semantics. If there
|
||||
are errors in the error list it will print all warnings and errors on
|
||||
stderr and throw std::runtime_error.
|
||||
*/
|
||||
~ErrorGuard();
|
||||
void terminate() const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> error_list;
|
||||
std::vector<std::pair<std::string, std::string>> warning_list;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -24,10 +24,21 @@ namespace Opm {
|
||||
|
||||
namespace InputError {
|
||||
|
||||
|
||||
/*
|
||||
The THROW_EXCEPTION and EXIT1 error handlers are overlapping, the
|
||||
intention os that the EXIT1 handler should be used in situations which
|
||||
are clearly user errors where an exception/traceback is of no use to
|
||||
the developers. The prototype of an error mode which should be handled
|
||||
with EXIT1 is PARSE_MISSING_INCLUDE.
|
||||
*/
|
||||
|
||||
enum Action {
|
||||
THROW_EXCEPTION = 0,
|
||||
WARN = 1,
|
||||
IGNORE = 2
|
||||
IGNORE = 2,
|
||||
EXIT1 = 3,
|
||||
DELAYED_EXIT1 = 4
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
@@ -41,6 +42,7 @@ namespace Opm {
|
||||
actions are goverened by the InputError::Action enum:
|
||||
|
||||
InputError::THROW_EXCEPTION
|
||||
InputError::EXIT1
|
||||
InputError::WARN
|
||||
InputError::IGNORE
|
||||
|
||||
@@ -77,19 +79,23 @@ namespace Opm {
|
||||
recognizd keys will be allowed.
|
||||
*/
|
||||
|
||||
class ErrorGuard;
|
||||
|
||||
class ParseContext {
|
||||
public:
|
||||
ParseContext();
|
||||
explicit ParseContext(InputError::Action default_action);
|
||||
explicit ParseContext(const std::vector<std::pair<std::string , InputError::Action>>& initial);
|
||||
|
||||
void handleError( const std::string& errorKey, const std::string& msg ) const;
|
||||
void handleError( const std::string& errorKey, const std::string& msg, ErrorGuard& errors ) const;
|
||||
void handleUnknownKeyword(const std::string& keyword, ErrorGuard& errors) const;
|
||||
bool hasKey(const std::string& key) const;
|
||||
ParseContext withKey(const std::string& key, InputError::Action action = InputError::WARN) const;
|
||||
ParseContext& withKey(const std::string& key, InputError::Action action = InputError::WARN);
|
||||
void updateKey(const std::string& key , InputError::Action action);
|
||||
void update(InputError::Action action);
|
||||
void update(const std::string& keyString , InputError::Action action);
|
||||
void ignoreKeyword(const std::string& keyword);
|
||||
InputError::Action get(const std::string& key) const;
|
||||
std::map<std::string,InputError::Action>::const_iterator begin() const;
|
||||
std::map<std::string,InputError::Action>::const_iterator end() const;
|
||||
@@ -242,6 +248,7 @@ namespace Opm {
|
||||
*/
|
||||
const static std::string SUMMARY_UNKNOWN_WELL;
|
||||
const static std::string SUMMARY_UNKNOWN_GROUP;
|
||||
const static std::string SUMMARY_UNHANDLED_KEYWORD;
|
||||
|
||||
/*
|
||||
A well must be specified (e.g. WELSPECS) and have completions
|
||||
@@ -250,13 +257,69 @@ namespace Opm {
|
||||
*/
|
||||
const static std::string SCHEDULE_INVALID_NAME;
|
||||
|
||||
|
||||
/*
|
||||
Only keywords explicitly white-listed can be included in the ACTIONX
|
||||
block. This error flag controls what should happen when an illegal
|
||||
keyword is encountered in an ACTIONX block.
|
||||
*/
|
||||
const static std::string ACTIONX_ILLEGAL_KEYWORD;
|
||||
|
||||
|
||||
/*
|
||||
The RPTSCH, RPTSOL and RPTSCHED keywords have two alternative forms,
|
||||
in the old style all the items are set as integers, i.e. the RPTRST
|
||||
keyword can be configured as:
|
||||
|
||||
RPTRST
|
||||
0 0 0 1 0 1 0 2 0 0 0 0 0 1 0 0 2/
|
||||
|
||||
The new way is based on string mneomnics which can optionally have an
|
||||
integer value, i.e something like:
|
||||
|
||||
RPTRST
|
||||
BASIC=2 FLOWS ALLPROS /
|
||||
|
||||
It is strictly illegal to mix the two ways to configure keywords. A
|
||||
situation with mixed input style is identified if any of the items are
|
||||
integers. To avoid that the values in the assignments like BASIC=2 are
|
||||
interpreted as integers it is essential that there are no spaces
|
||||
around the '=', and that is also documented in the manual. However -
|
||||
it turns out that Eclipse actually handles e.g.
|
||||
|
||||
RPTRST
|
||||
BASIC = 2 /
|
||||
|
||||
So we have introduced a error mode RPT_MIXED_STYLE which tries to
|
||||
handle this situation. Observe that really mixed input style is
|
||||
impossible to handle, and will lead to a hard exception, but with the
|
||||
RPT_MIXED_STYLE error mode it is possible to configure lenient
|
||||
behavior towards interpreting the input as new style string mneomnics.
|
||||
*/
|
||||
const static std::string RPT_MIXED_STYLE;
|
||||
|
||||
const static std::string RPT_UNKNOWN_MNEMONIC;
|
||||
|
||||
|
||||
/*
|
||||
The SIMULATOR_KEYWORD_ errormodes are for the situation where the
|
||||
parser recognizes, and correctly parses a keyword, but we know that
|
||||
the simulator does not support the intended use of the keyword. These
|
||||
errormodes are invoked from the simulator.
|
||||
*/
|
||||
const static std::string SIMULATOR_KEYWORD_NOT_SUPPORTED;
|
||||
const static std::string SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED;
|
||||
|
||||
private:
|
||||
void initDefault();
|
||||
void initEnv();
|
||||
void envUpdate( const std::string& envVariable , InputError::Action action );
|
||||
void patternUpdate( const std::string& pattern , InputError::Action action);
|
||||
|
||||
std::map<std::string , InputError::Action> m_errorContexts;
|
||||
}; }
|
||||
std::set<std::string> ignore_keywords;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Opm {
|
||||
|
||||
class Deck;
|
||||
class ParseContext;
|
||||
class ErrorGuard;
|
||||
class RawKeyword;
|
||||
|
||||
/// The hub of the parsing process.
|
||||
@@ -53,10 +54,17 @@ namespace Opm {
|
||||
|
||||
/// The starting point of the parsing process. The supplied file is parsed, and the resulting Deck is returned.
|
||||
Deck parseFile(const std::string &dataFile,
|
||||
const ParseContext& = ParseContext()) const;
|
||||
const ParseContext&,
|
||||
ErrorGuard& errors) const;
|
||||
|
||||
Deck parseFile(const std::string& datafile);
|
||||
|
||||
Deck parseString(const std::string &data,
|
||||
const ParseContext& = ParseContext()) const;
|
||||
Deck parseStream(std::unique_ptr<std::istream>&& inputStream , const ParseContext& parseContext) const;
|
||||
const ParseContext&,
|
||||
ErrorGuard& errors) const;
|
||||
Deck parseString(const std::string &data) const;
|
||||
|
||||
Deck parseStream(std::unique_ptr<std::istream>&& inputStream , const ParseContext& parseContext, ErrorGuard& errors) const;
|
||||
|
||||
/// Method to add ParserKeyword instances, these holding type and size information about the keywords and their data.
|
||||
void addParserKeyword(const Json::JsonObject& jsonKeyword);
|
||||
@@ -90,27 +98,30 @@ namespace Opm {
|
||||
addParserKeyword( std::unique_ptr< ParserKeyword >( new T ) );
|
||||
}
|
||||
|
||||
static EclipseState parse(const Deck& deck, const ParseContext& context = ParseContext());
|
||||
static EclipseState parse(const std::string &filename, const ParseContext& context = ParseContext());
|
||||
static EclipseState parseData(const std::string &data, const ParseContext& context = ParseContext());
|
||||
static EclipseState parse(const Deck& deck, const ParseContext& context, ErrorGuard& errors);
|
||||
static EclipseState parse(const std::string &filename, const ParseContext& context, ErrorGuard& errors);
|
||||
static EclipseState parseData(const std::string &data, const ParseContext& context, ErrorGuard& errors);
|
||||
|
||||
/// Parses the deck specified in filename. If context contains ParseContext::PARSE_PARTIAL_DECK,
|
||||
/// we construct only a lean grid, otherwise, we construct a full EclipseState and return the
|
||||
/// fully constructed InputGrid
|
||||
static EclipseGrid parseGrid(const std::string &filename,
|
||||
const ParseContext& context = ParseContext());
|
||||
const ParseContext& context,
|
||||
ErrorGuard& errors);
|
||||
|
||||
/// Parses the provided deck. If context contains ParseContext::PARSE_PARTIAL_DECK,
|
||||
/// we construct only a lean grid, otherwise, we construct a full EclipseState and return the
|
||||
/// fully constructed InputGrid
|
||||
static EclipseGrid parseGrid(const Deck& deck,
|
||||
const ParseContext& context = ParseContext());
|
||||
const ParseContext& context,
|
||||
ErrorGuard& errors);
|
||||
|
||||
/// Parses the provided deck string. If context contains ParseContext::PARSE_PARTIAL_DECK,
|
||||
/// we construct only a lean grid, otherwise, we construct a full EclipseState and return the
|
||||
/// fully constructed InputGrid
|
||||
static EclipseGrid parseGridData(const std::string &data,
|
||||
const ParseContext& context = ParseContext());
|
||||
const ParseContext& context,
|
||||
ErrorGuard& errors);
|
||||
|
||||
private:
|
||||
// associative map of the parser internal name and the corresponding ParserKeyword object
|
||||
|
||||
@@ -37,9 +37,11 @@ namespace Opm {
|
||||
class Deck;
|
||||
class DeckKeyword;
|
||||
class ParseContext;
|
||||
class ErrorGuard;
|
||||
class ParserDoubleItem;
|
||||
class RawKeyword;
|
||||
class string_view;
|
||||
class ErrorGuard;
|
||||
|
||||
/*
|
||||
Small helper struct to assemble the information needed to infer the size
|
||||
@@ -122,7 +124,7 @@ namespace Opm {
|
||||
SectionNameSet::const_iterator validSectionNamesBegin() const;
|
||||
SectionNameSet::const_iterator validSectionNamesEnd() const;
|
||||
|
||||
DeckKeyword parse(const ParseContext& parseContext , std::shared_ptr< RawKeyword > rawKeyword) const;
|
||||
DeckKeyword parse(const ParseContext& parseContext, ErrorGuard& errors, std::shared_ptr< RawKeyword > rawKeyword) const;
|
||||
enum ParserKeywordSizeEnum getSizeType() const;
|
||||
const KeywordSize& getKeywordSize() const;
|
||||
bool isDataKeyword() const;
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Opm {
|
||||
class ParseContext;
|
||||
class ParserItem;
|
||||
class RawRecord;
|
||||
class ErrorGuard;
|
||||
|
||||
class ParserRecord {
|
||||
public:
|
||||
@@ -42,7 +43,7 @@ namespace Opm {
|
||||
void addDataItem( ParserItem item );
|
||||
const ParserItem& get(size_t index) const;
|
||||
const ParserItem& get(const std::string& itemName) const;
|
||||
DeckRecord parse( const ParseContext&, RawRecord& ) const;
|
||||
DeckRecord parse( const ParseContext&, ErrorGuard&, RawRecord&) const;
|
||||
bool isDataRecord() const;
|
||||
bool equal(const ParserRecord& other) const;
|
||||
bool hasDimension() const;
|
||||
|
||||
@@ -70,6 +70,8 @@ namespace Opm {
|
||||
gas_inverse_formation_volume_factor,
|
||||
oil_inverse_formation_volume_factor,
|
||||
water_inverse_formation_volume_factor,
|
||||
liquid_productivity_index,
|
||||
gas_productivity_index
|
||||
};
|
||||
|
||||
explicit UnitSystem(UnitType unit = UnitType::UNIT_TYPE_METRIC);
|
||||
@@ -97,6 +99,7 @@ namespace Opm {
|
||||
void to_si( measure, std::vector<double>& ) const;
|
||||
const char* name( measure ) const;
|
||||
|
||||
static ert_ecl_unit_enum ecl_units(UnitType opm_unit);
|
||||
static UnitSystem newMETRIC();
|
||||
static UnitSystem newFIELD();
|
||||
static UnitSystem newLAB();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%define tag final
|
||||
|
||||
Name: opm-common
|
||||
Version: 2018.04
|
||||
Version: 2018.10
|
||||
Release: 0
|
||||
Summary: Open Porous Media - common helpers and buildsystem
|
||||
License: GPL-3.0
|
||||
|
||||
@@ -88,7 +88,6 @@ namespace {
|
||||
const auto* well = wells[wellID];
|
||||
|
||||
if (well == nullptr) { continue; }
|
||||
|
||||
const auto& conns = well->getActiveConnections(sim_step, grid);
|
||||
const int niSI = static_cast<int>(well->getTotNoConn());
|
||||
std::map <std::size_t, const Opm::Connection*> sIToConn;
|
||||
@@ -151,7 +150,7 @@ namespace {
|
||||
iConn[Ix::CellK] = conn.getK() + 1;
|
||||
|
||||
iConn[Ix::ConnStat] = (conn.state() == ConnState::OPEN)
|
||||
? 1 : -1000;
|
||||
? 1 : 0;
|
||||
|
||||
iConn[Ix::Drainage] = conn.getDefaultSatTabId()
|
||||
? 0 : conn.satTableId();
|
||||
@@ -159,9 +158,10 @@ namespace {
|
||||
// Don't support differing sat-func tables for
|
||||
// draining and imbibition curves at connections.
|
||||
iConn[Ix::Imbibition] = iConn[Ix::Drainage];
|
||||
|
||||
//iConn[Ix::ComplNum] = std::abs(conn.complnum);
|
||||
iConn[Ix::ComplNum] = iConn[Ix::SeqIndex];
|
||||
|
||||
//complnum is(1 too large): 1 - based while icon is 0 - based?
|
||||
iConn[Ix::ComplNum] = std::abs(conn.complnum());
|
||||
//iConn[Ix::ComplNum] = iConn[Ix::SeqIndex];
|
||||
|
||||
iConn[Ix::ConnDir] = conn.dir();
|
||||
iConn[Ix::Segment] = conn.attachedToSegment()
|
||||
@@ -260,7 +260,7 @@ namespace {
|
||||
}
|
||||
|
||||
if (Q.has(R::gas)) {
|
||||
xConn[Ix::WaterRate] =
|
||||
xConn[Ix::GasRate] =
|
||||
- units.from_si(M::gas_surface_rate, Q.get(R::gas));
|
||||
}
|
||||
|
||||
@@ -302,8 +302,38 @@ captureDeclaredConnData(const Schedule& sched,
|
||||
const std::size_t sim_step)
|
||||
{
|
||||
const auto& wells = sched.getWells(sim_step);
|
||||
|
||||
connectionLoop(wells, grid, sim_step, [&units, &xw, this]
|
||||
//
|
||||
// construct a composite vector of connection objects holding
|
||||
// rates for all open connectons
|
||||
//
|
||||
std::map<std::string, std::vector<const Opm::data::Connection*> > allWellConnections;
|
||||
for (const auto wl : wells) {
|
||||
const auto& conns = wl->getActiveConnections(sim_step, grid);
|
||||
std::vector<const Opm::data::Connection*> initConn (conns.size(), nullptr);
|
||||
allWellConnections.insert(std::make_pair(wl->name(), initConn));
|
||||
const auto it = allWellConnections.find(wl->name());
|
||||
const auto xr = xw.find(wl->name());
|
||||
size_t rCInd = 0;
|
||||
if ((it != allWellConnections.end()) && (xr != xw.end())) {
|
||||
for (auto nConn = conns.size(), connID = 0*nConn; connID < nConn; connID++) {
|
||||
//
|
||||
// WellRates connections are only defined for OPEN connections
|
||||
if ((conns[connID].state() == Opm::WellCompletion::StateEnum::OPEN) &&
|
||||
(rCInd < xr->second.connections.size())) {
|
||||
it->second[connID] = &(xr->second.connections[rCInd]);
|
||||
rCInd+= 1;
|
||||
}
|
||||
else if ((conns[connID].state() == Opm::WellCompletion::StateEnum::OPEN) && (rCInd >= xr->second.connections.size())) {
|
||||
throw std::invalid_argument {
|
||||
"Inconsistent number of open connections I in vector<Opm::data::Connection*> (" +
|
||||
std::to_string(xr->second.connections.size()) + ") in Well " + wl->name()
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
connectionLoop(wells, grid, sim_step, [&units, &allWellConnections, this]
|
||||
(const Well& well, const std::size_t wellID,
|
||||
const Connection& conn, const std::size_t connID) -> void
|
||||
{
|
||||
@@ -313,14 +343,15 @@ captureDeclaredConnData(const Schedule& sched,
|
||||
IConn::staticContrib(conn, connID, ic);
|
||||
SConn::staticContrib(conn, units, sc);
|
||||
|
||||
auto xi = xw.find(well.name());
|
||||
if ((xi != xw.end()) &&
|
||||
(connID < xi->second.connections.size()))
|
||||
auto xi = allWellConnections.find(well.name());
|
||||
if ((xi != allWellConnections.end()) &&
|
||||
(connID < xi->second.size()))
|
||||
//(connID < xi->second.connections.size()))
|
||||
{
|
||||
auto xc = this->xConn_(wellID, connID);
|
||||
|
||||
XConn::dynamicContrib(xi->second.connections[connID],
|
||||
units, xc);
|
||||
//XConn::dynamicContrib(xi->second.connections[connID],
|
||||
if (xi->second[connID]) XConn::dynamicContrib(*(xi->second[connID]), units, xc);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
*/
|
||||
|
||||
#include <opm/output/eclipse/AggregateGroupData.hpp>
|
||||
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
@@ -550,6 +549,14 @@ captureDeclaredGroupData(const Opm::Schedule& sched,
|
||||
auto xg = this->xGroup_[groupID];
|
||||
XGrp::dynamicContrib( restart_group_keys, restart_field_keys, groupKeyToIndex, fieldKeyToIndex, group, sumState, ecl_compatible_rst, xg);
|
||||
});
|
||||
|
||||
// Define Static Contributions to ZGrp Array.
|
||||
groupLoop(curGroups,
|
||||
[this](const Group& group, const std::size_t groupID) -> void
|
||||
{
|
||||
auto zw = this->zGroup_[groupID];
|
||||
zw[0] = group.name();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
@@ -31,9 +31,8 @@
|
||||
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
//#include <opm/output/data/Wells.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
@@ -70,6 +69,19 @@ namespace {
|
||||
return inteHead[180];
|
||||
}
|
||||
|
||||
std::vector<std::size_t>
|
||||
inflowSegmentsIndex(const Opm::WellSegments& segSet, std::size_t segIndex) {
|
||||
auto segNumber = segSet[segIndex].segmentNumber();
|
||||
std::vector<std::size_t> inFlowSegNum;
|
||||
for (int ind = 0; ind < segSet.size(); ind++) {
|
||||
auto i_outletSeg = segSet[ind].outletSegment();
|
||||
if (segNumber == i_outletSeg) {
|
||||
inFlowSegNum.push_back(ind);
|
||||
}
|
||||
}
|
||||
return inFlowSegNum;
|
||||
}
|
||||
|
||||
Opm::RestartIO::Helpers::BranchSegmentPar
|
||||
getBranchSegmentParam(const Opm::WellSegments& segSet, const int branch)
|
||||
{
|
||||
@@ -100,6 +112,155 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
std::vector <std::size_t> segmentNoFromOrderedSegmentNo(const Opm::WellSegments& segSet, const std::vector<std::size_t>& ordSegNo) {
|
||||
std::vector <std::size_t> sNFOSN (segSet.size()+1,0);
|
||||
for (int segNumber = 0; segNumber < segSet.size(); segNumber++) {
|
||||
sNFOSN[ordSegNo[segNumber]] = segNumber+1;
|
||||
}
|
||||
return sNFOSN;
|
||||
}
|
||||
std::vector<std::size_t> segmentOrder(const Opm::WellSegments& segSet, const std::size_t segIndex) {
|
||||
std::vector<std::size_t> ordSegNumber;
|
||||
std::vector<std::size_t> tempOrdVect;
|
||||
std::vector<std::size_t> segIndCB;
|
||||
// Store "heel" segment since that will not always be at the end of the list
|
||||
segIndCB.push_back(segIndex);
|
||||
int newSInd = segIndex;
|
||||
auto origBranchNo = segSet[segIndex].branchNumber();
|
||||
bool endOrigBranch = true;
|
||||
// loop down branch to find all segments in branch and number from "toe" to "heel"
|
||||
while (newSInd < segSet.size()) {
|
||||
endOrigBranch = true;
|
||||
const auto iSInd = inflowSegmentsIndex(segSet, newSInd);
|
||||
for (auto isi : iSInd ) {
|
||||
auto inflowBranch = segSet[isi].branchNumber();
|
||||
if (origBranchNo == inflowBranch) {
|
||||
endOrigBranch = false;
|
||||
}
|
||||
}
|
||||
if (iSInd.size() > 0) {
|
||||
for (auto ind : iSInd) {
|
||||
auto inflowBranch = segSet[ind].branchNumber();
|
||||
if (origBranchNo == inflowBranch) {
|
||||
// if inflow segment belongs to same branch add contribution
|
||||
segIndCB.insert(segIndCB.begin(), ind);
|
||||
// search recursively down this branch to find more inflow branches
|
||||
newSInd = ind;
|
||||
}
|
||||
else {
|
||||
// if inflow segment belongs to different branch, start new search
|
||||
auto nSOrd = segmentOrder(segSet, ind);
|
||||
// copy the segments already found and indexed into the total ordered segment vector
|
||||
for (std::size_t indOS = 0; indOS < nSOrd.size(); indOS++) {
|
||||
ordSegNumber.push_back(nSOrd[indOS]);
|
||||
}
|
||||
if (endOrigBranch) {
|
||||
newSInd = segSet.size();
|
||||
}
|
||||
// increment the local branch sequence number counter
|
||||
}
|
||||
}
|
||||
}
|
||||
if (endOrigBranch || (iSInd.size()==0)) {
|
||||
// have come to toe of current branch - store segment indicies of current branch
|
||||
for (std::size_t indOS = 0; indOS < segIndCB.size(); indOS++) {
|
||||
ordSegNumber.push_back(segIndCB[indOS]);
|
||||
}
|
||||
// set new index to exit while loop
|
||||
newSInd = segSet.size();
|
||||
}
|
||||
}
|
||||
|
||||
if (origBranchNo == 1) {
|
||||
// make the vector of ordered segments
|
||||
tempOrdVect.resize(ordSegNumber.size());
|
||||
for (std::size_t ov_ind = 0; ov_ind < ordSegNumber.size(); ov_ind++) {
|
||||
tempOrdVect[ordSegNumber[ov_ind]] = ov_ind+1;
|
||||
}
|
||||
return tempOrdVect;
|
||||
} else {
|
||||
return ordSegNumber;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Opm::RestartIO::Helpers::SegmentSetSourceSinkTerms
|
||||
getSegmentSetSSTerms(const Opm::WellSegments& segSet, const std::vector<Opm::data::Connection>& rateConns,
|
||||
const Opm::WellConnections& welConns, const Opm::UnitSystem& units)
|
||||
{
|
||||
std::vector<double> qosc (segSet.size()+1, 0.);
|
||||
std::vector<double> qwsc (segSet.size()+1, 0.);
|
||||
std::vector<double> qgsc (segSet.size()+1, 0.);
|
||||
std::vector<const Opm::Connection* > openConnections;
|
||||
using M = ::Opm::UnitSystem::measure;
|
||||
using R = ::Opm::data::Rates::opt;
|
||||
for (auto nConn = welConns.size(), connID = 0*nConn; connID < nConn; connID++) {
|
||||
if (welConns[connID].state() == Opm::WellCompletion::StateEnum::OPEN) openConnections.push_back(&welConns[connID]);
|
||||
}
|
||||
if (openConnections.size() != rateConns.size()) {
|
||||
throw std::invalid_argument {
|
||||
"Inconsistent number of open connections I in Opm::WellConnections (" +
|
||||
std::to_string(welConns.size()) + ") and vector<Opm::data::Connection> (" +
|
||||
std::to_string(rateConns.size()) + ") in Well " + segSet.wellName()
|
||||
};
|
||||
}
|
||||
for (auto nConn = openConnections.size(), connID = 0*nConn; connID < nConn; connID++) {
|
||||
auto segNo = openConnections[connID]->segment();
|
||||
const auto& Q = rateConns[connID].rates;
|
||||
qosc[segNo] += -units.from_si(M::liquid_surface_rate, Q.get(R::oil));
|
||||
qwsc[segNo] += -units.from_si(M::liquid_surface_rate, Q.get(R::wat));
|
||||
qgsc[segNo] += -units.from_si(M::gas_surface_rate, Q.get(R::gas));
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
qosc,
|
||||
qwsc,
|
||||
qgsc
|
||||
};
|
||||
}
|
||||
|
||||
Opm::RestartIO::Helpers::SegmentSetFlowRates
|
||||
getSegmentSetFlowRates(const Opm::WellSegments& segSet, const std::vector<Opm::data::Connection>& rateConns,
|
||||
const Opm::WellConnections& welConns, const Opm::UnitSystem& units)
|
||||
{
|
||||
std::vector<double> sofr (segSet.size()+1, 0.);
|
||||
std::vector<double> swfr (segSet.size()+1, 0.);
|
||||
std::vector<double> sgfr (segSet.size()+1, 0.);
|
||||
//
|
||||
//call function to calculate the individual segment source/sink terms
|
||||
auto sSSST = getSegmentSetSSTerms(segSet, rateConns, welConns, units);
|
||||
|
||||
// find an ordered list of segments
|
||||
std::size_t segmentInd = 0;
|
||||
auto orderedSegmentNo = segmentOrder(segSet, segmentInd);
|
||||
auto sNFOSN = segmentNoFromOrderedSegmentNo(segSet, orderedSegmentNo);
|
||||
// loop over segments according to the ordered segments sequence which ensures that the segments alway are traversed in the from
|
||||
// inflow to outflow direction (a branch toe is the innermost inflow end)
|
||||
for (std::size_t indOSN = 1; indOSN < sNFOSN.size(); indOSN++) {
|
||||
auto segNo = sNFOSN[indOSN];
|
||||
// the segment flow rates is the sum of the the source/sink terms for each segment plus the flow rates from the inflow segments
|
||||
// add source sink terms
|
||||
sofr[segNo] += sSSST.qosc[segNo];
|
||||
swfr[segNo] += sSSST.qwsc[segNo];
|
||||
sgfr[segNo] += sSSST.qgsc[segNo];
|
||||
// add flow from all inflow segments
|
||||
for (const auto& ifSeg : segSet[segSet.segmentNumberToIndex(segNo)].inletSegments()) {
|
||||
sofr[segNo] += sofr[ifSeg];
|
||||
swfr[segNo] += swfr[ifSeg];
|
||||
sgfr[segNo] += sgfr[ifSeg];
|
||||
}
|
||||
}
|
||||
for (std::size_t sN = 1; sN < sofr.size(); sN++) {
|
||||
}
|
||||
return {
|
||||
sofr,
|
||||
swfr,
|
||||
sgfr
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::size_t> SegmentSetBranches(const Opm::WellSegments& segSet) {
|
||||
std::vector<std::size_t> branches;
|
||||
for (int segNo = 1; segNo <= segSet.size(); segNo++) {
|
||||
@@ -126,9 +287,9 @@ namespace {
|
||||
return firstSegNo;
|
||||
}
|
||||
|
||||
int noConnectionsSegment(const Opm::WellConnections& compSet,
|
||||
int noConnectionsSegment(const Opm::WellConnections& compSet,
|
||||
const Opm::WellSegments& segSet,
|
||||
const std::size_t segIndex)
|
||||
const std::size_t segIndex)
|
||||
{
|
||||
auto segNumber = segSet[segIndex].segmentNumber();
|
||||
int noConnections = 0;
|
||||
@@ -141,10 +302,10 @@ namespace {
|
||||
|
||||
return noConnections;
|
||||
}
|
||||
|
||||
|
||||
int sumConnectionsSegment(const Opm::WellConnections& compSet,
|
||||
const Opm::WellSegments& segSet,
|
||||
const std::size_t segIndex)
|
||||
const Opm::WellSegments& segSet,
|
||||
const std::size_t segIndex)
|
||||
{
|
||||
// This function returns (for a given segment) the sum of number of connections for each segment
|
||||
// with lower segment index than the currnet segment
|
||||
@@ -162,20 +323,6 @@ namespace {
|
||||
return sumConn;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::size_t>
|
||||
inflowSegmentsIndex(const Opm::WellSegments& segSet, std::size_t segIndex) {
|
||||
auto segNumber = segSet[segIndex].segmentNumber();
|
||||
std::vector<std::size_t> inFlowSegNum;
|
||||
for (int ind = 0; ind < segSet.size(); ind++) {
|
||||
auto i_outletSeg = segSet[ind].outletSegment();
|
||||
if (segNumber == i_outletSeg) {
|
||||
inFlowSegNum.push_back(ind);
|
||||
}
|
||||
}
|
||||
return inFlowSegNum;
|
||||
}
|
||||
|
||||
int noInFlowBranches(const Opm::WellSegments& segSet, std::size_t segIndex) {
|
||||
auto segNumber = segSet[segIndex].segmentNumber();
|
||||
auto branch = segSet[segIndex].branchNumber();
|
||||
@@ -189,100 +336,31 @@ namespace {
|
||||
}
|
||||
return noIFBr;
|
||||
}
|
||||
//find the number of inflow branches (different from the current branch)
|
||||
//find the number of inflow branch-segments (segments that has a branch) from the
|
||||
// first segment to the current segment for segments that has at least one inflow branch
|
||||
// Segments with no inflow branches get the value zero
|
||||
int sumNoInFlowBranches(const Opm::WellSegments& segSet, std::size_t segIndex) {
|
||||
int sumIFB = 0;
|
||||
auto segBranch = segSet[segIndex].branchNumber();
|
||||
const auto iSInd = inflowSegmentsIndex(segSet, segIndex);
|
||||
for (auto ind : iSInd) {
|
||||
auto inflowBranch = segSet[ind].branchNumber();
|
||||
// if inflow segment belongs to different branch add contribution
|
||||
if (segBranch != inflowBranch) {
|
||||
sumIFB+=1;
|
||||
// search recursively down this branch to find more inflow branches
|
||||
sumIFB += sumNoInFlowBranches(segSet, ind);
|
||||
auto segNo =segSet[segIndex].segmentNumber();
|
||||
while (segNo >=1) {
|
||||
auto segInd = segSet.segmentNumberToIndex(segNo);
|
||||
auto curBranch = segSet[segInd].branchNumber();
|
||||
const auto iSInd = inflowSegmentsIndex(segSet, segInd);
|
||||
for (auto inFlowInd : iSInd) {
|
||||
auto inFlowBranch = segSet[inFlowInd].branchNumber();
|
||||
// if inflow segment belongs to different branch add contribution
|
||||
if (curBranch != inFlowBranch) {
|
||||
sumIFB+=1;
|
||||
}
|
||||
}
|
||||
segNo-=1;
|
||||
}
|
||||
return sumIFB;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::size_t> segmentOrder(const Opm::WellSegments& segSet, const std::size_t segIndex) {
|
||||
std::vector<std::size_t> ordSegNumber;
|
||||
std::vector<std::size_t> tempOrdVect;
|
||||
std::vector<std::size_t> segIndCB;
|
||||
// Store "heel" segment since that will not always be at the end of the list
|
||||
segIndCB.push_back(segIndex);
|
||||
int newSInd = segIndex;
|
||||
auto origBranchNo = segSet[segIndex].branchNumber();
|
||||
bool endOrigBranch = true;
|
||||
//std::cout << "SegmentOrder-segIndex:" << segIndex << " origBranchno: " << origBranchNo << std::endl;
|
||||
// loop down branch to find all segments in branch and number from "toe" to "heel"
|
||||
while (newSInd < segSet.size()) {
|
||||
endOrigBranch = true;
|
||||
const auto iSInd = inflowSegmentsIndex(segSet, newSInd);
|
||||
//std::cout << " SO- inflowSegmentsIndex:" << std::endl;
|
||||
for (auto isi : iSInd ) {
|
||||
auto inflowBranch = segSet[isi].branchNumber();
|
||||
if (origBranchNo == inflowBranch) {
|
||||
endOrigBranch = false;
|
||||
}
|
||||
//std::cout << " SO- isi:" << isi << std::endl;
|
||||
}
|
||||
if (iSInd.size() > 0) {
|
||||
for (auto ind : iSInd) {
|
||||
auto inflowBranch = segSet[ind].branchNumber();
|
||||
if (origBranchNo == inflowBranch) {
|
||||
// if inflow segment belongs to same branch add contribution
|
||||
segIndCB.insert(segIndCB.begin(), ind);
|
||||
// search recursively down this branch to find more inflow branches
|
||||
newSInd = ind;
|
||||
//std::cout << "SO-ind-loop: origB=iflowB - ind:" << ind << std::endl;
|
||||
}
|
||||
else {
|
||||
// if inflow segment belongs to different branch, start new search
|
||||
//std::cout << "SO-ind-loop: origB!=iflowB - ind:" << ind << std::endl;
|
||||
auto nSOrd = segmentOrder(segSet, ind);
|
||||
// copy the segments already found and indexed into the total ordered segment vector
|
||||
for (std::size_t indOS = 0; indOS < nSOrd.size(); indOS++) {
|
||||
ordSegNumber.push_back(nSOrd[indOS]);
|
||||
//std::cout << "SO-ind-loop: origB!=iflowB - indOS:" << indOS << " nSOrd[indOS] " << nSOrd[indOS] << std::endl;
|
||||
}
|
||||
if (endOrigBranch) {
|
||||
newSInd = segSet.size();
|
||||
}
|
||||
// increment the local branch sequence number counter
|
||||
}
|
||||
}
|
||||
}
|
||||
if (endOrigBranch || (iSInd.size()==0)) {
|
||||
// have come to toe of current branch - store segment indicies of current branch
|
||||
//std::cout << "SO-Toe of current branch - newSInd :" << newSInd << std::endl;
|
||||
for (std::size_t indOS = 0; indOS < segIndCB.size(); indOS++) {
|
||||
ordSegNumber.push_back(segIndCB[indOS]);
|
||||
//std::cout << "SO end CB - indOS:" << indOS << " segIndCB[indOS] " << segIndCB[indOS] << std::endl;
|
||||
}
|
||||
// set new index to exit while loop
|
||||
newSInd = segSet.size();
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
if (origBranchNo == 1) {
|
||||
// make the vector of ordered segments
|
||||
//std::cout << "SO-OrBr=1 -ordSegNumber.size():" << ordSegNumber.size() << std::endl;
|
||||
tempOrdVect.resize(ordSegNumber.size());
|
||||
for (std::size_t ov_ind = 0; ov_ind < ordSegNumber.size(); ov_ind++) {
|
||||
tempOrdVect[ordSegNumber[ov_ind]] = ov_ind+1;
|
||||
//std::cout << "SO_OrBr=1- ov_ind:" << ov_ind << " ordSegNumber[ov_ind] " << ordSegNumber[ov_ind] << std::endl;
|
||||
}
|
||||
return tempOrdVect;
|
||||
} else {
|
||||
return ordSegNumber;
|
||||
}
|
||||
// check if the segment has inflow branches - if yes return sumIFB else return zero
|
||||
return (noInFlowBranches(segSet, segIndex) >= 1)
|
||||
? sumIFB : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int inflowSegmentCurBranch(const Opm::WellSegments& segSet, std::size_t segIndex) {
|
||||
auto branch = segSet[segIndex].branchNumber();
|
||||
auto segNumber = segSet[segIndex].segmentNumber();
|
||||
@@ -351,14 +429,14 @@ namespace {
|
||||
{
|
||||
if (well.isMultiSegment(rptStep)) {
|
||||
//loop over segment set and print out information
|
||||
auto welSegSet = well.getWellSegments(rptStep);
|
||||
auto completionSet = well.getConnections(rptStep);
|
||||
auto noElmSeg = nisegz(inteHead);
|
||||
const auto& welSegSet = well.getWellSegments(rptStep);
|
||||
const auto& completionSet = well.getConnections(rptStep);
|
||||
const auto& noElmSeg = nisegz(inteHead);
|
||||
std::size_t segmentInd = 0;
|
||||
auto orderedSegmentNo = segmentOrder(welSegSet, segmentInd);
|
||||
for (int ind_seg = 1; ind_seg <= welSegSet.size(); ind_seg++) {
|
||||
auto ind = welSegSet.segmentNumberToIndex(ind_seg);
|
||||
auto iS = (ind_seg-1)*noElmSeg;
|
||||
for (int segNumber = 1; segNumber <= welSegSet.size(); segNumber++) {
|
||||
auto ind = welSegSet.segmentNumberToIndex(segNumber);
|
||||
auto iS = (segNumber-1)*noElmSeg;
|
||||
iSeg[iS + 0] = orderedSegmentNo[ind];
|
||||
iSeg[iS + 1] = welSegSet[ind].outletSegment();
|
||||
iSeg[iS + 2] = inflowSegmentCurBranch(welSegSet, ind);
|
||||
@@ -396,47 +474,116 @@ namespace {
|
||||
}
|
||||
|
||||
template <class RSegArray>
|
||||
void staticContrib(const Opm::Well& well,
|
||||
const std::size_t rptStep,
|
||||
const std::vector<int>& inteHead,
|
||||
const Opm::UnitSystem& units,
|
||||
RSegArray& rSeg)
|
||||
void staticContrib_useMSW(const Opm::Well& well,
|
||||
const std::size_t rptStep,
|
||||
const std::vector<int>& inteHead,
|
||||
const Opm::EclipseGrid& grid,
|
||||
const Opm::UnitSystem& units,
|
||||
const ::Opm::SummaryState& smry,
|
||||
const Opm::data::WellRates& wr,
|
||||
RSegArray& rSeg)
|
||||
{
|
||||
if (well.isMultiSegment(rptStep)) {
|
||||
int segNumber = 1;
|
||||
|
||||
// 'stringSegNum' is one-based (1 .. #segments inclusive)
|
||||
std::string stringSegNum = std::to_string(segNumber);
|
||||
|
||||
using M = ::Opm::UnitSystem::measure;
|
||||
const auto gfactor = (units.getType() == Opm::UnitSystem::UnitType::UNIT_TYPE_FIELD)
|
||||
? 0.1781076 : 0.001;
|
||||
|
||||
//loop over segment set and print out information
|
||||
auto welSegSet = well.getWellSegments(rptStep);
|
||||
auto completionSet = well.getCompletions(rptStep);
|
||||
auto noElmSeg = nrsegz(inteHead);
|
||||
//treat the top segment individually
|
||||
rSeg[0] = units.from_si(M::length, welSegSet.lengthTopSegment());
|
||||
rSeg[1] = units.from_si(M::length, welSegSet.depthTopSegment());
|
||||
rSeg[5] = units.from_si(M::volume, welSegSet.volumeTopSegment());
|
||||
rSeg[6] = rSeg[0];
|
||||
rSeg[7] = rSeg[1];
|
||||
// set item ind + 10 to 0.5 based on tests on E100
|
||||
rSeg[10] = 0.5;
|
||||
const auto noElmSeg = nrsegz(inteHead);
|
||||
const auto& welSegSet = well.getWellSegments(rptStep);
|
||||
const auto& welConns = well.getActiveConnections(rptStep, grid);
|
||||
const auto& wname = well.name();
|
||||
const auto wPKey = "WBHP:" + wname;
|
||||
const auto& wRatesIt = wr.find(wname);
|
||||
bool haveWellRes = wRatesIt != wr.end();
|
||||
//
|
||||
//Initialize temporary variables
|
||||
double temp_o = 0.;
|
||||
double temp_w = 0.;
|
||||
double temp_g = 0.;
|
||||
|
||||
// segment pressure (to be added!!)
|
||||
rSeg[ 39] = 0;
|
||||
// find well connections and calculate segment rates based on well connection production/injection terms
|
||||
auto sSFR = Opm::RestartIO::Helpers::SegmentSetFlowRates{};
|
||||
if (haveWellRes) {
|
||||
|
||||
sSFR = getSegmentSetFlowRates(welSegSet, wRatesIt->second.connections, welConns, units);
|
||||
|
||||
}
|
||||
auto get = [&smry, &wname, &stringSegNum](const std::string& vector)
|
||||
{
|
||||
// 'stringSegNum' is one-based (1 .. #segments inclusive)
|
||||
const auto key = vector + ':' + wname + ':' + stringSegNum;
|
||||
return smry.has(key) ? smry.get(key) : 0.0;
|
||||
};
|
||||
|
||||
//Default values
|
||||
rSeg[ 39] = 1.0;
|
||||
// Treat the top segment individually
|
||||
rSeg[0] = units.from_si(M::length, welSegSet.lengthTopSegment());
|
||||
rSeg[1] = units.from_si(M::length, welSegSet.depthTopSegment());
|
||||
rSeg[5] = units.from_si(M::volume, welSegSet.volumeTopSegment());
|
||||
rSeg[6] = rSeg[0];
|
||||
rSeg[7] = rSeg[1];
|
||||
//
|
||||
//Field units:
|
||||
//Rseg[8]= 1.0*sofr+0.1*swfr + 0.1781076*sgfr (= 1.0*sofr+0.1*swfr+0.001*1000*0.1781076*sgfr )
|
||||
//Rseg[9] = swfr*0.1/ Rseg[8]
|
||||
//Rseg[10]= sgfr*0.1781076*/ Rseg[8]
|
||||
|
||||
rSeg[105] = 1.0;
|
||||
rSeg[106] = 1.0;
|
||||
rSeg[107] = 1.0;
|
||||
rSeg[108] = 1.0;
|
||||
rSeg[109] = 1.0;
|
||||
rSeg[110] = 1.0;
|
||||
//Metric units:
|
||||
//Rseg[8]= 1.0*sofr+0.1*swfr + 0.001*sgfr
|
||||
//Rseg[9] = swfr*0.1/ Rseg[8]
|
||||
//Rseg[10]= sgfr*0.001/ Rseg[8]
|
||||
|
||||
// branch according to whether multisegment well calculations are switched on or not
|
||||
|
||||
|
||||
if (haveWellRes && wRatesIt->second.segments.size() < 2) {
|
||||
// Note: Segment flow rates and pressure from 'smry' have correct
|
||||
// output units and sign conventions.
|
||||
temp_o = sSFR.sofr[segNumber];
|
||||
temp_w = sSFR.swfr[segNumber]*0.1;
|
||||
temp_g = sSFR.sgfr[segNumber]*gfactor;
|
||||
//Item 12 Segment pressure - use well flow bhp
|
||||
rSeg[11] = (smry.has(wPKey)) ? smry.get(wPKey) :0.0;
|
||||
}
|
||||
else {
|
||||
// Note: Segment flow rates and pressure from 'smry' have correct
|
||||
// output units and sign conventions.
|
||||
temp_o = get("SOFR");
|
||||
temp_w = get("SWFR")*0.1;
|
||||
temp_g = get("SGFR")*gfactor;
|
||||
//Item 12 Segment pressure
|
||||
rSeg[11] = get("SPR");
|
||||
}
|
||||
|
||||
rSeg[ 8] = temp_o + temp_w + temp_g;
|
||||
rSeg[ 9] = (std::abs(temp_w) > 0) ? temp_w / rSeg[8] : 0.;
|
||||
rSeg[10] = (std::abs(temp_g) > 0) ? temp_g / rSeg[8] : 0.;
|
||||
|
||||
// value is 1. based on tests on several data sets
|
||||
rSeg[ 39] = 1.;
|
||||
|
||||
rSeg[105] = 1.0;
|
||||
rSeg[106] = 1.0;
|
||||
rSeg[107] = 1.0;
|
||||
rSeg[108] = 1.0;
|
||||
rSeg[109] = 1.0;
|
||||
rSeg[110] = 1.0;
|
||||
|
||||
//Treat subsequent segments
|
||||
for (int ind_seg = 2; ind_seg <= welSegSet.size(); ind_seg++) {
|
||||
for (segNumber = 2; segNumber <= welSegSet.size(); segNumber++) {
|
||||
// 'stringSegNum' is one-based (1 .. #segments inclusive)
|
||||
stringSegNum = std::to_string(segNumber);
|
||||
|
||||
// set the elements of the rSeg array
|
||||
auto ind = welSegSet.segmentNumberToIndex(ind_seg);
|
||||
auto ind = welSegSet.segmentNumberToIndex(segNumber);
|
||||
auto outSeg = welSegSet[ind].outletSegment();
|
||||
auto ind_ofs = welSegSet.segmentNumberToIndex(outSeg);
|
||||
auto iS = (ind_seg-1)*noElmSeg;
|
||||
auto iS = (segNumber-1)*noElmSeg;
|
||||
rSeg[iS + 0] = units.from_si(M::length, (welSegSet[ind].totalLength() - welSegSet[ind_ofs].totalLength()));
|
||||
rSeg[iS + 1] = units.from_si(M::length, (welSegSet[ind].depth() - welSegSet[ind_ofs].depth()));
|
||||
rSeg[iS + 2] = units.from_si(M::length, (welSegSet[ind].internalDiameter()));
|
||||
@@ -448,13 +595,32 @@ namespace {
|
||||
rSeg[iS + 6] = units.from_si(M::length, (welSegSet[ind].totalLength()));
|
||||
rSeg[iS + 7] = units.from_si(M::length, (welSegSet[ind].depth()));
|
||||
|
||||
// set item ind + 10 to 0.5 based on tests on E100
|
||||
rSeg[10] = 0.5;
|
||||
// segment pressure (to be added!!)
|
||||
rSeg[iS + 11] = 0;
|
||||
//see section above for explanation of values
|
||||
// branch according to whether multisegment well calculations are switched on or not
|
||||
if (haveWellRes && wRatesIt->second.segments.size() < 2) {
|
||||
// Note: Segment flow rates and pressure from 'smry' have correct
|
||||
// output units and sign conventions.
|
||||
temp_o = sSFR.sofr[segNumber];
|
||||
temp_w = sSFR.swfr[segNumber]*0.1;
|
||||
temp_g = sSFR.sgfr[segNumber]*gfactor;
|
||||
//Item 12 Segment pressure - use well flow bhp
|
||||
rSeg[iS + 11] = (smry.has(wPKey)) ? smry.get(wPKey) :0.0;
|
||||
}
|
||||
else {
|
||||
// Note: Segment flow rates and pressure from 'smry' have correct
|
||||
// output units and sign conventions.
|
||||
temp_o = get("SOFR");
|
||||
temp_w = get("SWFR")*0.1;
|
||||
temp_g = get("SGFR")*gfactor;
|
||||
//Item 12 Segment pressure
|
||||
rSeg[iS + 11] = get("SPR");
|
||||
}
|
||||
|
||||
rSeg[iS + 8] = temp_o + temp_w + temp_g;
|
||||
rSeg[iS + 9] = (std::abs(temp_w) > 0) ? temp_w / rSeg[iS + 8] : 0.;
|
||||
rSeg[iS + 10] = (std::abs(temp_g) > 0) ? temp_g / rSeg[iS + 8] : 0.;
|
||||
|
||||
//Default values
|
||||
rSeg[iS + 39] = 1.0;
|
||||
rSeg[iS + 39] = 1.;
|
||||
|
||||
rSeg[iS + 105] = 1.0;
|
||||
rSeg[iS + 106] = 1.0;
|
||||
@@ -465,11 +631,12 @@ namespace {
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw std::invalid_argument("No such multisegment well: " + well.name());
|
||||
throw std::invalid_argument("No such multisegment well: " + well.name());
|
||||
}
|
||||
}
|
||||
} // RSeg
|
||||
|
||||
|
||||
namespace ILBS {
|
||||
std::size_t entriesPerMSW(const std::vector<int>& inteHead)
|
||||
{
|
||||
@@ -573,7 +740,10 @@ captureDeclaredMSWData(const Schedule& sched,
|
||||
const std::size_t rptStep,
|
||||
const Opm::UnitSystem& units,
|
||||
const std::vector<int>& inteHead,
|
||||
const Opm::EclipseGrid& grid)
|
||||
const Opm::EclipseGrid& grid,
|
||||
const Opm::SummaryState& smry,
|
||||
const Opm::data::WellRates& wr
|
||||
)
|
||||
{
|
||||
const auto& wells = sched.getWells(rptStep);
|
||||
auto msw = std::vector<const Opm::Well*>{};
|
||||
@@ -585,7 +755,7 @@ captureDeclaredMSWData(const Schedule& sched,
|
||||
|
||||
// Extract Contributions to ISeg Array
|
||||
{
|
||||
MSWLoop(msw, [rptStep, inteHead, grid, this]
|
||||
MSWLoop(msw, [rptStep, inteHead, &grid, this]
|
||||
(const Well& well, const std::size_t mswID) -> void
|
||||
{
|
||||
auto imsw = this->iSeg_[mswID];
|
||||
@@ -596,12 +766,12 @@ captureDeclaredMSWData(const Schedule& sched,
|
||||
|
||||
// Extract Contributions to RSeg Array
|
||||
{
|
||||
MSWLoop(msw, [&units, rptStep, inteHead, this]
|
||||
MSWLoop(msw, [&units, rptStep, inteHead, &grid, &smry, this, &wr]
|
||||
(const Well& well, const std::size_t mswID) -> void
|
||||
{
|
||||
auto rmsw = this->rSeg_[mswID];
|
||||
|
||||
RSeg::staticContrib(well, rptStep, inteHead, units, rmsw);
|
||||
RSeg::staticContrib_useMSW(well, rptStep, inteHead, grid, units, smry, wr, rmsw);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
@@ -200,15 +199,15 @@ namespace {
|
||||
using WMCtrlVal = ::Opm::RestartIO::Helpers::
|
||||
VectorItems::IWell::Value::WellCtrlMode;
|
||||
|
||||
{
|
||||
/*{
|
||||
const auto stat = well.getStatus(sim_step);
|
||||
|
||||
using WStat = ::Opm::WellCommon::StatusEnum;
|
||||
|
||||
if ((stat == WStat::SHUT) || (stat == WStat::STOP)) {
|
||||
if (stat == WStat::SHUT) {
|
||||
return WMCtrlVal::Shut;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (well.isInjector(sim_step)) {
|
||||
const auto& prop = well
|
||||
@@ -237,7 +236,16 @@ namespace {
|
||||
case CMode::GRUP: return WMCtrlVal::Group;
|
||||
|
||||
default:
|
||||
return WMCtrlVal::WMCtlUnk;
|
||||
{
|
||||
const auto stat = well.getStatus(sim_step);
|
||||
|
||||
using WStat = ::Opm::WellCommon::StatusEnum;
|
||||
|
||||
if (stat == WStat::SHUT) {
|
||||
return WMCtrlVal::Shut;
|
||||
}
|
||||
}
|
||||
return WMCtrlVal::WMCtlUnk;
|
||||
}
|
||||
}
|
||||
else if (well.isProducer(sim_step)) {
|
||||
@@ -255,9 +263,19 @@ namespace {
|
||||
case CMode::THP: return WMCtrlVal::THP;
|
||||
case CMode::BHP: return WMCtrlVal::BHP;
|
||||
case CMode::CRAT: return WMCtrlVal::CombRate;
|
||||
case CMode::GRUP: return WMCtrlVal::Group;
|
||||
case CMode::GRUP: return WMCtrlVal::Group;
|
||||
|
||||
default:
|
||||
{
|
||||
const auto stat = well.getStatus(sim_step);
|
||||
|
||||
default: return WMCtrlVal::WMCtlUnk;
|
||||
using WStat = ::Opm::WellCommon::StatusEnum;
|
||||
|
||||
if (stat == WStat::SHUT) {
|
||||
return WMCtrlVal::Shut;
|
||||
}
|
||||
}
|
||||
return WMCtrlVal::WMCtlUnk;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +340,7 @@ namespace {
|
||||
iWell[Ix::WType] = wellType (well, sim_step);
|
||||
iWell[Ix::WCtrl] = ctrlMode (well, sim_step);
|
||||
iWell[Ix::VFPTab] = wellVFPTab(well, sim_step);
|
||||
iWell[Ix::XFlow] = well.getAllowCrossFlow() ? 1 : 0;
|
||||
|
||||
// The following items aren't fully characterised yet, but
|
||||
// needed for restart of M2. Will need further refinement.
|
||||
@@ -425,11 +444,11 @@ namespace {
|
||||
zero , zero , infty, infty, zero , dflt , // 12.. 17 ( 2)
|
||||
infty, infty, infty, infty, infty, zero , // 18.. 23 ( 3)
|
||||
one , zero , zero , zero , zero , zero , // 24.. 29 ( 4)
|
||||
zero , one , zero , infty, zero , zero , // 30.. 35 ( 5)
|
||||
zero , one , zero , zero, zero , zero , // 30.. 35 ( 5)
|
||||
zero , zero , zero , zero , zero , zero , // 36.. 41 ( 6)
|
||||
zero , zero , zero , zero , zero , zero , // 42.. 47 ( 7)
|
||||
zero , zero , zero , zero , zero , zero , // 48.. 53 ( 8)
|
||||
infty, zero , zero , zero , zero , zero , // 54.. 59 ( 9)
|
||||
zero, zero , zero , zero , zero , zero , // 54.. 59 ( 9)
|
||||
zero , zero , zero , zero , zero , zero , // 60.. 65 (10)
|
||||
zero , zero , zero , zero , zero , zero , // 66.. 71 (11)
|
||||
zero , zero , zero , zero , zero , zero , // 72.. 77 (12)
|
||||
@@ -477,50 +496,53 @@ namespace {
|
||||
|
||||
if (well.isProducer(sim_step)) {
|
||||
const auto& pp = well.getProductionProperties(sim_step);
|
||||
const auto& predMode = pp.predictionMode;
|
||||
|
||||
if (pp.OilRate != 0.0) {
|
||||
if ((pp.OilRate != 0.0) || (!predMode)) {
|
||||
sWell[Ix::OilRateTarget] =
|
||||
swprop(M::liquid_surface_rate, pp.OilRate);
|
||||
}
|
||||
|
||||
if (pp.WaterRate != 0.0) {
|
||||
if ((pp.WaterRate != 0.0) || (!predMode)) {
|
||||
sWell[Ix::WatRateTarget] =
|
||||
swprop(M::liquid_surface_rate, pp.WaterRate);
|
||||
}
|
||||
|
||||
if (pp.GasRate != 0.0) {
|
||||
if ((pp.GasRate != 0.0) || (!predMode)) {
|
||||
sWell[Ix::GasRateTarget] =
|
||||
swprop(M::gas_surface_rate, pp.GasRate);
|
||||
sWell[Ix::GasRateTarget_2] = sWell[Ix::GasRateTarget];
|
||||
}
|
||||
|
||||
if (pp.LiquidRate != 0.0) {
|
||||
if (pp.LiquidRate != 0.0 || (!predMode)) {
|
||||
sWell[Ix::LiqRateTarget] =
|
||||
swprop(M::liquid_surface_rate, pp.LiquidRate);
|
||||
sWell[Ix::LiqRateTarget_2] = sWell[Ix::LiqRateTarget];
|
||||
}
|
||||
else {
|
||||
sWell[Ix::LiqRateTarget] =
|
||||
swprop(M::liquid_surface_rate, pp.OilRate + pp.WaterRate);
|
||||
}
|
||||
|
||||
if (pp.ResVRate != 0.0) {
|
||||
if (pp.ResVRate != 0.0) {
|
||||
sWell[Ix::ResVRateTarget] =
|
||||
swprop(M::rate, pp.ResVRate);
|
||||
}
|
||||
else if (smry.has("WVPR:" + well.name())) {
|
||||
else if ((smry.has("WVPR:" + well.name())) && (!predMode)) {
|
||||
// Write out summary voidage production rate if
|
||||
// target/limit is not set
|
||||
sWell[Ix::ResVRateTarget] =
|
||||
static_cast<float>(smry.get("WVPR:" + well.name()));
|
||||
auto vr = static_cast<float>(smry.get("WVPR:" + well.name()));
|
||||
if (vr != 0.0) sWell[Ix::ResVRateTarget] = vr;
|
||||
}
|
||||
|
||||
if (pp.THPLimit != 0.0) {
|
||||
sWell[Ix::THPTarget] =
|
||||
swprop(M::pressure, pp.THPLimit);
|
||||
}
|
||||
sWell[Ix::THPTarget] = pp.THPLimit != 0.0
|
||||
? swprop(M::pressure, pp.THPLimit)
|
||||
: 0.;
|
||||
|
||||
sWell[Ix::BHPTarget] = pp.BHPLimit != 0.0
|
||||
? swprop(M::pressure, pp.BHPLimit)
|
||||
: swprop(M::pressure, 1.0*::Opm::unit::atm);
|
||||
sWell[Ix::BHPTarget_2] = sWell[Ix::BHPTarget];
|
||||
}
|
||||
else if (well.isInjector(sim_step)) {
|
||||
const auto& ip = well.getInjectionProperties(sim_step);
|
||||
@@ -534,9 +556,11 @@ namespace {
|
||||
}
|
||||
if (ip.injectorType == IT::WATER) {
|
||||
sWell[Ix::WatRateTarget] = swprop(M::liquid_surface_rate, ip.surfaceInjectionRate);
|
||||
}
|
||||
sWell[Ix::LiqRateTarget_2] = sWell[Ix::WatRateTarget];
|
||||
}
|
||||
if (ip.injectorType == IT::GAS) {
|
||||
sWell[Ix::GasRateTarget] = swprop(M::gas_surface_rate, ip.surfaceInjectionRate);
|
||||
sWell[Ix::GasRateTarget_2] = sWell[Ix::GasRateTarget];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,6 +575,7 @@ namespace {
|
||||
sWell[Ix::BHPTarget] = ip.hasInjectionControl(IP::BHP)
|
||||
? swprop(M::pressure, ip.BHPLimit)
|
||||
: swprop(M::pressure, 1.0E05*::Opm::unit::psia);
|
||||
sWell[Ix::BHPTarget_2] = sWell[Ix::BHPTarget];
|
||||
}
|
||||
|
||||
sWell[Ix::DatumDepth] =
|
||||
@@ -694,7 +719,9 @@ namespace {
|
||||
xWell[Ix::GasFVF] = (std::abs(xWell[Ix::GasPrRate]) > 0.0)
|
||||
? xWell[Ix::VoidPrRate] / xWell[Ix::GasPrRate]
|
||||
: 0.0;
|
||||
|
||||
|
||||
if (std::isnan(xWell[Ix::GasFVF])) xWell[Ix::GasFVF] = 0.;
|
||||
|
||||
// Not fully characterised.
|
||||
xWell[Ix::item38] = xWell[Ix::GasPrRate];
|
||||
xWell[Ix::item83] = xWell[Ix::GasInjTotal];
|
||||
|
||||
@@ -78,11 +78,12 @@ createDoubHead(const EclipseState& es,
|
||||
const std::size_t lookup_step,
|
||||
const double simTime)
|
||||
{
|
||||
const auto& usys = es.getDeckUnitSystem();
|
||||
const auto dh = DoubHEAD{}
|
||||
.tuningParameters(sched.getTuning(), lookup_step,
|
||||
getTimeConv(es.getDeckUnitSystem()))
|
||||
.tuningParameters(sched.getTuning(), lookup_step,
|
||||
getTimeConv(usys))
|
||||
.timeStamp (computeTimeStamp(sched, simTime))
|
||||
.drsdt (sched, lookup_step)
|
||||
.drsdt (sched, lookup_step, getTimeConv(usys))
|
||||
;
|
||||
|
||||
return dh.data();
|
||||
|
||||
@@ -36,9 +36,10 @@ createLogiHead(const EclipseState& es)
|
||||
{
|
||||
const auto& rspec = es.runspec();
|
||||
const auto& wsd = rspec.wellSegmentDimensions();
|
||||
const auto& hystPar = rspec.hysterPar();
|
||||
|
||||
const auto lh = LogiHEAD{}
|
||||
.variousParam(false, false, wsd.maxSegmentedWells())
|
||||
.variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active())
|
||||
;
|
||||
|
||||
return lh.data();
|
||||
|
||||
@@ -590,14 +590,15 @@ Opm::RestartIO::DoubHEAD::timeStamp(const TimeStamp& ts)
|
||||
|
||||
Opm::RestartIO::DoubHEAD&
|
||||
Opm::RestartIO::DoubHEAD::drsdt(const Schedule& sched,
|
||||
const std::size_t lookup_step)
|
||||
const std::size_t lookup_step,
|
||||
const double cnvT)
|
||||
{
|
||||
const auto& vappar =
|
||||
sched.getOilVaporizationProperties(lookup_step);
|
||||
|
||||
this->data_[dRsdt] =
|
||||
(vappar.getType() == Opm::OilVaporizationEnum::DRSDT)
|
||||
? vappar.getMaxDRSDT()
|
||||
(vappar.getType() == Opm::OilVaporizationEnum::DRDT)
|
||||
? vappar.getMaxDRSDT(0)*cnvT
|
||||
: 1.0e+20;
|
||||
|
||||
return *this;
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
|
||||
#include <opm/output/eclipse/RestartIO.hpp>
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
#include <opm/output/eclipse/Tables.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -205,7 +204,7 @@ class EclipseIO::Impl {
|
||||
public:
|
||||
Impl( const EclipseState&, EclipseGrid, const Schedule&, const SummaryConfig& );
|
||||
void writeINITFile( const data::Solution& simProps, std::map<std::string, std::vector<int> > int_data, const NNC& nnc) const;
|
||||
void writeEGRIDFile( const NNC& nnc ) const;
|
||||
void writeEGRIDFile( const NNC& nnc );
|
||||
|
||||
const EclipseState& es;
|
||||
EclipseGrid grid;
|
||||
@@ -374,7 +373,7 @@ void EclipseIO::Impl::writeINITFile( const data::Solution& simProps, std::map<st
|
||||
}
|
||||
|
||||
|
||||
void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) const {
|
||||
void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) {
|
||||
const auto& ioConfig = this->es.getIOConfig();
|
||||
|
||||
std::string egridFile( ERT::EclFilename( this->outputDir,
|
||||
@@ -382,14 +381,8 @@ void EclipseIO::Impl::writeEGRIDFile( const NNC& nnc ) const {
|
||||
ECL_EGRID_FILE,
|
||||
ioConfig.getFMTOUT() ));
|
||||
|
||||
{
|
||||
int idx = 0;
|
||||
auto* ecl_grid = const_cast< ecl_grid_type* >( this->grid.c_ptr() );
|
||||
for (const NNCdata& n : nnc.nncdata())
|
||||
ecl_grid_add_self_nnc( ecl_grid, n.cell1, n.cell2, idx++);
|
||||
|
||||
ecl_grid_fwrite_EGRID2(ecl_grid, egridFile.c_str(), this->es.getDeckUnitSystem().getEclType() );
|
||||
}
|
||||
this->grid.addNNC( nnc );
|
||||
this->grid.save( egridFile, this->es.getDeckUnitSystem().getType());
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -467,7 +460,6 @@ void EclipseIO::writeTimeStep(int report_step,
|
||||
ioConfig.getUNIFOUT() ? ECL_UNIFIED_RESTART_FILE : ECL_RESTART_FILE,
|
||||
report_step,
|
||||
ioConfig.getFMTOUT() );
|
||||
|
||||
RestartIO::save(filename, report_step, secs_elapsed, value, es, grid, schedule,
|
||||
this->impl->summary.get_restart_vectors(), write_double);
|
||||
}
|
||||
@@ -535,6 +527,11 @@ EclipseIO::EclipseIO( const EclipseState& es,
|
||||
}
|
||||
|
||||
|
||||
const SummaryState& EclipseIO::summaryState() const {
|
||||
return this->impl->summary.get_restart_vectors();
|
||||
}
|
||||
|
||||
|
||||
EclipseIO::~EclipseIO() {}
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
@@ -10,7 +10,7 @@ lh_002 = 2 , // FALSE
|
||||
lh_003 = 3 , // FALSE Flag set to FALSE for a non-radial model, TRUE for a radial model (ECLIPSE 300 and other simulators)
|
||||
lh_004 = 4 , // FALSE Flag set to FALSE for a non-radial model, TRUE for a radial model (ECLIPSE 100)
|
||||
lh_005 = 5 , // FALSE
|
||||
lh_006 = 6 , // FALSE
|
||||
lh_006 = 6 , // FALSE Flag set to FALSE when no hysteresis, TRUE when hysteresis option is used
|
||||
lh_007 = 7 , // FALSE
|
||||
lh_008 = 8 , // FALSE
|
||||
lh_009 = 9 , // FALSE
|
||||
@@ -142,12 +142,13 @@ Opm::RestartIO::LogiHEAD::LogiHEAD()
|
||||
|
||||
Opm::RestartIO::LogiHEAD&
|
||||
Opm::RestartIO::LogiHEAD::
|
||||
variousParam(const bool e300_radial, const bool e100_radial, const int nswlmx)
|
||||
variousParam(const bool e300_radial, const bool e100_radial, const int nswlmx, const bool enableHyster)
|
||||
{
|
||||
this -> data_[lh_000] = true;
|
||||
this -> data_[lh_001] = true;
|
||||
this -> data_[lh_003] = e300_radial;
|
||||
this -> data_[lh_004] = e100_radial;
|
||||
this -> data_[lh_006] = enableHyster;
|
||||
//this -> data_[lh_016] = true;
|
||||
//this -> data_[lh_018] = true;
|
||||
//this -> data_[lh_031] = true;
|
||||
|
||||
@@ -28,19 +28,21 @@
|
||||
#include <opm/output/eclipse/AggregateWellData.hpp>
|
||||
#include <opm/output/eclipse/AggregateConnectionData.hpp>
|
||||
#include <opm/output/eclipse/AggregateMSWData.hpp>
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
#include <opm/output/eclipse/WriteRestartHelpers.hpp>
|
||||
|
||||
#include <opm/output/eclipse/libECLRestart.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Tables/Eqldims.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
@@ -134,14 +136,14 @@ namespace {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto active_index = grid.activeIndex(i, j, k);
|
||||
const auto global_index = grid.getGlobalIndex(i, j, k);
|
||||
|
||||
const auto& connection =
|
||||
std::find_if(well.connections.begin(),
|
||||
well.connections.end(),
|
||||
[active_index](const data::Connection& c)
|
||||
[global_index](const data::Connection& c)
|
||||
{
|
||||
return c.index == active_index;
|
||||
return c.index == global_index;
|
||||
});
|
||||
|
||||
if (connection == well.connections.end()) {
|
||||
@@ -309,10 +311,10 @@ namespace {
|
||||
grpKeyToInd, fldKeyToInd,
|
||||
ecl_compatible_rst,
|
||||
simStep, sumState, ih);
|
||||
|
||||
write_kw(rst_file, "IGRP", groupData.getIGroup());
|
||||
write_kw(rst_file, "SGRP", groupData.getSGroup());
|
||||
write_kw(rst_file, "XGRP", groupData.getXGroup());
|
||||
write_kw(rst_file, "ZGRP", serialize_ZWEL(groupData.getZGroup()));
|
||||
}
|
||||
|
||||
void writeMSWData(::Opm::RestartIO::ecl_rst_file_type* rst_file,
|
||||
@@ -320,12 +322,14 @@ namespace {
|
||||
const UnitSystem& units,
|
||||
const Schedule& schedule,
|
||||
const EclipseGrid& grid,
|
||||
const Opm::SummaryState& sumState,
|
||||
const Opm::data::Wells& wells,
|
||||
const std::vector<int>& ih)
|
||||
{
|
||||
// write ISEG, RSEG, ILBS and ILBR to restart file
|
||||
const size_t simStep = static_cast<size_t> (sim_step);
|
||||
auto MSWData = Helpers::AggregateMSWData(ih);
|
||||
MSWData.captureDeclaredMSWData(schedule, simStep, units, ih, grid);
|
||||
MSWData.captureDeclaredMSWData(schedule, simStep, units, ih, grid, sumState, wells);
|
||||
|
||||
write_kw(rst_file, "ISEG", MSWData.getISeg());
|
||||
write_kw(rst_file, "ILBS", MSWData.getILBs());
|
||||
@@ -372,13 +376,13 @@ namespace {
|
||||
|
||||
write_kw(rst_file, "ICON", connectionData.getIConn());
|
||||
write_kw(rst_file, "SCON", connectionData.getSConn());
|
||||
//write_kw(rst_file, "XCON", connectionData.getXConn());
|
||||
write_kw(rst_file, "XCON", connectionData.getXConn());
|
||||
}
|
||||
|
||||
void writeSolution(ecl_rst_file_type* rst_file,
|
||||
const RestartValue& value,
|
||||
const bool ecl_compatible_rst,
|
||||
const bool write_double)
|
||||
const bool ecl_compatible_rst,
|
||||
const bool write_double_arg)
|
||||
{
|
||||
ecl_rst_file_start_solution(rst_file);
|
||||
|
||||
@@ -396,7 +400,7 @@ namespace {
|
||||
|
||||
if (elm.second.target == data::TargetType::RESTART_SOLUTION)
|
||||
{
|
||||
write(elm.first, elm.second.data, write_double);
|
||||
write(elm.first, elm.second.data, write_double_arg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +419,7 @@ namespace {
|
||||
|
||||
for (const auto& elm : value.solution) {
|
||||
if (elm.second.target == data::TargetType::RESTART_AUXILIARY) {
|
||||
write(elm.first, elm.second.data, write_double);
|
||||
write(elm.first, elm.second.data, write_double_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -468,12 +472,31 @@ void save(const std::string& filename,
|
||||
const auto inteHD = writeHeader(rst_file.get(), sim_step, report_step,
|
||||
seconds_elapsed, schedule, grid, es);
|
||||
|
||||
writeGroup(rst_file.get(), sim_step, ecl_compatible_rst, schedule, sumState, inteHD);
|
||||
writeGroup(rst_file.get(), sim_step, ecl_compatible_rst,
|
||||
schedule, sumState, inteHD);
|
||||
|
||||
writeMSWData(rst_file.get(), sim_step, units, schedule, grid, inteHD);
|
||||
// Write well and MSW data only when applicable (i.e., when present)
|
||||
{
|
||||
const auto& wells = schedule.getWells(sim_step);
|
||||
|
||||
writeWell(rst_file.get(), sim_step, ecl_compatible_rst, es.runspec().phases(), units,
|
||||
grid, schedule, value.wells, sumState, inteHD);
|
||||
if (! wells.empty()) {
|
||||
const auto numMSW =
|
||||
std::count_if(std::begin(wells), std::end(wells),
|
||||
[sim_step](const Well* well)
|
||||
{
|
||||
return well->isMultiSegment(sim_step);
|
||||
});
|
||||
|
||||
if (numMSW > 0) {
|
||||
writeMSWData(rst_file.get(), sim_step, units,
|
||||
schedule, grid, sumState, value.wells, inteHD);
|
||||
}
|
||||
|
||||
writeWell(rst_file.get(), sim_step, ecl_compatible_rst,
|
||||
es.runspec().phases(), units, grid, schedule,
|
||||
value.wells, sumState, inteHD);
|
||||
}
|
||||
}
|
||||
|
||||
writeSolution(rst_file.get(), value, ecl_compatible_rst, write_double);
|
||||
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <initializer_list>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
|
||||
@@ -36,16 +38,23 @@
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/WellProductionProperties.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
#include <opm/output/eclipse/Summary.hpp>
|
||||
#include <opm/output/eclipse/RegionCache.hpp>
|
||||
|
||||
#include <ert/ecl/smspec_node.h>
|
||||
#include <ert/ecl/ecl_smspec.h>
|
||||
#include <ert/ecl/smspec_node.hpp>
|
||||
#include <ert/ecl/ecl_smspec.hpp>
|
||||
#include <ert/ecl/ecl_kw_magic.h>
|
||||
|
||||
namespace {
|
||||
struct SegmentResultDescriptor
|
||||
{
|
||||
std::string vector;
|
||||
std::string well;
|
||||
std::size_t segNumber;
|
||||
};
|
||||
|
||||
std::vector<std::string> requiredRestartVectors()
|
||||
{
|
||||
return {
|
||||
@@ -95,6 +104,42 @@ namespace {
|
||||
return entities;
|
||||
}
|
||||
|
||||
std::vector<SegmentResultDescriptor>
|
||||
requiredSegmentVectors(const ::Opm::Schedule& sched)
|
||||
{
|
||||
using SRD = SegmentResultDescriptor;
|
||||
auto ret = std::vector<SRD>{};
|
||||
|
||||
auto makeVectors =
|
||||
[&ret](const std::string& well,
|
||||
const std::size_t segNumber) -> void
|
||||
{
|
||||
ret.push_back(SRD{"SOFR", well, segNumber});
|
||||
ret.push_back(SRD{"SGFR", well, segNumber});
|
||||
ret.push_back(SRD{"SWFR", well, segNumber});
|
||||
ret.push_back(SRD{"SPR" , well, segNumber});
|
||||
};
|
||||
|
||||
const auto last_timestep = sched.getTimeMap().last();
|
||||
|
||||
for (const auto* well : sched.getWells()) {
|
||||
if (! well->isMultiSegment(last_timestep)) {
|
||||
// Don't allocate MS summary vectors for non-MS wells.
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto& wname = well->name();
|
||||
const auto nSeg =
|
||||
well->getWellSegments(last_timestep).size();
|
||||
|
||||
for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
|
||||
makeVectors(wname, segID + 1); // One-based
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string genKey(const std::string& vector,
|
||||
const std::string& entity)
|
||||
{
|
||||
@@ -103,19 +148,23 @@ namespace {
|
||||
: vector + ':' + entity;
|
||||
}
|
||||
|
||||
ERT::ert_unique_ptr<smspec_node_type, smspec_node_free>
|
||||
std::string genKey(const SegmentResultDescriptor& segRes)
|
||||
{
|
||||
return segRes.vector + ':' + segRes.well +
|
||||
':' + std::to_string(segRes.segNumber);
|
||||
}
|
||||
|
||||
std::unique_ptr<ecl::smspec_node>
|
||||
makeRestartVectorSMSPEC(const std::string& vector,
|
||||
const std::string& entity)
|
||||
{
|
||||
const auto var_type =
|
||||
ecl_smspec_identify_var_type(vector.c_str());
|
||||
return std::unique_ptr<ecl::smspec_node>( new ecl::smspec_node(0, vector.c_str(), entity.c_str(), "UNIT", 0.0f, ":"));
|
||||
}
|
||||
|
||||
const int dims[] = { 1, 1, 1 };
|
||||
|
||||
return ERT::ert_unique_ptr<smspec_node_type, smspec_node_free> {
|
||||
smspec_node_alloc(var_type, entity.c_str(), vector.c_str(),
|
||||
"UNIT", ":", dims, 0, 0, 0.0f)
|
||||
};
|
||||
std::unique_ptr<ecl::smspec_node>
|
||||
makeRestartVectorSMSPEC(const SegmentResultDescriptor& segRes)
|
||||
{
|
||||
return std::unique_ptr<ecl::smspec_node>(new ecl::smspec_node(0, segRes.vector.c_str(), segRes.well.c_str(), static_cast<int>(segRes.segNumber), "UNIT", 0.0f, ":"));
|
||||
}
|
||||
} // namespace Anonymous
|
||||
|
||||
@@ -275,6 +324,24 @@ measure rate_unit< rt::reservoir_oil >() { return measure::rate; }
|
||||
template<> constexpr
|
||||
measure rate_unit< rt::reservoir_gas >() { return measure::rate; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit < rt::productivity_index_water > () { return measure::liquid_productivity_index; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit < rt::productivity_index_oil > () { return measure::liquid_productivity_index; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit < rt::productivity_index_gas > () { return measure::gas_productivity_index; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit< rt::well_potential_water >() { return measure::liquid_surface_rate; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit< rt::well_potential_oil >() { return measure::liquid_surface_rate; }
|
||||
|
||||
template<> constexpr
|
||||
measure rate_unit< rt::well_potential_gas >() { return measure::gas_surface_rate; }
|
||||
|
||||
double efac( const std::vector<std::pair<std::string,double>>& eff_factors, const std::string& name ) {
|
||||
auto it = std::find_if( eff_factors.begin(), eff_factors.end(),
|
||||
[&] ( const std::pair< std::string, double > elem )
|
||||
@@ -363,6 +430,39 @@ inline quantity crate( const fn_args& args ) {
|
||||
return { v, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
template< rt phase, bool polymer = false >
|
||||
inline quantity srate( const fn_args& args ) {
|
||||
const quantity zero = { 0, rate_unit< phase >() };
|
||||
// The args.num value is the literal value which will go to the
|
||||
// NUMS array in the eclispe SMSPEC file; the values in this array
|
||||
// are offset 1 - whereas we need to use this index here to look
|
||||
// up a completion with offset 0.
|
||||
const size_t segNumber = args.num;
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
|
||||
const auto& well = args.schedule_wells.front();
|
||||
const auto& name = well->name();
|
||||
if( args.wells.count( name ) == 0 ) return zero;
|
||||
|
||||
const auto& well_data = args.wells.at( name );
|
||||
|
||||
const auto& segment = well_data.segments.find(segNumber);
|
||||
|
||||
if( segment == well_data.segments.end() ) return zero;
|
||||
|
||||
double eff_fac = efac( args.eff_factors, name );
|
||||
double concentration = polymer
|
||||
? well->getPolymerProperties( args.sim_step ).m_polymerConcentration
|
||||
: 1;
|
||||
|
||||
auto v = segment->second.rates.get( phase, 0.0 ) * eff_fac * concentration;
|
||||
//switch sign of rate - opposite convention in flow vs eclipse
|
||||
v *= -1;
|
||||
|
||||
if( polymer ) return { v, measure::mass_rate };
|
||||
return { v, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
inline quantity trans_factors ( const fn_args& args ) {
|
||||
const quantity zero = { 0, measure::transmissibility };
|
||||
|
||||
@@ -387,10 +487,35 @@ inline quantity trans_factors ( const fn_args& args ) {
|
||||
|
||||
if( connection == connections.end() ) return zero;
|
||||
|
||||
const auto& v = connection->CF();
|
||||
const auto& v = connection->CF() * connection->wellPi();
|
||||
return { v, measure::transmissibility };
|
||||
}
|
||||
|
||||
inline quantity spr ( const fn_args& args ) {
|
||||
const quantity zero = { 0, measure::pressure };
|
||||
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
// Like completion rate we need to look
|
||||
// up a connection with offset 0.
|
||||
const size_t segNumber = args.num;
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
|
||||
const auto& well = args.schedule_wells.front();
|
||||
const auto& name = well->name();
|
||||
if( args.wells.count( name ) == 0 ) return zero;
|
||||
|
||||
const auto& well_data = args.wells.at( name );
|
||||
|
||||
const auto& segment = well_data.segments.find(segNumber);
|
||||
|
||||
if( segment == well_data.segments.end() ) return zero;
|
||||
|
||||
|
||||
const auto& v = segment->second.pressure;
|
||||
return { v, measure::pressure };
|
||||
}
|
||||
|
||||
|
||||
inline quantity bhp( const fn_args& args ) {
|
||||
const quantity zero = { 0, measure::pressure };
|
||||
if( args.schedule_wells.empty() ) return zero;
|
||||
@@ -530,6 +655,27 @@ quantity region_rate( const fn_args& args ) {
|
||||
return { -sum, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
template < rt phase, bool outputProducer = true, bool outputInjector = true>
|
||||
inline quantity potential_rate( const fn_args& args ) {
|
||||
double sum = 0.0;
|
||||
|
||||
for( const auto* sched_well : args.schedule_wells ) {
|
||||
const auto& name = sched_well->name();
|
||||
if( args.wells.count( name ) == 0 ) continue;
|
||||
|
||||
if (sched_well->isInjector(args.sim_step) && outputInjector) {
|
||||
const auto v = args.wells.at(name).rates.get(phase, 0.0);
|
||||
sum += v;
|
||||
}
|
||||
else if (sched_well->isProducer(args.sim_step) && outputProducer) {
|
||||
const auto v = args.wells.at(name).rates.get(phase, 0.0);
|
||||
sum += v;
|
||||
}
|
||||
}
|
||||
|
||||
return { sum, rate_unit< phase >() };
|
||||
}
|
||||
|
||||
template< typename F, typename G >
|
||||
auto mul( F f, G g ) -> bin_op< F, G, std::multiplies< quantity > >
|
||||
{ return { f, g }; }
|
||||
@@ -645,6 +791,13 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
duration ) },
|
||||
{ "GVPT", mul( sum( sum( rate< rt::reservoir_water, producer >, rate< rt::reservoir_oil, producer > ),
|
||||
rate< rt::reservoir_gas, producer > ), duration ) },
|
||||
// Group potential
|
||||
{ "GWPP", potential_rate< rt::well_potential_water , true, false>},
|
||||
{ "GOPP", potential_rate< rt::well_potential_oil , true, false>},
|
||||
{ "GGPP", potential_rate< rt::well_potential_gas , true, false>},
|
||||
{ "GWPI", potential_rate< rt::well_potential_water , false, true>},
|
||||
{ "GOPI", potential_rate< rt::well_potential_oil , false, true>},
|
||||
{ "GGPI", potential_rate< rt::well_potential_gas , false, true>},
|
||||
|
||||
{ "WWPRH", production_history< Phase::WATER > },
|
||||
{ "WOPRH", production_history< Phase::OIL > },
|
||||
@@ -785,6 +938,14 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
duration ) },
|
||||
{ "FVIT", mul( sum( sum( rate< rt::reservoir_water, injector>, rate< rt::reservoir_oil, injector >),
|
||||
rate< rt::reservoir_gas, injector>), duration)},
|
||||
// Field potential
|
||||
{ "FWPP", potential_rate< rt::well_potential_water , true, false>},
|
||||
{ "FOPP", potential_rate< rt::well_potential_oil , true, false>},
|
||||
{ "FGPP", potential_rate< rt::well_potential_gas , true, false>},
|
||||
{ "FWPI", potential_rate< rt::well_potential_water , false, true>},
|
||||
{ "FOPI", potential_rate< rt::well_potential_oil , false, true>},
|
||||
{ "FGPI", potential_rate< rt::well_potential_gas , false, true>},
|
||||
|
||||
|
||||
{ "FWPRH", production_history< Phase::WATER > },
|
||||
{ "FOPRH", production_history< Phase::OIL > },
|
||||
@@ -835,6 +996,23 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
{ "ROPT" , mul( region_rate< rt::oil, producer >, duration ) },
|
||||
{ "RGPT" , mul( region_rate< rt::gas, producer >, duration ) },
|
||||
{ "RWPT" , mul( region_rate< rt::wat, producer >, duration ) },
|
||||
//Multisegment well segment data
|
||||
{ "SOFR", srate< rt::oil > },
|
||||
{ "SWFR", srate< rt::wat > },
|
||||
{ "SGFR", srate< rt::gas > },
|
||||
{ "SPR", spr },
|
||||
// Well productivity index
|
||||
{ "WPIW", potential_rate< rt::productivity_index_water >},
|
||||
{ "WPIO", potential_rate< rt::productivity_index_oil >},
|
||||
{ "WPIG", potential_rate< rt::productivity_index_gas >},
|
||||
{ "WPIL", sum( potential_rate< rt::productivity_index_water >, potential_rate< rt::productivity_index_oil>)},
|
||||
// Well potential
|
||||
{ "WWPP", potential_rate< rt::well_potential_water , true, false>},
|
||||
{ "WOPP", potential_rate< rt::well_potential_oil , true, false>},
|
||||
{ "WGPP", potential_rate< rt::well_potential_gas , true, false>},
|
||||
{ "WWPI", potential_rate< rt::well_potential_water , false, true>},
|
||||
{ "WOPI", potential_rate< rt::well_potential_oil , false, true>},
|
||||
{ "WGPI", potential_rate< rt::well_potential_gas , false, true>},
|
||||
};
|
||||
|
||||
|
||||
@@ -885,14 +1063,17 @@ static const std::unordered_map< std::string, UnitSystem::measure> block_units =
|
||||
};
|
||||
|
||||
inline std::vector< const Well* > find_wells( const Schedule& schedule,
|
||||
const smspec_node_type* node,
|
||||
const ecl::smspec_node* node,
|
||||
const int sim_step,
|
||||
const out::RegionCache& regionCache ) {
|
||||
|
||||
const auto* name = smspec_node_get_wgname( node );
|
||||
const auto type = smspec_node_get_var_type( node );
|
||||
|
||||
if( type == ECL_SMSPEC_WELL_VAR || type == ECL_SMSPEC_COMPLETION_VAR ) {
|
||||
if ((type == ECL_SMSPEC_WELL_VAR) ||
|
||||
(type == ECL_SMSPEC_COMPLETION_VAR) ||
|
||||
(type == ECL_SMSPEC_SEGMENT_VAR))
|
||||
{
|
||||
const auto* well = schedule.getWell( name );
|
||||
if( !well ) return {};
|
||||
return { well };
|
||||
@@ -936,15 +1117,14 @@ namespace out {
|
||||
class Summary::keyword_handlers {
|
||||
public:
|
||||
using fn = ofun;
|
||||
std::vector< std::pair< smspec_node_type*, fn > > handlers;
|
||||
std::map< std::string, smspec_node_type* > single_value_nodes;
|
||||
std::map< std::pair <std::string, int>, smspec_node_type* > region_nodes;
|
||||
std::map< std::pair <std::string, int>, smspec_node_type* > block_nodes;
|
||||
std::vector< std::pair< const ecl::smspec_node*, fn > > handlers;
|
||||
std::map< std::string, const ecl::smspec_node* > single_value_nodes;
|
||||
std::map< std::pair <std::string, int>, const ecl::smspec_node* > region_nodes;
|
||||
std::map< std::pair <std::string, int>, const ecl::smspec_node* > block_nodes;
|
||||
|
||||
// Memory management for restart-related summary vectors
|
||||
// that are not requested in SUMMARY section.
|
||||
std::vector<ERT::ert_unique_ptr<smspec_node_type,
|
||||
smspec_node_free>> rstvec_backing_store;
|
||||
std::vector<std::unique_ptr<ecl::smspec_node>> rstvec_backing_store;
|
||||
};
|
||||
|
||||
Summary::Summary( const EclipseState& st,
|
||||
@@ -982,6 +1162,9 @@ Summary::Summary( const EclipseState& st,
|
||||
restart_step = init_config.getRestartStep();
|
||||
} else
|
||||
OpmLog::warning("Restart case too long - not embedded in SMSPEC file");
|
||||
|
||||
this->prev_time_elapsed =
|
||||
schedule.getTimeMap().getTimePassedUntil(restart_step);
|
||||
}
|
||||
ecl_sum.reset( ecl_sum_alloc_restart_writer2(basename,
|
||||
restart_case,
|
||||
@@ -1001,7 +1184,8 @@ Summary::Summary( const EclipseState& st,
|
||||
std::set< std::string > unsupported_keywords;
|
||||
|
||||
for( const auto& node : sum ) {
|
||||
const auto* keyword = smspec_node_get_keyword(node.get());
|
||||
ecl_smspec_type * smspec = ecl_sum_get_smspec(this->ecl_sum.get());
|
||||
std::string keyword = node.keyword();
|
||||
|
||||
const auto single_value_pair = single_values_units.find( keyword );
|
||||
const auto funs_pair = funs.find( keyword );
|
||||
@@ -1009,60 +1193,36 @@ Summary::Summary( const EclipseState& st,
|
||||
const auto block_pair = block_units.find( keyword );
|
||||
|
||||
/*
|
||||
All summary values of the type ECL_SMSPEC_MISC_VAR
|
||||
and ECL_SMSPEC_FIELD_VAR must be passed explicitly
|
||||
in the misc_values map when calling
|
||||
add_timestep.
|
||||
*/
|
||||
All summary values of the type ECL_SMSPEC_MISC_VAR
|
||||
and ECL_SMSPEC_FIELD_VAR must be passed explicitly
|
||||
in the misc_values map when calling
|
||||
add_timestep.
|
||||
*/
|
||||
if (single_value_pair != single_values_units.end()) {
|
||||
auto node_type = smspec_node_get_var_type(node.get());
|
||||
auto node_type = node.type();
|
||||
if ((node_type != ECL_SMSPEC_FIELD_VAR) && (node_type != ECL_SMSPEC_MISC_VAR)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( single_value_pair->second ),
|
||||
0 );
|
||||
|
||||
auto* nodeptr = ecl_smspec_add_node( smspec, keyword.c_str(), st.getUnits().name( single_value_pair->second ), 0);
|
||||
this->handlers->single_value_nodes.emplace( keyword, nodeptr );
|
||||
} else if (region_pair != region_units.end()) {
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( region_pair->second ),
|
||||
0 );
|
||||
|
||||
this->handlers->region_nodes.emplace( std::make_pair(keyword, smspec_node_get_num(node.get())), nodeptr );
|
||||
|
||||
auto* nodeptr = ecl_smspec_add_node( smspec, keyword.c_str(), node.num(), st.getUnits().name( region_pair->second ), 0);
|
||||
this->handlers->region_nodes.emplace( std::make_pair(keyword, node.num()), nodeptr );
|
||||
} else if (block_pair != block_units.end()) {
|
||||
if (smspec_node_get_var_type(node.get()) != ECL_SMSPEC_BLOCK_VAR)
|
||||
if (node.type() != ECL_SMSPEC_BLOCK_VAR)
|
||||
continue;
|
||||
|
||||
int global_index = smspec_node_get_num(node.get()) - 1;
|
||||
int global_index = node.num() - 1;
|
||||
if (!this->grid.cellActive(global_index))
|
||||
continue;
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( block_pair->second ),
|
||||
0 );
|
||||
|
||||
this->handlers->block_nodes.emplace( std::make_pair(keyword, smspec_node_get_num(node.get())), nodeptr );
|
||||
|
||||
|
||||
|
||||
auto* nodeptr = ecl_smspec_add_node( smspec, keyword.c_str(), node.num(), st.getUnits().name( block_pair->second ), 0 );
|
||||
this->handlers->block_nodes.emplace( std::make_pair(keyword, node.num()), nodeptr );
|
||||
} else if (funs_pair != funs.end()) {
|
||||
auto node_type = smspec_node_get_var_type(node.get());
|
||||
auto node_type = node.type();
|
||||
|
||||
if ((node_type == ECL_SMSPEC_COMPLETION_VAR) || (node_type == ECL_SMSPEC_BLOCK_VAR)) {
|
||||
int global_index = smspec_node_get_num(node.get()) - 1;
|
||||
int global_index = node.num() - 1;
|
||||
if (!this->grid.cellActive(global_index))
|
||||
continue;
|
||||
}
|
||||
@@ -1074,7 +1234,7 @@ Summary::Summary( const EclipseState& st,
|
||||
const fn_args no_args { dummy_wells, // Wells from Schedule object
|
||||
0, // Duration of time step
|
||||
0, // Simulation step
|
||||
smspec_node_get_num(node.get()), // NUMS value for the summary output.
|
||||
node.num(),
|
||||
{}, // Well results - data::Wells
|
||||
{}, // Region <-> cell mappings.
|
||||
this->grid,
|
||||
@@ -1082,13 +1242,7 @@ Summary::Summary( const EclipseState& st,
|
||||
|
||||
const auto val = handle( no_args );
|
||||
|
||||
auto* nodeptr = ecl_sum_add_var( this->ecl_sum.get(),
|
||||
keyword,
|
||||
smspec_node_get_wgname(node.get()),
|
||||
smspec_node_get_num(node.get()),
|
||||
st.getUnits().name( val.unit ),
|
||||
0 );
|
||||
|
||||
auto * nodeptr = ecl_smspec_add_node( smspec, keyword.c_str(), node.wgname().c_str(), node.num(), st.getUnits().name( val.unit ), 0 );
|
||||
this->handlers->handlers.emplace_back( nodeptr, handle );
|
||||
} else {
|
||||
unsupported_keywords.insert(keyword);
|
||||
@@ -1105,6 +1259,7 @@ Summary::Summary( const EclipseState& st,
|
||||
auto& rvec = this->handlers->rstvec_backing_store;
|
||||
auto& hndlrs = this->handlers->handlers;
|
||||
|
||||
// Required restart vectors for wells, groups, and field.
|
||||
for (const auto& vector : requiredRestartVectors(schedule)) {
|
||||
const auto& kw = vector.first;
|
||||
const auto& entity = vector.second;
|
||||
@@ -1126,12 +1281,32 @@ Summary::Summary( const EclipseState& st,
|
||||
rvec.push_back(makeRestartVectorSMSPEC(kw, entity));
|
||||
hndlrs.emplace_back(rvec.back().get(), func->second);
|
||||
}
|
||||
|
||||
// Required restart vectors for segments (if applicable).
|
||||
for (const auto& segRes : requiredSegmentVectors(schedule)) {
|
||||
const auto key = genKey(segRes);
|
||||
if (ecl_sum_has_key(this->ecl_sum.get(), key.c_str())) {
|
||||
// Segment result already requested in SUMMARY section.
|
||||
// Don't add a second evaluation of this.
|
||||
continue;
|
||||
}
|
||||
|
||||
auto func = funs.find(segRes.vector);
|
||||
if (func == std::end(funs)) {
|
||||
throw std::logic_error {
|
||||
"Unable to find handler for '" + segRes.vector + "'"
|
||||
};
|
||||
}
|
||||
|
||||
rvec.push_back(makeRestartVectorSMSPEC(segRes));
|
||||
hndlrs.emplace_back(rvec.back().get(), func->second);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair : this->handlers->handlers) {
|
||||
const auto * nodeptr = pair.first;
|
||||
if (smspec_node_is_total(nodeptr))
|
||||
this->prev_state.add(smspec_node_get_gen_key1(nodeptr), 0);
|
||||
if (nodeptr->is_total())
|
||||
this->prev_state.add(*nodeptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1152,21 +1327,22 @@ Summary::Summary( const EclipseState& st,
|
||||
*
|
||||
*/
|
||||
std::vector< std::pair< std::string, double > >
|
||||
well_efficiency_factors( const smspec_node_type* type,
|
||||
const Schedule& schedule,
|
||||
const std::vector< const Well* >& schedule_wells,
|
||||
const int sim_step ) {
|
||||
well_efficiency_factors( const ecl::smspec_node* node,
|
||||
const Schedule& schedule,
|
||||
const std::vector< const Well* >& schedule_wells,
|
||||
const int sim_step ) {
|
||||
std::vector< std::pair< std::string, double > > efac;
|
||||
|
||||
if( smspec_node_get_var_type(type) != ECL_SMSPEC_GROUP_VAR
|
||||
&& smspec_node_get_var_type(type) != ECL_SMSPEC_FIELD_VAR
|
||||
&& smspec_node_get_var_type(type) != ECL_SMSPEC_REGION_VAR
|
||||
&& !smspec_node_is_total( type ) ) {
|
||||
auto var_type = node->get_var_type();
|
||||
if( var_type != ECL_SMSPEC_GROUP_VAR
|
||||
&& var_type != ECL_SMSPEC_FIELD_VAR
|
||||
&& var_type != ECL_SMSPEC_REGION_VAR
|
||||
&& !node->is_total()) {
|
||||
return efac;
|
||||
}
|
||||
|
||||
const bool is_group = smspec_node_get_var_type(type) == ECL_SMSPEC_GROUP_VAR;
|
||||
const bool is_rate = !smspec_node_is_total( type );
|
||||
const bool is_group = (var_type == ECL_SMSPEC_GROUP_VAR);
|
||||
const bool is_rate = !node->is_total();
|
||||
const auto &groupTree = schedule.getGroupTree(sim_step);
|
||||
|
||||
for( const auto* well : schedule_wells ) {
|
||||
@@ -1175,19 +1351,19 @@ well_efficiency_factors( const smspec_node_type* type,
|
||||
if ( !well->hasBeenDefined( sim_step ) )
|
||||
continue;
|
||||
|
||||
const auto* node = &schedule.getGroup(well->getGroupName(sim_step));
|
||||
const auto* group_node = &schedule.getGroup(well->getGroupName(sim_step));
|
||||
|
||||
while(true){
|
||||
if(( is_group
|
||||
&& is_rate
|
||||
&& node->name() == smspec_node_get_wgname(type) ))
|
||||
&& group_node->name() == node->get_wgname() ))
|
||||
break;
|
||||
eff_factor *= node->getGroupEfficiencyFactor( sim_step );
|
||||
eff_factor *= group_node->getGroupEfficiencyFactor( sim_step );
|
||||
|
||||
const auto& parent = groupTree.parent( node->name() );
|
||||
const auto& parent = groupTree.parent( group_node->name() );
|
||||
if( !schedule.hasGroup( parent ) )
|
||||
break;
|
||||
node = &schedule.getGroup( parent );
|
||||
group_node = &schedule.getGroup( parent );
|
||||
}
|
||||
efac.emplace_back( well->name(), eff_factor );
|
||||
}
|
||||
@@ -1204,6 +1380,21 @@ void Summary::add_timestep( int report_step,
|
||||
const std::map<std::string, std::vector<double>>& region_values,
|
||||
const std::map<std::pair<std::string, int>, double>& block_values) {
|
||||
|
||||
if (secs_elapsed < this->prev_time_elapsed) {
|
||||
const auto& usys = es.getUnits();
|
||||
const auto elapsed = usys.from_si(measure::time, secs_elapsed);
|
||||
const auto prev_el = usys.from_si(measure::time, this->prev_time_elapsed);
|
||||
const auto unt = '[' + std::string{ usys.name(measure::time) } + ']';
|
||||
|
||||
throw std::invalid_argument {
|
||||
"Elapsed time ("
|
||||
+ std::to_string(elapsed) + ' ' + unt
|
||||
+ ") must not precede previous elapsed time ("
|
||||
+ std::to_string(prev_el) + ' ' + unt
|
||||
+ "). Incorrect restart time?"
|
||||
};
|
||||
}
|
||||
|
||||
auto* tstep = ecl_sum_add_tstep( this->ecl_sum.get(), report_step, secs_elapsed );
|
||||
const double duration = secs_elapsed - this->prev_time_elapsed;
|
||||
SummaryState st;
|
||||
@@ -1216,7 +1407,6 @@ void Summary::add_timestep( int report_step,
|
||||
|
||||
for( auto& f : this->handlers->handlers ) {
|
||||
const int num = smspec_node_get_num( f.first );
|
||||
const auto* genkey = smspec_node_get_gen_key1( f.first );
|
||||
|
||||
const auto schedule_wells = find_wells( schedule, f.first, sim_step, this->regionCache );
|
||||
auto eff_factors = well_efficiency_factors( f.first, schedule, schedule_wells, sim_step );
|
||||
@@ -1231,22 +1421,22 @@ void Summary::add_timestep( int report_step,
|
||||
eff_factors});
|
||||
|
||||
double unit_applied_val = es.getUnits().from_si( val.unit, val.value );
|
||||
if (smspec_node_is_total(f.first))
|
||||
if (smspec_node_is_total(f.first)) {
|
||||
const auto* genkey = smspec_node_get_gen_key1( f.first );
|
||||
unit_applied_val += this->prev_state.get(genkey);
|
||||
}
|
||||
|
||||
st.add(genkey, unit_applied_val);
|
||||
st.add(*f.first, unit_applied_val);
|
||||
}
|
||||
|
||||
for( const auto& value_pair : single_values ) {
|
||||
const std::string key = value_pair.first;
|
||||
const auto node_pair = this->handlers->single_value_nodes.find( key );
|
||||
if (node_pair != this->handlers->single_value_nodes.end()) {
|
||||
const auto * nodeptr = node_pair->second;
|
||||
const auto * genkey = smspec_node_get_gen_key1( nodeptr );
|
||||
const auto unit = single_values_units.at( key );
|
||||
double si_value = value_pair.second;
|
||||
double output_value = es.getUnits().from_si(unit , si_value );
|
||||
st.add(genkey, output_value);
|
||||
st.add(*node_pair->second, output_value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1256,13 +1446,12 @@ void Summary::add_timestep( int report_step,
|
||||
const auto node_pair = this->handlers->region_nodes.find( std::make_pair(key, reg+1) );
|
||||
if (node_pair != this->handlers->region_nodes.end()) {
|
||||
const auto * nodeptr = node_pair->second;
|
||||
const auto* genkey = smspec_node_get_gen_key1( nodeptr );
|
||||
const auto unit = region_units.at( key );
|
||||
|
||||
assert (smspec_node_get_num( nodeptr ) - 1 == static_cast<int>(reg));
|
||||
double si_value = value_pair.second[reg];
|
||||
double output_value = es.getUnits().from_si(unit , si_value );
|
||||
st.add(genkey, output_value);
|
||||
st.add(*nodeptr, output_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1272,19 +1461,30 @@ void Summary::add_timestep( int report_step,
|
||||
const auto node_pair = this->handlers->block_nodes.find( key );
|
||||
if (node_pair != this->handlers->block_nodes.end()) {
|
||||
const auto * nodeptr = node_pair->second;
|
||||
const auto * genkey = smspec_node_get_gen_key1( nodeptr );
|
||||
const auto unit = block_units.at( key.first );
|
||||
double si_value = value_pair.second;
|
||||
double output_value = es.getUnits().from_si(unit , si_value );
|
||||
st.add(genkey, output_value);
|
||||
st.add(*nodeptr, output_value);
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pair: st) {
|
||||
const auto* key = pair.first.c_str();
|
||||
{
|
||||
const ecl_sum_type * ecl_sum = this->ecl_sum.get();
|
||||
const ecl_smspec_type * smspec = ecl_sum_get_smspec(ecl_sum);
|
||||
auto num_nodes = ecl_smspec_num_nodes(smspec);
|
||||
for (int node_index = 0; node_index < num_nodes; node_index++) {
|
||||
const auto& smspec_node = ecl_smspec_iget_node(smspec, node_index);
|
||||
// The TIME node is treated specially, it is created internally in
|
||||
// the ecl_sum instance when the timestep is created - and
|
||||
// furthermore it is not in st SummaryState instance.
|
||||
if (smspec_node.get_params_index() == ecl_smspec_get_time_index(smspec))
|
||||
continue;
|
||||
|
||||
if (ecl_sum_has_key(this->ecl_sum.get(), key)) {
|
||||
ecl_sum_tstep_set_from_key(tstep, key, pair.second);
|
||||
const std::string key = smspec_node.get_gen_key1();
|
||||
if (st.has(key))
|
||||
ecl_sum_tstep_iset(tstep, smspec_node.get_params_index(), st.get(key));
|
||||
else
|
||||
OpmLog::warning("Have configured UDQ variable " + key + " for summary output - but it has not been calculated");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 Statoil ASA.
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <opm/output/eclipse/SummaryState.hpp>
|
||||
|
||||
namespace Opm{
|
||||
|
||||
void SummaryState::add(const std::string& key, double value) {
|
||||
this->values[key] = value;
|
||||
}
|
||||
|
||||
|
||||
bool SummaryState::has(const std::string& key) const {
|
||||
return (this->values.find(key) != this->values.end());
|
||||
}
|
||||
|
||||
|
||||
double SummaryState::get(const std::string& key) const {
|
||||
const auto iter = this->values.find(key);
|
||||
if (iter == this->values.end())
|
||||
throw std::invalid_argument("XX No such key: " + key);
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
SummaryState::const_iterator SummaryState::begin() const {
|
||||
return this->values.begin();
|
||||
}
|
||||
|
||||
|
||||
SummaryState::const_iterator SummaryState::end() const {
|
||||
return this->values.end();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -189,7 +189,7 @@ namespace { namespace SatFunc {
|
||||
const auto& pc = t.getPcogColumn();
|
||||
std::transform(std::begin(pc), std::end(pc),
|
||||
linTable.column(tableID, primID, 2),
|
||||
[&units, uPress](const double Pc) -> double
|
||||
[&units](const double Pc) -> double
|
||||
{
|
||||
return units.from_si(uPress, Pc);
|
||||
});
|
||||
@@ -264,7 +264,7 @@ namespace { namespace SatFunc {
|
||||
const auto& pc = t.getPcogColumn();
|
||||
std::transform(std::begin(pc), std::end(pc),
|
||||
linTable.column(tableID, primID, 2),
|
||||
[&units, uPress](const double Pc) -> double
|
||||
[&units](const double Pc) -> double
|
||||
{
|
||||
return units.from_si(uPress, Pc);
|
||||
});
|
||||
@@ -916,7 +916,7 @@ namespace { namespace SatFunc {
|
||||
const auto& pc = t.getPcowColumn();
|
||||
std::transform(std::begin(pc), std::end(pc),
|
||||
linTable.column(tableID, primID, 2),
|
||||
[&units, uPress](const double Pc) -> double
|
||||
[&units](const double Pc) -> double
|
||||
{
|
||||
return units.from_si(uPress, Pc);
|
||||
});
|
||||
@@ -991,7 +991,7 @@ namespace { namespace SatFunc {
|
||||
const auto& pc = t.getPcowColumn();
|
||||
std::transform(std::begin(pc), std::end(pc),
|
||||
linTable.column(tableID, primID, 2),
|
||||
[&units, uPress](const double Pc) -> double
|
||||
[&units](const double Pc) -> double
|
||||
{
|
||||
return units.from_si(uPress, Pc);
|
||||
});
|
||||
|
||||
@@ -1570,28 +1570,6 @@ char * util_alloc_string_copy(const char *src ) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
//namespace {
|
||||
|
||||
static const int NIWELZ = 11; //Number of data elements per well in IWEL array in restart file
|
||||
static const int NZWELZ = 3; //Number of 8-character words per well in ZWEL array restart file
|
||||
static const int NICONZ = 15; //Number of data elements per completion in ICON array restart file
|
||||
|
||||
/**
|
||||
* The constants NIWELZ and NZWELZ referes to the number of
|
||||
* elements per well that we write to the IWEL and ZWEL eclipse
|
||||
* restart file data arrays. The constant NICONZ refers to the
|
||||
* number of elements per completion in the eclipse restart file
|
||||
* ICON data array.These numbers are written to the INTEHEAD
|
||||
* header.
|
||||
*
|
||||
* Observe that all of these values are our "current-best-guess"
|
||||
* for how many numbers are needed; there might very well be third
|
||||
* party applications out there which have a hard expectation for
|
||||
* these values.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Calling scope will handle the NULL return value, and (optionally)
|
||||
reopen the fortio stream and then call the ecl_file_kw_get_kw()
|
||||
@@ -1901,11 +1879,11 @@ static void LOCK_INIT( ::Opm::RestartIO::lock_type * rwlock ) {
|
||||
|
||||
#else
|
||||
|
||||
static void __hash_rdlock(::Opm::RestartIO::hash_type * hash) {}
|
||||
static void __hash_wrlock(::Opm::RestartIO::hash_type * hash) {}
|
||||
static void __hash_unlock(::Opm::RestartIO::hash_type * hash) {}
|
||||
static void LOCK_DESTROY(::Opm::RestartIO::lock_type * rwlock) {}
|
||||
static void LOCK_INIT(::Opm::RestartIO::lock_type * rwlock) {}
|
||||
static void __hash_rdlock(::Opm::RestartIO::hash_type *) {}
|
||||
static void __hash_wrlock(::Opm::RestartIO::hash_type *) {}
|
||||
static void __hash_unlock(::Opm::RestartIO::hash_type *) {}
|
||||
static void LOCK_DESTROY(::Opm::RestartIO::lock_type *) {}
|
||||
static void LOCK_INIT(::Opm::RestartIO::lock_type *) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2290,7 +2268,7 @@ void size_t_vector_free_container(::Opm::RestartIO::size_t_vector_type * vector)
|
||||
void size_t_vector_free(::Opm::RestartIO::size_t_vector_type * vector) {
|
||||
if (vector->data_owner)
|
||||
::Opm::RestartIO::util_safe_free( vector->data );
|
||||
::Opm::RestartIO::size_t_vector_free_container( vector );
|
||||
::Opm::RestartIO::size_t_vector_free_container( vector );
|
||||
}
|
||||
|
||||
void inv_map_free( ::Opm::RestartIO::inv_map_type * map ) {
|
||||
@@ -3367,7 +3345,7 @@ static char ** hash_alloc_keylist__(::Opm::RestartIO::hash_type *hash , bool loc
|
||||
if (lock) ::Opm::RestartIO::__hash_rdlock( hash );
|
||||
{
|
||||
if (hash->elements > 0) {
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
::Opm::RestartIO::hash_node_type *node = NULL;
|
||||
keylist = (char**)std::calloc(hash->elements , sizeof *keylist);
|
||||
{
|
||||
@@ -3381,9 +3359,9 @@ static char ** hash_alloc_keylist__(::Opm::RestartIO::hash_type *hash , bool loc
|
||||
|
||||
while (node != NULL) {
|
||||
const char *key = ::Opm::RestartIO::hash_node_get_key(node);
|
||||
keylist[i] = ::Opm::RestartIO::util_alloc_string_copy(key);
|
||||
keylist[j] = ::Opm::RestartIO::util_alloc_string_copy(key);
|
||||
node = hash_internal_iter_next(hash , node);
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
} else keylist = NULL;
|
||||
}
|
||||
@@ -4166,7 +4144,7 @@ void ecl_rst_file_fwrite_SEQNUM( Opm::RestartIO::ecl_rst_file_type * rst_file ,
|
||||
::Opm::RestartIO::ecl_kw_free( seqnum_kw );
|
||||
}
|
||||
|
||||
static ::Opm::RestartIO::ecl_kw_type * ecl_rst_file_alloc_INTEHEAD( ::Opm::RestartIO::ecl_rst_file_type * rst_file,
|
||||
static ::Opm::RestartIO::ecl_kw_type * ecl_rst_file_alloc_INTEHEAD(::Opm::RestartIO::ecl_rst_file_type * /* rst_file */,
|
||||
::Opm::RestartIO::ecl_rsthead_type * rsthead,
|
||||
int simulator ) {
|
||||
::Opm::RestartIO::ecl_kw_type * intehead_kw = ::Opm::RestartIO::ecl_kw_alloc( INTEHEAD_KW , INTEHEAD_RESTART_SIZE , ECL_INT_2 );
|
||||
@@ -4246,7 +4224,7 @@ static ::Opm::RestartIO::ecl_kw_type * ecl_rst_file_alloc_LOGIHEAD( int simulato
|
||||
return logihead_kw;
|
||||
}
|
||||
|
||||
static ::Opm::RestartIO::ecl_kw_type * ecl_rst_file_alloc_DOUBHEAD( ::Opm::RestartIO::ecl_rst_file_type * rst_file , double days) {
|
||||
static ::Opm::RestartIO::ecl_kw_type * ecl_rst_file_alloc_DOUBHEAD( ::Opm::RestartIO::ecl_rst_file_type * /* rst_file */, double days) {
|
||||
::Opm::RestartIO::ecl_kw_type * doubhead_kw = ::Opm::RestartIO::ecl_kw_alloc( DOUBHEAD_KW , DOUBHEAD_RESTART_SIZE , ECL_DOUBLE );
|
||||
::Opm::RestartIO::ecl_kw_scalar_set_type( doubhead_kw , ECL_DOUBLE_TYPE, 0);
|
||||
::Opm::RestartIO::ecl_kw_iset_type( doubhead_kw , ECL_DOUBLE_TYPE, DOUBHEAD_DAYS_INDEX , days );
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user