opm-common
Loading...
Searching...
No Matches
ParseContext.hpp
1/*
2 Copyright 2015 Statoil ASA.
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20
21#ifndef OPM_PARSE_CONTEXT_HPP
22#define OPM_PARSE_CONTEXT_HPP
23
24#include <map>
25#include <optional>
26#include <set>
27#include <string>
28#include <vector>
29
30namespace Opm {
31
32enum class InputErrorAction;
33class KeywordLocation;
34
35
36 /*
37 The ParseContext class is meant to control the behavior of the
38 parsing and EclipseState construction phase when
39 errors/inconsistencies/... are encountered in the input.
40
41 For each of the possible problems encountered the possible
42 actions are goverened by the InputError::Action enum:
43
44 InputError::THROW_EXCEPTION
45 InputError::EXIT1
46 InputError::WARN
47 InputError::IGNORE
48
49 The internal datastructure is a map between string keys and
50 enum InputError::Action values. The string keys are meant to be
51 descriptive like:
52
53 "PARSE_RANDOMTEXT"
54
55
56 The constructor will consult the env variable
57 OPM_ERRORS_IGNORE, OPM_ERRORS_WARN and OPM_ERRORS_EXCEPTION
58 when initializing. The variables should be set as strings of
59 update syntax.
60
61 update_syntax: The main function for updating the policy of a
62 parseContext instance is the update() method. That takes a string
63 as input, and updates the matching flags. The string can
64 contain wildcards ('* and '?' mathced with fnmatch()) and is
65 split on ':' or '|' to allow multiple settings to be applied in
66 one go:
67
68 Just set one variable:
69 update("PARSE_RANDOM_SLASH" , InputError::IGNORE)
70
71 Ignore all unsupported features:
72 update("UNSUPPORTED_*" , InputError::IGNORE)
73
74 Set two variables:
75 update("UNSUPPORTED_INIITIAL_THPRES:PARSE_RANDOM_SLASH" , InputError::IGNORE)
76
77 The update function itself is quite tolerant, and will silently
78 ignore unknown keys. If you use the updateKey() function only
79 recognizd keys will be allowed.
80 */
81
82 class ErrorGuard;
83
84 class ParseContext {
85 public:
86 ParseContext();
87 explicit ParseContext(InputErrorAction default_action);
88 explicit ParseContext(const std::vector<std::pair<std::string , InputErrorAction>>& initial);
89
90 void handleError( const std::string& errorKey, const std::string& msg, const std::optional<KeywordLocation>& location, ErrorGuard& errors) const;
91 void handleUnknownKeyword(const std::string& keyword, const std::optional<KeywordLocation>& location, ErrorGuard& errors) const;
92 bool hasKey(const std::string& key) const;
93 ParseContext withKey(const std::string& key, InputErrorAction action) const;
94 ParseContext& withKey(const std::string& key, InputErrorAction action);
95 void updateKey(const std::string& key , InputErrorAction action);
96 void update(InputErrorAction action);
97 void update(const std::string& keyString , InputErrorAction action);
98 void ignoreKeyword(const std::string& keyword);
99 InputErrorAction get(const std::string& key) const;
100 std::map<std::string,InputErrorAction>::const_iterator begin() const;
101 std::map<std::string,InputErrorAction>::const_iterator end() const;
102 /*
103 When the key is added it is inserted in 'strict mode',
104 i.e. with the value 'InputError::THROW_EXCEPTION. If you
105 want a different value you must subsequently call the update
106 method.
107 */
108 void addKey(const std::string& key, InputErrorAction default_action);
109 /*
110 The PARSE_EXTRA_RECORDS field regulates how the parser
111 responds to keywords whose size has been defined in the
112 previous keyword.
113 Example:
114 EQLDIMS
115 2 100 20 1 1 /
116 EQUIL\n
117 2469 382.4 1705.0 0.0 500 0.0 1 1 20 /
118 2469 382.4 1705.0 0.0 500 0.0 1 1 20 /
119 2470 382.4 1705.0 0.0 500 0.0 1 1 20 /
120 EQLDIMS's first entry is 2 and defines the record size of the
121 EQUIL keyword. Since there are 3 records in EQUIL, this results
122 in an error that needs to be handled by the parser. By default,
123 an exception is thrown, or it may be specified in the
124 PARSE_EXTRA_RECORDS field that this error is to be ignored.
125 */
126 const static std::string PARSE_EXTRA_RECORDS;
127 /*
128 The unknownKeyword field regulates how the parser should
129 react when it encounters an unknwon keyword. Observe that
130 'keyword' in this context means:
131
132 o A string of 8 characters or less - starting in column
133 0.
134
135 o A string consisiting of UPPERCASE characters and
136 numerals, staring with an UPPERCASE character [Hmmm -
137 actually lowercase is also accepted?!]
138
139 Observe that unknownKeyword does *not* consult any global
140 collection of keywords to see if a particular string
141 corresponds to a known valid keyword which we just happen
142 to ignore for this particualar parse operation.
143
144 The 'unknownkeyword' and 'randomText' error situations are
145 not fully orthogonal, and in particualar if a unknown
146 keyword has been encountered - without halting the parser, a
147 subsequent piece of 'random text' might not be identified
148 correctly as such.
149 */
150 const static std::string PARSE_UNKNOWN_KEYWORD;
151
152 /*
153 With random text we mean a string in the input deck is not
154 correctly formatted as a keyword heading.
155 */
156 const static std::string PARSE_RANDOM_TEXT;
157
158 /*
159 It turns out that random '/' - i.e. typically an extra slash
160 which is not needed - is quite common. This is therefor a
161 special case treatment of the 'randomText' behaviour.
162 */
163 const static std::string PARSE_RANDOM_SLASH;
164
165
166 /*
167 For some keywords the number of records (i.e. size) is given
168 as an item in another keyword. A typical example is the
169 EQUIL keyword where the number of records is given by the
170 NTEQUL item of the EQLDIMS keyword. If the size defining
171 XXXDIMS keyword is not in the deck, we can use the default
172 values of the XXXDIMS keyword; this is regulated by the
173 'missingDIMskeyword' field.
174
175 Observe that a fully defaulted XXXDIMS keyword does not
176 trigger this behavior.
177 */
178 const static std::string PARSE_MISSING_DIMS_KEYWORD;
179
180 /*
181 If the number of elements in the input record exceeds the
182 number of items in the keyword configuration this error
183 situation will be triggered. Many keywords end with several
184 ECLIPSE300 only items - in some cases we have omitted those
185 items in the Json configuration; that will typically trigger
186 this error situation when encountering an ECLIPSE300 deck.
187 */
188 const static std::string PARSE_EXTRA_DATA;
189
190 /*
191 If an include file is not found we can configure the parser
192 to contine reading; of course the resulting deck can
193 obviously be quite broken.
194 */
195 const static std::string PARSE_MISSING_INCLUDE;
196
197 /*
198 For certain keywords, other, specific keywords are either
199 required or prohibited. When such keywords are found in an
200 invalid combination (missing required or present prohibited
201 keyword), this error situation occurs.
202 */
203 const static std::string PARSE_INVALID_KEYWORD_COMBINATION;
204
207 const static std::string RUNSPEC_NUMWELLS_TOO_LARGE;
208
211 const static std::string RUNSPEC_CONNS_PER_WELL_TOO_LARGE;
212
215 const static std::string RUNSPEC_NUMGROUPS_TOO_LARGE;
216
219 const static std::string RUNSPEC_GROUPSIZE_TOO_LARGE;
220
223 const static std::string RUNSPEC_NUMMSW_TOO_LARGE;
224
227 const static std::string RUNSPEC_NUMSEG_PER_WELL_TOO_LARGE;
228
231 const static std::string RUNSPEC_NUMBRANCH_TOO_LARGE;
232
233 /*
234 Should we allow keywords of length more than eight characters? If the
235 keyword is too long it will be internalized using only the eight first
236 characters.
237 */
238 const static std::string PARSE_LONG_KEYWORD;
239
240 /*
241 The unit system specified via the FILEUNIT keyword is different from the unit
242 system used by the deck.
243 */
244 const static std::string UNIT_SYSTEM_MISMATCH;
245
246
247 /*
248 If the third item in the THPRES keyword is defaulted the
249 threshold pressure is inferred from the initial pressure;
250 this currently not supported.
251 */
252 const static std::string UNSUPPORTED_INITIAL_THPRES;
253
254 /*
255 If the second item in the WHISTCTL keyword is set to YES
256 The simulator is supposed to terminate if the well is
257 changed to BHP control. This feature is not yet supported.
258 */
259 const static std::string UNSUPPORTED_TERMINATE_IF_BHP;
260
261 const static std::string UDQ_PARSE_ERROR;
262 const static std::string UDQ_TYPE_ERROR;
263
266 const static std::string UDQ_DEFINE_CANNOT_EVAL;
267
268 /*
269 If the third item in the THPRES keyword is defaulted the
270 threshold pressure is inferred from the initial pressure -
271 if you still ask the ThresholdPressure instance for a
272 pressure value this error will be signalled. this currently
273 not supported.
274 */
275 const static std::string INTERNAL_ERROR_UNINITIALIZED_THPRES;
276
277 /*
278 If the deck is partial deck, and thus a full EclipseState is
279 meaningless, we can still construct a slim EclipseGrid.
280 */
281 const static std::string PARSE_MISSING_SECTIONS;
282
283 /*
284 When defining wells and groups with the WELSPECS and GRUPTREE keywords
285 we do not allow leading or trailing spaces. The code in Schedule.cpp
286 will *unconditionally* remove the spaces, but with PARSE_WGNAME_SPACE
287 setting you can additionally configure the normal IGNORE|WARN|ERROR
288 behavior.
289 */
290 const static std::string PARSE_WGNAME_SPACE;
291
292 /*
293 If you have configured a specific well in the summary section,
294 which is not recognized - how to handle.
295 */
296 const static std::string SUMMARY_UNKNOWN_WELL;
297 const static std::string SUMMARY_UNKNOWN_GROUP;
298 const static std::string SUMMARY_UNKNOWN_NODE;
299 const static std::string SUMMARY_UNKNOWN_AQUIFER;
300 const static std::string SUMMARY_UNHANDLED_KEYWORD;
301 const static std::string SUMMARY_UNDEFINED_UDQ;
302 const static std::string SUMMARY_UDQ_MISSING_UNIT;
303 const static std::string SUMMARY_INVALID_FIPNUM;
304 const static std::string SUMMARY_EMPTY_REGION;
305 const static std::string SUMMARY_REGION_TOO_LARGE;
306 /*
307 A well must be specified (e.g. WELSPECS) and have completions
308 (e.g. COMPDAT) to be able to set control mode (e.g. WCONPROD).
309 A well missing specification and/or completion(s) will throw.
310 */
311 const static std::string SCHEDULE_INVALID_NAME;
312
313
314 /*
315 Only keywords explicitly white-listed can be included in the ACTIONX
316 or PYACTION block. These error flags controls what should happen when
317 an illegal keyword is encountered in an ACTIONX and a PYACTION block.
318 */
319 const static std::string ACTIONX_ILLEGAL_KEYWORD;
320 const static std::string PYACTION_ILLEGAL_KEYWORD;
321
322 /*
323 Error flag marking parser errors ic ACTIONX conditions
324 */
325 const static std::string ACTIONX_CONDITION_ERROR;
326 /*
327 Error flag marking that an ACTIONX has no condition
328 */
329 const static std::string ACTIONX_NO_CONDITION;
330
331 /*
332 The RPTSCH, RPTSOL and RPTSCHED keywords have two alternative forms,
333 in the old style all the items are set as integers, i.e. the RPTRST
334 keyword can be configured as:
335
336 RPTRST
337 0 0 0 1 0 1 0 2 0 0 0 0 0 1 0 0 2/
338
339 The new way is based on string mneomnics which can optionally have an
340 integer value, i.e something like:
341
342 RPTRST
343 BASIC=2 FLOWS ALLPROS /
344
345 It is strictly illegal to mix the two ways to configure keywords. A
346 situation with mixed input style is identified if any of the items are
347 integers. To avoid that the values in the assignments like BASIC=2 are
348 interpreted as integers it is essential that there are no spaces
349 around the '=', and that is also documented in the manual. However -
350 it turns out that Eclipse actually handles e.g.
351
352 RPTRST
353 BASIC = 2 /
354
355 So we have introduced a error mode RPT_MIXED_STYLE which tries to
356 handle this situation. Observe that really mixed input style is
357 impossible to handle, and will lead to a hard exception, but with the
358 RPT_MIXED_STYLE error mode it is possible to configure lenient
359 behavior towards interpreting the input as new style string mneomnics.
360 */
361 const static std::string RPT_MIXED_STYLE;
362
363 const static std::string RPT_UNKNOWN_MNEMONIC;
364
365 const static std::string SCHEDULE_GROUP_ERROR;
366 const static std::string SCHEDULE_IGNORED_GUIDE_RATE;
367 const static std::string SCHEDULE_WELL_IN_FIELD_GROUP;
368
369 const static std::string SCHEDULE_COMPSEGS_INVALID;
370 const static std::string SCHEDULE_COMPSEGS_NOT_SUPPORTED;
371
372 const static std::string SCHEDULE_COMPDAT_INVALID;
373 /*
374 The SIMULATOR_KEYWORD_ errormodes are for the situation where the
375 parser recognizes, and correctly parses a keyword, but we know that
376 the simulator does not support the intended use of the keyword. These
377 errormodes are invoked from the simulator.
378 */
379 const static std::string SIMULATOR_KEYWORD_NOT_SUPPORTED;
380 const static std::string SIMULATOR_KEYWORD_NOT_SUPPORTED_CRITICAL;
381 const static std::string SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED;
382 const static std::string SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED_CRITICAL;
383
384 void setInputSkipMode(const std::string& skip_mode);
385 bool isActiveSkipKeyword(const std::string& deck_name) const;
386
387 private:
388 void initDefault();
389 void initEnv();
390 void envUpdate( const std::string& envVariable , InputErrorAction action );
391 void patternUpdate( const std::string& pattern , InputErrorAction action);
392
393 std::map<std::string , InputErrorAction> m_errorContexts;
394 std::set<std::string> ignore_keywords;
395 std::string m_input_skip_mode{"100"};
396 };
397}
398
399
400#endif
Definition ErrorGuard.hpp:30
Definition KeywordLocation.hpp:27
static const std::string RUNSPEC_NUMMSW_TOO_LARGE
Dynamic number of multi-segmented wells exceeds maximum declared in RUNSPEC keyword WSEGDIMS (item 1)...
Definition ParseContext.hpp:223
static const std::string UDQ_DEFINE_CANNOT_EVAL
Cannot evaluate the defining expression of a UDQ at the point of definition due to missing objects,...
Definition ParseContext.hpp:266
static const std::string RUNSPEC_NUMWELLS_TOO_LARGE
Dynamic number of wells exceeds maximum declared in RUNSPEC keyword WELLDIMS (item 1).
Definition ParseContext.hpp:207
static const std::string RUNSPEC_CONNS_PER_WELL_TOO_LARGE
Dynamic number of connections per well exceeds maximum declared in RUNSPEC keyword WELLDIMS (item 2).
Definition ParseContext.hpp:211
static const std::string RUNSPEC_NUMBRANCH_TOO_LARGE
Dynamic number of branches exceeds maximum number declared in RUNSPEC keyword WSEGDIMS (item 3).
Definition ParseContext.hpp:231
static const std::string RUNSPEC_GROUPSIZE_TOO_LARGE
Dynamic group size exceeds maximum number declared in RUNSPEC keyword WELLDIMS (item 4).
Definition ParseContext.hpp:219
static const std::string RUNSPEC_NUMGROUPS_TOO_LARGE
Dynamic number of groups exceeds maximum number declared in RUNSPEC keyword WELLDIMS (item 3).
Definition ParseContext.hpp:215
static const std::string RUNSPEC_NUMSEG_PER_WELL_TOO_LARGE
Dynamic number of segments per MS well exceeds maximum declared in RUNSPEC keyword WSEGDIMS (item 2).
Definition ParseContext.hpp:227
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30