diff --git a/dev/.documenter-siteinfo.json b/dev/.documenter-siteinfo.json index 269933b..f700a34 100644 --- a/dev/.documenter-siteinfo.json +++ b/dev/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-28T07:38:49","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-06T16:59:51","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/dev/index.html b/dev/index.html index aa619b7..352ac85 100644 --- a/dev/index.html +++ b/dev/index.html @@ -1,7 +1,7 @@ Home · GeoEnergyIO.jl

GeoEnergyIO

Documentation for GeoEnergyIO.

Parsing of simulation cases

The main feature of this module is at the time of writing a parser for .DATA reservoir simulation cases. The format originated with the Eclipse reservoir simulator produced by SLB and is now used by many reservoir simulators. The most useful publicly available description of one such dialect is found in the OPM Flow manual.

GeoEnergyIO.InputParser.parse_data_fileFunction
parse_data_file(filename; units = :si)
 parse_data_file(filename; units = :field)
-data = parse_data_file("MY_MODEL.DATA")

Parse a .DATA file given by the path in filename (industry standard input file) into a Dict with String keys. Units will be converted to strict SI unless you pass an alternative unit system like units = :field. Setting units = nothing will skip unit conversion. Note that the simulators in JutulDarcy.jl assumes that the unit system is internally consistent. It is highly recommended to parse to the SI units if you want to perform simulations with JutulDarcy.jl.

The best publicly available documentation on this format is available from the Open Porous Media (OPM) project's webpages: OPM Flow manual .

Keyword arguments

  • warn_parsing=true: Produce a warning when keywords are not supported (or partially supported) by the parser.
  • warn_feature=true: Produce a warning when keywords are supported, but have limited or missing support in the numerical solvers in JutulDarcy.jl.
  • units=:si: Symbol that indicates the unit system to be used in the output. Setting this to nothing will return values without conversion, i.e. exactly what is in the input files. :si will use strict SI. Other alternatives are :field and :metric. :lab is currently unsupported.
  • verbose=false: Produce verbose output about parsing progress. For larger files, a lot of output will be generated. Useful when figuring out where a parser fails or spends a lot of time.

Note

This function only covers a small portion of the keywords that exist for various simulators. You will get warnings that indicate the level of support for keywords in both the parser and the numerical solvers when known keywords with limited support. Pull requests for new keywords are welcome!

The SUMMARY section is skipped due to the large volume of available keywords that are not essential to define simulation cases.

source

Let us for example parse the SPE1 dataset, turning into a nested Dict containing all the entries of the data file. We use the unexported test_input_file_path utility to get the path of a test file.

using GeoEnergyIO
+data = parse_data_file("MY_MODEL.DATA")

Parse a .DATA file given by the path in filename (industry standard input file) into a Dict with String keys. Units will be converted to strict SI unless you pass an alternative unit system like units = :field. Setting units = nothing will skip unit conversion. Note that the simulators in JutulDarcy.jl assumes that the unit system is internally consistent. It is highly recommended to parse to the SI units if you want to perform simulations with JutulDarcy.jl.

The best publicly available documentation on this format is available from the Open Porous Media (OPM) project's webpages: OPM Flow manual .

Keyword arguments

  • warn_parsing=true: Produce a warning when keywords are not supported (or partially supported) by the parser.
  • warn_feature=true: Produce a warning when keywords are supported, but have limited or missing support in the numerical solvers in JutulDarcy.jl.
  • units=:si: Symbol that indicates the unit system to be used in the output. Setting this to nothing will return values without conversion, i.e. exactly what is in the input files. :si will use strict SI. Other alternatives are :field and :metric. :lab is currently unsupported.
  • verbose=false: Produce verbose output about parsing progress. For larger files, a lot of output will be generated. Useful when figuring out where a parser fails or spends a lot of time.

Note

This function only covers a small portion of the keywords that exist for various simulators. You will get warnings that indicate the level of support for keywords in both the parser and the numerical solvers when known keywords with limited support. Pull requests for new keywords are welcome!

The SUMMARY section is skipped due to the large volume of available keywords that are not essential to define simulation cases.

source

Let us for example parse the SPE1 dataset, turning into a nested Dict containing all the entries of the data file. We use the unexported test_input_file_path utility to get the path of a test file.

using GeoEnergyIO
 spe1_pth = GeoEnergyIO.test_input_file_path("SPE1", "SPE1.DATA")
 spe1 = parse_data_file(spe1_pth)
