diff --git a/ResSimpy/FileOperations/file_operations.py b/ResSimpy/FileOperations/file_operations.py index 925be245..08df0edd 100644 --- a/ResSimpy/FileOperations/file_operations.py +++ b/ResSimpy/FileOperations/file_operations.py @@ -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 diff --git a/ResSimpy/Nexus/DataModels/Network/NexusProc.py b/ResSimpy/Nexus/DataModels/Network/NexusProc.py index db82eb63..24fae6e1 100644 --- a/ResSimpy/Nexus/DataModels/Network/NexusProc.py +++ b/ResSimpy/Nexus/DataModels/Network/NexusProc.py @@ -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 @@ -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: @@ -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.""" @@ -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) } @@ -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) diff --git a/ResSimpy/Nexus/DataModels/Network/NexusProcs.py b/ResSimpy/Nexus/DataModels/Network/NexusProcs.py index c71c2e84..9dc1a02f 100644 --- a/ResSimpy/Nexus/DataModels/Network/NexusProcs.py +++ b/ResSimpy/Nexus/DataModels/Network/NexusProcs.py @@ -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 @@ -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 diff --git a/ResSimpy/Nexus/DataModels/NexusWellList.py b/ResSimpy/Nexus/DataModels/Network/NexusWellList.py similarity index 100% rename from ResSimpy/Nexus/DataModels/NexusWellList.py rename to ResSimpy/Nexus/DataModels/Network/NexusWellList.py diff --git a/ResSimpy/Nexus/DataModels/Network/NexusWellLists.py b/ResSimpy/Nexus/DataModels/Network/NexusWellLists.py index 31a178e9..8c33dade 100644 --- a/ResSimpy/Nexus/DataModels/Network/NexusWellLists.py +++ b/ResSimpy/Nexus/DataModels/Network/NexusWellLists.py @@ -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 diff --git a/ResSimpy/Nexus/NexusNetwork.py b/ResSimpy/Nexus/NexusNetwork.py index 19257a77..ea8a3bd0 100644 --- a/ResSimpy/Nexus/NexusNetwork.py +++ b/ResSimpy/Nexus/NexusNetwork.py @@ -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 @@ -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: @@ -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 diff --git a/ResSimpy/Nexus/nexus_collect_tables.py b/ResSimpy/Nexus/nexus_collect_tables.py index b7e51d82..2e2ea58c 100644 --- a/ResSimpy/Nexus/nexus_collect_tables.py +++ b/ResSimpy/Nexus/nexus_collect_tables.py @@ -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 diff --git a/ResSimpy/Nexus/nexus_constraint_operations.py b/ResSimpy/Nexus/nexus_constraint_operations.py index 26d1eb56..a16ba520 100644 --- a/ResSimpy/Nexus/nexus_constraint_operations.py +++ b/ResSimpy/Nexus/nexus_constraint_operations.py @@ -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 diff --git a/ResSimpy/Nexus/nexus_file_operations.py b/ResSimpy/Nexus/nexus_file_operations.py index 78ff8c07..7afb95c7 100644 --- a/ResSimpy/Nexus/nexus_file_operations.py +++ b/ResSimpy/Nexus/nexus_file_operations.py @@ -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 diff --git a/ResSimpy/Nexus/nexus_model_file_generator.py b/ResSimpy/Nexus/nexus_model_file_generator.py index 5f294d75..144f47e2 100644 --- a/ResSimpy/Nexus/nexus_model_file_generator.py +++ b/ResSimpy/Nexus/nexus_model_file_generator.py @@ -48,6 +48,7 @@ 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() @@ -55,9 +56,10 @@ def output_surface_section(self) -> str: 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() @@ -77,7 +79,7 @@ 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] @@ -85,6 +87,11 @@ def output_surface_section(self) -> str: 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) @@ -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: diff --git a/tests/FileOperations/test_file_operations.py b/tests/FileOperations/test_file_operations.py index 429cee3d..994036db 100644 --- a/tests/FileOperations/test_file_operations.py +++ b/tests/FileOperations/test_file_operations.py @@ -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'], diff --git a/tests/Nexus/nexus_simulator/test_nexus_conlist.py b/tests/Nexus/nexus_simulator/test_nexus_conlist.py index 7907cd75..31877ca8 100644 --- a/tests/Nexus/nexus_simulator/test_nexus_conlist.py +++ b/tests/Nexus/nexus_simulator/test_nexus_conlist.py @@ -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 diff --git a/tests/Nexus/nexus_simulator/test_nexus_network.py b/tests/Nexus/nexus_simulator/test_nexus_network.py index c47f9d85..44ae3f43 100644 --- a/tests/Nexus/nexus_simulator/test_nexus_network.py +++ b/tests/Nexus/nexus_simulator/test_nexus_network.py @@ -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 @@ -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={ @@ -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' diff --git a/tests/Nexus/nexus_simulator/test_nexus_network_procedures.py b/tests/Nexus/nexus_simulator/test_nexus_network_procedures.py index 02fd4614..7201c656 100644 --- a/tests/Nexus/nexus_simulator/test_nexus_network_procedures.py +++ b/tests/Nexus/nexus_simulator/test_nexus_network_procedures.py @@ -1,8 +1,14 @@ +from datetime import datetime + +import pytest + from ResSimpy.Nexus.DataModels.Network.NexusNode import NexusNode from ResSimpy.Nexus.DataModels.Network.NexusProc import NexusProc from ResSimpy.Nexus.DataModels.Network.NexusProcs import NexusProcs from ResSimpy.Nexus.DataModels.NexusFile import NexusFile +from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat from ResSimpy.Nexus.NexusNetwork import NexusNetwork +from ResSimpy.Time.ISODateTime import ISODateTime from tests.utility_for_tests import get_fake_nexus_simulator @@ -22,7 +28,8 @@ def test_load_nexus_procedures_basic(mocker): # create object # date must be the same as the start_date - expected_proc = NexusProc(date='01/01/2023', contents=["THIS IS TEXT"]) + expected_proc = NexusProc(date='01/01/2023', contents=["THIS IS TEXT"], date_format=DateFormat.MM_DD_YYYY, + start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) @@ -38,7 +45,6 @@ def test_load_nexus_procedures_basic(mocker): nexus_net.procs = nexus_procs # Act - # nexus_procs.load(surface_file, start_date, default_units=UnitSystem.ENGLISH) result = nexus_procs.get_all() # Assert @@ -64,7 +70,8 @@ def test_load_nexus_procedures_date(mocker): # create object # date must be the same as the start_date - expected_proc = NexusProc(date='01/01/2024', contents=["THIS IS TEXT"]) + expected_proc = NexusProc(date='01/01/2024', contents=["THIS IS TEXT"], date_format=DateFormat.MM_DD_YYYY, + start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) @@ -106,7 +113,8 @@ def test_load_nexus_procedures_name_priority(mocker): # create object # date must be the same as the start_date - expected_proc = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) + expected_proc = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=DateFormat.MM_DD_YYYY, start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) @@ -151,9 +159,10 @@ def test_load_nexus_procedures_multiple_procs_one_time(mocker): # create object # date must be the same as the start_date - expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) + expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=DateFormat.MM_DD_YYYY, start_date=start_date) expected_proc2 = NexusProc(date='01/01/2024', name='DYNAMIC_VARS', priority=2, - contents=["THIS IS MORE TEXT"]) + contents=["THIS IS MORE TEXT"], date_format=DateFormat.MM_DD_YYYY, start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) @@ -197,15 +206,18 @@ def test_load_nexus_procedures_same_proc_multiple_time(mocker): """ surface_file = NexusFile(location='surface.dat', file_content_as_list=surface_file_contents.splitlines()) - + date_format = DateFormat.DD_MM_YYYY # create object # date must be the same as the start_date - expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) - expected_proc2 = NexusProc(date='01/01/2025', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) + expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=date_format, start_date=start_date) + expected_proc2 = NexusProc(date='01/01/2025', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=date_format, start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) dummy_model._start_date = start_date + dummy_model.date_format = date_format dummy_model.model_files.surface_files = {1: surface_file} nexus_net = NexusNetwork(model=dummy_model) @@ -251,10 +263,13 @@ def test_load_nexus_procedures_multiple_procs_multiple_times(mocker): # create object # date must be the same as the start_date - expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) - expected_proc2 = NexusProc(date='01/01/2025', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"]) + expected_proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=DateFormat.MM_DD_YYYY, start_date=start_date) + expected_proc2 = NexusProc(date='01/01/2025', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=DateFormat.MM_DD_YYYY, start_date=start_date) expected_proc3 = NexusProc(date='01/01/2025', name='DYNAMIC_VARS', priority=2, - contents=["THIS IS DIFFERENT TEXT"]) + contents=["THIS IS DIFFERENT TEXT"], date_format=DateFormat.MM_DD_YYYY, + start_date=start_date) # create a nexus network object dummy_model = get_fake_nexus_simulator(mocker) @@ -506,3 +521,37 @@ def test_load_nexus_procedures_proc_func_counts_single_letter_no_spaces_do_loop( assert result[0].contents_breakdown['P'] == 1 assert result[0].contents_breakdown['DO'] == 1 +@pytest.mark.parametrize('date_to_output, expected_result', [ + (ISODateTime(2024, 1, 1), """PROCS NAME STATIC_VARS PRIORITY 1 +IF(ABS(MAX(X)) > ABS(MAX(Y))) THEN +PRINTOUT(2)!PRINTOUT is a built in nexus proc function +ENDIF +ENDPROCS +"""), + (ISODateTime(2025, 1, 1), """PROCS NAME STATIC_VARS PRIORITY 1 +THIS IS TEXT +ENDPROCS +PROCS NAME DYNAMIC_VARS PRIORITY 2 +THIS IS DIFFERENT TEXT +ENDPROCS +""")]) +def test_proc_to_string_for_date(date_to_output: ISODateTime, expected_result: str): + # Arrange + dateformat = DateFormat.DD_MM_YYYY + proc1 = NexusProc(date='01/01/2024', name='STATIC_VARS', priority=1, contents=['IF(ABS(MAX(X)) > ABS(MAX(Y))) THEN', + 'PRINTOUT(2)!PRINTOUT is a built in nexus proc function', + 'ENDIF'], + date_format=dateformat) + proc2 = NexusProc(date='01/01/2025', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=dateformat) + proc3 = NexusProc(date='01/01/2025', name='DYNAMIC_VARS', priority=2, + contents=["THIS IS DIFFERENT TEXT"], date_format=dateformat) + + procs_object = NexusProcs(parent_network=None) + procs_object._add_to_memory([proc1, proc2, proc3]) + + # Act + result = procs_object.to_string_for_date(date_to_output) + + # Assert + assert result == expected_result diff --git a/tests/Nexus/nexus_simulator/test_nexus_nodelist.py b/tests/Nexus/nexus_simulator/test_nexus_nodelist.py index e03fdf7c..2393f196 100644 --- a/tests/Nexus/nexus_simulator/test_nexus_nodelist.py +++ b/tests/Nexus/nexus_simulator/test_nexus_nodelist.py @@ -4,7 +4,7 @@ from ResSimpy.Nexus.DataModels.Network.NexusConList import NexusConList from ResSimpy.Nexus.DataModels.Network.NexusNodeList import NexusNodeList 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 diff --git a/tests/Nexus/nexus_simulator/test_nexus_simulator.py b/tests/Nexus/nexus_simulator/test_nexus_simulator.py index 8d786532..d01a9fe7 100644 --- a/tests/Nexus/nexus_simulator/test_nexus_simulator.py +++ b/tests/Nexus/nexus_simulator/test_nexus_simulator.py @@ -31,13 +31,13 @@ from ResSimpy.Nexus.DataModels.NexusGasliftMethod import NexusGasliftMethod from ResSimpy.Nexus.DataModels.Network.NexusNode import NexusNode from ResSimpy.Nexus.DataModels.Network.NexusNodeConnection import NexusNodeConnection -from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList +from ResSimpy.Nexus.DataModels.Network.NexusWellList import NexusWellList from ResSimpy.Nexus.DataModels.StructuredGrid.NexusGrid import NexusGrid from ResSimpy.Nexus.NexusNetwork import NexusNetwork from ResSimpy.Nexus.NexusEnums.DateFormatEnum import DateFormat from ResSimpy.Nexus.NexusIPRMethods import NexusIprMethods from ResSimpy.Nexus.DataModels.NexusIPRMethod import NexusIprMethod -from pytest_mock import MockerFixture, mocker +from pytest_mock import MockerFixture from unittest.mock import Mock from ResSimpy.Enums.UnitsEnum import UnitSystem from ResSimpy.Nexus.NexusWells import NexusWells diff --git a/tests/Nexus/test_load_wells.py b/tests/Nexus/test_load_wells.py index 56cc4e8f..d9816dc3 100644 --- a/tests/Nexus/test_load_wells.py +++ b/tests/Nexus/test_load_wells.py @@ -1,5 +1,3 @@ -import warnings - import pytest from pytest_mock import MockerFixture diff --git a/tests/Nexus/test_nexus_welllist.py b/tests/Nexus/test_nexus_welllist.py index c929f8e1..0b5eb573 100644 --- a/tests/Nexus/test_nexus_welllist.py +++ b/tests/Nexus/test_nexus_welllist.py @@ -4,7 +4,7 @@ from ResSimpy.Enums.UnitsEnum import UnitSystem from ResSimpy.Nexus.DataModels.Network.NexusWellLists import NexusWellLists 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.NexusNetwork import NexusNetwork from ResSimpy.Nexus.nexus_collect_tables import collect_all_tables_to_objects diff --git a/tests/Nexus/writing_tests/test_nexus_write_schedule.py b/tests/Nexus/writing_tests/test_nexus_write_schedule.py index 1342ef0a..b31e8412 100644 --- a/tests/Nexus/writing_tests/test_nexus_write_schedule.py +++ b/tests/Nexus/writing_tests/test_nexus_write_schedule.py @@ -9,13 +9,15 @@ from ResSimpy.Nexus.DataModels.Network.NexusNode import NexusNode from ResSimpy.Nexus.DataModels.Network.NexusNodeConnection import NexusNodeConnection from ResSimpy.Nexus.DataModels.Network.NexusNodeList import NexusNodeList +from ResSimpy.Nexus.DataModels.Network.NexusProc import NexusProc from ResSimpy.Nexus.DataModels.Network.NexusTarget import NexusTarget from ResSimpy.Nexus.DataModels.Network.NexusWellConnection import NexusWellConnection -from ResSimpy.Nexus.DataModels.NexusWellList import NexusWellList +from ResSimpy.Nexus.DataModels.Network.NexusWellhead import NexusWellhead +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_model_file_generator import NexusModelFileGenerator -from tests.utility_for_tests import get_fake_nexus_simulator + @pytest.mark.parametrize('pvt_type, eos_details, expected_pvt_string', [ (PvtType.BLACKOIL, None, 'BLACKOIL'), @@ -45,6 +47,12 @@ def test_write_surface_section(pvt_type, eos_details, expected_pvt_string): date='01/01/2020', unit_system=UnitSystem.METRIC, date_format=DateFormat.DD_MM_YYYY, start_date=start_date) model.network.well_connections._add_to_memory([wellcon1, wellcon2, wellcon2_additional_wellcon]) + + wellhead1 = NexusWellhead(name='P01WH', date='01/01/2020', unit_system=UnitSystem.METRIC, + date_format=DateFormat.DD_MM_YYYY, hyd_method=23, depth=2052.2, well='P01') + wellhead2 = NexusWellhead(name='P02WH', date='01/01/2020', unit_system=UnitSystem.METRIC, + date_format=DateFormat.DD_MM_YYYY, hyd_method=25, depth=2152.2, well='P02') + model.network.wellheads._add_to_memory([wellhead1, wellhead2]) # add some constraints constraints = {'P01': [NexusConstraint(name='P01', max_gor=100000, max_pressure=234.223, @@ -105,6 +113,10 @@ def test_write_surface_section(pvt_type, eos_details, expected_pvt_string): NexusNodeList(name='nodelist_2', date='01/01/2021', date_format=DateFormat.DD_MM_YYYY, elements_in_the_list=['NODE3', 'NODE4']), ]) + + # add some procs + model.network.procs._add_to_memory([NexusProc(date='15/10/2021', name='STATIC_VARS', priority=1, contents=["THIS IS TEXT"], + date_format=DateFormat.DD_MM_YYYY)]) expected_result = f"""{expected_pvt_string} @@ -113,12 +125,19 @@ def test_write_surface_section(pvt_type, eos_details, expected_pvt_string): ENDCONSTRAINTS TIME 01/01/2020 + WELLS NAME STREAM NUMBER DATUM DATGRAD CROSS_SHUT CROSSFLOW ND GASMOB P01 PRODUCER 1 14000 MOBGRAD OFF OFF NA NA P02 PRODUCER 2 14000 MOBGRAD OFF ON ND GASMETHOD ENDWELLS +WELLHEAD +WELL NAME DEPTH METHOD +P01 P01WH 2052.2 23 +P02 P02WH 2152.2 25 +ENDWELLHEAD + NODES NAME TYPE DEPTH NODE1 test NA @@ -156,6 +175,7 @@ def test_write_surface_section(pvt_type, eos_details, expected_pvt_string): ENDCONSTRAINTS TIME 01/01/2021 + WELLLIST welllist1 CLEAR ADD @@ -185,12 +205,17 @@ def test_write_surface_section(pvt_type, eos_details, expected_pvt_string): ENDACTIVATE TIME 15/10/2021 + DEACTIVATE CONNECTION P02 P01 ENDDEACTIVATE +PROCS NAME STATIC_VARS PRIORITY 1 +THIS IS TEXT +ENDPROCS + """ # Act diff --git a/tests/Nexus/writing_tests/test_write_out_simulator.py b/tests/Nexus/writing_tests/test_write_out_simulator.py index fd7a5d7c..904252d8 100644 --- a/tests/Nexus/writing_tests/test_write_out_simulator.py +++ b/tests/Nexus/writing_tests/test_write_out_simulator.py @@ -268,6 +268,7 @@ def test_write_new_simulator(self, mocker): expected_surface_file_content = '''BLACKOIL TIME 01/01/2020 + CONSTRAINTS well1 QOSMAX 10240 ENDCONSTRAINTS