Compare commits

..

306 Commits

Author SHA1 Message Date
Joakim Hove
b900441ac6 Merge pull request #610 from jalvestad/restart_hyster
Add changes to correct problems/errors with Eclipse restarts from flow  with hysteresis and well crossflow
2019-02-06 16:45:17 +01:00
Joakim Hove
76f709aa70 Merge pull request #635 from joakim-hove/multio
Read keywords MULTIN and MULTOUT
2019-02-04 12:52:10 +01:00
Joakim Hove
57d19c9cdb Read keywords MULTIN and MULTOUT 2019-02-04 09:55:40 +01:00
Bård Skaflestad
e9756c3ee5 Merge pull request #622 from joakim-hove/udq-units
UDQ - hook the configuration up in the Schedule object
2019-02-03 22:24:02 +01:00
Bård Skaflestad
19c81fad9c Merge pull request #632 from joakim-hove/summary-pull
Change from push to pull when initializing ecl_sum object
2019-02-03 22:23:07 +01:00
Bård Skaflestad
ecca175ccd Merge pull request #615 from joakim-hove/msim-actionx
Msim actionx
2019-02-03 22:19:54 +01:00
Joakim Hove
2caf82baff Move check for legitimate keywords to ActionX 2019-02-03 18:07:04 +01:00
Joakim Hove
d82be29745 ACTIONX: Works with WELOPEN and msim 2019-02-02 17:35:56 +01:00
Joakim Hove
8eb10b33ce Change from push to pull when initializing ecl_sum object 2019-02-02 17:21:41 +01:00
Joakim Hove
42d08db25b Add UDQ configuration as DynamicState<> to schedule 2019-02-02 17:09:44 +01:00
Joakim Hove
d7d3d2538a Merge pull request #634 from sogoogos/patch-1
include `<cstdlib>`
2019-02-02 08:20:38 +01:00
Sogo Shiozawa
e0fad15f0a include <cstdlib>
add `#include <cstdlib>` to support older version of clang.
2019-02-02 09:38:33 +09:00
Jostein Alvestad
4c2105f85c changes to correct problem / error on output of historical injection rates and cumulatives 2019-02-01 08:36:12 +01:00
Jostein Alvestad
981e6c9b22 Added changes to improve code quality according to comments from Joakim Hove 2019-02-01 08:36:11 +01:00
Jostein Alvestad
4e83b63a0d minor change on code in CreateDoutHead to avoid conflicts with pullrequest 548 2019-02-01 08:36:09 +01:00
Jostein Alvestad
4c1333fb4f Added correction to element [25] in DoubHead (DRSDT) to account for unitsystem conversion of time 2019-02-01 08:36:07 +01:00
Jostein Alvestad
6db8a45d88 Changes to avoid name conflict 2019-02-01 08:36:05 +01:00
Jostein Alvestad
c33f69fd1b Added changes to extend the eclipse restart file export to handle hysteresis option in eclipse 2019-02-01 08:33:13 +01:00
Joakim Hove
bb5b2f4232 Merge pull request #629 from joakim-hove/initial-complump
Initial completion number set to connection number
2019-01-31 15:42:48 +01:00
Joakim Hove
ebe2f28c67 Initial completion number set to connection number 2019-01-31 12:40:39 +01:00
Joakim Hove
414661b898 Merge pull request #630 from akva2/janitoring
changed: add some harmless comparisons to test
2019-01-31 11:31:40 +01:00
Arne Morten Kvarving
4e00897117 changed: add some harmless comparisons to test
to avoid unused variable compiler warnings
2019-01-31 10:26:48 +01:00
Bård Skaflestad
98133f44fc Merge pull request #627 from GitPaean/fixing_restart_perf
[Disussion]using global_index in serialize_OPM_XWEL()
2019-01-31 10:05:19 +01:00
Joakim Hove
1574d7714d Merge pull request #617 from joakim-hove/simulator-missing-keyword
Simulator missing keyword
2019-01-30 16:26:50 +01:00
Joakim Hove
3c41d4c17a Merge pull request #626 from joakim-hove/MINVALUE-bug
Ensure units are applied with the MINVALUE and MAXVALUE keywords
2019-01-30 11:44:05 +01:00
Kai Bao
ef606711f2 using global_index in serialize_OPM_XWEL()
it looks like in data::Wells the index is global index.
2019-01-30 10:35:33 +01:00
Joakim Hove
ed9827bfcf Ensure units are applied with the MINVALUE and MAXVALUE keywords 2019-01-29 20:58:39 +01:00
Joakim Hove
fcadc69e49 Merge pull request #621 from joakim-hove/rename-UDQConfig
Renamed UDQConfig -> UDQParams
2019-01-28 17:40:39 +01:00
Joakim Hove
27eaeb2ec9 Renamed UDQConfig -> UDQParams 2019-01-28 16:53:01 +01:00
Joakim Hove
420b66822b Add iterators to the keywords in the body of ACTIONX 2019-01-28 11:58:31 +01:00
Joakim Hove
9913cb8600 Merge pull request #620 from joakim-hove/schedule-minor
Schedule minor
2019-01-28 11:58:09 +01:00
Joakim Hove
c874c8b6ea Add Schedule::simTime() method 2019-01-28 10:32:57 +01:00
Joakim Hove
6ca6f27640 White space cleanup 2019-01-28 10:32:22 +01:00
Joakim Hove
bd4e872230 Merge pull request #618 from joakim-hove/get-summary-state
Export SummaryState from EclipseIO object
2019-01-28 10:31:52 +01:00
Joakim Hove
3a9bab6285 Merge pull request #619 from atgeirr/fix-missing-include
Add missing <string> include.
2019-01-28 09:30:49 +01:00
Atgeirr Flø Rasmussen
30e2577f31 Add missing <string> include. 2019-01-28 09:13:27 +01:00
Joakim Hove
959502e8cd Export SummaryState from EclipseIO object 2019-01-28 08:59:19 +01:00
Joakim Hove
4a3c6b2058 Left adjust error messages from ErrorGuard 2019-01-25 18:07:46 +01:00
Joakim Hove
29db657757 Add new error modes SIMULATOR_KEYWORD_NOT_SUPPORTED 2019-01-25 18:07:46 +01:00
Joakim Hove
91734f13c4 Merge pull request #616 from joakim-hove/msim-actionx-preparations
Msim actionx preparations
2019-01-23 10:34:58 +01:00
Joakim Hove
b4c86e73af Members ActionX::last_run and ActionX::run_count mutable 2019-01-22 18:08:14 +01:00
Joakim Hove
f3a82ddd70 Add Schedule::simTime() method 2019-01-22 18:08:14 +01:00
Joakim Hove
4174602da2 Remove Schedule::evalAction() and add Schedule::actions() 2019-01-22 16:36:11 +01:00
Joakim Hove
749353a4b0 Merge pull request #614 from joakim-hove/msim-on
Turn on the mock simulator by default
2019-01-22 15:56:22 +01:00
Joakim Hove
a8db1f155c Default building of MOCK simulator to ON 2019-01-22 13:12:06 +01:00
Joakim Hove
59b4ca4b20 Change msim simulator to not hold Schedule object 2019-01-22 13:12:06 +01:00
Joakim Hove
261f7c3c03 Merge pull request #609 from joakim-hove/capture-wells-operation
Capture wells operation
2019-01-22 12:03:37 +01:00
Joakim Hove
a1214ba49e Merge pull request #613 from totto82/tstepLAB
Fix TSTEP unit in LAB mode
2019-01-21 19:05:48 +01:00
Joakim Hove
d9585d6585 Reorganized the ACTIONX implementation - made large parts private 2019-01-21 18:07:24 +01:00
Tor Harald Sandve
a668248aa1 Fix TSTEP unit in LAB mode
If unit system is LAB, the TSTEP is interpreted as hours not days
2019-01-21 15:37:15 +01:00
Atgeirr Flø Rasmussen
d40177dacb Merge pull request #612 from akva2/janitoring
Some janitoring
2019-01-21 14:53:09 +01:00
Arne Morten Kvarving
67acaaa637 Merge pull request #611 from andlaus/fix_jenkins_warning
try to get around a non-fatal bash warning in the jenkins build script
2019-01-21 14:23:13 +01:00
Andreas Lauser
33c5b79d98 fix the pre-build hook logic
currently, the following message is produced:

