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