Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions ResSimpy/FileOperations/file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,14 +804,20 @@ def split_file_as_list_by_date(file_as_list: list[str], date_token: str = 'TIME'
of that token.
"""
split_file: dict[str, list[str]] = {}
current_token_value = None
date_token_value = None
no_token_dict_key = f'BEFORE_FIRST_{date_token}'

for i, line in enumerate(file_as_list):
if check_token(date_token, line, comment_characters=comment_characters):
# TODO handle 3 part dates in this bit
current_token_value = get_expected_token_value(token=date_token, token_line=line,
file_list=file_as_list[i:],
comment_characters=comment_characters)
split_file[current_token_value] = [line]
elif current_token_value is not None:
split_file[current_token_value].append(line)
date_token_value = get_expected_token_value(token=date_token, token_line=line,
file_list=file_as_list[i:],
comment_characters=comment_characters)
split_file[date_token_value] = [line]
elif date_token_value is None:
if no_token_dict_key not in split_file:
split_file[no_token_dict_key] = []
split_file[no_token_dict_key].append(line)
elif date_token_value is not None:
split_file[date_token_value].append(line)
return split_file
56 changes: 33 additions & 23 deletions ResSimpy/Nexus/DataModels/Network/NexusProc.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from dataclasses import dataclass
from typing import Optional, Mapping
from typing import Optional

from ResSimpy.DataModelBaseClasses.NetworkObject import NetworkObject
from ResSimpy.Enums.UnitsEnum import UnitSystem
from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat
from ResSimpy.Nexus.NexusKeywords.proc_keywords import PREDEFINED_VARS, CONDITIONAL_KEYWORDS, NEXUS_ALL_PROC_FUNCS
from ResSimpy.Units.AttributeMappings.BaseUnitMapping import BaseUnitMapping


# set custom error message
Expand All @@ -9,18 +14,15 @@ class SetError(Exception):


@dataclass(kw_only=True, repr=True)
class NexusProc:
class NexusProc(NetworkObject):
"""Class that represents a single nexus procedure."""
__date: Optional[str]
__name: Optional[str]
__priority: Optional[int]
__contents: Optional[list[str]]
__contents_breakdown: dict[str, int]

def __init__(self, date: Optional[str] = None,
contents: Optional[list[str]] = None,
name: Optional[str] = None,
priority: Optional[int] = None) -> None:
def __init__(self, date: Optional[str] = None, contents: Optional[list[str]] = None,
name: Optional[str] = None, priority: Optional[int] = None, unit_system: Optional[UnitSystem] = None,
start_date: Optional[str] = None, date_format: Optional[DateFormat] = None) -> None:
"""Initialize the attributes of the class.

Attributes:
Expand All @@ -33,33 +35,23 @@ def __init__(self, date: Optional[str] = None,
Methods:
reset_nexus_proc_function_counts(): Returns a dictionary of zero counts for the nexus proc functions.
"""

self.__date = date
self.__name = name
self.__priority = priority
self.__contents = contents

self.__contents_breakdown = self.reset_nexus_proc_function_counts()
super().__init__(properties_dict={}, date=date, date_format=date_format, start_date=start_date,
unit_system=unit_system, name=name)

@property
def contents(self) -> Optional[list[str]]:
"""Returns the contents of the main body of the procedure."""
return self.__contents

@property
def date(self) -> Optional[str]:
"""Returns the date that the procedure occurred."""
return self.__date

@property
def priority(self) -> Optional[int]:
"""Returns the priority of the procedure."""
return self.__priority

@property
def name(self) -> Optional[str]:
"""Returns the name of the procedure."""
return self.__name

@property
def contents_breakdown(self) -> dict[str, int]:
"""Returns the dictionary counts of the proc functions."""
Expand All @@ -76,9 +68,9 @@ def contents_breakdown(self, value: dict) -> None:
'Nexus Keyword Manual page 1013.')

@staticmethod
def get_keyword_mapping() -> Mapping[str, tuple[str, type]]:
def get_keyword_mapping() -> dict[str, tuple[str, type]]:
"""Gets the mapping of nexus keywords to attribute definitions."""
keywords = {
keywords: dict[str, tuple[str, type]] = {
'NAME': ('name', str),
'PRIORITY': ('priority', str)
}
Expand All @@ -99,3 +91,21 @@ def reset_nexus_proc_function_counts() -> dict[str, int]:
to_search = predef_vars | cond | all_proc_funcs

return to_search

def to_string(self) -> str:
"""Outputs the procedure as a string in the format it would be written in a Nexus file."""
output_str = "PROCS"
if self.name is not None:
output_str += f" NAME {self.name}"
if self.priority is not None:
output_str += f" PRIORITY {self.priority}"
output_str += '\n'
if self.contents is not None:
output_str += '\n'.join(self.contents) + '\n'
output_str += "ENDPROCS\n"
return output_str

@property
def units(self) -> BaseUnitMapping:
"""Returns the attribute to unit map for the data object."""
return BaseUnitMapping(None)
9 changes: 9 additions & 0 deletions ResSimpy/Nexus/DataModels/Network/NexusProcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from typing import Sequence, TYPE_CHECKING

from ResSimpy.Nexus.DataModels.Network.NexusProc import NexusProc
from ResSimpy.Time.ISODateTime import ISODateTime

if TYPE_CHECKING:
from ResSimpy.Nexus.NexusNetwork import NexusNetwork
Expand Down Expand Up @@ -35,3 +36,11 @@ def get_all(self) -> Sequence[NexusProc]:
def _add_to_memory(self, procs_to_add: list[NexusProc]) -> None:
"""Adds the list of Nexus procedure objects to memory."""
self.__procs.extend(procs_to_add)

def to_string_for_date(self, date: ISODateTime) -> str:
"""Outputs the procedures for a specific date."""
output_str = ''
procs_for_date = [x for x in self.__procs if x.iso_date == date]
for proc in procs_for_date:
output_str += proc.to_string()
return output_str
2 changes: 1 addition & 1 deletion ResSimpy/Nexus/DataModels/Network/NexusWellLists.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from ResSimpy.DataModelBaseClasses.NetworkList import NetworkList
from ResSimpy.GenericContainerClasses.NetworkLists import NetworkLists
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList

if TYPE_CHECKING:
from ResSimpy.Nexus.NexusNetwork import NexusNetwork
Expand Down
10 changes: 5 additions & 5 deletions ResSimpy/Nexus/NexusNetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
from ResSimpy.Nexus.DataModels.Network.NexusWellhead import NexusWellhead
from ResSimpy.Nexus.DataModels.Network.NexusWellheads import NexusWellheads
from ResSimpy.Nexus.DataModels.NexusFile import NexusFile
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusEnums.ActivationChangeEnum import ActivationChangeEnum
from ResSimpy.Nexus.nexus_collect_tables import collect_all_tables_to_objects

Expand Down Expand Up @@ -163,9 +163,8 @@ def __load_procs(self) -> list[NexusProc]:
time = self.__model.start_date
name_ = None
priority_ = None
# initialize an empty proc object, so we can use its staticmethod reset_nexus_proc_function_counts
proc_obj = NexusProc()
nexus_proc_function_counts = proc_obj.reset_nexus_proc_function_counts()
nexus_proc_function_counts = NexusProc.reset_nexus_proc_function_counts()
date_format = self.__model.date_format

for line in file_contents:

Expand All @@ -176,7 +175,8 @@ def __load_procs(self) -> list[NexusProc]:
# check for keyword ENDPROCS to signal end of the procedure
if fo.check_token('ENDPROCS', line=line):
# create the proc object
proc_obj = NexusProc(contents=proc_contents, date=time, name=name_, priority=priority_)
proc_obj = NexusProc(contents=proc_contents, date=time, name=name_, priority=priority_,
date_format=date_format, start_date=self.__model.start_date)

# set the proc function counts
proc_obj.contents_breakdown = nexus_proc_function_counts
Expand Down
2 changes: 1 addition & 1 deletion ResSimpy/Nexus/nexus_collect_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ResSimpy.Nexus.DataModels.Network.NexusNodeLists import NexusNodeLists
from ResSimpy.Nexus.DataModels.Network.NexusConstraint import NexusConstraint
from ResSimpy.Nexus.DataModels.Network.NexusWellLists import NexusWellLists
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusEnums.ActivationChangeEnum import ActivationChangeEnum
from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat
from ResSimpy.Nexus.nexus_constraint_operations import load_inline_constraints
Expand Down
2 changes: 1 addition & 1 deletion ResSimpy/Nexus/nexus_constraint_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ResSimpy.DataModelBaseClasses.DataObjectMixin import DataObjectMixinDictType
from ResSimpy.Nexus.DataModels.Network.NexusConstraint import NexusConstraint
from ResSimpy.Enums.UnitsEnum import UnitSystem
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat
from ResSimpy.Nexus.nexus_file_operations import get_next_value, correct_datatypes
from ResSimpy.Utils.invert_nexus_map import nexus_keyword_to_attribute_name
Expand Down
2 changes: 1 addition & 1 deletion ResSimpy/Nexus/nexus_file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
strip_file_of_comments, load_file_as_list
from ResSimpy.Nexus.DataModels.Network.NexusNodeConnection import NexusNodeConnection
from ResSimpy.Nexus.DataModels.Network.NexusWellConnection import NexusWellConnection
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat
from ResSimpy.Nexus.NexusKeywords.nexus_keywords import VALID_NEXUS_KEYWORDS
from ResSimpy.Nexus.NexusKeywords.structured_grid_keywords import GRID_ARRAY_KEYWORDS
Expand Down
18 changes: 15 additions & 3 deletions ResSimpy/Nexus/nexus_model_file_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,18 @@ def output_surface_section(self) -> str:
if self.model.network is None:
return full_schedule
all_well_connections = self.model.network.well_connections.get_all()
all_wellheads = self.model.network.wellheads.get_all()
all_targets = self.model.network.targets.get_all()
all_welllists = self.model.network.welllists.get_all()
all_conlists = self.model.network.conlists.get_all()
all_nodelists = self.model.network.nodelists.get_all()
all_nodes = self.model.network.nodes.get_all()
all_connections = self.model.network.connections.get_all()
all_activations = self.model.network.activation_changes.get_all()
all_procs = self.model.network.procs.get_all()

network_objects = [all_well_connections, all_targets, all_welllists, all_nodes, all_connections,
all_activations, all_conlists, all_nodelists]
network_objects = [all_well_connections, all_wellheads, all_targets, all_welllists, all_nodes, all_connections,
all_activations, all_conlists, all_nodelists, all_procs]

all_constraints = self.model.network.constraints.get_all()

Expand All @@ -77,14 +79,19 @@ def output_surface_section(self) -> str:
# Write out all events for each date
for date in ordered_all_event_dates:
if date != self.model.start_iso_date:
full_schedule += f"TIME {date.strftime_dateformat(self.model.date_format)}\n"
full_schedule += f"TIME {date.strftime_dateformat(self.model.date_format)}\n\n"

well_connections_for_date = [x for x in all_well_connections if x.iso_date == date]

if any(well_connections_for_date) and self.model.network.well_connections is not None:
full_schedule += self.model.network.well_connections.to_string_for_date(date=date)
full_schedule += '\n'

wellheads_for_date = [x for x in all_wellheads if x.iso_date == date]
if any(wellheads_for_date) and self.model.network.wellheads is not None:
full_schedule += self.model.network.wellheads.to_string_for_date(date=date)
full_schedule += '\n'

welllists_for_date = [x for x in all_welllists if x.iso_date == date]
if any(welllists_for_date) and self.model.network.welllists is not None:
full_schedule += self.model.network.welllists.to_string_for_date(date=date)
Expand Down Expand Up @@ -123,6 +130,11 @@ def output_surface_section(self) -> str:
full_schedule += self.model.network.activation_changes.to_string_for_date(date=date)
full_schedule += '\n'

procs_for_date = [x for x in all_procs if x.iso_date == date]
if any(procs_for_date) and self.model.network.procs is not None:
full_schedule += self.model.network.procs.to_string_for_date(date=date)
full_schedule += '\n'

return full_schedule

def output_wells_section(self) -> str:
Expand Down
4 changes: 3 additions & 1 deletion tests/FileOperations/test_file_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,11 @@ def test_get_full_file_path(mocker, origin, rootdir, is_nexus, expected_full_pat

def test_split_file_as_list_by_date():
# Arrange
file_as_list = ['TIME 01/01/2020\n', 'OTHERLINE\n', 'TIME 01/02/2020\n', 'OTHERLINE2\n',
file_as_list = ['Some content before the token card\n', 'another line\n', 'TIME 01/01/2020\n', 'OTHERLINE\n',
'TIME 01/02/2020\n', 'OTHERLINE2\n',
'TIME 01/03/2020\n', 'TIME 01/04/2020\n', '! TIME 01/05/2021\n', 'OTHERLINE3\n', 'Otherline4\n']
expected_result = {
'BEFORE_FIRST_TIME': ['Some content before the token card\n', 'another line\n'],
'01/01/2020': ['TIME 01/01/2020\n', 'OTHERLINE\n'],
'01/02/2020': ['TIME 01/02/2020\n', 'OTHERLINE2\n'],
'01/03/2020': ['TIME 01/03/2020\n'],
Expand Down
2 changes: 1 addition & 1 deletion tests/Nexus/nexus_simulator/test_nexus_conlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from ResSimpy.Enums.UnitsEnum import UnitSystem
from ResSimpy.Nexus.DataModels.Network.NexusConList import NexusConList
from ResSimpy.Nexus.DataModels.NexusFile import NexusFile
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat
from ResSimpy.Nexus.nexus_collect_tables import collect_all_tables_to_objects
from ResSimpy.Nexus.nexus_load_list_table import load_table_to_lists
Expand Down
11 changes: 6 additions & 5 deletions tests/Nexus/nexus_simulator/test_nexus_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from ResSimpy.Nexus.DataModels.Network.NexusTarget import NexusTarget
from ResSimpy.Nexus.DataModels.Network.NexusTargets import NexusTargets
from ResSimpy.Nexus.DataModels.Network.NexusWellLists import NexusWellLists
from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList
from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList
from ResSimpy.Nexus.NexusNetwork import NexusNetwork
from ResSimpy.Enums.WellTypeEnum import WellType
from ResSimpy.Nexus.DataModels.Network.NexusActivationChange import NexusActivationChange
Expand Down Expand Up @@ -1424,18 +1424,20 @@ def test_load_between_procs(mocker):
cp01_gaslift GAS CP01 GASLIFT NONE NA ! Checked NODECON 13/05/2020
ENDNODECON
'''
start_date = '01/01/2023'
expected_nodecons = [NexusNodeConnection(name='CP01', node_in='CP01', node_out='wh_cp01', con_type='PIPE',
hyd_method='2', delta_depth=7002.67, date='01/01/2023',
unit_system=UnitSystem.ENGLISH, properties_dict={},
date_format=DateFormat.DD_MM_YYYY, start_date='01/01/2023'),
date_format=DateFormat.DD_MM_YYYY, start_date=start_date),
NexusNodeConnection(name='cp01_gaslift', node_in='GAS', node_out='CP01', con_type='GASLIFT',
hyd_method=None, delta_depth=None, date='01/01/2023',
unit_system=UnitSystem.ENGLISH, properties_dict={},
date_format=DateFormat.DD_MM_YYYY, start_date='01/01/2023')]
date_format=DateFormat.DD_MM_YYYY, start_date=start_date)]

expected_proc = NexusProc(date='01/01/2023', name='TUNING',
contents=['REAL_1D list\n', 'REAL t_last = 0\n', 'IF (t_last == 0 THEN\n',
't_last = TIME\n', 'ENDIF\n'], )
't_last = TIME\n', 'ENDIF\n'], date_format=DateFormat.DD_MM_YYYY,
start_date=start_date)

def mock_open_wrapper(filename, mode):
mock_open = mock_multiple_files(mocker, filename, potential_file_dict={
Expand All @@ -1445,7 +1447,6 @@ def mock_open_wrapper(filename, mode):
}).return_value
return mock_open

start_date = '01/01/2023'
mocker.patch("builtins.open", mock_open_wrapper)

fcs_file_path = 'fcs_file.fcs'
Expand Down
Loading