```
/var/lib/jenkins/workspace/opm-material-PR-builder/deps/opm-common/jenkins/build-opm-module.sh: line 88: cd: -D: invalid option
```

this is caused by trying to change the working directory to $1 which
represents additional cmake parameters, instead of to $3 which
represents the source directory. This mistake currently (probably)
prevents the pre-build hook from ever being executed.
2019-01-21 12:59:47 +01:00
Arne Morten Kvarving
7790fe743e initialize variable to quell compiler warning 2019-01-21 12:36:20 +01:00
Arne Morten Kvarving
40a2e848cb fixed: signed/unsigned comparison warning 2019-01-21 12:21:32 +01:00
Joakim Hove
7f6fd34fd3 Merge pull request #585 from jalvestad/group-field-potentials
Add output of group and field phase potential injection and production rates to Summary file
2019-01-17 15:02:44 +01:00
Joakim Hove
586f296de0 The matching wells are compined with && or || 2019-01-17 11:33:57 +01:00
Joakim Hove
8a2c2304e7 Merge pull request #608 from joakim-hove/wlist
Add WList implementation
2019-01-17 11:33:44 +01:00
Joakim Hove
9df659370c Merge pull request #605 from andlaus/add_jenkins_pre-build_hook
jenkins: allow modules to specify a pre-build check
2019-01-15 19:47:27 +01:00
Joakim Hove
66650a20fb Add WLIST implentation to Schedule 2019-01-14 23:26:02 +01:00
Joakim Hove
eae4a080cd Add WList manager 2019-01-14 11:30:29 +01:00
Joakim Hove
eb5454aeaf Add WList implementation 2019-01-14 11:30:28 +01:00
Atgeirr Flø Rasmussen
dc0ccc010a Merge pull request #607 from joakim-hove/errguard-dump-format
Format the ErrorGuard::dump() nicer
2019-01-14 09:20:00 +01:00
Joakim Hove
aa63d772d7 Merge pull request #593 from GitPaean/fixing_history_mode_part_2
fixing the BHP limit for the history matching wells
2019-01-11 18:04:45 +01:00
Joakim Hove
91afb0b656 Format the ErrorGuard::dump() nicer 2019-01-11 18:00:17 +01:00
Kai Bao
666cc9210b fxing some reviewing comments. 2019-01-11 14:27:49 +01:00
Jostein Alvestad
bdd82445d2 changed name of function for calculation of potential rates 2019-01-11 09:56:41 +01:00
Jostein Alvestad
bf9a142b6d Added corrections to tests/parser/SummaryConfigTests.cpp for list of ALL summary vectors
Removed comments from  Summary.cpp
2019-01-11 09:56:39 +01:00
Jostein Alvestad
9bbacfe710 Final changes to add unit tests for the well, group and field production / injection potential rates 2019-01-11 09:56:38 +01:00
Jostein Alvestad
982b221753 Initial changes to add unit tests for well potential rates 2019-01-11 09:56:36 +01:00
Jostein Alvestad
a4d0bb685b Additional changes to accomodate for loop over several wells beloning to
either a group or the field in generation of the group or field production or
injection potential rates
2019-01-11 09:56:35 +01:00
Jostein Alvestad
3429db8fc1 Initial changes to allow for writing group and field production / injection potential rates to
the summary file
2019-01-11 09:56:33 +01:00
Joakim Hove
fc0e61518b Merge pull request #566 from joakim-hove/capture-wells
Add functionality to capture matching wells when evaluating ACTIONX
2019-01-09 18:05:56 +01:00
Andreas Lauser
b7eefe8b18 jenkins: allow modules to specify a pre-build check
this is purely optional. opm-material will use this to make sure that
auto-generated code does not get manually modified.
2019-01-09 15:09:12 +01:00
Joakim Hove
0d5b3a5285 Merge pull request #604 from atgeirr/silence-warnings
Silence various warnings discovered with new version of clang.
2019-01-09 07:51:42 +01:00
Joakim Hove
3eef43b904 Merge pull request #589 from totto82/sort_multregt
Make the ordering of MULTREGT arbitary
2019-01-08 21:55:44 +01:00
Atgeirr Flø Rasmussen
db90ecd88c Silence various warnings discovered with new version of clang. 2019-01-08 14:51:20 +01:00
Tor Harald Sandve
68769e5b1d Make the ordering of MULTREGT arbitary
With this fix

MULTREGT
1 2 1 /
2 1 2 /
/