Dict{String, Any} with 6 entries:
   "RUNSPEC"  => OrderedDict{String, Any}("TITLE"=>"SPE1 - CASE 2", "DIMENS"=>[1…
@@ -9,7 +9,7 @@
   "PROPS"    => OrderedDict{String, Any}("PVTW"=>Any[[2.77e7, 1.038, 4.67022e-1…
   "SUMMARY"  => OrderedDict{String, Any}()
   "SCHEDULE" => Dict{String, Any}("STEPS"=>OrderedDict{String, Any}[OrderedDict…
-  "SOLUTION" => OrderedDict{String, Any}("EQUIL"=>Any[[2560.32, 3.30948e7, 2575…

Handling unsupported keywords

Not all keywords are supported by the parser, but not all keywords are important. The input format is such that it is difficult to automatically skip keywords, but you an manually add keywords to the skip list:

GeoEnergyIO.InputParser.skip_kw!Function
skip_kw!(kw, num, msg = nothing)

Add a keyword to list of records that will be skipped on parsing.

kw is the symbol (usually capitalized) of the keyword to skip, num is the number of expected records:

  • 0 means that the keyword to skip has no data (for example "WATER" with no data to follow)
  • 1 means that the keyword has a single record terminated by /
  • Any other number means a fixed number of lines, without termination by empty record.
  • Inf means that the keyword has any number of records, terminated by a record without entries.
source

Adding keywords to the skip list is not persistent across Julia sessions and can be added to the top of your script. Contributions to the global skip list defined in the __init__ function of the parser are welcome.

using GeoEnergyIO
+  "SOLUTION" => OrderedDict{String, Any}("EQUIL"=>Any[[2560.32, 3.30948e7, 2575…

Handling unsupported keywords

Not all keywords are supported by the parser, but not all keywords are important. The input format is such that it is difficult to automatically skip keywords, but you an manually add keywords to the skip list:

GeoEnergyIO.InputParser.skip_kw!Function
skip_kw!(kw, num, msg = nothing)

Add a keyword to list of records that will be skipped on parsing.

kw is the symbol (usually capitalized) of the keyword to skip, num is the number of expected records:

  • 0 means that the keyword to skip has no data (for example "WATER" with no data to follow)
  • 1 means that the keyword has a single record terminated by /
  • Any other number means a fixed number of lines, without termination by empty record.
  • Inf means that the keyword has any number of records, terminated by a record without entries.
source

Adding keywords to the skip list is not persistent across Julia sessions and can be added to the top of your script. Contributions to the global skip list defined in the __init__ function of the parser are welcome.

using GeoEnergyIO
 # Skip keyword without data
 GeoEnergyIO.InputParser.skip_kw!(:MY_KW, 0)
 # Keyword with a single record of data, e.g.
@@ -42,7 +42,7 @@
  (:WLIST, Inf, GeoEnergyIO.InputParser.PARSER_MISSING_SUPPORT)
  (:MY_KW, 0, nothing)
  (:MY_DATA_KW, 1, nothing)
- (:MY_LONG_DATA_KW, Inf, nothing)

Parsing and processing of corner-point grids

Corner-point meshes are the de-facto standard format for simulation of subsurface flow. These meshes are semi-structured, but can have quite complex structure in practice due to eroded and collapsed cells and the presence of faults. This module includes a processor to convert the input format into a mesh that can be used for simulation. Converting the corner-points into a mesh with a connected topology is non-trivial, but the included algorithm has been verified on a number of real-field assets.

There are two main functions to parse and process corner-point inputs:

GeoEnergyIO.InputParser.parse_grdecl_fileFunction
parse_grdecl_file("mygrid.grdecl"; actnum_path = missing, kwarg...)

Parse a GRDECL file separately from the full input file. Note that the GRID section does not contain units - passing the input_units keyword is therefore highly recommended.

Keyword arguments

  • actnum_path=missing: Path to ACTNUM file, if this is not included in the main file.
  • units=:si: Units to use for return values. Requires input_units to be set.
  • input_units=nothing: The units the file is given in.
  • verbose=false: Toggle verbosity.
  • extra_paths: List of extra paths to parse as a part of grid section, ex: ["PORO.inc", "PERM.inc"].
source
GeoEnergyIO.CornerPointGrid.mesh_from_grid_sectionFunction
mesh_from_grid_section(f, actnum = missing, repair_zcorn = true, process_pinch = false)

Generate a Jutul unstructured mesh from a grid section. The input arugment f can be one of the following:

  • (1) An already parsed complete data file read using parse_data_file. The "GRID" field will be used.
  • (2) A parsed "GRID" section from parse_grdecl_file.
  • (3) The file-name of a .GRDECL file to be parsed before processing.

Optionally the actnum can be specified separately. The actnum should have equal length to the number of logical cells in the grid with true/false indicating if a cell is to be included in the processed mesh.

The additional argument repair_zcorn only applies when the grid is defined using COORD/ZCORN arrays. If set to true, the monotonicity of the ZCORN coordinates in each corner-point pillar will be checked and optionally fixed prior to mesh construction. Note that if non-monotone ZCORN are fixed, if the first input argument to this function is an already parsed data structure, the ZCORN array will be mutated during fixing to avoid a copy.

source

Example corner point meshes

The module ships with several corner point grids suitable for testing. These include partially collapsed cells, faults and other degenerate cases that the parser should be able to handle. We can make a few plots of such test grids. The first example is a single hexahedral cell:

using GeoEnergyIO, Jutul, CairoMakie
+ (:MY_LONG_DATA_KW, Inf, nothing)

Parsing and processing of corner-point grids

Corner-point meshes are the de-facto standard format for simulation of subsurface flow. These meshes are semi-structured, but can have quite complex structure in practice due to eroded and collapsed cells and the presence of faults. This module includes a processor to convert the input format into a mesh that can be used for simulation. Converting the corner-points into a mesh with a connected topology is non-trivial, but the included algorithm has been verified on a number of real-field assets.

There are two main functions to parse and process corner-point inputs:

GeoEnergyIO.InputParser.parse_grdecl_fileFunction
parse_grdecl_file("mygrid.grdecl"; actnum_path = missing, kwarg...)

Parse a GRDECL file separately from the full input file. Note that the GRID section does not contain units - passing the input_units keyword is therefore highly recommended.

Keyword arguments

  • actnum_path=missing: Path to ACTNUM file, if this is not included in the main file.
  • units=:si: Units to use for return values. Requires input_units to be set.
  • input_units=nothing: The units the file is given in.
  • verbose=false: Toggle verbosity.
  • extra_paths: List of extra paths to parse as a part of grid section, ex: ["PORO.inc", "PERM.inc"].
source
GeoEnergyIO.CornerPointGrid.mesh_from_grid_sectionFunction
mesh_from_grid_section(f, actnum = missing, repair_zcorn = true, process_pinch = false)

Generate a Jutul unstructured mesh from a grid section. The input arugment f can be one of the following:

  • (1) An already parsed complete data file read using parse_data_file. The "GRID" field will be used.
  • (2) A parsed "GRID" section from parse_grdecl_file.
  • (3) The file-name of a .GRDECL file to be parsed before processing.

Optionally the actnum can be specified separately. The actnum should have equal length to the number of logical cells in the grid with true/false indicating if a cell is to be included in the processed mesh.

The additional argument repair_zcorn only applies when the grid is defined using COORD/ZCORN arrays. If set to true, the monotonicity of the ZCORN coordinates in each corner-point pillar will be checked and optionally fixed prior to mesh construction. Note that if non-monotone ZCORN are fixed, if the first input argument to this function is an already parsed data structure, the ZCORN array will be mutated during fixing to avoid a copy.

source

Example corner point meshes

The module ships with several corner point grids suitable for testing. These include partially collapsed cells, faults and other degenerate cases that the parser should be able to handle. We can make a few plots of such test grids. The first example is a single hexahedral cell:

using GeoEnergyIO, Jutul, CairoMakie
 pth = GeoEnergyIO.test_input_file_path("grdecl", "1cell.txt")
 grdecl = parse_grdecl_file(pth)
 g = mesh_from_grid_section(grdecl)
@@ -80,4 +80,4 @@
 plot_cell_data!(ax, g, ix, shading = NoShading, rasterize = true, colormap = :seaborn_icefire_gradient)
 fig
Example block output

Utilities

GeoEnergyIO.InputParser.get_data_file_cell_regionFunction
region = get_data_file_cell_region(data, t::Symbol; active = nothing)
 satnum = get_data_file_cell_region(data, :satnum)
-pvtnum = get_data_file_cell_region(data, :pvtnum, active = 1:10)

Get the region indicator of some type for each cell of the domain stored in data (the output from parse_data_file). The optional keyword argument active can be used to extract the values for a subset of cells.

t should be one of the following:

  • :satnum (saturation function region)
  • :pvtnum (PVT function region)
  • :eqlnum (equilibriation region)
  • :eosnum (equation-of-state region)
source
GeoEnergyIO.InputParser.number_of_tablesFunction
number_of_tables(outer_data, t::Symbol)

Number of declared tables for given type t. Should be one of the following:

  • :satnum (saturation function region)
  • :pvtnum (PVT function region)
  • :eqlnum (equilibriation region)
  • :eosnum (equation-of-state region)
source

Internals

GeoEnergyIO.InputParser.keyword_default_valueFunction
keyword_default_value(x::AbstractString, T::Type)

Get the default value of a keyword (as String or ::Val{X} where X is a Symbol) when placed in a array with element type T. This is used to initialize defaulted entries when using COPY, ADD, MULTIPLY and so on.

source

Index of functions

+pvtnum = get_data_file_cell_region(data, :pvtnum, active = 1:10)

Get the region indicator of some type for each cell of the domain stored in data (the output from parse_data_file). The optional keyword argument active can be used to extract the values for a subset of cells.

t should be one of the following:

source
GeoEnergyIO.InputParser.number_of_tablesFunction
number_of_tables(outer_data, t::Symbol)

Number of declared tables for given type t. Should be one of the following:

  • :satnum (saturation function region)
  • :pvtnum (PVT function region)
  • :eqlnum (equilibriation region)
  • :eosnum (equation-of-state region)
source

Internals

GeoEnergyIO.InputParser.keyword_default_valueFunction
keyword_default_value(x::AbstractString, T::Type)

Get the default value of a keyword (as String or ::Val{X} where X is a Symbol) when placed in a array with element type T. This is used to initialize defaulted entries when using COPY, ADD, MULTIPLY and so on.

source

Index of functions