Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add totals as measurements #284

Merged
merged 13 commits into from
Jan 4, 2021
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).

## Unreleased

### Added
- [#284](https://github.com/equinor/flownet/pull/284) Added the option to specify cumulative phase rates as observations (WOPT, WWPT, WGPT, WGIT, WWIT)

### Fixes
- [#256](https://github.com/equinor/flownet/pull/256) Fixes issues with duplicate names in hyperopt by using the full path in yaml for hyperopt parameter names.
- [#272](https://github.com/equinor/flownet/pull/272) Adds resampling of observation dates at requested frequency by finding nearest date among existing observation dates (i.e., no interpolated dates added)
Expand Down
71 changes: 71 additions & 0 deletions src/flownet/config_parser/_config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,51 @@ def _to_abs_path(path: Optional[str]) -> str:
},
},
},
"WOPT": {
Copy link
Collaborator

@olelod olelod Dec 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When adding WOPT (or WGPT or WWPT), should we allow for also adding WOPR (or WGPR or WWPR)? Conditioning on both rates and cumulatives i guess is kind of a messy thing with all the correlation going on. Should we add a check in the config_parser to make sure both are not defined?

Update: Let's leave it for now and add an issue on it so we don't forget about it completely

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make a new issue suggesting this and add an item to the CHANGELOG

MK.Type: types.NamedDict,
MK.Content: {
"rel_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
"min_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
},
},
"WGPT": {
MK.Type: types.NamedDict,
MK.Content: {
"rel_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
"min_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
},
},
"WWPT": {
MK.Type: types.NamedDict,
MK.Content: {
"rel_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
"min_error": {
MK.Type: types.Number,
MK.Required: False,
MK.AllowNone: True,
},
},
},
"WOPR": {
MK.Type: types.NamedDict,
MK.Content: {
Expand Down Expand Up @@ -201,6 +246,32 @@ def _to_abs_path(path: Optional[str]) -> str:
},
},
},
"WWIT": {
MK.Type: types.NamedDict,
MK.Content: {
"rel_error": {
MK.Type: types.Number,
MK.AllowNone: True,
},
"min_error": {
MK.Type: types.Number,
MK.AllowNone: True,
},
},
},
"WGIT": {
MK.Type: types.NamedDict,
MK.Content: {
"rel_error": {
MK.Type: types.Number,
MK.AllowNone: True,
},
"min_error": {
MK.Type: types.Number,
MK.AllowNone: True,
},
},
},
},
},
},
Expand Down
19 changes: 18 additions & 1 deletion src/flownet/data/from_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ def _production_data(self) -> pd.DataFrame:
- WOPR Well Oil Production Rate
- WGPR Well Gas Production Rate
- WWPR Well Water Production Rate
- WOPT Well Cumulative Oil Production
- WGPT Well Cumulative Gas Production Rate
- WWPT Well Cumulative Water Production Rate
- WBHP Well Bottom Hole Pressure
- WTHP Well Tubing Head Pressure
- WGIR Well Gas Injection Rate
Expand All @@ -153,7 +156,21 @@ def _production_data(self) -> pd.DataFrame:
* Improve robustness pf setting of Phase and Type.