will multiply transmissibilities between region 1 and 2 with 2.
2019-01-08 08:35:15 +01:00
Joakim Hove
85949d44ac Merge pull request #602 from joakim-hove/error-list
Add small class ErrorGuard to store errors from parsing
2019-01-08 07:46:57 +01:00
Joakim Hove
690e00a079 Merge pull request #601 from joakim-hove/summary-state-wells
Add method wells() to the SummaryState class
2019-01-08 07:44:56 +01:00
Joakim Hove
cf42146d84 Add error mode DELAYED_EXIT1 to collect all errors 2019-01-07 12:38:05 +01:00
Joakim Hove
23cbe9035b Add separate - non BOOST - test program to test exit(1) 2019-01-04 16:52:10 +01:00
Joakim Hove
2cd6fa2f49 Add overloads without ParseContext and ErrorGuard - update all tests 2019-01-04 13:59:28 +01:00
Kai Bao
1b1f7b807d re-organizing the handleWCONINH from Schedule 2019-01-03 13:26:29 +01:00
Joakim Hove
bf52e6d123 Added ErrorGuard& arguments to library 2019-01-03 13:14:40 +01:00
Kai Bao
c6bbe5d24b re-organizing the history() for WellProductionProperties 2019-01-03 12:21:25 +01:00
Joakim Hove
ad001df804 Add small class ErrorGuard to manage errors from parsing 2019-01-03 11:54:48 +01:00
Joakim Hove
69e921b33a Merge pull request #603 from joakim-hove/rm-parsecontext
Rm parsecontext
2019-01-03 11:54:37 +01:00
Kai Bao
875626b738 handling the transition between injector and producer 2019-01-03 09:47:11 +01:00
Kai Bao
7e05d51e6f handle the WELTARG with WCONINJH 2019-01-03 09:47:11 +01:00
Kai Bao
0dc80689c0 assigning BHP limit for WCONHIST and WCONINJH keywords 2019-01-03 09:47:11 +01:00
Joakim Hove
ae8b81c7ae Changed EclipseState constructor to use const ParseContext& 2019-01-02 18:52:54 +01:00
Joakim Hove
ba0675997a Remove unused ParseContext member in EclipseState 2019-01-02 18:52:54 +01:00
Joakim Hove
15c473e3bb Implement support for well capture when evaluating ACTIONX 2019-01-02 14:03:25 +01:00
Joakim Hove
6465b5b23c Add small class ActionValue to hold action eval result 2019-01-02 14:03:25 +01:00
Joakim Hove
9e93dc5af2 Add method wells() to ActionContext class 2019-01-02 11:30:56 +01:00
Joakim Hove
481123ed25 Add method wells() to the SummaryState class 2019-01-02 11:22:07 +01:00
Joakim Hove
4968c35ad8 Add method wells() to the SummaryState class 2019-01-02 11:13:49 +01:00
Joakim Hove
f6136e69fe Merge pull request #599 from joakim-hove/parsecontext-RPT
Fix mismerge of broken formatting
2018-12-20 18:19:55 +01:00
Joakim Hove
6832788eef Fix mismerge of broken formatting 2018-12-20 16:40:03 +01:00
Joakim Hove
4c0776e3d2 Merge pull request #598 from joakim-hove/parsecontext-RPT
Parsecontext rpt
2018-12-20 15:21:09 +01:00
Joakim Hove
00d1607347 Add error modes RPT_MIXED_STYLE and RPT_UNKNOWN_MNEONIC 2018-12-20 13:47:31 +01:00
Atgeirr Flø Rasmussen
142c0a12c3 Merge pull request #597 from atgeirr/workaround-liq
Workaround: LIQ preferred phase treated as OIL.
2018-12-20 13:25:59 +01:00
Joakim Hove
25fbff2632 Add ParseContext argument to the RPTxxx parsing 2018-12-20 12:27:49 +01:00
Atgeirr Flø Rasmussen
1833ee2c43 Workaround: LIQ preferred phase treated as OIL. 2018-12-20 12:10:14 +01:00
Atgeirr Flø Rasmussen
f5851bcb92 Merge pull request #596 from blattms/fix-pr-578
[bugfix] Fix influence of logging on return of getWriteRestartFile
2018-12-20 00:21:39 +01:00
Markus Blatt
5632fc6662 [bugfix] Fix influence of logging on return of getWriteRestartFile
In PR #578 a bool was introduced that should determine whether we log warnings
during RestartConfig::getWriteRestartFile. Unfortunately, it introduced a bug that
made a false value of log return false from the function. This is fixed by this commit.
2018-12-19 23:05:17 +01:00
Joakim Hove
8375516c82 Merge pull request #595 from joakim-hove/region2region
Region2region
2018-12-19 15:40:52 +01:00
Joakim Hove
bf6732559f Add ParseContext error mode SUMMARY_UNHANDLED_KEWORD 2018-12-19 10:09:02 +01:00
Joakim Hove
3b951985ec Initial support for region 2 region keywords 2018-12-19 10:01:38 +01:00
Joakim Hove
9c98b5ceb4 Merge pull request #590 from joakim-hove/rptrst-bug
Handle space in the 'BASIC = ?' RPT mnemonics
2018-12-18 14:00:28 +01:00
Joakim Hove
161f555bc0 Handle space in the 'BASIC = ?' RPT mnemonics 2018-12-18 08:48:59 +01:00
Atgeirr Flø Rasmussen
39a6871b1d Merge pull request #588 from atgeirr/add-last-test-time
Add function WellTestState::lastTestTime().
2018-12-17 11:47:40 +01:00
Atgeirr Flø Rasmussen
175da3d436 Add function WellTestState::lastTestTime(). 2018-12-14 11:38:28 +01:00
Joakim Hove
cf61068ad1 Merge pull request #587 from bska/compare-ecl-ignoreextra
Make Summary Comparison Able to Ignore Different Number of Keywords
2018-12-13 21:31:28 +01:00
Joakim Hove
bf7b2697ee Merge pull request #586 from joakim-hove/remove-compare-summary
Removed unused file compareSummary.cpp
2018-12-13 21:10:37 +01:00
Bård Skaflestad
9098316775 Make Summary Comparison Able to Ignore Different Number of Keywords
This commit adds the ability of SummaryRegressionTest to bypass the
check for equal number keywords/summary vectors in the two result
sets being compared.  The primary purpose of this is to continue
comparing contents of existing summary vectors if new summary
keywords are introduced in a GitHub Pull Request.

Extend the 'compareECL' utility to take advantage of this ability.
2018-12-13 20:10:34 +01:00
Joakim Hove
1249ef0dd2 Removed unused file compareSummary.cpp 2018-12-13 19:16:05 +01:00
Bård Skaflestad
2b2d4901d1 Merge pull request #584 from bska/fix-open-conn-logic-for-output
Check Size Inconsistencies Only for Open Connections
2018-12-12 14:00:42 +01:00
Bård Skaflestad
d4740ae249 Check Size Inconsistencies Only for Open Connections
The previous logic was slightly incomplete in that it checked size
inconsistencies for all connections, not just open connections.
This, in turn would in turn generate diagnostics like

    Report step 19/247 at day 252/3312, date = 16-Jul-1998

    Time step 0, stepsize 16 days.
    ERROR: Uncaught std::exception when running tasklet: Inconsistent number of open connections I in vector<Opm::data::Connection*> (3) in Well B-4H. Trying to continue.

With this update we look for size inconsistencies between a well's
open connections and data::Wells::connections only.
2018-12-12 12:40:18 +01:00
Atgeirr Flø Rasmussen
49eda9fc72 Merge pull request #580 from bska/restore-gcc49
Restore Build on GCC 4.9
2018-12-11 19:11:40 +01:00
Bård Skaflestad
3ea522d7ba Restore Build on GCC 4.9
Commit 334dbe4e broke GCC 4.9 (invoking explicit constructor with an
empty initializer_list).  Restore build by using the actual type.
2018-12-11 17:30:43 +01:00
Atgeirr Flø Rasmussen
70172f5771 Merge pull request #579 from atgeirr/silence-warnings
Silence various warnings
2018-12-11 12:52:38 +01:00
Bård Skaflestad
91306c12f4 Merge pull request #549 from jalvestad/segment-summary
Improve eclipse-restart file for multi segment wells
2018-12-10 17:03:03 +01:00
Atgeirr Flø Rasmussen
67f96f4996 Fix: add required include and std:: qualification. 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
39bb94c2c8 Silence unused argument warnings. 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
7955805dd5 Do not return by const value (no effect). 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
74c06ea703 Silence various warnings in libECLRestart.cpp.
There are still systematic warnings that need suppression in this file:
 -Wgnu-zero-variadic-macro-arguments
 -Wformat-nonliteral
 -Wcast-align
