diff --git a/src/topupheat/common/fluids.py b/src/topupheat/common/fluids.py index ba44066dbb879d6229cc861cbee70920866f0154..1c78d69e8b0a3f4a29595b95f3182644e9b4087e 100644 --- a/src/topupheat/common/fluids.py +++ b/src/topupheat/common/fluids.py @@ -336,9 +336,9 @@ class Fluid: # kinematic_viscosity: float = field(init=False) db: InitVar[FluidDatabase] = None - ideal_gas: InitVar[bool] = None + ideal_gas: InitVar[bool] = False - def __post_init__(self, db: FluidDatabase, ideal_gas: bool): + def __post_init__(self, db: FluidDatabase, ideal_gas: bool = False): # if a database has been provided @@ -363,7 +363,7 @@ class Fluid: db.mass_density[self.phase][db.key_TEMPERATURE], db.mass_density[self.phase][db.key_PRESSURE], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 # interpolate data from database using temperature @@ -371,43 +371,43 @@ class Fluid: db.mass_density[self.phase][db.key_TEMPERATURE], db.mass_density[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.specific_heat = interp1d( db.specific_heat[self.phase][db.key_TEMPERATURE], db.specific_heat[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.dynamic_viscosity = interp1d( db.dynamic_viscosity[self.phase][db.key_TEMPERATURE], db.dynamic_viscosity[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.thermal_conductivity = interp1d( db.thermal_conductivity[self.phase][db.key_TEMPERATURE], db.thermal_conductivity[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.thermal_diffusivity = interp1d( db.thermal_diffusivity[self.phase][db.key_TEMPERATURE], db.thermal_diffusivity[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.prandtl_number = interp1d( db.prandtl_number[self.phase][db.key_TEMPERATURE], db.prandtl_number[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 self.coefficient_expansion = interp1d( db.coefficient_expansion[self.phase][db.key_TEMPERATURE], db.coefficient_expansion[self.phase][db.key_DATA], kind=interpolation_type - )(self.temperature) + )(self.temperature)*1 # self.surface_tension = interp1d( # db.surface_tension[self.phase][db.key_TEMPERATURE], @@ -447,17 +447,26 @@ class Fluid: ) # convert to np.float - - self.mass_density = np.float64(self.mass_density) - self.specific_heat = np.float64(self.specific_heat) - self.dynamic_viscosity = np.float64(self.dynamic_viscosity) - self.thermal_conductivity = np.float64(self.thermal_conductivity) - self.thermal_diffusivity = np.float64(self.thermal_diffusivity) - self.prandtl_number = np.float64(self.prandtl_number) - self.coefficient_expansion = np.float64(self.coefficient_expansion) - # self.surface_tension = np.float64(self.surface_tension) - # self.heat_vaporisation = np.float64(self.heat_vaporisation) - self.kinematic_viscosity = np.float64(self.kinematic_viscosity) + if type(self.mass_density) == np.ndarray: + + print('bahn') + print(self.temperature) + print(self.mass_density) + print(db.mass_density[self.phase][db.key_TEMPERATURE]) + print(db.mass_density[self.phase][db.key_DATA]) + print(type(db.mass_density[self.phase][db.key_TEMPERATURE])) + print(type(db.mass_density[self.phase][db.key_DATA])) + assert False + self.mass_density = float(self.mass_density) + self.specific_heat = float(self.specific_heat) + self.dynamic_viscosity = float(self.dynamic_viscosity) + self.thermal_conductivity = float(self.thermal_conductivity) + self.thermal_diffusivity = float(self.thermal_diffusivity) + self.prandtl_number = float(self.prandtl_number) + self.coefficient_expansion = float(self.coefficient_expansion) + # self.surface_tension = float(self.surface_tension) + # self.heat_vaporisation = float(self.heat_vaporisation) + self.kinematic_viscosity = float(self.kinematic_viscosity) #****************************************************************************** #****************************************************************************** diff --git a/src/topupheat/pipes/system.py b/src/topupheat/pipes/system.py index 6380c41044ad7308f9c7e7c863737802ae896332..c446094533058bf95dc8f4d1cc4761880e9d72fb 100644 --- a/src/topupheat/pipes/system.py +++ b/src/topupheat/pipes/system.py @@ -163,7 +163,7 @@ class SupplyReturnPipeSystem: tuple(return_pipe) if self.pipes_are_different else None ) # pressure - self.pressure = pressure + self.pressure = tuple(pressure) # temperatures self.supply_temperature = tuple(supply_temperature) self.return_temperature = tuple(return_temperature) @@ -174,10 +174,10 @@ class SupplyReturnPipeSystem: fic.Fluid( phase=phase, temperature=(st+rt)/2, - pressure=pressure, + pressure=p, db=fluid_db ) - for st, rt in zip(supply_temperature, return_temperature) + for st, rt, p in zip(self.supply_temperature, self.return_temperature, self.pressure) ] else: # each pipe has its own temperature @@ -185,19 +185,19 @@ class SupplyReturnPipeSystem: fic.Fluid( phase=phase, temperature=st, - pressure=pressure, + pressure=p, db=fluid_db ) - for st in zip(supply_temperature) + for st, p in zip(self.supply_temperature, self.pressure) ] self.return_fluid = [ fic.Fluid( phase=phase, temperature=rt, - pressure=pressure, + pressure=p, db=fluid_db ) - for rt in zip(return_temperature) + for rt, p in zip(self.return_temperature, self.pressure) ] elif (isinstance(pressure, Real) and isinstance(supply_temperature, Real) and @@ -451,7 +451,7 @@ class SupplyReturnPipeSystem: fn_max_specific_pressure_loss: list = None, unit_conversion_factor: float = 1.0 ) -> tuple: - # TODO: check the type for max_specific_pressure_loss + # check the type for max_specific_pressure_loss if type(max_specific_pressure_loss) == list: mspl = max_specific_pressure_loss elif type(max_specific_pressure_loss) == type(None): @@ -559,6 +559,91 @@ class SupplyReturnPipeSystem: def specific_pressure_loss(self): # pressure loss divided by the trench (not pipe) length raise NotImplementedError + + # ************************************************************************* + + def simplified_specific_heat_transfer_surroundings( + self, + specific_heat_transfer_coefficient: float or list, + temperature_surroundings: float or list, + unit_conversion_factor: float = 1.0 + ): + + # length >> options + # specific_heat_transfer_coefficient >> options + # temperature_surroundings >> temporal + # determine if the inputs are for temporal vector/normal mode + if isinstance(temperature_surroundings, Real): + temporal_vector_mode = False + elif (type(temperature_surroundings) == list or + type(temperature_surroundings) == tuple): + temporal_vector_mode = True + else: + raise ValueError('Incompatible inputs.') + + # confirm inputs are consistent with vector/normal mode + if ((not self.vector_mode and + not isinstance(specific_heat_transfer_coefficient, Real)) or + (self.vector_mode and + len(self.supply_temperature) < 1 + ) + ): + raise TypeError('Inconsistent inputs.') + + if self.vector_mode: + # vector mode: multiple options + if temporal_vector_mode: + out = [ + [((st+rt)*0.5-ts)* + shtc* + unit_conversion_factor* + (1 if self.losses_are_positive else -1)* + (1 if self.twin_pipes else 2) + for ts in temperature_surroundings + ] + for st, rt, shtc in zip( + self.supply_temperature, + self.return_temperature, + specific_heat_transfer_coefficient + ) + ] + else: + # one time step + out = [ + ((st+rt)*0.5-temperature_surroundings)* + shtc* + unit_conversion_factor* + (1 if self.losses_are_positive else -1)* + (1 if self.twin_pipes else 2) + for st, rt, shtc in zip( + self.supply_temperature, + self.return_temperature, + specific_heat_transfer_coefficient + ) + ] + else: + # normal mode: one option + if temporal_vector_mode: + # multiple time steps + out = [ + ((self.supply_temperature+self.return_temperature)*0.5-ts)* + specific_heat_transfer_coefficient* + unit_conversion_factor* + (1 if self.losses_are_positive else -1)* + (1 if self.twin_pipes else 2) + for ts in temperature_surroundings + ] + else: + # one time step + out = ( + ((self.supply_temperature+self.return_temperature)*0.5- + temperature_surroundings)* + specific_heat_transfer_coefficient* + unit_conversion_factor* + (1 if self.losses_are_positive else -1)* + (1 if self.twin_pipes else 2) + ) + return out # ************************************************************************* diff --git a/src/topupheat/pipes/trenches.py b/src/topupheat/pipes/trenches.py index 07f7ba240c62c01a559765be10b34e9d16dec468..d8e988dbf8b8f568003f80ebf7d7019ebe009889 100644 --- a/src/topupheat/pipes/trenches.py +++ b/src/topupheat/pipes/trenches.py @@ -33,38 +33,32 @@ SHT_MODELS = ( TRGTPT_MULTIPOLE_SECOND_ORDER, TRGTPT_TWO_MODEL_APPROX) -# TODO: create easy way to identify which methods are available for each cse -# SHT_MODELS = { -# SHT_METHOD_DIRECT: [ -# TRGTPT_KRISCHER1936, -# TRGTPT_MULTIPOLE_ZERO_ORDER, -# TRGTPT_MULTIPOLE_FIRST_ORDER, -# TRGTPT_MULTIPOLE_SECOND_ORDER, -# TRGTPT_TWO_MODEL_APPROX -# ], -# SHT_METHOD_SYM_ASYM: [ -# TRGTPT_KRISCHER1936, -# TRGTPT_MULTIPOLE_ZERO_ORDER, -# TRGTPT_MULTIPOLE_FIRST_ORDER, -# TRGTPT_MULTIPOLE_SECOND_ORDER, -# TRGTPT_TWO_MODEL_APPROX -# ], -# } +VALID_PAIRS_TWIN_PIPE = [ + # option 1, option 2 + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_ZERO_ORDER), + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_FIRST_ORDER), + (SHT_METHOD_SYM_ASYM, TRGTPT_TWO_MODEL_APPROX), + ] -# Wallenten: single -# TRGTPT_MULTIPOLE_ZERO_ORDER -# TRGTPT_MULTIPOLE_FIRST_ORDER - -# Wallenten: twin -# TRGTPT_MULTIPOLE_ZERO_ORDER -# TRGTPT_MULTIPOLE_FIRST_ORDER -# TRGTPT_TWO_MODEL_APPROX - -# two buried pipes: -# TRGTPT_KRISCHER1936 -# TRGTPT_MULTIPOLE_ZERO_ORDER -# TRGTPT_MULTIPOLE_FIRST_ORDER +VALID_PAIRS_TWO_SINGLE_PIPES = [ + # option 1, option 2 + (SHT_METHOD_SYM_ASYM, TRGTPT_KRISCHER1936), + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_ZERO_ORDER), + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_FIRST_ORDER), + (SHT_METHOD_DIRECT, TRGTPT_KRISCHER1936), + (SHT_METHOD_DIRECT, TRGTPT_MULTIPOLE_ZERO_ORDER), + (SHT_METHOD_DIRECT, TRGTPT_MULTIPOLE_FIRST_ORDER), + ] +VALID_PAIRS_ONE_PIPE = [ + # option 1, option 2 + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_ZERO_ORDER), + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_FIRST_ORDER), + (SHT_METHOD_SYM_ASYM, TRGTPT_MULTIPOLE_SECOND_ORDER), + (SHT_METHOD_DIRECT, TRGTPT_MULTIPOLE_ZERO_ORDER), + (SHT_METHOD_DIRECT, TRGTPT_MULTIPOLE_FIRST_ORDER), + (SHT_METHOD_DIRECT, TRGTPT_MULTIPOLE_SECOND_ORDER), + ] #****************************************************************************** #****************************************************************************** @@ -119,14 +113,10 @@ class SupplyReturnPipeTrench(SupplyReturnPipeSystem): 'The pipe objects must be for insulated pipes.' ) # heat transfer ground model - if sht_model not in SHT_MODELS: + if not self.model_config_is_known(sht_method, sht_model): raise ValueError( - 'Unindentified model for the heat transfer calculations.') + 'Unknown model for the heat transfer calculations.') self.sht_model = sht_model - # heat transfer calculation method - if sht_method not in SHT_METHODS: - raise ValueError( - 'Unindentified method to perform heat transfer calculations.') self.sht_method = sht_method # check if the trench data format matches the rest if (self.vector_mode and not self.twin_pipes and @@ -164,6 +154,18 @@ class SupplyReturnPipeTrench(SupplyReturnPipeSystem): # ************************************************************************* # ************************************************************************* + + def model_config_is_known(self, sht_method, sht_model) -> bool: + "Returns True if a given model configuration is accepted." + if self.twin_pipes and (sht_method, sht_model) in VALID_PAIRS_TWIN_PIPE: + return True + elif not self.twin_pipes and (sht_method, sht_model) in VALID_PAIRS_TWO_SINGLE_PIPES: + return True + else: + return False + + # ************************************************************************* + # ************************************************************************* def heat_transfer_surroundings( self, diff --git a/tests/test_system.py b/tests/test_system.py index a71ca10c062939b7e4f327d46ad94f0b1a34ebd7..0f66084769552fbd57047a7099a598bacc017c55 100644 --- a/tests/test_system.py +++ b/tests/test_system.py @@ -121,6 +121,13 @@ class TestPipeSystem: ) assert isclose(sht, sht_true, abs_tol=sht_tol) + + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coef, + temperature_surroundings=temperature_surroundings, + ) + + assert isclose(sht, sht_true, abs_tol=sht_tol) number_steps = 2 @@ -137,6 +144,16 @@ class TestPipeSystem: for _sht in sht: assert isclose(_sht, sht_true, abs_tol=sht_tol) + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coef, + temperature_surroundings=[ + temperature_surroundings for i in range(number_steps)], + ) + assert type(sht) == list + assert len(sht) == number_steps + for _sht in sht: + assert isclose(_sht, sht_true, abs_tol=sht_tol) + # try using incorrect option-based inputs error_raised = False @@ -150,6 +167,16 @@ class TestPipeSystem: except TypeError: error_raised = True assert error_raised + + error_raised = False + try: + srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=[u_coef], + temperature_surroundings=temperature_surroundings + ) + except TypeError: + error_raised = True + assert error_raised # ***************************************************************** @@ -165,6 +192,15 @@ class TestPipeSystem: assert isclose(sht, sht_true*ucf, abs_tol=sht_tol*ucf) + ucf = 2 + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coef, + temperature_surroundings=temperature_surroundings, + unit_conversion_factor=ucf + ) + + assert isclose(sht, sht_true*ucf, abs_tol=sht_tol*ucf) + number_steps = 2 sht = srps.simplified_heat_transfer_surroundings( @@ -180,6 +216,17 @@ class TestPipeSystem: assert len(sht) == number_steps for _sht in sht: assert isclose(_sht, sht_true*ucf, abs_tol=sht_tol*ucf) + + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coef, + temperature_surroundings=[ + temperature_surroundings for i in range(number_steps)], + unit_conversion_factor=ucf + ) + assert type(sht) == list + assert len(sht) == number_steps + for _sht in sht: + assert isclose(_sht, sht_true*ucf, abs_tol=sht_tol*ucf) # ************************************************************************* @@ -300,8 +347,21 @@ class TestPipeSystem: specific_heat_losses, specific_heat_losses_tol ): - assert isclose(_sht, sht_true, abs_tol=sht_tol) + assert isclose(_sht, sht_true, abs_tol=sht_tol) + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coefficients, + temperature_surroundings=temperature_surroundings, + ) + + assert type(sht) == list + assert len(sht) == number_options + for _sht, sht_true, sht_tol in zip( + sht, + specific_heat_losses, + specific_heat_losses_tol + ): + assert isclose(_sht, sht_true, abs_tol=sht_tol) # simplified heat transfer surroundings (temporal vector mode) number_steps = 3 @@ -313,6 +373,25 @@ class TestPipeSystem: time_interval_duration=[1 for i in range(number_steps)] ) + assert type(sht) == list + assert len(sht) == number_options + for _sht, sht_true, sht_tol in zip( + sht, + specific_heat_losses, + specific_heat_losses_tol + ): + assert type(_sht) == list + assert len(_sht) == number_steps + for __sht in _sht: + assert isclose(__sht, sht_true, abs_tol=sht_tol) + + number_steps = 3 + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coefficients, + temperature_surroundings=[ + temperature_surroundings for i in range(number_steps)] + ) + assert type(sht) == list assert len(sht) == number_options for _sht, sht_true, sht_tol in zip( @@ -338,6 +417,16 @@ class TestPipeSystem: except TypeError: error_raised = True assert error_raised + + error_raised = False + try: + srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coefficients[0], + temperature_surroundings=temperature_surroundings + ) + except TypeError: + error_raised = True + assert error_raised # ********************************************************************* @@ -361,6 +450,20 @@ class TestPipeSystem: ): assert isclose(_sht, sht_true*ucf, abs_tol=sht_tol*ucf) + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coefficients, + temperature_surroundings=temperature_surroundings, + unit_conversion_factor=ucf + ) + + assert type(sht) == list + assert len(sht) == number_options + for _sht, sht_true, sht_tol in zip( + sht, + specific_heat_losses, + specific_heat_losses_tol + ): + assert isclose(_sht, sht_true*ucf, abs_tol=sht_tol*ucf) # simplified heat transfer surroundings (temporal vector mode) number_steps = 3 @@ -384,6 +487,26 @@ class TestPipeSystem: assert len(_sht) == number_steps for __sht in _sht: assert isclose(__sht, sht_true*ucf, abs_tol=sht_tol*ucf) + + number_steps = 3 + sht = srps.simplified_specific_heat_transfer_surroundings( + specific_heat_transfer_coefficient=u_coefficients, + temperature_surroundings=[ + temperature_surroundings for i in range(number_steps)], + unit_conversion_factor=ucf + ) + + assert type(sht) == list + assert len(sht) == number_options + for _sht, sht_true, sht_tol in zip( + sht, + specific_heat_losses, + specific_heat_losses_tol + ): + assert type(_sht) == list + assert len(_sht) == number_steps + for __sht in _sht: + assert isclose(__sht, sht_true*ucf, abs_tol=sht_tol*ucf) # ************************************************************************* # ************************************************************************* @@ -395,7 +518,7 @@ class TestPipeSystem: waterdata_file = 'tests/data/incropera2006_saturated_water.csv' phase = FluidDatabase.fluid_LIQUID fluid_db = FluidDatabase( - fluid='fluid', + fluid='water', phase=phase, source=waterdata_file ) @@ -654,7 +777,7 @@ class TestPipeSystem: # vector mode, use different fluid properties - number_points = 2 + number_points = 4 srps = SupplyReturnPipeSystem( fluid_db=fluid_db, phase=phase, @@ -673,6 +796,7 @@ class TestPipeSystem: heat_transfer_rates_true = [ 12922.276900000026, 129222.76900000026, + 1292227.6900000026, 1292227.6900000026 ] heat_transfer_rates = srps.heat_transfer_rate(mass_flow_rates)