"""
keys = ["WOPR", "WGPR", "WWPR", "WBHP", "WTHP", "WGIR", "WWIR", "WSTAT"]
keys = [
"WOPR",
"WGPR",
"WWPR",
"WOPT",
"WGPT",
"WWPT",
"WBHP",
"WTHP",
"WGIR",
"WWIR",
"WGIT",
"WWIT",
"WSTAT",
]

df_production_data = pd.DataFrame()

Expand Down
5 changes: 5 additions & 0 deletions src/flownet/realization/_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ def _calculate_wconhist(self):
oil_rate=value["WOPR"],
water_rate=value["WWPR"],
gas_rate=value["WGPR"],
oil_total=value["WOPT"],
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recalculating could potentially mean that one doesn't have to supply this at all.

water_total=value["WWPT"],
gas_total=value["WGPT"],
bhp=value["WBHP"],
thp=value["WTHP"],
)
Expand Down Expand Up @@ -230,6 +233,7 @@ def _calculate_wconinjh(self):
inj_type="WATER",
status=value["WSTAT"],
rate=value["WWIR"],
total=value["WWIT"],
bhp=value["WBHP"],
thp=value["WTHP"],
inj_control_mode=self._inj_control_mode,
Expand All @@ -243,6 +247,7 @@ def _calculate_wconinjh(self):
inj_type="GAS",
status=value["WSTAT"],
rate=value["WGIR"],
total=value["WGIT"],
bhp=value["WBHP"],
thp=value["WTHP"],
inj_control_mode=self._inj_control_mode,
Expand Down
8 changes: 8 additions & 0 deletions src/flownet/realization/_simulation_keywords.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ def __init__(
oil_rate: float = np.nan,
water_rate: float = np.nan,
gas_rate: float = np.nan,
oil_total: float = np.nan,
water_total: float = np.nan,
gas_total: float = np.nan,
vfp_table: str = "1*",
artificial_lift: str = "1*",
thp: float = np.nan,
Expand All @@ -120,6 +123,9 @@ def __init__(
self.oil_rate: float = oil_rate
self.water_rate: float = water_rate
self.gas_rate: float = gas_rate
self.oil_total: float = oil_total
self.water_total: float = water_total
self.gas_total: float = gas_total
self.vfp_table: str = vfp_table
self.artificial_lift: str = artificial_lift
self.thp: float = thp
Expand All @@ -146,6 +152,7 @@ def __init__(
inj_type: str,
status: str = "1*",
rate: float = np.nan,
total: float = np.nan,
bhp: float = np.nan,
thp: float = np.nan,
vfp_table: str = "1*",
Expand All @@ -157,6 +164,7 @@ def __init__(
self.inj_type: str = inj_type
self.status: str = status
self.rate: float = rate
self.total: float = total
self.bhp: float = bhp
self.thp: float = thp
self.vfp_table: str = vfp_table
Expand Down
17 changes: 16 additions & 1 deletion src/flownet/templates/observations.ertobs.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,16 @@
{%- set index_name = date.strftime('%d_%m_%Y') -%}
{%- set date_formatted = date.strftime('%d/%m/%Y') %}

{%- if not isnan(kw.oil_rate) and error_config.WOPR.rel_error is not none and error_config.WOPR.min_error is not none: -%}
{%- if not isnan(kw.oil_total) and error_config.WOPT.rel_error is not none and error_config.WOPT.min_error is not none: -%}
SUMMARY_OBSERVATION WOPT_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.oil_total }}; ERROR = {{ [error_config.WOPT.rel_error * kw.oil_total, error_config.WOPT.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WOPT:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.gas_total) and error_config.WGPT.rel_error is not none and error_config.WGPT.min_error is not none: %}
SUMMARY_OBSERVATION WGPT_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.gas_total }}; ERROR = {{ [error_config.WGPT.rel_error * kw.gas_total, error_config.WGPT.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WGPT:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.water_total) and error_config.WWPT.rel_error is not none and error_config.WWPT.min_error is not none: %}
SUMMARY_OBSERVATION WWPT_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.water_total }}; ERROR = {{ [error_config.WWPT.rel_error * kw.water_total, error_config.WWPT.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WWPT:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.oil_rate) and error_config.WOPR.rel_error is not none and error_config.WOPR.min_error is not none: %}
SUMMARY_OBSERVATION WOPR_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.oil_rate }}; ERROR = {{ [error_config.WOPR.rel_error * kw.oil_rate, error_config.WOPR.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WOPR:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.gas_rate) and error_config.WGPR.rel_error is not none and error_config.WGPR.min_error is not none: %}
Expand Down Expand Up @@ -43,6 +52,12 @@ SUMMARY_OBSERVATION WGIR_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.rat
{%- if not isnan(kw.rate) and kw.inj_type == "WATER" and error_config.WWIR.rel_error is not none and error_config.WWIR.min_error is not none: %}
SUMMARY_OBSERVATION WWIR_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.rate }}; ERROR = {{ [error_config.WWIR.rel_error * kw.rate, error_config.WWIR.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WWIR:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.total) and kw.inj_type == "GAS" and error_config.WGIT.rel_error is not none and error_config.WGIT.min_error is not none: %}
SUMMARY_OBSERVATION WGIT_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.total }}; ERROR = {{ [error_config.WGIT.rel_error * kw.total, error_config.WGIT.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WGIT:{{ kw.well_name }}; };
{%- endif %}
{%- if not isnan(kw.total) and kw.inj_type == "WATER" and error_config.WWIT.rel_error is not none and error_config.WWIT.min_error is not none: %}
SUMMARY_OBSERVATION WWIR_{{ kw.well_name }}_{{ index_name }} { VALUE = {{ kw.total }}; ERROR = {{ [error_config.WWIT.rel_error * kw.total, error_config.WWIT.min_error] | max }}; DATE = {{ date_formatted }}; KEY = WWIT:{{ kw.well_name }}; };
{%- endif %}

{% endfor %}
{%- endif %}
Expand Down
85 changes: 85 additions & 0 deletions src/flownet/templates/observations.yamlobs.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,57 @@ smry:
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WOPT.rel_error is not none) and (error_config.WOPT.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONHIST", well_name=well_name, ignore_nan="oil_total", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
- key: WOPT:{{ well_name }}
observations:
{%- endif %}
- date: {{ kw.date.strftime('%Y-%m-%d') }}
value: {{ kw.oil_total }}
error: {{ [error_config.WOPT.rel_error * kw.oil_total, error_config.WOPT.min_error] | max }}
comment:
{%- if (kw.date > last_training_date) -%}
{{ " Test" }}
{%- else -%}
{{ " Training" }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WWPT.rel_error is not none) and (error_config.WWPT.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONHIST", well_name=well_name, ignore_nan="water_total", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
- key: WWPT:{{ well_name }}
observations:
{%- endif %}
- date: {{ kw.date.strftime('%Y-%m-%d') }}
value: {{ kw.water_total }}
error: {{ [error_config.WWPT.rel_error * kw.water_total, error_config.WWPT.min_error] | max }}
comment:
{%- if (kw.date > last_training_date) -%}
{{ " Test" }}
{%- else -%}
{{ " Training" }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WGPT.rel_error is not none) and (error_config.WGPT.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONHIST", well_name=well_name, ignore_nan="gas_total", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
- key: WGPT:{{ well_name }}
observations:
{%- endif %}
- date: {{ kw.date.strftime('%Y-%m-%d') }}
value: {{ kw.gas_total }}
error: {{ [error_config.WGPT.rel_error * kw.gas_total, error_config.WGPT.min_error] | max }}
comment:
{%- if (kw.date > last_training_date) -%}
{{ " Test" }}
{%- else -%}
{{ " Training" }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WBHP.rel_error is not none) and (error_config.WBHP.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONHIST", well_name=well_name, ignore_nan="bhp", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
Expand Down Expand Up @@ -156,4 +207,38 @@ smry:
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WGIT.rel_error is not none) and (error_config.WGIT.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONINJH", well_name=well_name, ignore_nan="thp", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
- key: WGIT:{{ well_name }}
observations:
{%- endif %}
- date: {{ kw.date.strftime('%Y-%m-%d') }}
value: {{ kw.total }}
error: {{ [error_config.WGIT.rel_error * kw.total, error_config.WGIT.min_error] | max }}
comment:
{%- if (kw.date > last_training_date) -%}
{{ " Test" }}
{%- else -%}
{{ " Training" }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- if (error_config.WWIT.rel_error is not none) and (error_config.WWIT.min_error is not none) -%}
{%- for kw in schedule.get_keywords(kw_class="WCONINJH", well_name=well_name, ignore_nan="thp", dates=dates[num_beginning_date:num_end_date]) -%}
{% if loop.first and not loop.last: %}
- key: WWIT:{{ well_name }}
observations:
{%- endif %}
- date: {{ kw.date.strftime('%Y-%m-%d') }}
value: {{ kw.total }}
error: {{ [error_config.WWIT.rel_error * kw.total, error_config.WWIT.min_error] | max }}
comment:
{%- if (kw.date > last_training_date) -%}
{{ " Test" }}
{%- else -%}
{{ " Training" }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- endfor -%}
Loading