These are too hard to fix quickly, and likely not indicating errors.
2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
71b0c2883f Avoid shadowing of variables. 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
334dbe4e1f Initialize all struct elements. 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
53252e6694 Use struct for MULTREGTRecord, match order of variables to usage. 2018-12-10 16:10:25 +01:00
Atgeirr Flø Rasmussen
e27df951f6 Merge pull request #578 from blattms/allow-silent-getWriteRestartFile-call
Allow to switch of logging during getWriteRestartFile call.
2018-12-07 18:53:41 +01:00
Markus Blatt
1062fb836b Allow to switch of logging during getWriteRestartFile call.
This needed for parallel runs as otherwise all processes will
do logging.
2018-12-07 15:52:53 +01:00
Jostein Alvestad
343d060118 changed CMakeLists_files.cmake to account for unit tests which are not finished and ready for use yet
The changes and additions in this version have been extensively tested on various input data
sets and proved to work properly and correctly
2018-12-07 12:38:33 +01:00
Jostein Alvestad
b15fab221b Corrected tests to be consistent with changes / corrections made to the various parameters 2018-12-07 12:38:31 +01:00
Jostein Alvestad
88b16f981c Removed test/debug comments 2018-12-07 12:38:30 +01:00
Jostein Alvestad
dc3f1cbf40 Added improvements to handle more general recompletion strategies
to eclipse compatible restart file
2018-12-07 12:38:29 +01:00
Jostein Alvestad
01e3aa377c Corrections to Summary.cpp for sicontinuities in rates/cumulatives
Improved messages from AggregateMSWData
2018-12-07 12:38:27 +01:00
Jostein Alvestad
44102f83a0 one more minor correction to test_AggregateMSWData.cpp 2018-12-07 12:38:26 +01:00
Jostein Alvestad
2c13cdfa18 Added minor correction to test_AggregateMSWData.cpp 2018-12-07 12:38:24 +01:00
Jostein Alvestad
1d22e3b0ed Reset change to complump for output to Restart file 2018-12-07 12:38:23 +01:00
Jostein Alvestad
2add79d122 Added corrections / improvements - generalisations for Eclipse compatible restartfiles 2018-12-07 12:38:22 +01:00
Jostein Alvestad
0cfbfb9957 Added ZGRP data to the eclipse restart file 2018-12-07 12:38:20 +01:00
Jostein Alvestad
92f65b7958 Additional changes to handle --use-multisegment-well=false 2018-12-07 12:38:19 +01:00
Jostein Alvestad
79037f93b2 Initial changes to allow for eclipse restart when using option --enable-opm-rst-file=false 2018-12-07 12:38:17 +01:00
Jostein Alvestad
633a5883f7 Added changes to prepare for unit testing of AggregateMSWdata 2018-12-07 12:38:15 +01:00
Jostein Alvestad
63590f95b0 Added initial changes to enable unit testing for AggregateMSWData 2018-12-07 12:38:14 +01:00
Jostein Alvestad
e783eaafc0 Added unit test for AggregateMSWdata 2018-12-07 12:38:13 +01:00
Atgeirr Flø Rasmussen
e341bd1c08 Merge pull request #577 from GitPaean/updating_liquid_rate_for_wconhist
updating liquid rate for WCONHIST
2018-12-07 09:58:18 +01:00
Atgeirr Flø Rasmussen
f9ce82547c Merge pull request #559 from kel85uk/fix_influx_coeff
Fix for aquifer making connection
2018-12-07 09:56:40 +01:00
Kai Bao
b349b3b217 updating liquid rate for WCONHIST 2018-12-03 16:40:42 +01:00
Joakim Hove
983ed5fcb8 Merge pull request #575 from joakim-hove/smspec-c++
Adapt to C++ changes in libecl
2018-11-30 08:09:31 +01:00
Joakim Hove
f414f5b8ad Adapt to C++ changes in libecl 2018-11-26 17:30:09 +01:00
Joakim Hove
7c52f6f5a8 Merge pull request #560 from blattms/edit-nnc-2nd-try
Represent EDITNNC in the deck representation.
2018-11-26 16:57:18 +01:00
Joakim Hove
188eb23911 Merge pull request #574 from joakim-hove/parsecontext-exit1
Parsecontext exit1
2018-11-26 14:25:34 +01:00
Joakim Hove
72ad2eaa7f Merge pull request #562 from trinemykk/addtracer
Added missing support for tracers in the parser
2018-11-26 13:02:19 +01:00
Joakim Hove
92870dc1e9 Merge pull request #576 from akva2/janitoring
Some SCA error janitoring
2018-11-26 11:56:38 +01:00
Arne Morten Kvarving
2d43ccaf8f fixed: initialize members 2018-11-26 10:41:29 +01:00
Arne Morten Kvarving
b2e0eb2507 fixed: remove unnecessary variable initialization 2018-11-26 10:41:29 +01:00
Trine S Mykkeltvedt
5085fb35c0 removed WTRACER from RPTRST_DECK.DATA to make tests pass 2018-11-26 09:44:31 +01:00
Joakim Hove
8d33ec55bd Add ParseContext error handler EXIT1 for user error 2018-11-25 11:53:34 +01:00
Joakim Hove
d70b86484d White space 2018-11-25 08:56:20 +01:00
Joakim Hove
0089fa9287 Merge pull request #572 from nairr/fix_influx_mult
fix default value influx_mult
2018-11-24 00:14:32 +01:00
6b80dd10e6 fix default value influx_mult 2018-11-23 17:42:48 +01:00
Joakim Hove
f4a9298cf4 Merge pull request #569 from joakim-hove/OPERATER
Add support for OPERATER keyword
2018-11-23 13:05:08 +01:00
Atgeirr Flø Rasmussen
7de217b8fb Merge pull request #567 from joakim-hove/normalize-case
Force UPPER_CASE when input deck has MixeDCase basename
2018-11-23 11:08:54 +01:00
Joakim Hove
039fdb70de Merge pull request #520 from GitPaean/adding_injectivity_keywords_june
Adding injectivity keywords
2018-11-23 10:56:18 +01:00
Bård Skaflestad
2f7a0bc532 Merge pull request #570 from bska/fix-rsconst-kw
Correct RSCONST and RSCONSTT Specifications
2018-11-22 14:38:16 +01:00
Bård Skaflestad
fda1719eab Correct RSCONST and RSCONSTT Specifications
This commit ensures that we never try to read more than a single
record of data when parsing the RSCONST keyword.  Previously, the
parser would attempt to parse RSCONST as if it were an unbounded
keyword that was terminated by an empty record.  This, in turn,
would produce the diagnostic message

    Inner exception: Malformed floating point number 'INCLUDE'

when trying to read a specification like

    RSCONST
     0.35  932  /

    -- Check for these data in the future this is important
    INCLUDE
      'RP.dat'  /

While here, also implement 'getSIDouble()' for the Rs value (item 1)
in keywords RSCONST and RSCONSTT by adding the correct unit of
measurement ("dimension") to the keyword specification.

