diff --git a/.gitignore b/.gitignore index 29cf53ef64723c8b6822c87dc308132d623475bf..783a7aa28f771cc42ba8cc5cee2609bede24c08f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ dist tests/resources/test_output -pydoubletcalc_install \ No newline at end of file +pydoubletcalc_install + +workdir \ No newline at end of file diff --git a/pixi.lock b/pixi.lock index e0f720c2709a21cbfcbcf64c7cbe2b2cc8018d4d..b8901cf9ba2b0f8305d9b33472d52ea4357c5bb7 100644 --- a/pixi.lock +++ b/pixi.lock @@ -52,9 +52,11 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/dask-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dask-core-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/dbus-1.13.6-h5008d03_3.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distributed-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/et_xmlfile-2.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.0-h5888daf_0.conda @@ -63,6 +65,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/gflags-2.2.2-h5888daf_1005.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/glog-0.7.1-hbabe93e_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/google-crc32c-1.7.1-py313h74173ec_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-1.7.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda @@ -164,6 +167,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h3f2d84a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numba-0.62.1-py313hd8e3f9f_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numcodecs-0.16.5-py313h08cd8bf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.5-py313h17eae1a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.3-h5fbd93e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openpyxl-3.1.5-py313h9c9eb82_1.conda @@ -231,11 +235,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/virtualenv-20.34.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/watchdog-6.0.0-py313h78bf25f_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2024.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.17.3-py313h07c4f96_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2025.12.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxdmcp-1.1.5-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xyzservices-2025.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.1.5-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/zlib-1.3.1-hb9d3cd8_2.conda @@ -306,14 +312,17 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/cytoolz-1.0.1-py313ha7868ed_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dask-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/dask-core-2025.5.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/distributed-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/docutils-0.21.2-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/et_xmlfile-2.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/exceptiongroup-1.3.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/filelock-3.19.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/fsspec-2025.5.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/ghp-import-2.1.0-pyhd8ed1ab_2.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/google-crc32c-1.7.1-py313h5327936_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-1.7.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/h2-4.2.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/hpack-4.1.0-pyhd8ed1ab_0.conda @@ -400,6 +409,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/nh3-0.2.21-py39he870945_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numba-0.62.1-py313h924e429_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/numcodecs-0.16.5-py313hc90dcd4_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/numpy-2.2.5-py313hefb8edb_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.3-h4d64b90_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/openpyxl-3.1.5-py313he57e174_1.conda @@ -470,11 +480,13 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/watchdog-6.0.0-py313hfa70ccb_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/wheel-0.45.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/win_inet_pton-1.1.0-pyh7428d3b_8.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2024.9.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/wrapt-1.17.3-py313h5ea7bf4_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2025.12.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxau-1.0.12-h0e40799_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/xorg-libxdmcp-1.1.5-h0e40799_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/xyzservices-2025.4.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.1.5-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/zipp-3.21.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/zstandard-0.23.0-py313ha7868ed_2.conda @@ -1624,6 +1636,18 @@ packages: purls: [] size: 618596 timestamp: 1640112124844 +- conda: https://conda.anaconda.org/conda-forge/noarch/deprecated-1.3.1-pyhd8ed1ab_0.conda + sha256: c994a70449d548dd388768090c71c1da81e1e128a281547ab9022908d46878c5 + md5: bf74a83f7a0f2a21b5d709997402cac4 + depends: + - python >=3.10 + - wrapt <2,>=1.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/deprecated?source=hash-mapping + size: 15815 + timestamp: 1761813872696 - conda: https://conda.anaconda.org/conda-forge/noarch/distlib-0.4.0-pyhd8ed1ab_0.conda sha256: 6d977f0b2fc24fee21a9554389ab83070db341af6d6f09285360b2e09ef8b26e md5: 003b8ba0a94e2f1e117d0bd46aebc901 @@ -1674,6 +1698,18 @@ packages: - pkg:pypi/docutils?source=hash-mapping size: 402700 timestamp: 1733217860944 +- conda: https://conda.anaconda.org/conda-forge/noarch/donfig-0.8.1.post1-pyhd8ed1ab_1.conda + sha256: d58e97d418f71703e822c422af5b9c431e3621a0ecdc8b0334c1ca33e076dfe7 + md5: c56a7fa5597ad78b62e1f5d21f7f8b8f + depends: + - python >=3.9 + - pyyaml + license: MIT + license_family: MIT + purls: + - pkg:pypi/donfig?source=hash-mapping + size: 22491 + timestamp: 1734368817583 - conda: https://conda.anaconda.org/conda-forge/noarch/et_xmlfile-2.0.0-pyhd8ed1ab_1.conda sha256: 2209534fbf2f70c20661ff31f57ab6a97b82ee98812e8a2dcb2b36a0d345727c md5: 71bf9646cbfabf3022c8da4b6b4da737 @@ -1864,6 +1900,37 @@ packages: purls: [] size: 143452 timestamp: 1718284177264 +- conda: https://conda.anaconda.org/conda-forge/linux-64/google-crc32c-1.7.1-py313h74173ec_1.conda + sha256: 81ca7fb5c0756e3a5934fe18b44b90be475a03329bcd715334455aec340e34c0 + md5: 8580f244242b4d6a8c1933d8d0475b9c + depends: + - __glibc >=2.17,<3.0.a0 + - libcrc32c >=1.1.2,<1.2.0a0 + - libgcc >=14 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/google-crc32c?source=hash-mapping + size: 24798 + timestamp: 1755850411927 +- conda: https://conda.anaconda.org/conda-forge/win-64/google-crc32c-1.7.1-py313h5327936_1.conda + sha256: 5d1a3322ab5949c63326bbb779feaf47f95902849a9687da094e8de490250e22 + md5: 35b1131e4ea5eb0f27664eeb68c9a29b + depends: + - libcrc32c >=1.1.2,<1.2.0a0 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: Apache-2.0 + license_family: Apache + purls: + - pkg:pypi/google-crc32c?source=hash-mapping + size: 27799 + timestamp: 1755850484807 - conda: https://conda.anaconda.org/conda-forge/noarch/griffe-1.7.3-pyhd8ed1ab_0.conda sha256: c1e4039c9b6d613e8e9feafa21fae58db5eebeaa5f8bece5d8610154ae6ebf80 md5: aafe052f140a58b1afaf8ab473f5ac0d @@ -4178,6 +4245,46 @@ packages: - pkg:pypi/numba?source=hash-mapping size: 5706597 timestamp: 1759165298367 +- conda: https://conda.anaconda.org/conda-forge/linux-64/numcodecs-0.16.5-py313h08cd8bf_0.conda + sha256: 7c35d46639f8638849535a22cb7ae1b7210121be0c7b053d8e2ab7ed485e6bff + md5: 0f394ef25fb81d1dec8ff4fa716f00bd + depends: + - __glibc >=2.17,<3.0.a0 + - deprecated + - libgcc >=14 + - libstdcxx >=14 + - msgpack-python + - numpy >=1.23,<3 + - numpy >=1.24 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - typing_extensions + license: MIT + license_family: MIT + purls: + - pkg:pypi/numcodecs?source=hash-mapping + size: 808201 + timestamp: 1764782369322 +- conda: https://conda.anaconda.org/conda-forge/win-64/numcodecs-0.16.5-py313hc90dcd4_0.conda + sha256: 008d11564f2a3bac16ea0e323a02b24ca06fb28f8b74c01cde13098003c35b9b + md5: 4006d795b35200d0d6e28a1de84dfcc5 + depends: + - deprecated + - msgpack-python + - numpy >=1.23,<3 + - numpy >=1.24 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - typing_extensions + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: MIT + license_family: MIT + purls: + - pkg:pypi/numcodecs?source=hash-mapping + size: 516677 + timestamp: 1764782612807 - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.2.5-py313h17eae1a_0.conda sha256: c0a200d0e53a1acbfa1d1e2277e3337ea2aa8cb584448790317a98c62dcaebce md5: 6ceeff9ed72e54e4a2f9a1c88f47bdde @@ -4945,10 +5052,10 @@ packages: - pypi: ./ name: pythermogis version: 1.2.0 - sha256: 35de67af8136fb6442b90f5a2956e6ac57f8a6f52f1fbbfad15768e83e08b31f + sha256: 5307b5b9e674861991952ee2bb4da21dfc517e11259fd4ed7735f28b5fb54408 requires_dist: - jpype1>=1.5.2,<2 - - xarray==2024.9.0.* + - xarray==2025.12.0.* - pandas>=2.2.3,<3 - pytz>=2024.1,<2025 - build>=1.2.2.post1,<2 @@ -5949,41 +6056,73 @@ packages: - pkg:pypi/win-inet-pton?source=hash-mapping size: 9555 timestamp: 1733130678956 -- conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2024.9.0-pyhd8ed1ab_1.conda - sha256: 8bb5b522cdf1905d831a9b371a3a3bd2932a9f53398332fbd38ed3442015bbaf - md5: dc790d427d89b85ae12fc094e264833f +- conda: https://conda.anaconda.org/conda-forge/linux-64/wrapt-1.17.3-py313h07c4f96_1.conda + sha256: 3688598866224e3fbeed8a74f12fd0a3c19dadcb931ce778bdc6cc2e04621b3b + md5: c2662497e9a9ff2153753682f53989c9 depends: - - numpy >=1.24 - - packaging >=23.1 - - pandas >=2.1 - - python >=3.10 + - __glibc >=2.17,<3.0.a0 + - libgcc >=14 + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt?source=hash-mapping + size: 64865 + timestamp: 1756851811052 +- conda: https://conda.anaconda.org/conda-forge/win-64/wrapt-1.17.3-py313h5ea7bf4_1.conda + sha256: 260a3295f39565c28be9232a11ca7ee435af6e9366ffd2569ff29a63e7c144a0 + md5: 3e199c8db04833fe628867462aeaca24 + depends: + - python >=3.13,<3.14.0a0 + - python_abi 3.13.* *_cp313 + - ucrt >=10.0.20348.0 + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + license: BSD-2-Clause + license_family: BSD + purls: + - pkg:pypi/wrapt?source=hash-mapping + size: 63385 + timestamp: 1756851987645 +- conda: https://conda.anaconda.org/conda-forge/noarch/xarray-2025.12.0-pyhcf101f3_0.conda + sha256: b35f6848f229d65dc6e6d58a232099a5e293405a5e3e369b15110ed255cf9872 + md5: efdb3ef0ff549959650ef070ba2c52d2 + depends: + - python >=3.11 + - numpy >=1.26 + - packaging >=24.1 + - pandas >=2.2 + - python constrains: - - seaborn-base >=0.12 - - distributed >=2023.9 - - scipy >=1.11 + - bottleneck >=1.4 + - cartopy >=0.23 + - cftime >=1.6 + - dask-core >=2024.6 + - distributed >=2024.6 + - flox >=0.9 + - h5netcdf >=1.3 + - h5py >=3.11 + - hdf5 >=1.14 + - iris >=3.9 + - matplotlib-base >=3.8 + - nc-time-axis >=1.4 - netcdf4 >=1.6.0 + - numba >=0.60 + - numbagg >=0.8 + - pint >=0.24 + - pydap >=3.5.0 + - scipy >=1.13 + - seaborn-base >=0.13 + - sparse >=0.15 - toolz >=0.12 - - nc-time-axis >=1.4 - - cftime >=1.6 - - h5netcdf >=1.2 - - matplotlib-base >=3.7 - - h5py >=3.8 - - zarr >=2.16 - - hdf5 >=1.12 - - numba >=0.57 - - iris >=3.7 - - cartopy >=0.22 - - dask-core >=2023.9 - - flox >=0.7 - - bottleneck >=1.3 - - pint >=0.22 - - sparse >=0.14 + - zarr >=2.18 license: Apache-2.0 license_family: APACHE purls: - pkg:pypi/xarray?source=hash-mapping - size: 801066 - timestamp: 1728453306227 + size: 994025 + timestamp: 1764974555156 - conda: https://conda.anaconda.org/conda-forge/linux-64/xorg-libxau-1.0.12-hb9d3cd8_0.conda sha256: ed10c9283974d311855ae08a16dfd7e56241fac632aec3b92e3cfe73cff31038 md5: f6ebe2cb3f82ba6c057dde5d9debe4f7 @@ -6062,6 +6201,27 @@ packages: purls: [] size: 63274 timestamp: 1641347623319 +- conda: https://conda.anaconda.org/conda-forge/noarch/zarr-3.1.5-pyhcf101f3_0.conda + sha256: c36bec7d02d2f227409fcc4cf586cf3a658af068b58374de7f8f2d0b5c1c84f9 + md5: c1844a94b2be61bb03bbb71574a0abfc + depends: + - python >=3.11 + - packaging >=22.0 + - numpy >=1.26 + - numcodecs >=0.14 + - typing_extensions >=4.9 + - donfig >=0.8 + - google-crc32c >=1.5 + - python + constrains: + - fsspec >=2023.10.0 + - obstore >=0.5.1 + license: MIT + license_family: MIT + purls: + - pkg:pypi/zarr?source=hash-mapping + size: 305998 + timestamp: 1763742695201 - conda: https://conda.anaconda.org/conda-forge/noarch/zict-3.0.0-pyhd8ed1ab_1.conda sha256: 5488542dceeb9f2874e726646548ecc5608060934d6f9ceaa7c6a48c61f9cc8d md5: e52c2ef711ccf31bb7f70ca87d144b9e diff --git a/pyproject.toml b/pyproject.toml index b0c22a3131b0acb86fdaf281056289941822f0c8..e418f04ff01ac1f51b1abb5c55780621e40827c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ license = { file = "LICENSE" } requires-python = ">=3.11" dependencies = [ "jpype1>=1.5.2,<2", - "xarray==2024.9.0.*", + "xarray==2025.12.0.*", "pandas>=2.2.3,<3", "pytz>=2024.1,<2025", "build>=1.2.2.post1,<2", @@ -42,6 +42,7 @@ platforms = ["win-64", "linux-64"] [tool.pixi.pypi-dependencies] pythermogis = { path = ".", editable = true } +#pydoubletcalc = { path = 'C:\Users\knappersfy\work\thermogis\pydoubletcalc', editable = true } [tool.pixi.tasks] test = "PYTHONPATH=src/pythermogis pytest -s tests/" @@ -53,7 +54,7 @@ pytg = "PYTHONPATH=src pixi run python src/pythermogis/main.py" [tool.pixi.dependencies] python = ">=3.13.2,<3.14" jpype1 = ">=1.5.2,<2" -xarray = "2024.9.0.*" +xarray = "2025.12.0.*" pandas = ">=2.2.3,<3" setuptools = ">=75.8.2,<76" wheel = ">=0.45.1,<0.46" @@ -71,6 +72,7 @@ pre-commit = ">=4.3.0,<5" python-dotenv = ">=1.2.1,<2" numba = ">=0.62.1,<0.63" ruff = ">=0.14.8,<0.15" +zarr = ">=3.1.5,<4" [tool.ruff] line-length = 88 diff --git a/src/pythermogis/thermogis_classes/doublet.py b/src/pythermogis/thermogis_classes/doublet.py index 50d31633c4abef871eecaac9fed89b9e0e2ed200..b802ca15b9ed516bdd25491967f1cd0f68800773 100644 --- a/src/pythermogis/thermogis_classes/doublet.py +++ b/src/pythermogis/thermogis_classes/doublet.py @@ -2,7 +2,7 @@ import numpy as np import xarray as xr from jpype import JClass from pythermogis.workflow.utc.doublet import calculate_doublet_performance, DoubletInput, DoubletOutput -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration def simulate_doublet( diff --git a/src/pythermogis/transmissivity/calculate_thick_perm_trans.py b/src/pythermogis/transmissivity/calculate_thick_perm_trans.py index aa485e7c230112f5b9149ef0388e66f43fdd6025..05a65b7ed7cc12e575df0f0c041881e3ac0bb658 100644 --- a/src/pythermogis/transmissivity/calculate_thick_perm_trans.py +++ b/src/pythermogis/transmissivity/calculate_thick_perm_trans.py @@ -1,6 +1,9 @@ import numpy as np from scipy import stats import xarray as xr +from numba import njit, prange +from numpy.typing import NDArray + def generate_thickness_permeability_transmissivity_for_pvalues(thickness_mean: float, thickness_sd: float, ln_permeability_mean: float, ln_permeability_sd: float, p_values: xr.DataArray, nSamples: int = 10000) -> float: """ @@ -52,4 +55,66 @@ def generate_thickness_permeability_transmissivity_for_pvalues(thickness_mean: f sample_indexes = np.array(p_value_fractions * nSamples) transmissivity_pvalues_sampled = transmissivity_samples[sample_indexes.astype(int)] - return thickness_pvalues, permeability_pvalues, transmissivity_pvalues_sampled \ No newline at end of file + return thickness_pvalues, permeability_pvalues, transmissivity_pvalues_sampled + + +@njit(parallel=True) +def calculate_transmissivity( + thickness_mean: NDArray[np.float64], + thickness_sd: NDArray[np.float64], + ln_perm_mean: NDArray[np.float64], + ln_perm_sd: NDArray[np.float64], + quantile: float, + z_score: float, + n_samples: int, +): + shape = thickness_mean.shape + tm_flat = thickness_mean.ravel() + ts_flat = thickness_sd.ravel() + lpm_flat = ln_perm_mean.ravel() + lps_flat = ln_perm_sd.ravel() + + n_cells = tm_flat.size + idx = int(quantile * n_samples) + + thickness_p = np.empty(n_cells) + permeability_p = np.empty(n_cells) + transmissivity_p = np.empty(n_cells) + + for i in prange(n_cells): + tm = tm_flat[i] + ts = ts_flat[i] + lpm = lpm_flat[i] + lps = lps_flat[i] + + if np.isnan(tm) or np.isnan(ts) or np.isnan(lpm) or np.isnan(lps): + thickness_p[i] = np.nan + permeability_p[i] = np.nan + transmissivity_p[i] = np.nan + continue + + # Generate samples for this cell + thickness_samples = np.empty(n_samples) + ln_perm_samples = np.empty(n_samples) + + for j in range(n_samples): + if ts == 0: + thickness_samples[j] = tm + else: + thickness_samples[j] = max(0.01, np.random.normal(tm, ts)) + ln_perm_samples[j] = np.random.normal(lpm, lps) + + # Transmissivity samples + tr_samples = np.exp(ln_perm_samples) * thickness_samples + tr_samples.sort() + transmissivity_p[i] = tr_samples[idx] + + # Analytical percentiles + thickness_p[i] = tm + z_score * ts if ts > 0 else tm + permeability_p[i] = np.exp(lpm + z_score * lps) + + return ( + thickness_p.reshape(shape), + permeability_p.reshape(shape), + transmissivity_p.reshape(shape), + ) \ No newline at end of file diff --git a/src/pythermogis/workflow/utc/utc_properties.py b/src/pythermogis/workflow/utc/configuration.py similarity index 82% rename from src/pythermogis/workflow/utc/utc_properties.py rename to src/pythermogis/workflow/utc/configuration.py index b9f939956f915275bdb3d071101dea87f3b6e992..483bc2e3e9fcdfb91bb84164d76f16a1e956539b 100644 --- a/src/pythermogis/workflow/utc/utc_properties.py +++ b/src/pythermogis/workflow/utc/configuration.py @@ -62,16 +62,16 @@ class UTCConfiguration: ) property_grid_infos: list[PropertyGridInfo] = field( default_factory=lambda: [ - PropertyGridInfo("Permeability", False, "__k.zmap"), - PropertyGridInfo("PermeabilityLNSD", False, "__k_lnsd.zmap"), - PropertyGridInfo("Porosity", False, "__phi.zmap"), - PropertyGridInfo("Thickness", False, "__thick.zmap"), - PropertyGridInfo("ThicknessSD", False, "__thick_sd.zmap"), - PropertyGridInfo("Depth", False, "__top.zmap"), - PropertyGridInfo("NetToGross", False, "__ntg.zmap"), - PropertyGridInfo("Temperature", True, "__temperature.zmap"), - PropertyGridInfo("HCAccum", True, "__hc_accum.zmap"), - PropertyGridInfo("BoundaryShapefile", True, "__BoundaryShapefile.shp"), + PropertyGridInfo("permeability", False, "__k.nc"), + PropertyGridInfo("permeability_lnsd", False, "__k_ln_sd.nc"), + PropertyGridInfo("porosity", False, "__phi.nc"), + PropertyGridInfo("thickness", False, "__thick.nc"), + PropertyGridInfo("thickness_sd", False, "__thick_sd.nc"), + PropertyGridInfo("depth", False, "__top.nc"), + PropertyGridInfo("ntg", False, "__ntg.nc"), + PropertyGridInfo("temperature", True, "__temperature.nc"), + PropertyGridInfo("hc_accum", False, "__hc_accum.nc"), + PropertyGridInfo("boundary_shapefile", True, "__BoundaryShapefile.nc"), ] ) copy_aquifer_files_info: list[AquiferFile] = field( @@ -82,15 +82,13 @@ class UTCConfiguration: AquiferFile("__points_QC.shp", "__points_QC.shp"), ] ) - scenario: str = "basecase" + scenario: str = "BaseCase" scen_suffix: str = "" temp_from_grid: bool = False exclude_hc_accum: bool = True use_bounding_shape: bool = False grid_ext: str = ".nc" - p_values: list[float] = field( - default_factory=lambda: [10.0, 30.0, 50.0, 70.0, 90.0] - ) + p_values: list[float] = field(default_factory=lambda: [10.0, 30.0, 50.0, 90.0]) # temp_voxet: 'Voxet' = None surface_temperature: float = 10.0 temp_gradient: float = 31.0 @@ -119,13 +117,13 @@ class UTCConfiguration: max_cooling_temp_range: float = 100.0 hp_minimum_injection_temperature: float = 15.0 ates_charge_temp: float = 80.0 - econ_lifetime_years: int = 15 + econ_lifetime_years: int = 30 ates_min_flow: float = 0.0 hp_include_elect_heat_in_power: bool = False set_all_values_to_final_rosim_year: bool = False max_flow: float = 500.0 charge_temp: float = 80.0 - anisotropy: float = 5.0 + anisotropy: float = 3.0 filter_fraction: float = 0.8 salinity_surface: float = 0.0 salinity_gradient: float = 46.67 @@ -160,19 +158,19 @@ class UTCConfiguration: stim_add_skin_prod: float = -3.0 stimulation_capex: float = 0.5 hp_calc_cop: bool = True - imposed_cop: float = 3.0 - hp_capex: float = 600.0 - hp_opex: float = 60.0 + imposed_cop: float = 4.0 + hp_capex: float = 200.0 + hp_opex: float = 10.0 hp_alternative_heating_price: float = 2.8 viscosity_mode: ViscosityMode = "batzlewang" # Economical data - economic_lifetime: int = 15 + economic_lifetime: int = 30 drilling_time: int = 2 tax_rate: float = 0.25 interest_loan: float = 0.05 - inflation: float = 0.02 - equity_return: float = 0.07 + inflation: float = 0.015 + equity_return: float = 0.145 debt_equity: float = 0.8 ecn_eia: float = 0.0 tolerance_utc_increase: float = 0.0 @@ -182,7 +180,7 @@ class UTCConfiguration: elec_purchase_price: float = 8.0 opex_per_energy: float = 0.19 opex_per_capex: float = 0.0 - well_cost_scaling: float = 1.5 + well_cost_scaling: float = 1.3 well_cost_const: float = 0.25 well_cost_z: float = 700.0 well_cost_z2: float = 0.2 diff --git a/src/pythermogis/workflow/utc/cooling_temp.py b/src/pythermogis/workflow/utc/cooling_temp.py index cca4291d4fb5b1c36fb054bbd555817e51725e8b..42caf4ddf6e432e736e49a1c8bc44ecd36bfdcec 100644 --- a/src/pythermogis/workflow/utc/cooling_temp.py +++ b/src/pythermogis/workflow/utc/cooling_temp.py @@ -6,8 +6,8 @@ from pythermogis.workflow.utc.doublet_utils import calc_lifetime from pythermogis.workflow.utc.flow import calculate_volumetric_flow if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration def calculate_cooling_temperature( diff --git a/src/pythermogis/workflow/utc/doublet.py b/src/pythermogis/workflow/utc/doublet.py index 61ecb11951f3a2783aa41e23217ed735ed6f8343..e35125d1f5784c93ac35a779acb176c452e3dc2a 100644 --- a/src/pythermogis/workflow/utc/doublet.py +++ b/src/pythermogis/workflow/utc/doublet.py @@ -3,6 +3,7 @@ from dataclasses import dataclass from typing import NamedTuple from pythermogis.utils.timer import print_time +from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.constants import DARCY_SI from pythermogis.workflow.utc.cooling_temp import calculate_cooling_temperature from pythermogis.workflow.utc.doublet_utils import ( @@ -10,7 +11,6 @@ from pythermogis.workflow.utc.doublet_utils import ( calculate_injection_temp_with_heat_pump, ) from pythermogis.workflow.utc.pressure import calculate_max_pressure, optimize_pressure -from pythermogis.workflow.utc.utc_properties import UTCConfiguration from pythermogis.workflow.utc.well_distance import optimize_well_distance EUR_PER_CT_PER_KWH = 0.36 diff --git a/src/pythermogis/workflow/utc/doubletcalc.py b/src/pythermogis/workflow/utc/doubletcalc.py index 78fc61f211e1b64e96e389ccde13ae731c51672b..8bf300b29499db94b5582e1818a0d98560fdc4fe 100644 --- a/src/pythermogis/workflow/utc/doubletcalc.py +++ b/src/pythermogis/workflow/utc/doubletcalc.py @@ -10,8 +10,8 @@ from pythermogis.workflow.utc.rock import get_geothermal_gradient from pythermogis.workflow.utc.water import get_salinity if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration INCH_SI = 0.0254 diff --git a/src/pythermogis/workflow/utc/economics.py b/src/pythermogis/workflow/utc/economics.py index de4329805314623fad11a7aed98ff9de99644f81..53865442baeec9c3aa768d9ee9c16a620550358b 100644 --- a/src/pythermogis/workflow/utc/economics.py +++ b/src/pythermogis/workflow/utc/economics.py @@ -9,8 +9,8 @@ from numpy.typing import NDArray from pythermogis.workflow.utc.doublet_utils import get_along_hole_length if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration SECONDS_IN_YEAR = 365 * 24 * 3600 MJ_TO_GJ = 1e-3 diff --git a/src/pythermogis/workflow/utc/flow.py b/src/pythermogis/workflow/utc/flow.py index 7fc51d20ea1c6c6cc53a36a3c78889dc9a7293e3..2c964d729f44060d7fd749f4229fd08644e9cee6 100644 --- a/src/pythermogis/workflow/utc/flow.py +++ b/src/pythermogis/workflow/utc/flow.py @@ -9,8 +9,8 @@ from pythermogis.workflow.utc.doubletcalc import doubletcalc from pythermogis.workflow.utc.heatpump import calculate_heat_pump_performance if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration class VolumetricFlowResults(NamedTuple): diff --git a/src/pythermogis/workflow/utc/heatpump.py b/src/pythermogis/workflow/utc/heatpump.py index b2d7a776fa8bbd7932f6c5a27895842a10633d89..86bcb60714c581300bc4f611e221da74873444a0 100644 --- a/src/pythermogis/workflow/utc/heatpump.py +++ b/src/pythermogis/workflow/utc/heatpump.py @@ -11,8 +11,8 @@ from pythermogis.workflow.utc.water import ( ) if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration class HeatPumpPerformanceResults(NamedTuple): diff --git a/src/pythermogis/workflow/utc/pressure.py b/src/pythermogis/workflow/utc/pressure.py index 244bab4d3ea0b1399ba07be67f5a7152c3d53218..6c2c9e4fb94cbbe52479b819f69b6da148986052 100644 --- a/src/pythermogis/workflow/utc/pressure.py +++ b/src/pythermogis/workflow/utc/pressure.py @@ -6,8 +6,8 @@ from pythermogis.workflow.utc.economics import calculate_economics from pythermogis.workflow.utc.flow import calculate_volumetric_flow if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration def calculate_max_pressure( diff --git a/src/pythermogis/workflow/utc/stats.py b/src/pythermogis/workflow/utc/stats.py new file mode 100644 index 0000000000000000000000000000000000000000..4ac8462d12cf3530f38c1e87147796a2f1564d46 --- /dev/null +++ b/src/pythermogis/workflow/utc/stats.py @@ -0,0 +1,12 @@ +import numpy as np +from scipy.stats import norm + + +def lognormal_quantile(mean, sd, p): + z = norm.ppf(1 - p / 100) + return mean * np.exp(sd * z) + + +def normal_quantile(mean, sd, p): + z = norm.ppf(1 - p / 100) + return mean + sd * z diff --git a/src/pythermogis/workflow/utc/utc.py b/src/pythermogis/workflow/utc/utc.py new file mode 100644 index 0000000000000000000000000000000000000000..129cabaf4bce342e6e469c56eecd323d4ab3b351 --- /dev/null +++ b/src/pythermogis/workflow/utc/utc.py @@ -0,0 +1,229 @@ +import time +from pathlib import Path + +import numpy as np +import xarray as xr +from scipy.special import ndtri + +from pythermogis.transmissivity.calculate_thick_perm_trans import ( + calculate_transmissivity, +) +from pythermogis.workflow.utc.configuration import UTCConfiguration +from pythermogis.workflow.utc.doublet import ( + DoubletInput, + DoubletOutput, + calculate_doublet_performance, +) + +OUTPUT_NAMES = list(DoubletOutput.__annotations__.keys()) +NAN_OUTPUTS = DoubletOutput(*[np.nan] * len(OUTPUT_NAMES)) # type: ignore[arg-type] +ZERO_OUTPUTS = DoubletOutput(*[0.0] * len(OUTPUT_NAMES)) # type: ignore[arg-type] + + +def run_utc_workflow(config: UTCConfiguration) -> xr.DataTree: + root = xr.DataTree() + base = Path(config.input_data_dir) + + temperature_model = xr.open_dataset( + base / "NetherlandsTemperatureModel_extended.nc" + ).transpose("y", "x", "z") + + for aquifer in config.aquifers: + aquifer_ds = xr.Dataset() + + for gridinfo in config.property_grid_infos: + if gridinfo.optional: + continue + + filename = f"{aquifer}{gridinfo.postfix}" + fullpath = base / filename + + if not fullpath.exists(): + raise FileNotFoundError(f"Required grid not found: {fullpath}") + + ds = xr.open_dataset(fullpath) + + varnames = [v for v in ds.data_vars if v != "oblique_stereographic"] + if len(varnames) != 1: + raise ValueError( + f"Expected exactly one property variable in" + f" {fullpath}, found {varnames}" + ) + + varname = varnames[0] + + aquifer_ds[gridinfo.name] = ds[varname] + + root[aquifer] = xr.DataTree(dataset=aquifer_ds, name=aquifer) + + for aquifer in root.children: + print(f"\nProcessing aquifer: {aquifer}") + + start = time.perf_counter() + + aquifer_ds = root[aquifer].to_dataset() + updated_ds = compute_results_for_aquifer( + aquifer_ds, aquifer, config, temperature_model + ) + root[aquifer] = xr.DataTree(dataset=updated_ds, name=aquifer) + + end = time.perf_counter() + elapsed = end - start + + print(f"Time required for aquifer {aquifer}: {elapsed:.2f} seconds.") + + if config.results_dir != "": + zarr_path = f"{config.results_dir}/ROSL_ROSLU_test.zarr" + root.to_zarr(zarr_path, mode="w") + + return root + + +def compute_results_for_aquifer( + aquifer_ds: xr.Dataset, + aquifer_name: str, + config: UTCConfiguration, + temperature_model: xr.Dataset, +): + # apply hc mask + hc_mask = aquifer_ds["hc_accum"] != 0 + vars_to_mask = [ + "thickness", + "ntg", + "depth", + "porosity", + ] + + for v in vars_to_mask: + aquifer_ds[v] = aquifer_ds[v].where(hc_mask) + + # calc temperature grid + mid_depth = -(aquifer_ds["depth"] + 0.5 * aquifer_ds["thickness"]) + temp_xy_aligned = temperature_model["temperature"].interp( + x=aquifer_ds.x, y=aquifer_ds.y, method="linear" + ) + temperature = temp_xy_aligned.interp(z=mid_depth, method="linear") + + aquifer_ds["temperature"] = temperature + + for p_value in config.p_values: + # calc transmissivity(_with_ntg) + stoch_results = apply_stochastics(aquifer_ds, p_value) + aquifer_ds["transmissivity"] = stoch_results["transmissivity"] + aquifer_ds["transmissivity_with_ntg"] = stoch_results["transmissivity_with_ntg"] + aquifer_ds["thickness"] = stoch_results["thickness"] + aquifer_ds["permeability"] = stoch_results["permeability"] + + results = xr.apply_ufunc( + cell_calculation, + 1.0e30, + aquifer_ds["thickness"], + aquifer_ds["transmissivity"], + aquifer_ds["transmissivity_with_ntg"], + aquifer_ds["ntg"], + aquifer_ds["depth"], + aquifer_ds["porosity"], + aquifer_ds["temperature"], + kwargs={"config": config}, + input_core_dims=[[]] * 8, + output_core_dims=[[] for _ in OUTPUT_NAMES], + vectorize=True, + dask="parallelized", + output_dtypes=[np.float64] * len(OUTPUT_NAMES), + ) + + for name, result in zip(OUTPUT_NAMES, results, strict=True): + aquifer_ds[f"{name}_p{p_value}"] = result + + aquifer_ds.compute() + + print(f"Computed results for {aquifer_name}") + + return aquifer_ds + + +def apply_stochastics( + aquifer_ds: xr.Dataset, + p_value: float, + n_samples: int = 10_000, +) -> xr.Dataset: + + q = 1.0 - p_value / 100.0 + z = ndtri(q) + + thickness_p, permeability_p, transmissivity_p = calculate_transmissivity( + aquifer_ds["thickness"].values, + aquifer_ds["thickness_sd"].values, + np.log(aquifer_ds["permeability"].values), + aquifer_ds["permeability_lnsd"].values, + q, + z, + n_samples, + ) + + transmissivity_with_ntg = transmissivity_p * aquifer_ds["ntg"] / 1000.0 + transmissivity_with_ntg = transmissivity_with_ntg.where( + transmissivity_with_ntg >= 0 + ) + + return xr.Dataset( + { + "thickness": (aquifer_ds["thickness"].dims, thickness_p), + "permeability": (aquifer_ds["thickness"].dims, permeability_p), + "transmissivity": (aquifer_ds["thickness"].dims, transmissivity_p), + "transmissivity_with_ntg": transmissivity_with_ntg, + }, + coords=aquifer_ds.coords, + ) + + +def cell_calculation( + unknown_input_value: float, + thickness: float, + transmissivity: float, + transmissivity_with_ntg: float, + ntg: float, + depth: float, + porosity: float, + temperature: float, + config: UTCConfiguration, +) -> DoubletOutput: + inputs = [ + unknown_input_value, + thickness, + transmissivity, + transmissivity_with_ntg, + ntg, + depth, + porosity, + temperature, + ] + if any(np.isnan(v) for v in inputs): + return NAN_OUTPUTS + + if transmissivity_with_ntg < config.kh_cutoff: + return ZERO_OUTPUTS + + doublet_input = DoubletInput( + unknown_input_value=unknown_input_value, + thickness=thickness, + transmissivity=transmissivity, + transmissivity_with_ntg=transmissivity_with_ntg, + ntg=ntg, + depth=depth, + porosity=porosity / 100, + temperature=temperature, + ) + + try: + result = calculate_doublet_performance(config, doublet_input) + except ValueError: + return NAN_OUTPUTS + + if result is None: + return NAN_OUTPUTS + + if result.utc > 1000: + result = result._replace(utc=1000) + + return result diff --git a/src/pythermogis/workflow/utc/well_distance.py b/src/pythermogis/workflow/utc/well_distance.py index 4a585274297843fa5249167a6b9fc440d8e26528..f84e75be96cd01f04219507429dfcb924c44e321 100644 --- a/src/pythermogis/workflow/utc/well_distance.py +++ b/src/pythermogis/workflow/utc/well_distance.py @@ -9,8 +9,8 @@ from pythermogis.workflow.utc.doublet_utils import calc_lifetime from pythermogis.workflow.utc.flow import calculate_volumetric_flow if TYPE_CHECKING: + from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.doublet import DoubletInput - from pythermogis.workflow.utc.utc_properties import UTCConfiguration def optimize_well_distance_original( diff --git a/tests/utc/test_calculate_volumetric_flow.py b/tests/utc/test_calculate_volumetric_flow.py index f3059727e750f4629d42d09c788abb5865c8dd34..aedbc493055ac508230bd013ef8cad7d1781f067 100644 --- a/tests/utc/test_calculate_volumetric_flow.py +++ b/tests/utc/test_calculate_volumetric_flow.py @@ -2,7 +2,7 @@ import numpy as np from pythermogis.workflow.utc.doublet import DoubletInput from pythermogis.workflow.utc.flow import calculate_volumetric_flow -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration def test_calculate_volumetric_flow(): diff --git a/tests/utc/test_doublet.py b/tests/utc/test_doublet.py index e42d93acbc41a18effb6747f9451640e18258733..e370b419a7579f02f3731ffc328f93de6e95c508 100644 --- a/tests/utc/test_doublet.py +++ b/tests/utc/test_doublet.py @@ -4,7 +4,7 @@ import numpy as np from pythermogis.workflow.utc.doublet import DoubletInput, calculate_doublet_performance -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration def test_calculate_doublet_performance_precise(): @@ -42,12 +42,12 @@ def test_calculate_doublet_performance_precise(): rtol = 0.005 # accurate to 0.5% assert np.isclose(result.flow, 227.2757568359375, rtol=rtol) assert np.isclose(result.pres, 60, rtol=rtol) - assert np.isclose(result.utc, 6.616096470753937, rtol=rtol) + assert np.isclose(result.utc, 5.885437310055949, rtol=rtol) assert np.isclose(result.welld, 1159.17968, rtol=rtol) assert np.isclose(result.power, 8.636903762817383, rtol=rtol) assert np.isclose(result.cop, 13.627557754516602, rtol=rtol) - assert np.isclose(result.var_opex, -7.510325908660889, rtol=rtol) - assert np.isclose(result.fixed_opex, -11.227973937988281, rtol=rtol) + assert np.isclose(result.var_opex, -16.189716379776353, rtol=rtol) + assert np.isclose(result.fixed_opex, -24.199008115259968, rtol=rtol) def test_calculate_doublet_performance_approximate(): # Arrange: instantiate default UTCConfiguration @@ -86,12 +86,12 @@ def test_calculate_doublet_performance_approximate(): rtol = 0.01 # accurate to 1% assert np.isclose(result.flow, 227.2757568359375, rtol=rtol) assert np.isclose(result.pres, 60, rtol=rtol) - assert np.isclose(result.utc, 6.616096470753937, rtol=rtol) + assert np.isclose(result.utc, 5.885437310055949, rtol=rtol) assert np.isclose(result.welld, 1159.17968, rtol=rtol) assert np.isclose(result.power, 8.636903762817383, rtol=rtol) assert np.isclose(result.cop, 13.627557754516602, rtol=rtol) - assert np.isclose(result.var_opex, -7.510325908660889, rtol=rtol) - assert np.isclose(result.fixed_opex, -11.227973937988281, rtol=rtol) + assert np.isclose(result.var_opex, -16.189716379776353, rtol=rtol) + assert np.isclose(result.fixed_opex, -24.199008115259968, rtol=rtol) def test_calculate_doublet_performance(): # 85ish it/s @@ -140,3 +140,26 @@ def test_calculate_doublet_performance(): f"{n_sims} simulations took: {time_elapsed:.1f} seconds\n" f"{n_sims/time_elapsed:.1f} simulations per second" ) + + +def test_why_does_this_fail(): + props = UTCConfiguration( + segment_length=1, + dh_return_temp=40 + ) + + # Create a minimal valid DoubletInput + input_data = DoubletInput( + unknown_input_value=-9999, + thickness=5.259, + transmissivity=1239.250, + transmissivity_with_ntg=1.032, + ntg=0.8331, + depth=852.969, + porosity=0.22168, + temperature=39.30, + ) + + # Act + results = calculate_doublet_performance(props, input_data) + print(results) diff --git a/tests/utc/test_doubletcalc.py b/tests/utc/test_doubletcalc.py index e49d5d10925f030c41ca77b3e45b39ee32d0e8c7..ce52c4f97bd7473e674925ee80bac8f292085d4a 100644 --- a/tests/utc/test_doubletcalc.py +++ b/tests/utc/test_doubletcalc.py @@ -5,7 +5,7 @@ import pytest from pythermogis.workflow.utc.doublet import DoubletInput from pythermogis.workflow.utc.doubletcalc import doubletcalc -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration def test_doubletcalc(): diff --git a/tests/utc/test_properties.py b/tests/utc/test_properties.py index ab98eb17c08247970d6bd8f91131fd2721919c52..06fbc9560ce0de1ebf8d9df61645836c977fb2f8 100644 --- a/tests/utc/test_properties.py +++ b/tests/utc/test_properties.py @@ -1,4 +1,4 @@ -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration def test_utc_configuration_instantiation(): @@ -10,20 +10,20 @@ def test_utc_configuration_instantiation(): assert isinstance(cfg.copy_aquifer_files_info, list) assert cfg.n_threads == 1 assert cfg.is_ates is False - assert cfg.scenario == "basecase" + assert cfg.scenario == "BaseCase" assert cfg.viscosity_mode == "batzlewang" assert cfg.surface_temperature == 10.0 assert cfg.temp_gradient == 31.0 assert 30.0 in cfg.p_values - assert cfg.p_values == [10.0, 30.0, 50.0, 70.0, 90.0] - assert cfg.property_grid_infos[0].name == "Permeability" + assert cfg.p_values == [10.0, 30.0, 50.0, 90.0] + assert cfg.property_grid_infos[0].name == "permeability" assert cfg.property_grid_infos[0].optional is False - assert cfg.property_grid_infos[0].postfix.endswith(".zmap") + assert cfg.property_grid_infos[0].postfix.endswith(".nc") assert len(cfg.aquifers) > 10 assert "NMRFT" in cfg.aquifers assert cfg.petrel_output_dir is None assert cfg.tax_rate == 0.25 assert cfg.interest_loan == 0.05 - assert cfg.economic_lifetime == 15 + assert cfg.economic_lifetime == 30 diff --git a/tests/utc/test_rosl_roslu.py b/tests/utc/test_rosl_roslu.py new file mode 100644 index 0000000000000000000000000000000000000000..39428d0ca4a7039d63ad8bdc15b89bc8cc007bdd --- /dev/null +++ b/tests/utc/test_rosl_roslu.py @@ -0,0 +1,24 @@ +# import matplotlib.pyplot as plt +# +# from pythermogis.workflow.utc.configuration import UTCConfiguration +# from pythermogis.workflow.utc.utc import run_utc_workflow +# +# def test_rosl_roslu(): +# """ +# Integration test that runs the whole ROSL_ROSLU aquifer. +# The input is identical to the java 2.5.3 input. +# The output is compared to the java output. +# """ +# config = UTCConfiguration( +# input_data_dir="C:/Users/knappersfy/work/thermogis/pythermogis/workdir/ROSL_ROSLU/input", +# results_dir="C:/Users/knappersfy/work/thermogis/pythermogis/workdir/ROSL_ROSLU/output", +# aquifers=["ROSL_ROSLU"], +# segment_length=1, +# p_values=[50] # For now only calculating this value, because it is way faster than 50 +# ) +# result = run_utc_workflow(config) +# +# result.ROSL_ROSLU.utc_p50.plot() # should match p value in config +# plt.show() +# +# print(result) \ No newline at end of file diff --git a/tests/utc/test_well_distance_optimizer.py b/tests/utc/test_well_distance_optimizer.py index 00401228f3d88d7f9051a2bcfe6dba0af8f2f36c..64ab18ea58f343fc0ae8b08a114aa7f4de63006d 100644 --- a/tests/utc/test_well_distance_optimizer.py +++ b/tests/utc/test_well_distance_optimizer.py @@ -1,7 +1,7 @@ import numpy as np from pythermogis.workflow.utc.doublet import DoubletInput -from pythermogis.workflow.utc.utc_properties import UTCConfiguration +from pythermogis.workflow.utc.configuration import UTCConfiguration from pythermogis.workflow.utc.well_distance import ( optimize_well_distance, optimize_well_distance_original,