Source code for enex_analysis.enex_engine

"""
Energy, Entropy, and Exergy Analysis Engine.

This module contains classes for modeling various energy systems including:
- Domestic hot water systems (electric boiler, gas boiler, heat pump boiler)
- Air source heat pumps (cooling and heating modes)
- Ground source heat pumps (cooling and heating modes)
- Solar-assisted systems
- Electric heaters
"""

import math
from dataclasses import dataclass

from . import calc_util as cu
from .air_source_heat_pump_boiler import AirSourceHeatPumpBoiler
from .components.fan import Fan
from .constants import c_a, c_w, k_w, rho_a, rho_w
from .enex_functions import (
    G_FLS,
    calc_ASHP_cooling_COP,
    calc_ASHP_heating_COP,
    calc_GSHP_COP,
)

# Phase 3 Refactoring: Re-exporting standalone boiler modules for backward compatibility

# Alias for backward compatibility since HeatPumpBoiler was the original name
HeatPumpBoiler = AirSourceHeatPumpBoiler

# class - Fan & Pump


# class - Domestic Hot Water System
# class - AirSourceHeatPump
[docs] @dataclass class AirSourceHeatPump_cooling: """Air source heat pump model for cooling mode. Simulates a single-step refrigerant cycle with indoor/outdoor heat exchangers and fans. Call ``system_update()`` after setting operating conditions to compute COP, capacities, and component powers. """ def __post_init__(self): # fan self.fan_int = Fan().fan1 self.fan_ext = Fan().fan2 # COP self.Q_r_max = 20000 # [W] # temperature self.T0 = 32 # environmental temperature [°C] self.T_a_room = 20 # room air temperature [°C] self.T_r_int = ( self.T_a_room - 15 ) # internal unit refrigerant temperature [°C] self.T_a_int_out = ( self.T_a_room - 10 ) # internal unit air outlet temperature [°C] self.T_a_ext_out = ( self.T0 + 10 ) # external unit air outlet temperature [°C] self.T_r_ext = ( self.T0 + 15 ) # external unit refrigerant temperature [°C] # load self.Q_r_int = 6000 # [W] # COP의 reference로 삼을 수 있는 값 self.COP_ref = 4
[docs] def system_update(self): # Celcius to Kelvin self.T0 = cu.C2K(self.T0) self.T_a_room = cu.C2K(self.T_a_room) self.T_a_int_out = cu.C2K(self.T_a_int_out) self.T_a_ext_out = cu.C2K(self.T_a_ext_out) self.T_r_int = cu.C2K(self.T_r_int) self.T_r_ext = cu.C2K(self.T_r_ext) # temperature self.T_a_int_in = ( self.T_a_room ) # internal unit air inlet temperature [K] self.T_a_ext_in = self.T0 # external unit air inlet temperature [K] # others self.COP = calc_ASHP_cooling_COP( self.T_a_int_out, self.T_a_ext_in, self.Q_r_int, self.Q_r_max, self.COP_ref, ) # COP [-] self.E_cmp = self.Q_r_int / self.COP # compressor power input [W] self.Q_r_ext = ( self.Q_r_int + self.E_cmp ) # heat transfer from external unit to refrigerant [W] # internal, external unit self.dV_int = self.Q_r_int / ( c_a * rho_a * (abs(self.T_a_int_out - self.T_a_int_in)) ) # volumetric flow rate of internal unit [m3/s] self.dV_ext = self.Q_r_ext / ( c_a * rho_a * (abs(self.T_a_ext_out - self.T_a_ext_in)) ) # volumetric flow rate of external unit [m3/s] # fan power self.E_fan_int = Fan().get_power( self.fan_int, self.dV_int ) # power input of internal unit fan [W] self.E_fan_ext = Fan().get_power( self.fan_ext, self.dV_ext ) # power input of external unit fan [W] # System COP self.COP_sys = self.Q_r_int / ( self.E_fan_int + self.E_fan_ext + self.E_cmp ) # exergy result self.X_a_int_in = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_in - self.T0) - self.T0 * math.log(self.T_a_int_in / self.T0) ) ) self.X_a_int_out = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_out - self.T0) - self.T0 * math.log(self.T_a_int_out / self.T0) ) ) self.X_a_ext_in = ( c_a * rho_a * self.dV_ext * ( (self.T_a_ext_in - self.T0) - self.T0 * math.log(self.T_a_ext_in / self.T0) ) ) self.X_a_ext_out = ( c_a * rho_a * self.dV_ext * ( (self.T_a_ext_out - self.T0) - self.T0 * math.log(self.T_a_ext_out / self.T0) ) ) self.X_r_int = -self.Q_r_int * (1 - self.T0 / self.T_r_int) self.X_r_ext = self.Q_r_ext * (1 - self.T0 / self.T_r_ext) # Internal unit of ASHP self.X_in_int = self.E_fan_int + self.X_r_int self.X_out_int = self.X_a_int_out - self.X_a_int_in self.X_c_int = self.X_in_int - self.X_out_int # Closed refrigerant loop system of ASHP self.X_in_r = self.E_cmp self.X_out_r = self.X_r_int + self.X_r_ext self.X_c_r = self.X_in_r - self.X_out_r # External unit of ASHP self.X_in_ext = self.E_fan_ext + self.X_r_ext self.X_out_ext = self.X_a_ext_out - self.X_a_ext_in self.X_c_ext = self.X_in_ext - self.X_out_ext # Total exergy of ASHP self.X_in = self.E_fan_int + self.E_cmp + self.E_fan_ext self.X_out = self.X_a_int_out - self.X_a_int_in self.X_c = self.X_in - self.X_out self.X_eff = self.X_out / self.X_in ## Exergy Balance ======================================== self.exergy_balance = {} # Internal Unit self.exergy_balance["internal unit"] = { "in": { "$E_{f,int}$": self.E_fan_int, "$X_{r,int}$": self.X_r_int, }, "con": { "$X_{c,int}$": self.X_c_int, }, "out": { "$X_{a,int,out}$": self.X_a_int_out, "$X_{a,int,in}$": self.X_a_int_in, }, } # Refrigerant self.exergy_balance["refrigerant loop"] = { "in": { "$E_{cmp}$": self.E_cmp, }, "con": { "$X_{c,r}$": self.X_c_r, }, "out": { "$X_{r,int}$": self.X_r_int, "$X_{r,ext}$": self.X_r_ext, }, } # External Unit self.exergy_balance["external unit"] = { "in": { "$E_{f,ext}$": self.E_fan_ext, "$X_{r,ext}$": self.X_r_ext, }, "con": { "$X_{c,ext}$": self.X_c_ext, }, "out": { "$X_{a,ext,out}$": self.X_a_ext_out, "$X_{a,ext,in}$": self.X_a_ext_in, }, }
[docs] @dataclass class AirSourceHeatPump_heating: """Air source heat pump model for heating mode. Mirror of ``AirSourceHeatPump_cooling`` configured for space heating. The condenser rejects heat to the indoor side while the evaporator absorbs from outdoor air. """ def __post_init__(self): # fan self.fan_int = Fan().fan1 self.fan_ext = Fan().fan2 # COP self.Q_r_max = 20000 # maximum heating capacity [W] # temperature self.T0 = 0 # environmental temperature [°C] self.T_a_room = 20 # room air temperature [°C] self.T_r_int = ( self.T_a_room + 15 ) # internal unit refrigerant temperature [°C] self.T_a_int_out = ( self.T_a_room + 10 ) # internal unit air outlet temperature [°C] self.T_a_ext_out = ( self.T0 - 10 ) # external unit air outlet temperature [°C] self.T_r_ext = ( self.T0 - 15 ) # external unit refrigerant temperature [°C] # load self.Q_r_int = 6000 # [W]
[docs] def system_update(self): # Celcius to Kelvin self.T0 = cu.C2K(self.T0) self.T_a_room = cu.C2K(self.T_a_room) self.T_a_int_out = cu.C2K(self.T_a_int_out) self.T_a_ext_out = cu.C2K(self.T_a_ext_out) self.T_r_int = cu.C2K(self.T_r_int) self.T_r_ext = cu.C2K(self.T_r_ext) # temperature self.T_a_int_in = self.T_a_room self.T_a_ext_in = self.T0 # external unit air inlet temperature [K] # others self.COP = calc_ASHP_heating_COP( T0=self.T0, Q_r_int=self.Q_r_int, Q_r_max=self.Q_r_max ) # COP [-] self.E_cmp = self.Q_r_int / self.COP # compressor power input [W] self.Q_r_ext = ( self.Q_r_int - self.E_cmp ) # heat transfer from external unit to refrigerant [W] # internal, external unit self.dV_int = self.Q_r_int / ( c_a * rho_a * abs(self.T_a_int_out - self.T_a_int_in) ) # volumetric flow rate of internal unit [m3/s] self.dV_ext = self.Q_r_ext / ( c_a * rho_a * abs(self.T_a_ext_out - self.T_a_ext_in) ) # volumetric flow rate of external unit [m3/s] # fan power self.E_fan_int = Fan().get_power( self.fan_int, self.dV_int ) # power input of internal unit fan [W] self.E_fan_ext = Fan().get_power( self.fan_ext, self.dV_ext ) # power input of external unit fan [W] # System COP self.COP_sys = self.Q_r_int / ( self.E_fan_int + self.E_fan_ext + self.E_cmp ) # exergy result self.X_a_int_in = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_in - self.T0) - self.T0 * math.log(self.T_a_int_in / self.T0) ) ) self.X_a_int_out = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_out - self.T0) - self.T0 * math.log(self.T_a_int_out / self.T0) ) ) self.X_a_ext_in = ( c_a * rho_a * self.dV_ext * ( (self.T_a_ext_in - self.T0) - self.T0 * math.log(self.T_a_ext_in / self.T0) ) ) self.X_a_ext_out = ( c_a * rho_a * self.dV_ext * ( (self.T_a_ext_out - self.T0) - self.T0 * math.log(self.T_a_ext_out / self.T0) ) ) self.X_r_int = self.Q_r_int * (1 - self.T0 / self.T_r_int) self.X_r_ext = -self.Q_r_ext * (1 - self.T0 / self.T_r_ext) # Internal unit of ASHP self.X_in_int = self.E_fan_int + self.X_r_int self.X_out_int = self.X_a_int_out - self.X_a_int_in self.X_c_int = ( self.E_fan_int + self.X_r_int - (self.X_a_int_out - self.X_a_int_in) ) # Refrigerant loop of ASHP self.X_in_r = self.E_cmp self.X_out_r = self.X_r_int + self.X_r_ext self.X_c_r = self.E_cmp - (self.X_r_int + self.X_r_ext) # External unit of ASHP self.X_in_ext = self.E_fan_ext + self.X_r_ext self.X_out_ext = self.X_a_ext_out - self.X_a_ext_in self.X_c_ext = ( self.E_fan_ext + self.X_r_ext - (self.X_a_ext_out - self.X_a_ext_in) ) # Total exergy of ASHP self.X_in = self.E_fan_int + self.E_cmp + self.E_fan_ext self.X_out = self.X_a_int_out - self.X_a_int_in self.X_c = self.X_in - self.X_out self.X_eff = self.X_out / self.X_in ## Exergy Balance ======================================== self.exergy_balance = {} # Internal Unit of ASHP self.exergy_balance["internal unit"] = { "in": { "$E_{f,int}$": self.E_fan_int, "$X_{r,int}$": self.X_r_int, }, "con": { "$X_{c,int}$": self.X_c_int, }, "out": { "$X_{a,int,out}$": self.X_a_int_out, "$X_{a,int,in}$": self.X_a_int_in, }, } # Refrigerant loop of ASHP self.exergy_balance["refrigerant loop"] = { "in": { "$E_{cmp}$": self.E_cmp, }, "con": { "$X_{c,r}$": self.X_c_r, }, "out": { "$X_{r,int}$": self.X_r_int, "$X_{r,ext}$": self.X_r_ext, }, } # External Unit of ASHP self.exergy_balance["external unit"] = { "in": { "$E_{f,ext}$": self.E_fan_ext, "$X_{r,ext}$": self.X_r_ext, }, "con": { "$X_{c,ext}$": self.X_c_ext, }, "out": { "$X_{a,ext,out}$": self.X_a_ext_out, "$X_{a,ext,in}$": self.X_a_ext_in, }, }
# class - GroundSourceHeatPump
[docs] @dataclass class GroundSourceHeatPump_cooling: """Ground source heat pump model for cooling mode. Uses borehole heat exchangers with finite-line-source g-functions for soil thermal response. Call ``system_update()`` each time step to advance the ground temperature history. """ def __post_init__(self): # Time self.time = 10 # [h] # Borehole parameters self.D_b = 0 # Borehole depth [m] self.H_b = 200 # Borehole height [m] self.r_b = 0.08 # Borehole radius [m] self.R_b = 0.108 # Effective borehole thermal resistance [mK/W] # Fluid parameters self.dV_f = 24 # Volumetric flow rate of fluid [L/min] # Ground parameters self.k_g = 2.0 # Ground thermal conductivity [W/mK] self.c_g = 800 # Ground specific heat capacity [J/(kgK)] self.rho_g = 2000 # Ground density [kg/m³] # Pump power of ground heat exchanger self.E_pmp = 200 # Pump power input [W] # Fan self.fan_int = Fan().fan1 # Temperature self.dT_r_exch = ( 5 # 예시: 열교환기의 온도 - 열교환후 지중순환수 온도 [K] ) self.T0 = 32 # environmental temperature [°C] self.T_g = 15 # initial ground temperature [°C] self.T_a_room = 20 # room air temperature [°C] self.T_r_exch = 25 # heat exchanger side refrigerant temperature [°C] self.T_r_int = ( self.T_a_room - 10 ) # internal unit refrigerant temperature [°C] self.T_a_int_out = ( self.T_a_room - 5 ) # internal unit air outlet temperature [°C] # Load self.Q_r_int = 6000 # W
[docs] def system_update(self): # Unit conversion self.dV_f = self.dV_f * cu.s2m * cu.L2m3 # L/min to m³/s self.time = self.time * cu.h2s # Convert hours to seconds self.T0 = cu.C2K(self.T0) self.T_a_room = cu.C2K(self.T_a_room) self.T_a_int_out = cu.C2K(self.T_a_int_out) self.T_r_int = cu.C2K(self.T_r_int) self.T_g = cu.C2K(self.T_g) # Others self.alpha = self.k_g / ( self.c_g * self.rho_g ) # thermal diffusivity of ground [m²/s] self.Lx = 2 * self.dV_f / (math.pi * self.alpha) self.x0 = self.H_b / self.Lx # dimensionless borehole depth self.k_sb = self.k_g / k_w # ratio of ground thermal conductivity # 반복 수치해법 적용 """ 반복 수치해법을 사용하는 이유: 1. 냉매 온도(T_r_exch)와 유체 입구 온도(T_f_in)가 서로 연동되어 직접 계산이 불가능함. 2. 보어홀 열저항, 유량, 토양물성 등 시스템 파라미터가 COP, 온도, 효율에 반영되도록 하기 위함. 3. 두 온도가 수렴할 때까지 반복 계산하여 물리적으로 일관된 해를 얻기 위함. """ max_iter = 20 tol = 1e-3 self.T_f = self.T_g # 초기값 self.T_f_in = ( self.T_f + self.dT_r_exch ) # 초기값, 열교환기에서의 순환수 유입 온도 for _ in range(max_iter): self.T_r_exch = self.T_f_in + self.dT_r_exch # 5 K 높게 설정 self.COP = calc_GSHP_COP( Tg=self.T_g, T_cond=self.T_r_exch, T_evap=self.T_r_int, theta_hat=0.3, ) self.E_cmp = self.Q_r_int / self.COP # compressor power input [W] self.Q_r_exch = self.Q_r_int + self.E_cmp self.Q_bh = (self.Q_r_exch + self.E_pmp) / self.H_b T_f_in_old = self.T_f_in self.g_i = G_FLS( t=self.time, ks=self.k_g, as_=self.alpha, rb=self.r_b, H=self.H_b, ) # g-function [mK/W] self.T_b = ( self.T_g + self.Q_bh * self.g_i ) # borehole wall temperature [K] self.T_f = self.T_b + self.Q_bh * self.R_b self.T_f_in = self.T_f + self.Q_bh * self.H_b / ( 2 * c_w * rho_w * self.dV_f ) # fluid inlet temperature [K] self.T_f_out = self.T_f - self.Q_bh * self.H_b / ( 2 * c_w * rho_w * self.dV_f ) # fluid outlet temperature [K] if abs(self.T_f_in - T_f_in_old) < tol: break # Temperature self.T_a_int_in = ( self.T_a_room ) # internal unit air inlet temperature [K] # Internal unit self.dV_int = self.Q_r_int / ( c_a * rho_a * (abs(self.T_a_int_out - self.T_a_int_in)) ) # volumetric flow rate of internal unit [m3/s] # Fan power self.E_fan_int = Fan().get_power( self.fan_int, self.dV_int ) # power input of internal unit fan [W] # Exergy result self.X_a_int_in = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_in - self.T0) - self.T0 * math.log(self.T_a_int_in / self.T0) ) ) self.X_a_int_out = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_out - self.T0) - self.T0 * math.log(self.T_a_int_out / self.T0) ) ) self.X_r_int = -self.Q_r_int * (1 - self.T0 / self.T_r_int) self.X_r_exch = -self.Q_r_exch * (1 - self.T0 / self.T_r_exch) self.X_f_in = ( c_w * rho_w * self.dV_f * ( (self.T_f_in - self.T0) - self.T0 * math.log(self.T_f_in / self.T0) ) ) self.X_f_out = ( c_w * rho_w * self.dV_f * ( (self.T_f_out - self.T0) - self.T0 * math.log(self.T_f_out / self.T0) ) ) self.X_g = (1 - self.T0 / self.T_g) * (-self.Q_bh * self.H_b) self.X_b = (1 - self.T0 / self.T_b) * (-self.Q_bh * self.H_b) # Ground self.X_in_g = self.X_g self.X_out_g = self.X_b self.X_c_g = self.X_in_g - self.X_out_g # Ground heat exchanger self.X_in_GHE = self.E_pmp + self.X_out_g + self.X_f_in self.X_out_GHE = self.X_f_out self.X_c_GHE = self.X_in_GHE - self.X_out_GHE # Heat exchanger self.X_in_exch = self.X_out_GHE self.X_out_exch = self.X_r_exch + self.X_f_in self.X_c_exch = self.X_in_exch - self.X_out_exch # Closed refrigerant loop system self.X_in_r = self.E_cmp + self.X_r_exch self.X_out_r = self.X_r_int self.X_c_r = self.X_in_r - self.X_out_r # Internal unit self.X_in_int = self.E_fan_int + self.X_r_int + self.X_a_int_in self.X_out_int = self.X_a_int_out self.X_c_int = self.X_in_int - self.X_out_int # Exergy efficiency self.X_eff = (self.X_a_int_out - self.X_a_int_in) / ( self.E_fan_int + self.E_cmp + self.E_pmp ) ## Exergy Balance ======================================== self.exergy_balance = {} # Internal Unit self.exergy_balance["internal unit"] = { "in": { "$X_{f,int}$": self.E_fan_int, "$X_{r,int}$": self.X_r_int, "$X_{a,int,in}$": self.X_a_int_in, }, "con": { "$X_{c,int}$": self.X_c_int, }, "out": { "$X_{a,int,out}$": self.X_a_int_out, }, } # Refrigerant loop self.exergy_balance["refrigerant loop"] = { "in": { "$X_{cmp}$": self.E_cmp, "$X_{r,exch}$": self.X_r_exch, }, "con": { "$X_{c,r}$": self.X_c_r, }, "out": { "$X_{r,int}$": self.X_r_int, }, } # Heat Exchanger self.exergy_balance["heat exchanger"] = { "in": { "$X_{f,out}$": self.X_f_out, }, "con": { "$X_{c,exch}$": self.X_c_exch, }, "out": { "$X_{r,exch}$": self.X_r_exch, "$X_{f,in}$": self.X_f_in, }, } # Ground Heat Exchanger self.exergy_balance["ground heat exchanger"] = { "in": { "$E_{pmp}$": self.E_pmp, "$X_{b}$": self.X_b, "$X_{f,in}$": self.X_f_in, }, "con": { "$X_{c,GHE}$": self.X_c_GHE, }, "out": { "$X_{f,out}$": self.X_f_out, }, } # Ground self.exergy_balance["ground"] = { "in": { "$X_{g}$": self.X_g, }, "con": { "$X_{c,g}$": self.X_c_g, }, "out": { "$X_{b}$": self.X_b, }, }
[docs] @dataclass class GroundSourceHeatPump_heating: """Ground source heat pump model for heating mode. Mirror of ``GroundSourceHeatPump_cooling`` configured for space heating. The evaporator absorbs heat from the ground loop while the condenser supplies heat indoors. """ def __post_init__(self): # Time self.time = 10 # [h] # Borehole parameters self.D_b = 0 # Borehole depth [m] self.H_b = 200 # Borehole height [m] self.r_b = 0.08 # Borehole radius [m] self.R_b = 0.108 # Effective borehole thermal resistance [mK/W] # Fluid parameters self.dV_f = 24 # Volumetric flow rate of fluid [L/min] # Ground parameters self.k_g = 2.0 # Ground thermal conductivity [W/mK] self.c_g = 800 # Ground specific heat capacity [J/(kgK)] self.rho_g = 2000 # Ground density [kg/m³] # Pump power of ground heat exchanger self.E_pmp = 200 # Pump power input [W] # Fan self.fan_int = Fan().fan1 # Temperature self.dT_r_exch = ( -5 ) # 예시: 열교환기 측 냉매 온도 - 열교환후 지중순환수 온도 [K] self.T0 = 0 # environmental temperature [°C] self.T_g = 15 # initial ground temperature [°C] self.T_a_room = 20 # room air temperature [°C] self.T_r_exch = 5 # heat exchanger side refrigerant temperature [°C] self.T_r_int = ( self.T_a_room + 15 ) # internal unit refrigerant temperature [°C] self.T_a_int_out = ( self.T_a_room + 10 ) # internal unit air outlet temperature [°C] # Load self.Q_r_int = 6000 # W
[docs] def system_update(self): # Unit conversion self.time = self.time * cu.h2s # Convert hours to seconds self.dV_f = self.dV_f * cu.s2m * cu.L2m3 # L/min to m³/s # Celcius to Kelvin self.T0 = cu.C2K(self.T0) self.T_a_room = cu.C2K(self.T_a_room) self.T_a_int_out = cu.C2K(self.T_a_int_out) self.T_r_int = cu.C2K(self.T_r_int) self.T_g = cu.C2K(self.T_g) # Others self.alpha = self.k_g / ( self.c_g * self.rho_g ) # thermal diffusivity of ground [m²/s] # 반복 수치해법 적용 """ 반복 수치해법을 사용하는 이유: 1. 냉매 온도(T_r_exch)와 유체 입구 온도(T_f_in)가 서로 연동되어 직접 계산이 불가능함. 2. 보어홀 열저항, 유량, 토양물성 등 시스템 파라미터가 COP, 온도, 효율에 반영되도록 하기 위함. 3. 두 온도가 수렴할 때까지 반복 계산하여 물리적으로 일관된 해를 얻기 위함. """ max_iter = 20 tol = 1e-3 self.T_f = self.T_g # 초기값 self.T_f_in = ( self.T_f + self.dT_r_exch ) # 초기값, 열교환기에서의 순환수 유입 온도 for _ in range(max_iter): self.T_r_exch = self.T_f_in + self.dT_r_exch # 5 K 높게 설정 self.COP = calc_GSHP_COP( Tg=self.T_g, T_cond=self.T_r_int, T_evap=self.T_r_exch, theta_hat=0.3, ) # Others self.E_cmp = self.Q_r_int / self.COP # compressor power input [W] self.Q_r_exch = ( self.Q_r_int - self.E_cmp ) # changed from Q_r_ext to Q_r_exch # Borehole self.Q_bh = ( (self.Q_r_exch - self.E_pmp) / self.H_b ) # heat flow rate from borehole to ground per unit length [W/m] self.g_i = G_FLS( t=self.time, ks=self.k_g, as_=self.alpha, rb=self.r_b, H=self.H_b, ) # g-function [mK/W] # fluid temperature & borehole wall temperature [K] T_f_in_old = self.T_f_in # 이전 유체 입구 온도 저장 self.T_b = ( self.T_g - self.Q_bh * self.g_i ) # borehole wall temperature [K] self.T_f = ( self.T_b - self.Q_bh * self.R_b ) # fluid temperature in borehole [K] self.T_f_in = self.T_f - self.Q_bh * self.H_b / ( 2 * c_w * rho_w * self.dV_f ) # fluid inlet temperature [K] self.T_f_out = self.T_f + self.Q_bh * self.H_b / ( 2 * c_w * rho_w * self.dV_f ) # fluid outlet temperature [K] if abs(self.T_f_in - T_f_in_old) < tol: break # Temperature self.T_a_int_in = ( self.T_a_room ) # internal unit air inlet temperature [K] # Internal unit self.dV_int = self.Q_r_int / ( c_a * rho_a * (abs(self.T_a_int_out - self.T_a_int_in)) ) # volumetric flow rate of internal unit [m3/s] # Fan power self.E_fan_int = Fan().get_power( self.fan_int, self.dV_int ) # power input of internal unit fan [W] # Exergy result self.X_a_int_in = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_in - self.T0) - self.T0 * math.log(self.T_a_int_in / self.T0) ) ) self.X_a_int_out = ( c_a * rho_a * self.dV_int * ( (self.T_a_int_out - self.T0) - self.T0 * math.log(self.T_a_int_out / self.T0) ) ) self.X_r_int = self.Q_r_int * (1 - self.T0 / self.T_r_int) self.X_r_exch = self.Q_r_exch * (1 - self.T0 / self.T_r_exch) self.X_f_in = ( c_w * rho_w * self.dV_f * ( (self.T_f_in - self.T0) - self.T0 * math.log(self.T_f_in / self.T0) ) ) self.X_f_out = ( c_w * rho_w * self.dV_f * ( (self.T_f_out - self.T0) - self.T0 * math.log(self.T_f_out / self.T0) ) ) self.X_g = (1 - self.T0 / self.T_g) * (self.Q_bh * self.H_b) self.X_b = (1 - self.T0 / self.T_b) * (self.Q_bh * self.H_b) # Internal unit self.X_in_int = self.E_fan_int + self.X_r_int + self.X_a_int_in self.X_out_int = self.X_a_int_out self.X_c_int = self.X_in_int - self.X_out_int # Closed refrigerant loop system self.X_in_r = self.E_cmp + self.X_r_exch self.X_out_r = self.X_r_int self.X_c_r = self.X_in_r - self.X_out_r # Heat exchanger self.X_in_exch = self.X_f_out self.X_out_exch = self.X_r_exch + self.X_f_in self.X_c_exch = self.X_in_exch - self.X_out_exch # Ground heat exchanger self.X_in_GHE = self.E_pmp + self.X_b + self.X_f_in self.X_out_GHE = self.X_f_out self.X_c_GHE = self.X_in_GHE - self.X_out_GHE # Ground self.X_in_g = self.X_g self.X_out_g = self.X_b self.X_c_g = self.X_in_g - self.X_out_g # Exergy efficiency self.X_eff = (self.X_a_int_out - self.X_a_int_in) / ( self.E_fan_int + self.E_cmp + self.E_pmp ) ## Exergy Balance ======================================== self.exergy_balance = {} # Internal Unit self.exergy_balance["internal unit"] = { "in": { "$X_{f,int}$": self.E_fan_int, "$X_{r,int}$": self.X_r_int, "$X_{a,int,in}$": self.X_a_int_in, }, "con": { "$X_{c,int}$": self.X_c_int, }, "out": { "$X_{a,int,out}$": self.X_a_int_out, }, } # Refrigerant loop self.exergy_balance["refrigerant loop"] = { "in": { "$X_{cmp}$": self.E_cmp, "$X_{r,exch}$": self.X_r_exch, }, "con": { "$X_{c,r}$": self.X_c_r, }, "out": { "$X_{r,int}$": self.X_r_int, }, } # Heat Exchanger self.exergy_balance["heat exchanger"] = { "in": { "$X_{f,out}$": self.X_f_out, }, "con": { "$X_{c,exch}$": self.X_c_exch, }, "out": { "$X_{r,exch}$": self.X_r_exch, "$X_{f,in}$": self.X_f_in, }, } # Ground Heat Exchanger self.exergy_balance["ground heat exchanger"] = { "in": { "$E_{pmp}$": self.E_pmp, "$X_{b}$": self.X_b, "$X_{f,in}$": self.X_f_in, }, "con": { "$X_{c,GHE}$": self.X_c_GHE, }, "out": { "$X_{f,out}$": self.X_f_out, }, } # Ground self.exergy_balance["ground"] = { "in": { "$X_{g}$": self.X_g, }, "con": { "$X_{c,g}$": self.X_c_g, }, "out": { "$X_{b}$": self.X_b, }, }
# class - Electric heater