Add unit tests to verify new behaviours.
2018-11-22 13:28:39 +01:00
Joakim Hove
c0e9b71eec Add postAddKeyword() overload for initializable properties 2018-11-22 12:06:12 +01:00
kel85uk
d93bd35b8e Change influx_coeff to double. Remove test of influx_coeff as it is difficult to check for equal collections of pointers. Change from false to nullptr when making AquiferCTTests. 2018-11-22 09:35:01 +01:00
kel85uk
afab0103e3 Fix memory leak due to pointer errors for influx_coeff. 2018-11-22 09:34:59 +01:00
kel85uk
62f39dacce Fixes the data type to shared_ptr for the working_buffer vector 2018-11-22 09:34:57 +01:00
kel85uk
1d7a12442e Fixes the default behaviour for the influx_coeff and default aquifer pressure with AQUCT by providing nullptr instead of values. 2018-11-22 09:34:55 +01:00
Markus Blatt
d69bf47a28 Added test for parsing EDITNNC 2018-11-21 22:14:27 +01:00
Markus Blatt
7064b96260 Test for next neighbour without using abs.
Substraction of two unsigned int might cause trouble as
the result might have to be signed to be meaningful. In
addition there have overload resolution issues with g++-7.
2018-11-21 22:14:27 +01:00
Joakim Hove
e0d5711f8e Add support for OPERATER keyword 2018-11-21 16:56:28 +01:00
Joakim Hove
3677f470fb Force UPPER_CASE when input deck has MixeDCase basename 2018-11-21 13:07:33 +01:00
Joakim Hove
44409c7a30 Merge pull request #565 from joakim-hove/schedule-eval-actions
Add method Schedule::evalActions() to evaluate ACTIONX
2018-11-21 08:21:08 +01:00
Markus Blatt
7c1e868973 Store EDITNNC in the EclipseState for latter usage by the simulator.
Only the simulator is able to determine all NNCs and therefore it needs
to apply the multiplicators itself.
2018-11-20 13:58:08 +01:00
Markus Blatt
0768c5a8b3 Revert "Merge pull request #535 from blattms/support-editnnc"
This reverts commit 7ebadbb055, reversing
changes made to 0f485c7801.
2018-11-20 13:58:08 +01:00
Trine Solberg Mykkeltvedt
ea7cb8d2c6 adding support for WTRACER keyword in EclipseState 2018-11-19 13:10:02 +01:00
Kai Bao
6858bd4578 adding the ScheduleTests for the following keywords
WPMITAB and WSKPTAB
2018-11-19 12:27:52 +01:00
Kai Bao
1b8680df7d implmentation of the polymer injectivity tables in one file
Moving PlymwinjTable.cpp PolyInjTable.cpp SkprpolyTable.cpp
SkprwatTable.cpp into one single file PolyInjTables.cpp

for better organization
2018-11-19 12:08:04 +01:00
Kai Bao
316324a78e renaming Simple2DTable to PolyInjTable
make it more clear that it is a talbe introduced for the polymer
injectivity study, not intended for general usage.
2018-11-19 12:08:04 +01:00
Kai Bao
2bf33c30d8 some cleaning up and sanity checks. 2018-11-19 12:08:04 +01:00
Kai Bao
862b3450d3 adding test for the following three keywords
SKPRWAT, SKPRPOLY and PLYMWINJ .
2018-11-19 12:08:04 +01:00
Kai Bao
082476f840 fixing errors from rebasing. 2018-11-19 12:08:04 +01:00
Kai Bao
49655b464c adding support for the few skin pressure related keywords
SKPRWAT SKPRPOLY WSKPTAB
2018-11-19 12:08:04 +01:00
Kai Bao
1432367e07 adding a few keywords related to skin pressure
SKPRPOLY, SKPRWAT, WSKPTAB
2018-11-19 12:08:04 +01:00
Kai Bao
e4912d4fcf adding keyword WPMITAB 2018-11-19 12:08:04 +01:00
Kai Bao
d0e5f8f470 beginning working on PlymwinjTable
it will go to Tables.cpp later.
2018-11-19 12:08:04 +01:00
Kai Bao
65ef90f471 removing NPLYVMH from PINTDIMS
from now on, the number of NPLYVMH will depend on the number of polymer
mixing regions, which is defined with NPLMIX from REGDIMS.
2018-11-19 12:08:04 +01:00
Kai Bao
bcb852e8f2 adding keyword PLYMWINJ 2018-11-19 12:08:04 +01:00
Trine Solberg Mykkeltvedt
927bf09688 added TBLK keyword 2018-11-19 10:25:42 +01:00
Joakim Hove
6921801eec Add method Schedule::evalActions() to evaluate ACTIONX 2018-11-19 09:57:06 +01:00
Joakim Hove
f21e2035c4 Merge pull request #563 from joakim-hove/msim-functions
Add functions for well rates and solutions to mock simulator
2018-11-16 12:43:56 +01:00
Joakim Hove
c1ffeeef53 Merge pull request #557 from joakim-hove/actioncontext-summary-state
Actioncontext summary state
2018-11-16 11:31:20 +01:00
Joakim Hove
e27abdd1a0 Merge pull request #561 from joakim-hove/dynamicstate-update-equal
Add method update_equal() to DynamicState
2018-11-16 09:43:25 +01:00
Joakim Hove
8b8285ae2b Merge pull request #556 from joakim-hove/summarystate-well-api
Summarystate well api
2018-11-16 09:42:01 +01:00
Joakim Hove
bdcb227a53 Add functions for well rates and solutions to mock simulator 2018-11-15 15:45:29 +01:00
Joakim Hove
88f043645a Removed two unused includes 2018-11-14 09:38:43 +01:00
Joakim Hove
ad55655a08 Add method update_equal() to DynamicState 2018-11-14 09:34:13 +01:00
Atgeirr Flø Rasmussen
6af3194c6c Merge pull request #554 from totto82/addPP
Add output of well phase potential
2018-11-13 14:30:17 +01:00
Joakim Hove
bb96eb9b70 Merge pull request #558 from bska/enable-stone2-kw
Recognise Requests for Stone's Second Model of 3-Phase Oil Relperm
2018-11-12 16:41:35 +01:00
Bård Skaflestad
baae4a3faf Recognise Requests for Stone's Second Model of 3-Phase Oil Relperm
This commit makes the parser aware of the keywords STONE and STONE2
which both request that the simulation run use Stone's second model
for three-phase relative permeability for oil.
2018-11-12 11:50:45 +01:00
Joakim Hove
36c3080f85 ActionContext internalizes a SummaryState object 2018-11-09 21:58:36 +01:00
Joakim Hove
c35832b155 Changed exception to std::out_of_range 2018-11-09 21:14:03 +01:00
Joakim Hove
ca9da29c53 Add well_var methods to SummaryState 2018-11-09 20:45:20 +01:00
Joakim Hove
1ba51534ae Move SummaryState implementation to EclipseState/Schedule/ 2018-11-09 20:44:37 +01:00
Joakim Hove
01abada947 Merge pull request #542 from joakim-hove/actionx-parse
Actionx parse
2018-11-09 20:20:26 +01:00
Joakim Hove
212a1fde5f Parse condition part in ACTIONX 2018-11-09 20:19:34 +01:00
Joakim Hove
0b8adcbee3 Merge pull request #555 from joakim-hove/minor
Minor
2018-11-08 12:25:17 +01:00
Joakim Hove
1d755859a6 Update msim after upstream changes 2018-11-07 15:45:25 +01:00
Tor Harald Sandve
5d3125c532 Add output of well phase potential 2018-11-07 15:38:23 +01:00
Joakim Hove
971d300243 Merge pull request #553 from akva2/fix_test_macro
Fix test macro
2018-11-07 14:14:27 +01:00
Arne Morten Kvarving
199b7d710a fixed: set property for correct test name 2018-11-07 11:33:31 +01:00
Arne Morten Kvarving
d60787188e fixed: simplify boost_dyn_test code and add to opm_add_test as well 2018-11-07 11:33:31 +01:00
Joakim Hove
819ad1bf9e Merge pull request #551 from akva2/janitoring
Some small cleanups
2018-11-07 10:59:34 +01:00
Arne Morten Kvarving
3cbc40bd4d remove unused variable 2018-11-07 09:46:10 +01:00
Arne Morten Kvarving
8e92a84c09 fix indent 2018-11-07 09:46:05 +01:00
Arne Morten Kvarving
ff8ab1c1dc changed: mark constructor explicit 2018-11-07 09:43:14 +01:00
Joakim Hove
9d45632628 Make Eclipse month indices available for use outside TimeMap 2018-11-07 09:25:02 +01:00
Joakim Hove
089b58f101 Merge pull request #547 from totto82/productivity_index
Add support for output of well productivity index
2018-11-06 09:38:55 +01:00
Joakim Hove
967e3ad3af Merge pull request #526 from totto82/addDRSDTR
Add DRSDTR and DRVDTR
2018-11-06 08:21:32 +01:00
Tor Harald Sandve
e2d748906e Fix failure in actionx test after rebase 2018-11-05 13:48:36 +01:00
Tor Harald Sandve
95179f393c Fix vappars and dr[sv]dt logic
The simulator should either use VAPPERS or dr[sv]dt, both the
combination drsdt and drvdt is allowed.
2018-11-05 13:38:42 +01:00
Tor Harald Sandve
6fee172f16 Add DRSDTR and DRVDTR 2018-11-05 13:37:22 +01:00
Joakim Hove
a241a1bd07 Merge pull request #545 from bska/summary-ensure-inc-elapsed
Summary: Ensure that we don't step backwards during simulation
2018-11-05 13:35:38 +01:00
Bård Skaflestad
4348438044 Summary: Ensure that we don't step backwards during simulation
This commit, a preparation for restoring cumulative quantities from
a restart file, reinitialises Summary::prev_time_elapsed in the case
of simulation restart and adds a check to

    Summary::write_timestep()

