|
1 | 1 | """Tests for fmu.tools.nestedhybridgrid.nestedhybrid.""" |
2 | 2 |
|
| 3 | +from unittest.mock import patch |
| 4 | + |
3 | 5 | import numpy as np |
4 | 6 | import pandas as pd |
5 | 7 | import pytest |
@@ -864,3 +866,130 @@ def test_empty_dataframe_writes_skeleton(self, tmp_path): |
864 | 866 | nnc_to_flowsimulator_input(df, out) |
865 | 867 | lines = out.read_text().splitlines() |
866 | 868 | assert lines == ["NNC", "/"] |
| 869 | + |
| 870 | + |
| 871 | +# --------------------------------------------------------------------------- |
| 872 | +# Tests for NestedHybridGrid.from_rms and .to_rms |
| 873 | +# --------------------------------------------------------------------------- |
| 874 | + |
| 875 | + |
| 876 | +class TestNestedHybridGridRmsIO: |
| 877 | + """Tests for from_rms and to_rms.""" |
| 878 | + |
| 879 | + def _make_nhg(self): |
| 880 | + """Create a minimal NestedHybridGrid for testing.""" |
| 881 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 882 | + return NestedHybridGrid(coarse_grid=grid, region=region, refinement=(1, 1, 1)) |
| 883 | + |
| 884 | + def test_from_rms_returns_nestedhybridgrid(self): |
| 885 | + """from_rms should return a NestedHybridGrid instance.""" |
| 886 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 887 | + |
| 888 | + with ( |
| 889 | + patch("xtgeo.grid_from_roxar", return_value=grid) as mock_grid, |
| 890 | + patch("xtgeo.gridproperty_from_roxar", return_value=region) as mock_prop, |
| 891 | + ): |
| 892 | + nhg = NestedHybridGrid.from_rms( |
| 893 | + project="mock_project", |
| 894 | + grid_name="Grid", |
| 895 | + region_name="REGION", |
| 896 | + refinement=(1, 1, 1), |
| 897 | + ) |
| 898 | + |
| 899 | + assert isinstance(nhg, NestedHybridGrid) |
| 900 | + mock_grid.assert_called_once_with("mock_project", "Grid") |
| 901 | + mock_prop.assert_called_once_with("mock_project", "Grid", "REGION") |
| 902 | + |
| 903 | + def test_from_rms_no_properties_does_not_load_extras(self): |
| 904 | + """from_rms with properties=None should only load the region property.""" |
| 905 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 906 | + |
| 907 | + with ( |
| 908 | + patch("xtgeo.grid_from_roxar", return_value=grid), |
| 909 | + patch("xtgeo.gridproperty_from_roxar", return_value=region) as mock_prop, |
| 910 | + ): |
| 911 | + NestedHybridGrid.from_rms( |
| 912 | + project="mock_project", |
| 913 | + grid_name="Grid", |
| 914 | + region_name="REGION", |
| 915 | + refinement=(1, 1, 1), |
| 916 | + ) |
| 917 | + |
| 918 | + mock_prop.assert_called_once_with("mock_project", "Grid", "REGION") |
| 919 | + |
| 920 | + def test_from_rms_loads_optional_properties(self): |
| 921 | + """from_rms should load and append extra properties when provided.""" |
| 922 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 923 | + poro = _make_constant_property(grid, "PORO", 0.3) |
| 924 | + sw = _make_constant_property(grid, "SW", 0.8) |
| 925 | + |
| 926 | + with ( |
| 927 | + patch("xtgeo.grid_from_roxar", return_value=grid), |
| 928 | + patch( |
| 929 | + "xtgeo.gridproperty_from_roxar", |
| 930 | + side_effect=[region, poro, sw], |
| 931 | + ) as mock_prop, |
| 932 | + ): |
| 933 | + nhg = NestedHybridGrid.from_rms( |
| 934 | + project="mock_project", |
| 935 | + grid_name="Grid", |
| 936 | + region_name="REGION", |
| 937 | + refinement=(1, 1, 1), |
| 938 | + properties=["PORO", "SW"], |
| 939 | + ) |
| 940 | + |
| 941 | + assert mock_prop.call_count == 3 |
| 942 | + mock_prop.assert_any_call("mock_project", "Grid", "REGION") |
| 943 | + mock_prop.assert_any_call("mock_project", "Grid", "PORO") |
| 944 | + mock_prop.assert_any_call("mock_project", "Grid", "SW") |
| 945 | + assert isinstance(nhg, NestedHybridGrid) |
| 946 | + |
| 947 | + def test_from_rms_optional_properties_appear_in_merged_grid(self): |
| 948 | + """Properties loaded via from_rms should be present on the merged grid.""" |
| 949 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 950 | + poro = _make_constant_property(grid, "PORO", 0.3) |
| 951 | + |
| 952 | + with ( |
| 953 | + patch("xtgeo.grid_from_roxar", return_value=grid), |
| 954 | + patch("xtgeo.gridproperty_from_roxar", side_effect=[region, poro]), |
| 955 | + ): |
| 956 | + nhg = NestedHybridGrid.from_rms( |
| 957 | + project="mock_project", |
| 958 | + grid_name="Grid", |
| 959 | + region_name="REGION", |
| 960 | + refinement=(1, 1, 1), |
| 961 | + properties=["PORO"], |
| 962 | + ) |
| 963 | + |
| 964 | + prop_names = {p.name for p in nhg.properties} |
| 965 | + assert prop_names == {"REGION", "PORO"} |
| 966 | + |
| 967 | + def test_to_rms_writes_grid_once(self): |
| 968 | + """to_rms should call to_roxar on the grid exactly once.""" |
| 969 | + nhg = self._make_nhg() |
| 970 | + |
| 971 | + with ( |
| 972 | + patch.object(xtgeo.Grid, "to_roxar") as mock_grid_write, |
| 973 | + patch.object(xtgeo.GridProperty, "to_roxar") as mock_prop_write, |
| 974 | + ): |
| 975 | + nhg.to_rms("mock_project", "NestedGrid") |
| 976 | + |
| 977 | + mock_grid_write.assert_called_once_with("mock_project", "NestedGrid") |
| 978 | + mock_prop_write.assert_called_once_with("mock_project", "NestedGrid", "REGION") |
| 979 | + |
| 980 | + def test_to_rms_writes_each_property(self): |
| 981 | + """to_rms should call to_roxar for every property with correct args.""" |
| 982 | + grid, region, _ = _make_box_grid_with_region(dimension=(6, 6, 2)) |
| 983 | + poro = _make_constant_property(grid, "PORO", 0.3) |
| 984 | + grid.append_prop(poro) |
| 985 | + nhg = NestedHybridGrid(coarse_grid=grid, region=region, refinement=(1, 1, 1)) |
| 986 | + |
| 987 | + with ( |
| 988 | + patch.object(xtgeo.Grid, "to_roxar"), |
| 989 | + patch.object(xtgeo.GridProperty, "to_roxar") as mock_prop_write, |
| 990 | + ): |
| 991 | + nhg.to_rms("mock_project", "NestedGrid") |
| 992 | + |
| 993 | + assert mock_prop_write.call_count == len(nhg.properties) |
| 994 | + for prop in nhg.properties: |
| 995 | + mock_prop_write.assert_any_call("mock_project", "NestedGrid", prop.name) |
0 commit comments