diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test1a/test1a_ste.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test1a/test1a_ste.py index f550c8ab..23735d48 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test1a/test1a_ste.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test1a/test1a_ste.py @@ -2,193 +2,111 @@ The work of (Ahmadfard and Bernier, 2019) provides a set of test cases that can be used to compare software tools with the ultimate goal of improving the reliability of design methods for sizing vertical ground heat exchangers. This document delivers the results on the test file using the GHEtool -L2-, L3-, and L4-sizing methods. +L2-, L3- and L4-sizing methods. -Test 1 - Synthetic balanced load – one borehole +Test 1 -Synthetic balanced load – one borehole References: ----------- - Ahmadfard, M., and M. Bernier. 2019. A review of vertical ground heat exchanger sizing tools including an inter-model comparison [in eng]. Renewable sustainable energy reviews (OXFORD) 110:247–265. """ - import os import time import numpy as np -import pygfunction as gt -import sys from GHEtool import * +def test_1b_6h_ste(): + # Ground properties + ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) -def initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=None): - """ - Initialize and set up borefield with necessary parameters. - """ - # Initiate borefield - borefield = Borefield() - - # Set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(1, 1, 6, 6, 110, 4, 0.075) - - # Set imposed Rb if provided - if imposed_Rb is not None: - borefield.set_Rb(imposed_Rb) - borefield.calculation_setup(use_constant_Rb=True) - - # Load the load profile into borefield - borefield.load = load - - # Set temperature bounds - borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - return borefield - - -def run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb=None): - """ - Run sizing for L2, L3, L4, L3_ste, and L4_ste methods with imposed Rb and return results. - If imposed_Rb is None, it uses the default calculated Rb. - """ - # Set peak duration - borefield.load.peak_duration = peak_duration - - # Define methods and short-term effects parameters - methods = ['L2', 'L3', 'L4', 'L3_ste', 'L4_ste'] - short_term_params = {'rho_cp_grout': 3800000.0, 'rho_cp_pipe': 1540000.0} - options = { - 'disp': False, - 'profiles': True, - 'method': 'equivalent', - 'cylindrical_correction': True, - 'short_term_effects': True, - 'ground_data': ground_data, - 'fluid_data': fluid_data, - 'pipe_data': pipe_data, - 'borefield': borefield, - 'short_term_effects_parameters': short_term_params, - } - - # Set results dictionary - results = {} + # Load fluid properties into FluidData + base_mfr = 0.440 # Baseline mass flow rate (kg/s) + fluid_data = FluidData(mfr=base_mfr, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) + + # Pipe properties + pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) - for method in methods: - start_time = time.time() - - # Re-initialize borefield if switching from L4 to L3_ste or L4_ste - if method in ['L3_ste', 'L4_ste']: - print(f"\nRe-initializing borefield for {method} method.") - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - borefield.set_options_gfunction_calculation(options) - # Perform sizing with short-term effects - depth = borefield.size(100, L3_sizing=(method == 'L3_ste'), L4_sizing=(method == 'L4_ste')) - else: - # Perform sizing for regular methods (L2, L3, L4) - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - depth = borefield.size(100, L2_sizing=(method == 'L2'), L3_sizing=(method == 'L3'), L4_sizing=(method == 'L4')) + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + # Initialize results dictionary + results = {} + + # Define function to store results + def log_results(method, depth, borefield, start_time): results[method] = { 'depth': depth, 'Rb': borefield.Rb, 'time': time.time() - start_time } - #if method == 'L4': - #borefield._plot_temperature_profile(plot_hourly=True) - - return results - - -def test1a_ste(use_pygfunction_media=False, Tf=0): - """ - Test the L2, L3, L4, L3_ste, and L4_ste sizing methods of the GHEtool library on a synthetic balanced load profile. - """ - """ - # Set up ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) - fluid_data = FluidData(mfr=0.440, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) - """ - # Initialize ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) - - # Base mass flow rate (kg/s) - base_mfr = 0.440 - # Initialize fluid data - if use_pygfunction_media: - # Use pygfunction to determine fluid data - # Create a water fluid object using pygfunction - fluid_str = 'Water' # Default fluid in pygfunction - percent = 0 # No mixture, pure water - fluid_object = gt.media.Fluid(fluid_str, percent, T=Tf) - fluid_data = FluidData() - fluid_data.import_fluid_from_pygfunction(fluid_object) - else: - # Use manual fluid data input - fluid_data = FluidData(mfr=base_mfr, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) - - # Create pipe data for a Multiple U-Tube configuration - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) - - # Load hourly profile load = HourlyGeothermalLoad(simulation_period=10) - csv_file_path = os.path.join(os.path.dirname(__file__), 'test1a.csv') - load.load_hourly_profile(csv_file_path, header=True, separator=",", col_extraction=1, col_injection=0) + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test1a.csv'), header=True, separator=",", + col_extraction=1, col_injection=0) - # Calculate delta temperature - delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) + # Calculate temperature bounds + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) - # Test cases: for peak durations 6 hours and 1 hour for peak_duration in [6, 1]: print(f"\nRunning test case for peak_duration = {peak_duration}") - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data) - - # Run sizing for calculated Rb (default behavior) - results_default_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t) - - # Print results for default Rb - print("\n--- Results for calculated Rb ---") - for method, result in results_default_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n----------------------------------") - - # Run sizing for imposed Rb (static value) - Rb_static = 0.13 # Imposed Rb value - use_constant_Rb = True - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, Rb_static) - results_imposed_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb) - - # Print results for imposed Rb - print("\n--- Results for imposed Rb (Rb* = 0.13) ---") - for method, result in results_imposed_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n-------------------------------<-------------") - - """ - # Add assertions for validation (replace with expected values for your case) - if peak_duration == 6: - assert np.isclose(results_default_Rb['L2']['depth'], 59.366, atol=0.1) - assert np.isclose(results_default_Rb['L3']['depth'], 59.543, atol=0.1) - assert np.isclose(results_default_Rb['L4']['depth'], 56.266, atol=0.1) - assert np.isclose(results_default_Rb['L4_ste']['depth'], 52.347, atol=0.1) - assert np.isclose(results_default_Rb['L3_ste']['depth'], 58.123, atol=0.1) # Example value - else: - # Adjust expected values based on 1-hour peak duration results - pass - """ + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(1, 1, 6, 6, 110, 4, 0.075) + # Set peak duration + borefield.load.peak_duration = peak_duration + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + borefield.load = load + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + borefield.set_options_gfunction_calculation(options) + + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.13) + + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time) + + # Print results + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s") if __name__ == "__main__": - test1a_ste() + test_1b_6h_ste() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test1b/test1b_ste.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test1b/test1b_ste.py index eb0e47c4..6353823a 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test1b/test1b_ste.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test1b/test1b_ste.py @@ -14,177 +14,94 @@ import os import time import numpy as np -import pygfunction as gt from GHEtool import * +def test_1b_6h_ste(): + # Ground properties + ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) -def initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=None): - """ - Initialize and set up borefield with necessary parameters. - """ - # Initiate borefield - borefield = Borefield() - - # Set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(1, 1, 6, 6, 110, 4, 0.075) - - # Set imposed Rb if provided - if imposed_Rb is not None: - borefield.set_Rb(imposed_Rb) - borefield.calculation_setup(use_constant_Rb=True) - - # Load the load profile into borefield - borefield.load = load - - # Set temperature bounds - borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - return borefield - - -def run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb=None): - """ - Run sizing for L2, L3, L4, L3_ste, and L4_ste methods with imposed Rb and return results. - If imposed_Rb is None, it uses the default calculated Rb. - """ - # Set peak duration - borefield.load.peak_duration = peak_duration - - # Define methods and short-term effects parameters - methods = ['L2', 'L3', 'L4', 'L3_ste', 'L4_ste'] - short_term_params = {'rho_cp_grout': 3800000.0, 'rho_cp_pipe': 1540000.0} - options = { - 'disp': False, - 'profiles': True, - 'method': 'equivalent', - 'cylindrical_correction': True, - 'short_term_effects': True, - 'ground_data': ground_data, - 'fluid_data': fluid_data, - 'pipe_data': pipe_data, - 'borefield': borefield, - 'short_term_effects_parameters': short_term_params, - } - - # Set results dictionary - results = {} + # Load fluid properties into FluidData + base_mfr = 0.5585 # Baseline mass flow rate (kg/s) + fluid_data = FluidData(mfr=base_mfr, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) + + # Pipe properties + pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) - for method in methods: - start_time = time.time() + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 - # Re-initialize borefield if switching from L4 to L3_ste or L4_ste - if method in ['L3_ste', 'L4_ste']: - print(f"\nRe-initializing borefield for {method} method.") - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - borefield.set_options_gfunction_calculation(options) - # Perform sizing with short-term effects - depth = borefield.size(100, L3_sizing=(method == 'L3_ste'), L4_sizing=(method == 'L4_ste'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) - else: - # Perform sizing for regular methods (L2, L3, L4) - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - depth = borefield.size(100, L2_sizing=(method == 'L2'), L3_sizing=(method == 'L3'), L4_sizing=(method == 'L4'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) + # Initialize results dictionary + results = {} + # Define function to store results + def log_results(method, depth, borefield, start_time): results[method] = { 'depth': depth, 'Rb': borefield.Rb, 'time': time.time() - start_time } - return results - + # Load hourly profile + load = HourlyGeothermalLoad(simulation_period=10) + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test1b.csv'), header=True, separator=";", + decimal_seperator=",", col_extraction=1, col_injection=0) + + # Calculate temperature bounds + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) + + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(1, 1, 6, 6, 110, 4, 0.075) + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + borefield.load = load + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + borefield.set_options_gfunction_calculation(options) -def test1b_ste(use_pygfunction_media=False, Tf=0): - """ - Test the L2, L3, L4, L3_ste, and L4_ste sizing methods of the GHEtool library on a synthetic balanced load profile. - """ - """ - # Set up ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) - fluid_data = FluidData(mfr=0.440, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) - """ - # Initialize ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=1.8, T_g=17.5, volumetric_heat_capacity=2073600, flux=0) + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.13) - # Base mass flow rate (kg/s) - base_mfr = 0.5585 - # Initialize fluid data - if use_pygfunction_media: - # Use pygfunction to determine fluid data - # Create a water fluid object using pygfunction - fluid_str = 'Water' # Default fluid in pygfunction - percent = 0 # No mixture, pure water - fluid_object = gt.media.Fluid(fluid_str, percent, T=Tf) - fluid_data = FluidData() - fluid_data.import_fluid_from_pygfunction(fluid_object) - else: - # Use manual fluid data input - fluid_data = FluidData(mfr=base_mfr, rho=1052, Cp=3795, mu=0.0052, k_f=0.48) - - # Create pipe data for a Multiple U-Tube configuration - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.075 / 2, k_g=1.4, k_p=0.43, number_of_pipes=1) + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time) - # Load hourly profile - load = HourlyGeothermalLoad(simulation_period=10) - csv_file_path = os.path.join(os.path.dirname(__file__), 'test1b.csv') - load.load_hourly_profile(csv_file_path, header=True, separator=";", decimal_seperator=",", col_extraction=1, col_injection=0) - - # Calculate delta temperature - delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) - - # Test cases: for peak durations 6 hours and 1 hour - for peak_duration in [6]: - print(f"\nRunning test case for peak_duration = {peak_duration}") - - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data) - - # Run sizing for calculated Rb (default behavior) - results_default_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t) - - # Print results for default Rb - print("\n--- Results for calculated Rb ---") - for method, result in results_default_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n----------------------------------") - - # Run sizing for imposed Rb (static value) - Rb_static = 0.13 # Imposed Rb value - use_constant_Rb = True - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, Rb_static) - results_imposed_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb) - - # Print results for imposed Rb - print("\n--- Results for imposed Rb (Rb* = 0.13) ---") - for method, result in results_imposed_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n--------------------------------------------") - - """ - # Add assertions for validation (replace with expected values for your case) - if peak_duration == 6: - assert np.isclose(results_default_Rb['L2']['depth'], 59.366, atol=0.1) - assert np.isclose(results_default_Rb['L3']['depth'], 59.543, atol=0.1) - assert np.isclose(results_default_Rb['L4']['depth'], 56.266, atol=0.1) - assert np.isclose(results_default_Rb['L4_ste']['depth'], 52.347, atol=0.1) - assert np.isclose(results_default_Rb['L3_ste']['depth'], 58.123, atol=0.1) # Example value - else: - # Adjust expected values based on 1-hour peak duration results - pass - """ + # Print results + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s") if __name__ == "__main__": - test1b_ste(use_pygfunction_media=False) + test_1b_6h_ste() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste.py index 27903a95..ccf2b821 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste.py @@ -1,187 +1,109 @@ """ -The work of (Ahmadfard and Bernier, 2019) provides a set of test cases that can be used to compare +The work of Ahmadfard and Bernier (2019) provides a set of test cases that can be used to compare software tools with the ultimate goal of improving the reliability of design methods for sizing vertical ground heat exchangers. This document delivers the results on the test file using the GHEtool -L2-, L3- and L4-sizing methods. +L2-, L3-, and L4-sizing methods. Test 2 – Shonder's test – 120 boreholes References: ----------- - Ahmadfard, M., and M. Bernier. 2019. A review of vertical ground heat exchanger sizing tools including an inter-model -comparison [in eng]. Renewable sustainable energy reviews (OXFORD) 110:247–265. + comparison [in eng]. Renewable sustainable energy reviews (OXFORD) 110:247–265. """ import os import time import numpy as np import pygfunction as gt import sys - -sys.path.append("C:\Workdir\Develop\ghetool") # Adjust the path to your GHEtool directory from GHEtool import * +def test_2_6h_ste(): + # Ground properties + ground_data = GroundFluxTemperature(k_s=2.25, T_g=12.41, volumetric_heat_capacity=2877000, flux=0) + + # Load fluid properties into FluidData + base_mfr = 2*29/120 # Baseline mass flow rate (kg/s) + fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) -def initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=None): - """ - Initialize and set up borefield with necessary parameters. - """ - # Initiate borefield - borefield = Borefield() - - # Set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(12, 10, 6, 6, 110, 3, 0.054) - - # Set imposed Rb if provided - if imposed_Rb is not None: - borefield.set_Rb(imposed_Rb) - borefield.calculation_setup(use_constant_Rb=True) - - # Load the load profile into borefield - borefield.load = load - - # Set temperature bounds - borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(4.4 - delta_t / 2) - - print('initrialisatie', 35 + delta_t / 2, borefield.Rb) - return borefield - - -def run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb=None): - """ - Run sizing for L2, L3, L4, L3_ste, and L4_ste methods with imposed Rb and return results. - If imposed_Rb is None, it uses the default calculated Rb. - """ - # Set peak duration - borefield.load.peak_duration = peak_duration - - # Define methods and short-term effects parameters - methods = ['L2', 'L3', 'L4', 'L3_ste', 'L4_ste'] - short_term_params = {'rho_cp_grout': 3800000.0, 'rho_cp_pipe': 1540000.0} - options = { - 'disp': False, - 'profiles': True, - 'method': 'equivalent', - 'cylindrical_correction': True, - 'short_term_effects': True, - 'ground_data': ground_data, - 'fluid_data': fluid_data, - 'pipe_data': pipe_data, - 'borefield': borefield, - 'short_term_effects_parameters': short_term_params, - } - - # Set results dictionary - results = {} + # Pipe properties + pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.0471 / 2, k_g=1.73, k_p=0.45) - for method in methods: - start_time = time.time() + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 - # Re-initialize borefield if switching from L4 to L3_ste or L4_ste - if method in ['L3_ste', 'L4_ste']: - print(f"\nRe-initializing borefield for {method} method.") - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - borefield.set_options_gfunction_calculation(options) - # Perform sizing with short-term effects - depth = borefield.size(100, L3_sizing=(method == 'L3_ste'), L4_sizing=(method == 'L4_ste'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) - else: - # Perform sizing for regular methods (L2, L3, L4) - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - depth = borefield.size(100, L2_sizing=(method == 'L2'), L3_sizing=(method == 'L3'), L4_sizing=(method == 'L4'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) + # Initialize results dictionary + results = {} + # Define function to store results + def log_results(method, depth, borefield, start_time): results[method] = { 'depth': depth, 'Rb': borefield.Rb, 'time': time.time() - start_time } - return results - - -def test2_6h_ste(use_pygfunction_media=False, Tf=0): - """ - Test the L2, L3, L4, L3_ste, and L4_ste sizing methods of the GHEtool library on Shonder's test. - """ - # Initialize ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=2.25, T_g=12.41, volumetric_heat_capacity=2877000, flux=0) - # Base mass flow rate (kg/s) - base_mfr = 29/120 - # Initialize fluid data - if use_pygfunction_media: - # Use pygfunction to determine fluid data - # Create a water fluid object using pygfunction - fluid_str = 'Water' # Default fluid in pygfunction - percent = 0 # No mixture, pure water - fluid_object = gt.media.Fluid(fluid_str, percent, T=Tf) - fluid_data = FluidData() - fluid_data.import_fluid_from_pygfunction(fluid_object) - else: - # Use manual fluid data input - fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - - # Create pipe data for a Multiple U-Tube configuration - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.0471 / 2, k_g=1.73, k_p=0.45) - # Load hourly profile load = HourlyGeothermalLoad(simulation_period=10) - csv_file_path = os.path.join(os.path.dirname(__file__), 'test2.csv') - load.load_hourly_profile(csv_file_path, header=True, separator=",", col_extraction=1, col_injection=0) - - # Calculate delta temperature - delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) - - # Test cases: for peak durations 6 hours and 1 hour - for peak_duration in [6]: - print(f"\nRunning test case for peak_duration = {peak_duration}") - - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data) - - # Run sizing for calculated Rb (default behavior) - results_default_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t) - - # Print results for default Rb - print("\n--- Results for calculated Rb ---") - for method, result in results_default_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n----------------------------------") - - # Run sizing for imposed Rb (static value) - Rb_static = 0.113 # Imposed Rb value - use_constant_Rb = True - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, Rb_static) - results_imposed_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb) - - # Print results for imposed Rb - print("\n--- Results for imposed Rb (Rb* = 0.13) ---") - for method, result in results_imposed_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n--------------------------------------------") - - """ - # Add assertions for validation (replace with expected values for your case) - if peak_duration == 6: - assert np.isclose(results_default_Rb['L2']['depth'], 59.366, atol=0.1) - assert np.isclose(results_default_Rb['L3']['depth'], 59.543, atol=0.1) - assert np.isclose(results_default_Rb['L4']['depth'], 56.266, atol=0.1) - assert np.isclose(results_default_Rb['L4_ste']['depth'], 52.347, atol=0.1) - assert np.isclose(results_default_Rb['L3_ste']['depth'], 58.123, atol=0.1) # Example value - else: - # Adjust expected values based on 1-hour peak duration results - pass - """ + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test2.csv'), header=True, separator=",", + col_extraction=1, col_injection=0) + + # Calculate temperature bounds + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) / 120 + + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(12, 10, 6, 6, 110, 3, 0.054) + borefield.load = load + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(4.4 - delta_t / 2) + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + borefield.set_options_gfunction_calculation(options) + + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.113) + + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time) + + # Print results + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s") + if __name__ == "__main__": - test2_6h_ste() + test_2_6h_ste() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_m_sweep.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_m_sweep.py new file mode 100644 index 00000000..ff4e8613 --- /dev/null +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_m_sweep.py @@ -0,0 +1,117 @@ +""" +The work of Ahmadfard and Bernier (2019) provides a set of test cases that can be used to compare +software tools with the ultimate goal of improving the reliability of design methods for sizing +vertical ground heat exchangers. This document delivers the results on the test file using the GHEtool +L2-, L3-, and L4-sizing methods. + +Test 2 – Shonder's test – 120 boreholes + +References: +----------- + - Ahmadfard, M., and M. Bernier. 2019. A review of vertical ground heat exchanger sizing tools including an inter-model + comparison [in eng]. Renewable sustainable energy reviews (OXFORD) 110:247–265. +""" +import os +import time +import numpy as np +import pygfunction as gt +import sys +from GHEtool import * + +def test_2_6h_ste_m_sweep(): + # Ground properties + ground_data = GroundFluxTemperature(k_s=2.25, T_g=12.41, volumetric_heat_capacity=2877000, flux=0) + + # Load fluid properties into FluidData + base_mfr = 0.2416667 # Baseline mass flow rate (kg/s) + fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) + + # Pipe properties + pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.0471 / 2, k_g=1.73, k_p=0.45) + + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + + # Initialize results dictionary + results = {} + + # Define function to store results + def log_results(method, depth, borefield, start_time, massflow_factor): + results[f"{method}_mfr_{massflow_factor}"] = { + 'depth': depth, + 'Rb': borefield.Rb, + 'time': time.time() - start_time, + 'massflow_factor': massflow_factor + } + + # Load hourly profile + load = HourlyGeothermalLoad(simulation_period=10) + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test2.csv'), header=True, separator=",", + col_extraction=1, col_injection=0) + + # Calculate temperature bounds + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) / 120 + + # Mass flow rate factors to test + massflow_factors = [0.2, 0.5, 1.0, 1.5, 2.0] + + # Test each mass flow rate factor + for massflow_factor in massflow_factors: + # Adjust mass flow rate based on the factor + fluid_data.mfr = base_mfr * massflow_factor + + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(12, 10, 6, 6, 110, 3, 0.054) + borefield.load = load + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(4.4 - delta_t / 2) + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + borefield.set_options_gfunction_calculation(options) + + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.113) + + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time, massflow_factor) + + # Print results + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s, Massflow Factor = {result['massflow_factor']}") + +if __name__ == "__main__": + test_2_6h_ste_m_sweep() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_old.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_old.py index 1505e314..fe51e72e 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_old.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test2/test2_ste_old.py @@ -16,10 +16,6 @@ import numpy as np import pygfunction as gt - -import sys -sys.path.append("C:\Workdir\Develop\ghetool") - from GHEtool import * @@ -27,17 +23,8 @@ def test_2_6h_ste(): # initiate ground, fluid and pipe data ground_data = GroundFluxTemperature(k_s=2.25, T_g=12.41, volumetric_heat_capacity=2877000, flux=0) base_mfr = 0.2416667 # Basis massastroom (kg/s) - - # Maak een water vloeistofobject via pygfunction - fluid_str = 'Water' # 'Water' is de standaard vloeistof in pygfunction - percent = 0 # Geen mengsel, dus 0% andere vloeistoffen - T_f = 0 # Temperatuur (bijvoorbeeld 20°C) - fluid_object = gt.media.Fluid(fluid_str, percent, T=T_f) # Maak fluid object - # Maak FluidData object aan en laad vloeistofgegevens van pygfunction fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - fluid_data.import_fluid_from_pygfunction(fluid_object) # Laad de vloeistofgegevens in FluidData - pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.0471 / 2, k_g=1.73, k_p=0.45) # start test with dynamic Rb* @@ -85,15 +72,8 @@ def test_2_6h_ste(): ground_data = GroundFluxTemperature(k_s=2.25, T_g=12.41, volumetric_heat_capacity=2877000, flux=0) base_mfr = 0.2416667 # Basis massastroom (kg/s) - # Maak een water vloeistofobject via pygfunction - fluid_str = 'Water' # 'Water' is de standaard vloeistof in pygfunction - percent = 0 # Geen mengsel, dus 0% andere vloeistoffen - #T_f = 0 # Temperatuur (bijvoorbeeld 20°C) - fluid_object = gt.media.Fluid(fluid_str, percent, T=T_f) # Maak fluid object - # Maak FluidData object aan en laad vloeistofgegevens van pygfunction fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - fluid_data.import_fluid_from_pygfunction(fluid_object) # Laad de vloeistofgegevens in FluidData pipe_data = MultipleUTube(r_in=0.0137, r_out=0.0167, D_s=0.0471 / 2, k_g=1.73, k_p=0.45) # Addidional input data needed for short-term model rho_cp_grout = 3800000.0 diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste.py index cb1cafc6..5d3866e4 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste.py @@ -15,170 +15,101 @@ import time import numpy as np import pygfunction as gt +import sys from GHEtool import * +def test_3_6h_ste(): + # Ground properties + ground_data = GroundFluxTemperature(k_s=2.25, T_g=10, volumetric_heat_capacity=2592000, flux=0) + + # Load fluid properties into FluidData + base_mfr = 33.1 / 49 # Baseline mass flow rate (kg/s) + fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) -def initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=None): - """ - Initialize and set up borefield with necessary parameters. - """ - # Initiate borefield - borefield = Borefield() - - # Set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(7, 7, 5, 5, 110, 2.5, 0.075) - - # Set imposed Rb if provided - if imposed_Rb is not None: - borefield.set_Rb(imposed_Rb) - borefield.calculation_setup(use_constant_Rb=True) - - # Load the load profile into borefield - borefield.load = load - - # Set temperature bounds - borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - return borefield - - -def run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb=None): - """ - Run sizing for L2, L3, L4, L3_ste, and L4_ste methods with imposed Rb and return results. - If imposed_Rb is None, it uses the default calculated Rb. - """ - # Set peak duration - borefield.load.peak_duration = peak_duration - - # Define methods and short-term effects parameters - methods = ['L2', 'L3', 'L4', 'L3_ste', 'L4_ste'] - short_term_params = {'rho_cp_grout': 3800000.0, 'rho_cp_pipe': 1540000.0} - options = { - 'disp': False, - 'profiles': True, - 'method': 'equivalent', - 'cylindrical_correction': True, - 'short_term_effects': True, - 'ground_data': ground_data, - 'fluid_data': fluid_data, - 'pipe_data': pipe_data, - 'borefield': borefield, - 'short_term_effects_parameters': short_term_params, - } - - # Set results dictionary - results = {} + # Pipe properties + pipe_data = MultipleUTube(r_in=0.013, r_out=0.0167, D_s=0.075 / 2, k_g=1.73, k_p=0.4, number_of_pipes=1) - for method in methods: - start_time = time.time() - - # Re-initialize borefield if switching from L4 to L3_ste or L4_ste - if method in ['L3_ste', 'L4_ste']: - print(f"\nRe-initializing borefield for {method} method.") - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - borefield.set_options_gfunction_calculation(options) - # Perform sizing with short-term effects - depth = borefield.size(100, L3_sizing=(method == 'L3_ste'), L4_sizing=(method == 'L4_ste'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) - else: - # Perform sizing for regular methods (L2, L3, L4) - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, imposed_Rb=borefield.Rb) - depth = borefield.size(100, L2_sizing=(method == 'L2'), L3_sizing=(method == 'L3'), L4_sizing=(method == 'L4'), use_constant_Rb=use_constant_Rb) - print(borefield.Rb) + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + + # Initialize results dictionary + results = {} + # Define function to store results + def log_results(method, depth, borefield, start_time): results[method] = { 'depth': depth, 'Rb': borefield.Rb, 'time': time.time() - start_time } - return results - - -def test3_ste(use_pygfunction_media=False, Tf=0): - """ - Test the L2, L3, L4, L3_ste, and L4_ste sizing methods of the GHEtool library on a synthetic balanced load profile. - """ - # Initialize ground, fluid, and pipe data - ground_data = GroundFluxTemperature(k_s=2.25, T_g=10, volumetric_heat_capacity=2592000, flux=0) - - # Base mass flow rate (kg/s) - base_mfr = 33.1 / 49 - # Initialize fluid data - if use_pygfunction_media: - # Use pygfunction to determine fluid data - # Create a water fluid object using pygfunction - fluid_str = 'Water' # Default fluid in pygfunction - percent = 0 # No mixture, pure water - fluid_object = gt.media.Fluid(fluid_str, percent, T=Tf) - fluid_data = FluidData() - fluid_data.import_fluid_from_pygfunction(fluid_object) - else: - # Use manual fluid data input - fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - - # Create pipe data for a Multiple U-Tube configuration - pipe_data = MultipleUTube(r_in=0.013, r_out=0.0167, D_s=0.075 / 2, k_g=1.73, k_p=0.4, number_of_pipes=1) + spacing = [3, 5, 7] + simulation_period = [1, 10] + + for s in simulation_period: + for B in spacing: + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(7, 7, B, B, 110, 2.5, 0.075) + + # Load hourly profile + load = HourlyGeothermalLoad(simulation_period=s) + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test3.csv'), header=True, separator=",", + col_extraction=1, col_injection=0) + borefield.load = load + + # Calculate temperature bounds + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) / 49 + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(35 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + borefield.set_options_gfunction_calculation(options) + + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.1) + + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time) + + # Print results + print(f"\n--- Results for {s}year simulation and {B}m spacing ---") + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s") - # Load hourly profile - load = HourlyGeothermalLoad(simulation_period=10) - csv_file_path = os.path.join(os.path.dirname(__file__), 'test3.csv') - load.load_hourly_profile(csv_file_path, header=True, separator=",", col_extraction=1, col_injection=0) - - # Calculate delta temperature - delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) - - # Test cases: for peak durations 6 hours and 1 hour - for peak_duration in [6]: - print(f"\nRunning test case for peak_duration = {peak_duration}") - - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data) - - # Run sizing for calculated Rb (default behavior) - results_default_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t) - - # Print results for default Rb - print("\n--- Results for calculated Rb ---") - for method, result in results_default_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n----------------------------------") - - # Run sizing for imposed Rb (static value) - Rb_static = 0.1 # Imposed Rb value - use_constant_Rb = True - # Initialize borefield with required parameters - borefield = initialize_borefield(load, delta_t, ground_data, fluid_data, pipe_data, Rb_static) - results_imposed_Rb = run_sizing_case(borefield, load, ground_data, fluid_data, pipe_data, peak_duration, delta_t, use_constant_Rb) - - # Print results for imposed Rb - print("\n--- Results for imposed Rb (Rb* = 0.13) ---") - for method, result in results_imposed_Rb.items(): - print(f"Method: {method}") - print(f" Depth: {result['depth']:.2f} m") - print(f" Rb: {result['Rb']:.3f}") - print(f" Time: {result['time']:.2f} s") - print("\n--------------------------------------------") - - """ - # Add assertions for validation (replace with expected values for your case) - if peak_duration == 6: - assert np.isclose(results_default_Rb['L2']['depth'], 59.366, atol=0.1) - assert np.isclose(results_default_Rb['L3']['depth'], 59.543, atol=0.1) - assert np.isclose(results_default_Rb['L4']['depth'], 56.266, atol=0.1) - assert np.isclose(results_default_Rb['L4_ste']['depth'], 52.347, atol=0.1) - assert np.isclose(results_default_Rb['L3_ste']['depth'], 58.123, atol=0.1) # Example value - else: - # Adjust expected values based on 1-hour peak duration results - pass - """ if __name__ == "__main__": - test3_ste(use_pygfunction_media=False) + test_3_6h_ste() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste_old.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste_old.py index 762b54dc..ae115318 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste_old.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test3/test3_ste_old.py @@ -13,13 +13,8 @@ """ import os import time - import numpy as np import pygfunction as gt - -import sys -sys.path.append("C:\Workdir\Develop\ghetool") - from GHEtool import * @@ -27,16 +22,8 @@ def test_3_6h_ste(): # initiate ground, fluid and pipe data ground_data = GroundFluxTemperature(k_s=2.25, T_g=10, volumetric_heat_capacity=2592000, flux=0) base_mfr = 33.1 / 49 # Basis massastroom (kg/s) - - # Maak een water vloeistofobject via pygfunction - fluid_str = 'Water' # 'Water' is de standaard vloeistof in pygfunction - percent = 0 # Geen mengsel, dus 0% andere vloeistoffen - T_f = 0 # Temperatuur (bijvoorbeeld 20°C) - fluid_object = gt.media.Fluid(fluid_str, percent, T=T_f) # Maak fluid object - - # Maak FluidData object aan en laad vloeistofgegevens van pygfunction + # Maak FluidData object aan en laad vloeistofgegevens van pygfunction fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - fluid_data.import_fluid_from_pygfunction(fluid_object) # Laad de vloeistofgegevens in FluidData pipe_data = MultipleUTube(r_in=0.013, r_out=0.0167, D_s=0.075 / 2, k_g=1.73, k_p=0.4, number_of_pipes=1) # start test with dynamic Rb* diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste.py index 49529fa9..4aa4d0b6 100644 --- a/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste.py +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste.py @@ -13,103 +13,71 @@ """ import os import time - -import matplotlib.pyplot as plt - import numpy as np import pygfunction as gt - import sys -sys.path.append("C:\Workdir\Develop\ghetool") - from GHEtool import * - -def test_4_ste(): - # initiate ground, fluid and pipe data +def test_4_6h_ste(): + # Ground properties ground_data = GroundFluxTemperature(k_s=1.9, T_g=15, volumetric_heat_capacity=2052000, flux=0) - base_mfr = 0.074 * 139.731 / 25 # Basis massastroom (kg/s) - - # Maak een water vloeistofobject via pygfunction - fluid_str = 'Water' # 'Water' is de standaard vloeistof in pygfunction - percent = 0 # Geen mengsel, dus 0% andere vloeistoffen - T_f = 0 # Temperatuur (bijvoorbeeld 20°C) - fluid_object = gt.media.Fluid(fluid_str, percent, T=T_f) # Maak fluid object - # Maak FluidData object aan en laad vloeistofgegevens van pygfunction + # Load fluid properties into FluidData + base_mfr = 0.074 * 139.731 / 25 # Baseline mass flow rate (kg/s) fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) - fluid_data.import_fluid_from_pygfunction(fluid_object) # Laad de vloeistofgegevens in FluidData + + # Pipe properties pipe_data = MultipleUTube(r_in=0.013, r_out=0.0167, D_s=0.083 / 2, k_g=0.69, k_p=0.4) - # start test with dynamic Rb* - # initiate borefield - borefield = Borefield() + # Short-term effect parameters + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + + # Initialize results dictionary + results = {} - # set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + # Define function to store results + def log_results(method, depth, borefield, start_time): + results[method] = { + 'depth': depth, + 'Rb': borefield.Rb, + 'time': time.time() - start_time + } - # load the hourly profile + # Load hourly profile load = HourlyGeothermalLoad(simulation_period=20) load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test4.csv'), header=True, separator=",", col_extraction=1, col_injection=0) - borefield.load = load - # convert inlet fluid temperature to heap pump constraints to constraints on average fluid temperature + # Calculate temperature bounds delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) / 25 - # set temperature bounds - borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - # Sizing with dynamic Rb - # according to L2 - L2_start = time.time() - depth_L2 = borefield.size(100, L2_sizing=True) - Rb_L2 = borefield.Rb - L2_stop = time.time() - - # according to L3 - L3_start = time.time() - depth_L3 = borefield.size(100, L3_sizing=True) - Rb_L3 = borefield.Rb - L3_stop = time.time() - - # according to L4 - L4_start = time.time() - depth_L4 = borefield.size(100, L4_sizing=True) - borefield._plot_temperature_profile(plot_hourly=True) - Rb_L4 = borefield.Rb - L4_stop = time.time() - - # initiate borefield - borefield = Borefield() - - # set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) - - borefield.load = load - - # set temperature bounds - borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - # Addidional input data needed for short-term model - rho_cp_grout = 3800000.0 - rho_cp_pipe = 1540000.0 - - # Sample dictionary with short-term effect parameters - short_term_effects_parameters = { - 'rho_cp_grout': rho_cp_grout, - 'rho_cp_pipe': rho_cp_pipe, - } - - options = { + # Test each sizing method + for method, dynamic_rb, short_term_effects in [ + ('L2', True, False), ('L3', True, False), ('L4', True, False), ('L3_ste', True, True), + ('L4_ste', True, True), ('L2_static', False, False), ('L3_static', False, False), + ('L4_static', False, False), ('L3_static_ste', False, True), ('L4_static_ste', False, True) + ]: + # Initialize borefield + borefield = Borefield() + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + borefield.load = load + + # Set temperature bounds + borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # Handle short-term effects + if short_term_effects: + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { 'disp': False, 'profiles': True, 'method': 'equivalent', @@ -121,125 +89,21 @@ def test_4_ste(): 'borefield': borefield, 'short_term_effects_parameters': short_term_effects_parameters, } + borefield.set_options_gfunction_calculation(options) - borefield.set_options_gfunction_calculation(options) - - # according to L4 - L4_ste_start = time.time() - depth_L4_ste = borefield.size(100, L4_sizing=True) - Rb_L4_ste = borefield.Rb - L4_ste_stop = time.time() - - # start test with constant Rb* - # initiate borefield - borefield = Borefield() - - # set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) - Rb_static = 0.2 - borefield.set_Rb(Rb_static) - - # set temperature bounds - borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - # load the hourly profile - borefield.load = load - - # Sizing with constant Rb - L2s_start = time.time() - depth_L2s = borefield.size(100, L2_sizing=True) - L2s_stop = time.time() - - # according to L3 - L3s_start = time.time() - depth_L3s = borefield.size(100, L3_sizing=True) - L3s_stop = time.time() - - # according to L4 - L4s_start = time.time() - depth_L4s = borefield.size(100, L4_sizing=True) - L4s_stop = time.time() - - # initiate borefield - borefield = Borefield() - - # set ground data in borefield - borefield.set_ground_parameters(ground_data) - borefield.set_fluid_parameters(fluid_data) - borefield.set_pipe_parameters(pipe_data) - borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) - Rb_static = 0.2 - borefield.set_Rb(Rb_static) - - # set temperature bounds - borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) - borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) - - # load the hourly profile - borefield.load = load - - # Addidional input data needed for short-term model - rho_cp_grout = 3800000.0 - rho_cp_pipe = 1540000.0 + # Use constant Rb if required + if not dynamic_rb: + borefield.set_Rb(0.2) - # Sample dictionary with short-term effect parameters - short_term_effects_parameters = { - 'rho_cp_grout': rho_cp_grout, - 'rho_cp_pipe': rho_cp_pipe, - } + # Perform sizing + start_time = time.time() + depth = borefield.size(100, L2_sizing=(method.startswith('L2')), L3_sizing=(method.startswith('L3')), L4_sizing=(method.startswith('L4'))) + log_results(method, depth, borefield, start_time) - options = { - 'disp': False, - 'profiles': True, - 'method': 'equivalent', - 'cylindrical_correction': True, - 'short_term_effects': True, - 'ground_data': ground_data, - 'fluid_data': fluid_data, - 'pipe_data': pipe_data, - 'borefield': borefield, - 'short_term_effects_parameters': short_term_effects_parameters, - } + # Print results + for method, result in results.items(): + print(f"Method {method}: Depth = {result['depth']:.2f}m, Rb* = {result['Rb']:.3f}, Time = {result['time']:.2f}s") - borefield.set_options_gfunction_calculation(options) - - # according to L4 - L4s_ste_start = time.time() - depth_L4s_ste = borefield.size(100, L4_sizing=True) - L4s_ste_stop = time.time() - - print( - f"The sizing according to L2 has a depth of {depth_L2:.2f}m (using dynamic Rb* of {Rb_L2:.3f}) and {depth_L2s:.2f}m (using constant Rb*)") - print( - f"The sizing according to L3 has a depth of {depth_L3:.2f}m (using dynamic Rb* of {Rb_L3:.3f}) and {depth_L3s:.2f}m (using constant Rb*)") - print( - f"The sizing according to L4 has a depth of {depth_L4:.2f}m (using dynamic Rb* of {Rb_L4:.3f}) and {depth_L4s:.2f}m (using constant Rb*)") - print( - f"The sizing according to L4 (inclusing short-term effects) has a depth of {depth_L4_ste}m (using dynamic Rb* of {Rb_L4_ste}) and {depth_L4s_ste}m (using constant Rb*)") - print( - f"Time needed for L4-sizing is {L4_stop-L4_start:.2f}s (using dynamic Rb*) or {L4s_stop-L4s_start:.2f}s (using constant Rb*)") - print( - f"Time needed for L4-sizing including short-term effect is {L4_ste_stop-L4_ste_start:.2f}s (using dynamic Rb*) or {L4s_ste_stop-L4s_ste_start:.2f}s (using constant Rb*)") - - plt.show() - - assert np.isclose(depth_L2, 124.02695636769329) - assert np.isclose(depth_L3, 124.67134582762849) - assert np.isclose(depth_L4, 122.461471483961) - assert np.isclose(depth_L4_ste, 116.61823578676353) - assert np.isclose(depth_L2s, 121.50772080500283) - assert np.isclose(depth_L3s, 122.15337731354852) - assert np.isclose(depth_L4s, 119.99581098989934) - assert np.isclose(depth_L4s_ste, 114.67191666829271) - assert np.isclose(Rb_L2, 0.21023380751472076) - assert np.isclose(Rb_L3, 0.21025731326271593) - assert np.isclose(Rb_L4, 0.2101772055278848) - assert np.isclose(Rb_L4_ste, 0.20997223493386377) - - -if __name__ == "__main__": # pragma: no cover - test_4_ste() \ No newline at end of file + +if __name__ == "__main__": + test_4_6h_ste() diff --git a/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste_old.py b/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste_old.py new file mode 100644 index 00000000..49529fa9 --- /dev/null +++ b/GHEtool/Validation/comparison_with_other_sizing_tools/test4/test4_ste_old.py @@ -0,0 +1,245 @@ +""" +The work of (Ahmadfard and Bernier, 2019) provides a set of test cases that can be used to compare +software tools with the ultimate goal of improving the reliability of design methods for sizing +vertical ground heat exchangers. This document delivers the results on the test file using the GHEtool +L2-, L3- and L4-sizing methods. + +Test 4 – High annual ground load imbalance + +References: +----------- + - Ahmadfard, M., and M. Bernier. 2019. A review of vertical ground heat exchanger sizing tools including an inter-model +comparison [in eng]. Renewable sustainable energy reviews (OXFORD) 110:247–265. +""" +import os +import time + +import matplotlib.pyplot as plt + +import numpy as np +import pygfunction as gt + +import sys +sys.path.append("C:\Workdir\Develop\ghetool") + +from GHEtool import * + + +def test_4_ste(): + # initiate ground, fluid and pipe data + ground_data = GroundFluxTemperature(k_s=1.9, T_g=15, volumetric_heat_capacity=2052000, flux=0) + base_mfr = 0.074 * 139.731 / 25 # Basis massastroom (kg/s) + + # Maak een water vloeistofobject via pygfunction + fluid_str = 'Water' # 'Water' is de standaard vloeistof in pygfunction + percent = 0 # Geen mengsel, dus 0% andere vloeistoffen + T_f = 0 # Temperatuur (bijvoorbeeld 20°C) + fluid_object = gt.media.Fluid(fluid_str, percent, T=T_f) # Maak fluid object + + # Maak FluidData object aan en laad vloeistofgegevens van pygfunction + fluid_data = FluidData(mfr=base_mfr, rho=1026, Cp=4019, mu=0.003377, k_f=0.468) + fluid_data.import_fluid_from_pygfunction(fluid_object) # Laad de vloeistofgegevens in FluidData + pipe_data = MultipleUTube(r_in=0.013, r_out=0.0167, D_s=0.083 / 2, k_g=0.69, k_p=0.4) + + # start test with dynamic Rb* + # initiate borefield + borefield = Borefield() + + # set ground data in borefield + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + + # load the hourly profile + load = HourlyGeothermalLoad(simulation_period=20) + load.load_hourly_profile(os.path.join(os.path.dirname(__file__), 'test4.csv'), header=True, separator=",", + col_extraction=1, col_injection=0) + borefield.load = load + + # convert inlet fluid temperature to heap pump constraints to constraints on average fluid temperature + delta_t = max(load.max_peak_extraction, load.max_peak_injection) * 1000 / (fluid_data.Cp * fluid_data.mfr) / 25 + + # set temperature bounds + borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # Sizing with dynamic Rb + # according to L2 + L2_start = time.time() + depth_L2 = borefield.size(100, L2_sizing=True) + Rb_L2 = borefield.Rb + L2_stop = time.time() + + # according to L3 + L3_start = time.time() + depth_L3 = borefield.size(100, L3_sizing=True) + Rb_L3 = borefield.Rb + L3_stop = time.time() + + # according to L4 + L4_start = time.time() + depth_L4 = borefield.size(100, L4_sizing=True) + borefield._plot_temperature_profile(plot_hourly=True) + Rb_L4 = borefield.Rb + L4_stop = time.time() + + # initiate borefield + borefield = Borefield() + + # set ground data in borefield + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + + borefield.load = load + + # set temperature bounds + borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # Addidional input data needed for short-term model + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + + # Sample dictionary with short-term effect parameters + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + + borefield.set_options_gfunction_calculation(options) + + # according to L4 + L4_ste_start = time.time() + depth_L4_ste = borefield.size(100, L4_sizing=True) + Rb_L4_ste = borefield.Rb + L4_ste_stop = time.time() + + # start test with constant Rb* + # initiate borefield + borefield = Borefield() + + # set ground data in borefield + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + Rb_static = 0.2 + borefield.set_Rb(Rb_static) + + # set temperature bounds + borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # load the hourly profile + borefield.load = load + + # Sizing with constant Rb + L2s_start = time.time() + depth_L2s = borefield.size(100, L2_sizing=True) + L2s_stop = time.time() + + # according to L3 + L3s_start = time.time() + depth_L3s = borefield.size(100, L3_sizing=True) + L3s_stop = time.time() + + # according to L4 + L4s_start = time.time() + depth_L4s = borefield.size(100, L4_sizing=True) + L4s_stop = time.time() + + # initiate borefield + borefield = Borefield() + + # set ground data in borefield + borefield.set_ground_parameters(ground_data) + borefield.set_fluid_parameters(fluid_data) + borefield.set_pipe_parameters(pipe_data) + borefield.create_rectangular_borefield(5, 5, 8, 8, 110, 4, 0.075) + Rb_static = 0.2 + borefield.set_Rb(Rb_static) + + # set temperature bounds + borefield.set_max_avg_fluid_temperature(38 + delta_t / 2) + borefield.set_min_avg_fluid_temperature(0 - delta_t / 2) + + # load the hourly profile + borefield.load = load + + # Addidional input data needed for short-term model + rho_cp_grout = 3800000.0 + rho_cp_pipe = 1540000.0 + + # Sample dictionary with short-term effect parameters + short_term_effects_parameters = { + 'rho_cp_grout': rho_cp_grout, + 'rho_cp_pipe': rho_cp_pipe, + } + + options = { + 'disp': False, + 'profiles': True, + 'method': 'equivalent', + 'cylindrical_correction': True, + 'short_term_effects': True, + 'ground_data': ground_data, + 'fluid_data': fluid_data, + 'pipe_data': pipe_data, + 'borefield': borefield, + 'short_term_effects_parameters': short_term_effects_parameters, + } + + borefield.set_options_gfunction_calculation(options) + + # according to L4 + L4s_ste_start = time.time() + depth_L4s_ste = borefield.size(100, L4_sizing=True) + L4s_ste_stop = time.time() + + print( + f"The sizing according to L2 has a depth of {depth_L2:.2f}m (using dynamic Rb* of {Rb_L2:.3f}) and {depth_L2s:.2f}m (using constant Rb*)") + print( + f"The sizing according to L3 has a depth of {depth_L3:.2f}m (using dynamic Rb* of {Rb_L3:.3f}) and {depth_L3s:.2f}m (using constant Rb*)") + print( + f"The sizing according to L4 has a depth of {depth_L4:.2f}m (using dynamic Rb* of {Rb_L4:.3f}) and {depth_L4s:.2f}m (using constant Rb*)") + print( + f"The sizing according to L4 (inclusing short-term effects) has a depth of {depth_L4_ste}m (using dynamic Rb* of {Rb_L4_ste}) and {depth_L4s_ste}m (using constant Rb*)") + print( + f"Time needed for L4-sizing is {L4_stop-L4_start:.2f}s (using dynamic Rb*) or {L4s_stop-L4s_start:.2f}s (using constant Rb*)") + print( + f"Time needed for L4-sizing including short-term effect is {L4_ste_stop-L4_ste_start:.2f}s (using dynamic Rb*) or {L4s_ste_stop-L4s_ste_start:.2f}s (using constant Rb*)") + + plt.show() + + assert np.isclose(depth_L2, 124.02695636769329) + assert np.isclose(depth_L3, 124.67134582762849) + assert np.isclose(depth_L4, 122.461471483961) + assert np.isclose(depth_L4_ste, 116.61823578676353) + assert np.isclose(depth_L2s, 121.50772080500283) + assert np.isclose(depth_L3s, 122.15337731354852) + assert np.isclose(depth_L4s, 119.99581098989934) + assert np.isclose(depth_L4s_ste, 114.67191666829271) + assert np.isclose(Rb_L2, 0.21023380751472076) + assert np.isclose(Rb_L3, 0.21025731326271593) + assert np.isclose(Rb_L4, 0.2101772055278848) + assert np.isclose(Rb_L4_ste, 0.20997223493386377) + + +if __name__ == "__main__": # pragma: no cover + test_4_ste() \ No newline at end of file