which throws if the input argument 'secs_elapsed' is prior to the
previously recorded elapsed time.  The latter is a change in the
behaviour of write_timestep(), but ensures that we don't integrate
rate quantities across a very large timestep in the case of
simulation restart and also prevents double accumulation.

Update impacted unit tests accordingly, and move FIRST_SIM's START
date into the RUNSPEC section where it belongs.
2018-11-04 21:48:35 +01:00
Joakim Hove
8e801a1fae Merge pull request #546 from bska/detect-thermal-run
Simulation Config: Add Predicate for Thermal Simulations
2018-11-03 19:28:32 +01:00
Tor Harald Sandve
2d5d0953ee Add support for output of well productivity index 2018-11-02 15:57:21 +01:00
Bård Skaflestad
9df3bea857 Simulation Config: Add Predicate for Thermal Simulations
This commit introduces a new predicate,

    bool SimulationConfig::isThermal() const

that determines whether or not either of the keywords

    TEMP or THERMAL

are specified in the RUNSPEC section of a simulation run.
2018-11-02 13:45:50 +01:00
Joakim Hove
056d6bccb4 Merge pull request #539 from joakim-hove/actionx-whitelist
ACTIONX container
2018-11-02 12:19:26 +01:00
Joakim Hove
68e6926355 Add Actions container and ActionContext for eval 2018-11-02 10:55:29 +01:00
Atgeirr Flø Rasmussen
2df9779a62 Merge pull request #544 from joakim-hove/parser-error-msg
Add a better error message for parse errors
2018-11-02 07:59:25 +01:00
Joakim Hove
60fb68d3fc Add a better error message for parse errors 2018-11-01 20:59:49 +01:00
Joakim Hove
ae9d5e97c7 Merge pull request #541 from lars-petter-hauge/include_wpimult_ctfac
Include WPIMULT for CTFAC output
2018-10-29 11:29:38 +01:00
Lars Petter Øren Hauge
d958da6542 Include WPIMULT for CTFAC output 2018-10-29 09:12:50 +01:00
Joakim Hove
b8c5d8c129 Add whitelist of keywords allowed in ACTIONX block 2018-10-27 15:59:32 +02:00
Joakim Hove
e7660b0613 White space change 2018-10-27 15:59:32 +02:00
Joakim Hove
7ebadbb055 Merge pull request #535 from blattms/support-editnnc
Added support for honoring keyword EDITNNC during deck parsing.
2018-10-25 15:49:06 +02:00
Joakim Hove
0f485c7801 Merge pull request #514 from bska/segment-summary
Serialization: Add Initial Support for Segment Information
2018-10-25 15:19:22 +02:00
Markus Blatt
a6ec18cd4e Use an approach for processing nncs without lambda. 2018-10-25 09:13:35 +02:00
Bård Skaflestad
af8f8c6bfd Segment Summary Vectors: Use Explict Keyword Whitelisting
We only support a small subset of segment-related summary vectors
and must avoid being tricked by other SUMMARY section keywords that
happen to begin with a character 'S' (e.g., SUMMARY itself or the
SUMTHIN keyword).  Add an explicit white-list of the vectors we do
support and bypass all others in helper function 'keywordS()'.

Introduce a dummy 'SUMTHIN' specification to SOFR_TEST.DATA to
ensure that we don't accidentally match this in 'keywordS()'.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
258bcbc186 Restart_Segment/Vectors_Present: Include SOFR Existence
We were checking "SGFR" twice due to copy-paste...

Pointy Hat: bska
2018-10-25 09:09:32 +02:00
Bård Skaflestad
2260efaad9 RSEG: Alert Reader that 'stringSegNum' is 1 .. #Segments Inclusive
Suggested by: [at]joakim-hove
2018-10-25 09:09:32 +02:00
Bård Skaflestad
624dec542a {I,R}SEG: Don't Copy Segment or Connection Sets
We only read from these objects so they can be reference-to-const.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
7ca8b46167 SummaryConfig: Consider All Timesteps for MS Well Predicate
This commit extends the logic of determining which wells to consider
as multi-segmented to scanning all declared report steps.  We also
use a similar protocol to determine the maximum number of segments
for an MS well across all declared report steps.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
8fbb93497a Summary: Include <map> in Public Interface
Needed to honour requirements of class Summary in isolation.  While
here, also move <unordered_map> to implementation file.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
ef5465dcfc MSWData/RSEG: Use SummaryState Values Directly
Segment flow rates and pressures retrieved from a SummaryState
object do not need additional processing steps.  The SummaryState
protocol guarantees that the quantities are already stored according
to their proper output unit conventions and abide by the flow rate
sign requirements of the summary/restart files (production
flows--from reservoir to well--treated as positive).

