diff --git a/docs/changelog.md b/docs/changelog.md index 05f4a84e9e2fbcdaa72a5a42b2ace1ee574050cf..ba6c6de4917f2423691597b74e99f798aa4902f7 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -18,3 +18,7 @@ Another bug was fixed, this occured when sampling for transmissivity with high o Additional Functionality: - two functions have been added to print out the environment variables THERMOGIS_JAR and JAVA_HOME. This enables users to debug if their are issues with their installation. +## v1.2.3 (27-11-2025) +Updating the Java jar which has a fixed implementation of the heat pump. Before the heat pump cop was not being correctly calculated. There is a test added to test_pythermogis_doublet_benchmark.py to showcase how the new heatpump mode +should be used. + diff --git a/docs/images/pyThermoGIS_transparent.png b/docs/images/pythermogis_transparent.png similarity index 100% rename from docs/images/pyThermoGIS_transparent.png rename to docs/images/pythermogis_transparent.png diff --git a/pyproject.toml b/pyproject.toml index 60532c27e59b82d0e5af179e79d84ba6ed08eaa2..390e14b763d0dac6264a3c9f3b8de811da9889c2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pythermogis" -version = "1.2.1" +version = "1.2.2" description = "This repository is used as a python API for the ThermoGIS Doublet simulations" authors = [ { name = "Hen Brett", email = "hen.brett@tno.nl" }, diff --git a/resources/thermogis_jar/thermogis-1.7.0-shaded.jar b/resources/thermogis_jar/thermogis-1.7.0-shaded.jar index 2c274aa1c6f077bcc55c5f71a355227e06136743..e9b30a8965c4e0eee1940138bed253869fc84cea 100644 --- a/resources/thermogis_jar/thermogis-1.7.0-shaded.jar +++ b/resources/thermogis_jar/thermogis-1.7.0-shaded.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7991ac4e8853db7f863de4c809f0d8035ea8c9ca5a90707e2e93799d6d6f39d6 -size 173317904 +oid sha256:207f0a0ecd48947dd4fdb2739edc17eaf60e1cd4351d06915adcc25d29b10e21 +size 173318007 diff --git a/tests/test_pyThermoGIS_Doublet_Benchmark.py b/tests/test_pyThermoGIS_Doublet_Benchmark.py deleted file mode 100644 index 01d934dd4f778315b3f8b8125f070ac89ec62903..0000000000000000000000000000000000000000 --- a/tests/test_pyThermoGIS_Doublet_Benchmark.py +++ /dev/null @@ -1,165 +0,0 @@ -from unittest import TestCase - -from pythermogis import * - -class ThermoGISDoubletBenchmark(TestCase): - """ - This is a series of tests which produce the same results found in the Java code and in test_ThermoGISDoublet_Benchmark, but using the ntended pythermogis implementation - """ - - def test_calculateDoubletPerformanceTest(self): - viscosity_mode = get_viscosity_mode("kestin") - utc_properties = (instantiate_utc_properties_builder() - .setDhReturnTemp(40) - .setViscosityMode(viscosity_mode) - .build()) - - input_data = xr.Dataset({ - "thickness_mean": ((), 100), - "thickness_sd": ((), 0.0), - "ntg": ((), 1.0), - "porosity": ((), 0.0), - "depth": ((), 2000), - "temperature": ((), 76), - "ln_permeability_mean": ((), np.log(175)), - "ln_permeability_sd": ((), 0.0), - }) - - results = calculate_doublet_performance_stochastic(input_data, utc_properties=utc_properties, rng_seed=0) - - # Assert - self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) - self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) - self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) - self.assertTrue(np.isclose(6.616096470753937, results.utc.data[0], 0.001)) - self.assertTrue(np.isclose(1159.17968, results.welld.data[0], 0.001)) - self.assertTrue(np.isclose(13.627557754516602, results.cop.data[0], 0.001)) - self.assertTrue(np.isclose(8.636903762817383, results.power.data[0], 0.001)) - - def test_calculateDoubletPerformance_directHeat(self): - """ - This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet - returns the same values. - """ - # Arrange - # Instantiate the UTC properties class - utc_properties = self.setup_template_utc_properties_builder().setOpexBase(0).build() - - input_data = xr.Dataset({ - "thickness_mean": ((), 100), - "thickness_sd": ((), 0.0), - "ntg": ((), 1.0), - "porosity": ((), 0.0), - "depth": ((), 2000), - "temperature": ((), 76), - "ln_permeability_mean": ((), np.log(175)), - "ln_permeability_sd": ((), 0.0), - }) - - # Act - results = calculate_doublet_performance_stochastic(input_data, utc_properties=utc_properties, rng_seed=0) - - - # Assert - self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) - self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) - self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) - self.assertTrue(np.isclose(5.229816400909403, results.utc.data[0], 0.001)) - self.assertTrue(np.isclose(1159.1796, results.welld.data[0], 0.001)) - self.assertTrue(np.isclose(13.623167037963867, results.cop.data[0], 0.001)) - self.assertTrue(np.isclose(8.624696731567383, results.power.data[0], 0.001)) - - def test_calculateDoubletPerformance_chiller(self): - """ - This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet - returns the same values. - """ - # Arrange - # Instantiate the UTC properties class - utc_properties = (self.setup_template_utc_properties_builder().setCapexConst(0.5) - .setCapexVariable(1100) - .setHeatExchangerEfficiency(0.4) - .setDhReturnTemp(60) - .setHeatExchangerParasitic(0.1).build()) - - input_data = xr.Dataset({ - "thickness_mean": ((), 100), - "thickness_sd": ((), 0.0), - "ntg": ((), 1.0), - "porosity": ((), 0.0), - "depth": ((), 2000), - "temperature": ((), 76), - "ln_permeability_mean": ((), np.log(175)), - "ln_permeability_sd": ((), 0.0), - }) - - # Act - results = calculate_doublet_performance_stochastic(input_data, utc_properties=utc_properties, rng_seed=0) - - # Assert - self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) - self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) - self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) - self.assertTrue(np.isclose(20.470115103822685, results.utc.data[0], 0.001)) - self.assertTrue(np.isclose(1227.1484375, results.welld.data[0], 0.001)) - self.assertTrue(np.isclose(1.8887300754346803, results.cop.data[0], 0.001)) - self.assertTrue(np.isclose(1.6594701766967774, results.power.data[0], 0.001)) - self.assertTrue(np.isclose(12.748051248109613, results.capex.data[0], 0.001)) - - def test_calculateDoubletPerformance_ORC(self): - """ - This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet - returns the same values. - """ - # Arrange - # Instantiate the UTC properties class - utc_properties = (self.setup_template_utc_properties_builder() - .setCapexConst(0) - .setCapexVariable(2300) - .setHeatExchangerEfficiency(0.6) - .setUseORC(True) - .setHeatExchangerBasetemp(20) - .setDhReturnTemp(60) - .build()) - - input_data = xr.Dataset({ - "thickness_mean": ((), 100), - "thickness_sd": ((), 0.0), - "ntg": ((), 1.0), - "porosity": ((), 0.0), - "depth": ((), 2000), - "temperature": ((), 100), - "ln_permeability_mean": ((), np.log(175)), - "ln_permeability_sd": ((), 0.0), - }) - - # Act - results = calculate_doublet_performance_stochastic(input_data, utc_properties=utc_properties, rng_seed=0) - - # Assert - self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) - self.assertTrue(np.isclose(293.6246643066406, results.flow_rate.data[0], 1)) - self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) - self.assertTrue(np.isclose(36.98296076530068, results.utc.data[0], 0.001)) - self.assertTrue(np.isclose(0.05274631495788107, results.power.data[0], 0.01)) - self.assertTrue(np.isclose(1306.4453125, results.welld.data[0], 0.001)) - self.assertTrue(np.isclose(0.06459403120103477, results.cop.data[0], 0.001)) - self.assertTrue(np.isclose(12.44409167482118, results.capex.data[0], 0.001)) - - def setup_template_utc_properties_builder(self): - viscosity_mode = get_viscosity_mode("kestin") - - return (instantiate_utc_properties_builder() - .setSalinityGradient(47.0) - .setDrillingTime(1) - .setTaxRate(20) - .setEquityReturn(15) - .setOpexBase(10000) - .setOpexPerPower(50) - .setWellCostScaling(1) - .setOpexPerEnergy(0) - .setWellCostConst(0.375) - .setWellCostZ(1050) - .setWellCostZ2(0.3) - .setDhReturnTemp(40) - .setViscosityMode(viscosity_mode)) \ No newline at end of file diff --git a/tests/test_pythermogis_doublet_benchmark.py b/tests/test_pythermogis_doublet_benchmark.py new file mode 100644 index 0000000000000000000000000000000000000000..cc274af2e9f263c9031411b1de5b07b0e3427b15 --- /dev/null +++ b/tests/test_pythermogis_doublet_benchmark.py @@ -0,0 +1,244 @@ +from unittest import TestCase + +from pythermogis import * + + +class ThermoGISDoubletBenchmark(TestCase): + """ + This is a series of tests which produce the same results found in the Java code and in test_ThermoGISDoublet_Benchmark, but using the ntended pythermogis implementation + """ + + def test_calculateDoubletPerformanceTest(self): + viscosity_mode = get_viscosity_mode("kestin") + utc_properties = ( + instantiate_utc_properties_builder() + .setDhReturnTemp(40) + .setViscosityMode(viscosity_mode) + .build() + ) + + input_data = xr.Dataset( + { + "thickness_mean": ((), 100), + "thickness_sd": ((), 0.0), + "ntg": ((), 1.0), + "porosity": ((), 0.0), + "depth": ((), 2000), + "temperature": ((), 76), + "ln_permeability_mean": ((), np.log(175)), + "ln_permeability_sd": ((), 0.0), + } + ) + + results = calculate_doublet_performance_stochastic( + input_data, utc_properties=utc_properties, rng_seed=0 + ) + + # Assert + self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) + self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) + self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) + self.assertTrue(np.isclose(6.616096470753937, results.utc.data[0], 0.001)) + self.assertTrue(np.isclose(1159.17968, results.welld.data[0], 0.001)) + self.assertTrue(np.isclose(13.627557754516602, results.cop.data[0], 0.001)) + self.assertTrue(np.isclose(8.636903762817383, results.power.data[0], 0.001)) + + def test_calculateDoubletPerformance_directHeat(self): + """ + This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet + returns the same values. + """ + # Arrange + # Instantiate the UTC properties class + utc_properties = ( + self.setup_template_utc_properties_builder().setOpexBase(0).build() + ) + + input_data = xr.Dataset( + { + "thickness_mean": ((), 100), + "thickness_sd": ((), 0.0), + "ntg": ((), 1.0), + "porosity": ((), 0.0), + "depth": ((), 2000), + "temperature": ((), 76), + "ln_permeability_mean": ((), np.log(175)), + "ln_permeability_sd": ((), 0.0), + } + ) + + # Act + results = calculate_doublet_performance_stochastic( + input_data, utc_properties=utc_properties, rng_seed=0 + ) + + # Assert + self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) + self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) + self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) + self.assertTrue(np.isclose(5.229816400909403, results.utc.data[0], 0.001)) + self.assertTrue(np.isclose(1159.1796, results.welld.data[0], 0.001)) + self.assertTrue(np.isclose(13.623167037963867, results.cop.data[0], 0.001)) + self.assertTrue(np.isclose(8.624696731567383, results.power.data[0], 0.001)) + + def test_calculateDoubletPerformance_chiller(self): + """ + This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet + returns the same values. + """ + # Arrange + # Instantiate the UTC properties class + utc_properties = ( + self.setup_template_utc_properties_builder() + .setCapexConst(0.5) + .setCapexVariable(1100) + .setHeatExchangerEfficiency(0.4) + .setDhReturnTemp(60) + .setHeatExchangerParasitic(0.1) + .build() + ) + + input_data = xr.Dataset( + { + "thickness_mean": ((), 100), + "thickness_sd": ((), 0.0), + "ntg": ((), 1.0), + "porosity": ((), 0.0), + "depth": ((), 2000), + "temperature": ((), 76), + "ln_permeability_mean": ((), np.log(175)), + "ln_permeability_sd": ((), 0.0), + } + ) + + # Act + results = calculate_doublet_performance_stochastic( + input_data, utc_properties=utc_properties, rng_seed=0 + ) + + # Assert + self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) + self.assertTrue(np.isclose(227.2757568359375, results.flow_rate.data[0], 1)) + self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) + self.assertTrue(np.isclose(20.470115103822685, results.utc.data[0], 0.001)) + self.assertTrue(np.isclose(1227.1484375, results.welld.data[0], 0.001)) + self.assertTrue(np.isclose(1.8887300754346803, results.cop.data[0], 0.001)) + self.assertTrue(np.isclose(1.6594701766967774, results.power.data[0], 0.001)) + self.assertTrue(np.isclose(12.748051248109613, results.capex.data[0], 0.001)) + + def test_calculateDoubletPerformance_ORC(self): + """ + This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet + returns the same values. + """ + # Arrange + # Instantiate the UTC properties class + utc_properties = ( + self.setup_template_utc_properties_builder() + .setCapexConst(0) + .setCapexVariable(2300) + .setHeatExchangerEfficiency(0.6) + .setUseORC(True) + .setHeatExchangerBasetemp(20) + .setDhReturnTemp(60) + .build() + ) + + input_data = xr.Dataset( + { + "thickness_mean": ((), 100), + "thickness_sd": ((), 0.0), + "ntg": ((), 1.0), + "porosity": ((), 0.0), + "depth": ((), 2000), + "temperature": ((), 100), + "ln_permeability_mean": ((), np.log(175)), + "ln_permeability_sd": ((), 0.0), + } + ) + + # Act + results = calculate_doublet_performance_stochastic( + input_data, utc_properties=utc_properties, rng_seed=0 + ) + + # Assert + self.assertTrue(np.isclose(17500, results.transmissivity.data[0], 0.001)) + self.assertTrue(np.isclose(293.6246643066406, results.flow_rate.data[0], 1)) + self.assertTrue(np.isclose(60, results.pres.data[0], 0.001)) + self.assertTrue(np.isclose(36.98296076530068, results.utc.data[0], 0.001)) + self.assertTrue(np.isclose(0.05274631495788107, results.power.data[0], 0.01)) + self.assertTrue(np.isclose(1306.4453125, results.welld.data[0], 0.001)) + self.assertTrue(np.isclose(0.06459403120103477, results.cop.data[0], 0.001)) + self.assertTrue(np.isclose(12.44409167482118, results.capex.data[0], 0.001)) + + def test_calculateDoubletPerformance_directHeat_and_heatpump(self): + """ + This is a copy of a test from the Java ThermoGisDoubletTest.java script; to validate that this python implementation of the ThermoGIS Doublet + returns the same values. + """ + # Arrange + # Instantiate the UTC properties class + utc_properties = ( + self.setup_template_utc_properties_builder() + .setOpexPerPower(100) + .setOpexBase(0) + .setHpDirectHeatInputTemp(70) + .setUseHeatPump(True) + .setDhReturnTemp(35) + .build() + ) + + input_data = xr.Dataset( + { + "thickness_mean": ((), 100), + "thickness_sd": ((), 0.0), + "ntg": ((), 1.0), + "porosity": ((), 0.0), + "depth": ((), 2000), + "temperature": ((), 50), + "ln_permeability_mean": ((), np.log(175)), + "ln_permeability_sd": ((), 0.0), + } + ) + + # Act + results = calculate_doublet_performance_stochastic( + input_data, utc_properties=utc_properties, rng_seed=0 + ) + power_hpelec = results.heat_pump_power / (results.cophp - 1) + power_ratio = results.power / (results.power + power_hpelec) + + + # Assert + self.assertTrue(np.isclose(5.856159806251526, results.power + power_hpelec, 0.1)) + self.assertTrue(np.isclose(8.83718197747828, results.utc * power_ratio, 0.1)) + self.assertTrue(np.isclose(17499.99940, 17500, 0.001)) + self.assertTrue(np.isclose(163.99771118164062, results.flow_rate, 0.001)) + self.assertTrue(np.isclose(60, results.pres, 0.001)) + self.assertTrue(np.isclose(4.97566556930542, results.power, 0.001)) + self.assertTrue(np.isclose(989.2578125, results.welld, 0.001)) + self.assertTrue(np.isclose(4.383212200392486, results.cop, 0.001)) + self.assertTrue(np.isclose(3.798196792602539, results.cophp, 0.001)) + self.assertTrue(np.isclose(10.401010755009017, results.utc, 0.001)) + self.assertTrue(np.isclose(16.50359210062243, results.capex, 0.001)) + + def setup_template_utc_properties_builder(self): + viscosity_mode = get_viscosity_mode("kestin") + + return ( + instantiate_utc_properties_builder() + .setSalinityGradient(47.0) + .setDrillingTime(1) + .setTaxRate(20) + .setEquityReturn(15) + .setOpexBase(10000) + .setOpexPerPower(50) + .setWellCostScaling(1) + .setOpexPerEnergy(0) + .setWellCostConst(0.375) + .setWellCostZ(1050) + .setWellCostZ2(0.3) + .setDhReturnTemp(40) + .setViscosityMode(viscosity_mode) + ) \ No newline at end of file