Remove the pertinent processing from RSeg::staticContrib().
2018-10-25 09:09:32 +02:00
Bård Skaflestad
f9eb32a235 Segment Summary: Test Read/Write Support
This commit completes the set of unit tests for the segment-related
summary vectors

    SOFR, SGFR, SWFR, and SPR

by adding a test (Restart_Segment/Write_Read) that serializes the
result of multiple Summary::add_timestep() calls for SOFR_TEST.DATA
and reads that summary file back in.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
f275fd6089 Summary: Transmit Segment Values to "prev_state"
This commit makes the helper function find_wells() aware of summary
vectors defined on segments.  Previously, this helper function would
return an empty list of wells in the case of ECL_SMSPEC_SEGMENT_VAR
whence all segment-related summary vectors would be zero at all
times.

Add a small set of unit tests to verify that we transmit the known
(small) set of segment-related summary vectors (SOFR, SGFR, SWFR,
SPR) to the internal "prev_state" with correct output units and sign
convention (producing flow rates--reservoir to well--positive).
2018-10-25 09:09:32 +02:00
Bård Skaflestad
decd0b10a9 SummaryConfig: Expand Segment Vector Record Processing
This commit extends the processing of segment-related summary
vectors to also support specifications of the form

    SOFR
    /

designating all segments of all multi-segmented wells at all times.

Expand SummaryConfig unit test to exercise this extended record
processing mode.
2018-10-25 09:09:32 +02:00
Bård Skaflestad
10c9da1a36 Summary: Guarantee Existence of Segment-Related Restart Vectors
This commit extends the set of summary vectors needed for restart to
include those needed for RSEG[8 .. 11] in the case of
multi-segmented wells.
2018-10-25 09:09:31 +02:00
Bård Skaflestad
47141dfabf data::Wells: Remove a few blank lines
Suggested by: [at]joakim-hove
2018-10-25 09:09:31 +02:00
Jostein Alvestad
613aafe4ae Changes in AggregateMSW data to write segment data to restart file
Changes in RestartIO to avoid writing of well and MSW data when wells not present
2018-10-25 09:09:31 +02:00
Bård Skaflestad
f867d7f82c SummaryConfig: Recognise Subset of Segment Vectors
This commit extends the SummaryConfig class to recognise a small
subset of segment-related summary vectors.  In particular, this
brings support for 'SGFR', 'SOFR', 'SPR', and 'SWFR'--at least in a
restricted sense.  We do not yet support cases like

    SOFR
    /

which designates all segments in all wells at all times.

The unit testing is presently minimal and must be expanded before
this is ready for inclusion into master.  In particular, we only
check that cases like

    SOFR
      'PROD01' 1 /
    /

generate the expected summary vector nodes (class SummaryNode).
2018-10-25 09:09:31 +02:00
Jostein Alvestad
fe060c7f48 Changes to contribute to write segment data to summary file 2018-10-25 09:09:31 +02:00
Bård Skaflestad
80154e8f5f Serialization: Add Initial Support for Segment Information
This commit extends Opm::data::Wells to include a set of output
vectors for well segment information.  At present we define output
structures for segment rates and segment pressures.  The immediate
use case is properly assigning restart vector items RSEG[8 .. 11],
but these same values are also usable for outputting the summary
vectors SPR, SOFR, SGFR, and SWFR.  Future expansion is likely.
2018-10-25 09:09:31 +02:00
Joakim Hove
ae0cb3e5ad Merge pull request #528 from totto82/minpvv
Add support for minpvv
2018-10-25 09:04:32 +02:00
Joakim Hove
133f89198f Merge pull request #507 from WesselDeZeeuw/aquifet
Aquifet parser implementation
2018-10-25 09:01:29 +02:00
Markus Blatt
03bb4da004 Added warning about ignored EDITNNC entries 2018-10-25 08:04:38 +02:00
Joakim Hove
e356a16ab2 Merge pull request #462 from joakim-hove/tranx-modifier
Add deckAssigned() method to GridProperty + default construct TRAN
2018-10-24 10:36:19 +02:00
Joakim Hove
eea23abedd Merge pull request #533 from joakim-hove/GDFILE-location
Update GDFILE hadling to parse DATA outside cwd
2018-10-22 13:45:27 +02:00
Markus Blatt
5f620f7451 Added support for honoring keyword EDITNNC during deck parsing.
If the keyword is present then the transimissibilities of the corresponding NNC
entries will be scalled with the factor specified via EDITNNC. Multiple entries
for the same cell pairs are allowed and will result in multiple scalings.
Cell pairs specified in EDITNNC that are not present in NNC are silently ignored.
2018-10-18 15:26:31 +02:00
Joakim Hove
c76ee877aa Update GDFILE handling to account for out-of-cwd
Make sure path to GDFILE is correct
2018-10-18 10:47:38 +02:00
Joakim Hove
fd36bf88fb Add function Deck::makeDeckPath() 2018-10-18 10:47:37 +02:00
Joakim Hove
24bd410313 Merge pull request #521 from joakim-hove/input-sim
Add skeleton for input simulator
2018-10-17 17:28:25 +02:00
Joakim Hove
984a308e24 Add skeleton for mock simulator 2018-10-17 17:21:11 +02:00
Joakim Hove
6ea7a1796d Merge pull request #530 from joakim-hove/GDFILE
Gdfile
2018-10-17 15:01:57 +02:00
Joakim Hove
ee0d256a12 Add method seconds() to Schedule and TimeMap 2018-10-17 12:09:45 +02:00
Joakim Hove
42d7587e1b Add size() method to the Schedule class 2018-10-17 06:47:57 +02:00
Joakim Hove
c75a50796b White space change 2018-10-16 00:21:49 +02:00
Joakim Hove
1190260d7d Add support for GDFILE keyword 2018-10-16 00:21:35 +02:00
Joakim Hove
5b8882d6f0 Add methods save() and addNNC() to EclipseGrid 2018-10-16 00:20:09 +02:00
Joakim Hove
f8e711246f GridDims class can initialize from binary file 2018-10-16 00:14:33 +02:00
Joakim Hove
5283611695 Add static method for conversion between unit system enums 2018-10-16 00:12:53 +02:00
Tor Harald Sandve
ca8e2f279b Add support for minpvv 2018-10-15 13:35:04 +02:00
Joakim Hove
c49b51ab23 Add test to prevent using ADD on TRANX 2018-10-15 10:50:58 +02:00
Joakim Hove
7c65850894 Merge pull request #525 from joakim-hove/find-alberta-fixup
Fixed ALBERTA_FOUND to OFF when not found
2018-10-15 10:44:29 +02:00
Joakim Hove
7279fd5ea8 Add deckAssigned() method to GridProperty + default construct TRAN
The deckAssigned() query method is added to the GridProperty class to enable the
simulator to check whether a property has been explicitly assigned in the deck
or autocreated through the use of some EDIT operators like MULTIPLY.
2018-10-15 10:29:01 +02:00
Joakim Hove
f279c7e374 Fixed ALBERTA_FOUND to OFF when not found 2018-10-15 09:42:13 +02:00
WesselZ
7b1595d0b2 Modification of the Aquifetp header and class files for the handling the default value of p0.
Small Changes to unit test of Aquifetp
2018-10-15 09:28:39 +02:00
Joakim Hove
8c8290f614 Merge pull request #505 from blattms/fix-alberta-linker-issues
Also search for Alberta (Fixes ebos compile issue with g++-8.2)
2018-10-11 16:32:44 +02:00
WesselZ
3819910396 Modification of AquifetpTests.cpp -- 100% test passing
Added nempty Aquifetp container -- Null object -- No parsing, succesfull
2018-10-10 12:00:15 +02:00
Joakim Hove
72b39e513a Merge pull request #515 from joakim-hove/parsecontext-ignore-kw
Ability to ignore named keywords in ParseContext
2018-10-09 17:06:33 +02:00
WesselZ
04a9e710d5 Added Improved Header Files and Class files, without the ecl dependency.
Added Testfile for fetkovich implementation
2018-10-09 16:42:39 +02:00
Bård Skaflestad
1c771a66fc Merge pull request #516 from atgeirr/fix-const-map-types
Use non-const string type in map.
2018-10-08 18:32:30 +02:00
Joakim Hove
c938765224 Ability to ignore named keywords in ParseContext 2018-10-08 18:07:21 +02:00
Atgeirr Flø Rasmussen
a37625b2cf Use non-const string type in map.
Using const string as key type instead of plain string fails with libc++,
the standard library implementation used by clang. The libc++ implementation
assumes that map keys can be copied, and the standard requires map keys to be
copyable.

Using const string as a value also fails with clang, I am not 100% sure why.
It does severely restrict how you can interact with the container, and seems to
make it noncopyable. The error is reported from DynamicState<GroupTree>::update(),
the std::fill() call.
2018-10-08 11:02:22 +02:00
Joakim Hove
83331033b5 Merge pull request #511 from bska/wellconnections-ctor
WellConnections: Initialise Head in Copy Constructor
2018-10-02 21:02:53 +02:00
Bård Skaflestad
58a5a4e371 WellConnections: Initialise Head in Copy Constructor
This commit ensures that the data members 'headI' and 'headJ' are
properly initialised in the constructor

    WellConnections(const WellConnections&, const EclipseGrid&)

which powers the implementation of

    Well::getActiveConnections()
2018-10-02 15:59:04 +02:00
Joakim Hove
3655213c40 Merge pull request #513 from joakim-hove/bump-versions-master
Bump versions
2018-10-02 15:50:50 +02:00
Joakim Hove
2844aa4468 Bump versions 2018-10-02 15:43:01 +02:00
Joakim Hove
c81e5027c9 Merge pull request #510 from bska/difftime
TimeMap: Use difftime() for Time Deltas as double
2018-10-02 14:44:44 +02:00
Bård Skaflestad
23950403f1 TimeMap: Use difftime() for Time Deltas as double
Reduces the amount of explicit arithmetic on std::time_t values and
thereby, implicitly, the assumption of targeting Posix systems only.
2018-10-02 13:11:02 +02:00
Bård Skaflestad
33372a3337 Merge pull request #506 from jalvestad/flow-flow-restart
EclipseRestart-improvements
2018-10-02 13:05:43 +02:00
Jostein Alvestad
c067e48276 Additional improvement and correction for writing of eclipse compatible restart file 2018-09-28 15:39:25 +02:00
Jostein Alvestad
5d398565c2 Improved the code structure - current improvement 2018-09-28 11:23:42 +02:00
Jostein Alvestad
a9a82e3814 Minor correction to previous commit rseg [39] was not properly assigned 2018-09-28 09:56:03 +02:00
Jostein Alvestad
3f94b580a2 Added changes to improve treatment of multi segment wells in Eclipse Restart
Added flowing well bottom hole pressure to item[8] and [39] plus adjusted item[9]
2018-09-28 09:48:03 +02:00
Jostein Alvestad
cfc1b29c08 Added improvements and corrections to handle writing of eclipse compatible restart file
for more general well data
2018-09-27 16:23:34 +02:00
Jostein Alvestad
264d451d56 Added additional changes to handle repeated read of COMPDAT
for same grid i,j,k cell.
Corrections for handling wells with only 1 connection
Correction for XWEL - BG being NaN
2018-09-27 16:23:32 +02:00
Jostein Alvestad
21eddfbdf2 Added changes to handle repeated read of COMPDAT for same grid cells 2018-09-27 16:23:31 +02:00
Markus Blatt
22b38f1031 Also search for Alberta
We do not use it in OPM, but for whatever reason I was experiencing
linker errors (unresolved symbol) when compiling ebos with DUNE 2.6
and g++-8.2. dune-grid exports its alberta wrapper libraries in dune-grid_LIBRARIES. Previously this did not pose a problem. Somehow it does now. If
I strip the libraries from the linker line everything is fine but this
is not a good solution.

Therefore I have added a test for Alberta that is triggered by the test of
dune-grid.
2018-09-27 15:05:04 +02:00
271 changed files with 12932 additions and 2706 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -49,6 +49,7 @@ list(APPEND EXTRA_TESTS EclipseStateTests)
foreach (test BoxTest
CheckDeckValidity
EclipseGridCreateFromDeck
EDITNNCTests
IncludeTest
IntegrationTests
IOConfigIntegrationTest

View File

@@ -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

View 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()

View File

@@ -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")

View File

@@ -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
View File

@@ -1,4 +1,4 @@
opm-common (2015.10-1~trusty) trusty; urgency=medium
opm-common (2019.04-pre~xenial) xenial; urgency=medium
* New release

View File

@@ -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
View 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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View 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
View 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;
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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
{

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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();

View File

@@ -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,

View File

@@ -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;
};

View 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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View 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

View File

@@ -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 ,

View File

@@ -65,6 +65,7 @@ namespace Opm {
private:
void init(const DeckKeyword& keyword);
void binary_init(const Deck& deck);
};
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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&,

View File

@@ -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& );

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};
}

View 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

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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;
};
}

View File

@@ -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

View File

@@ -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,

View File

@@ -230,8 +230,7 @@ namespace Opm {
enum OilVaporizationEnum{
UNDEF = 0,
VAPPARS = 1,
DRSDT = 2,
DRVDT = 3
DRDT = 2 // DRSDT or DRVDT
};

View 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

View File

@@ -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;

View File

@@ -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;
};
}

View File

@@ -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;
};
}

View 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;
};
}

View 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;
};
}

View File

@@ -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;

View File

@@ -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;
};
}

View File

@@ -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& );

View File

@@ -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;

View File

@@ -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& );

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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);
/*

View 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

View 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

View 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

View 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

View File

@@ -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;

View File

@@ -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;

View 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

View File

@@ -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
};
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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);
}
});
}

View File

@@ -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();
});
}

View File

@@ -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);
});
}

View File

@@ -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];

View File

@@ -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();

View File

@@ -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();

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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");
}
}

View File

@@ -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();
}
}

View File

@@ -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);
});

View File

@@ -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