From 9424307a8433d582dc0b42554989aeb53d7ae3be Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 08:27:49 +0100 Subject: [PATCH 001/105] regiter coolrop --- .gitmodules | 3 +++ externals/CoolProp | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 externals/CoolProp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..0900bbae3 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "externals/CoolProp"] + path = externals/CoolProp + url = ../CoolProp.git diff --git a/externals/CoolProp b/externals/CoolProp new file mode 160000 index 000000000..cc87fa1da --- /dev/null +++ b/externals/CoolProp @@ -0,0 +1 @@ +Subproject commit cc87fa1dabd85cd571c949360634bde63ce04ac3 From 9c46ff5e46ee73177d43cd20f037288d5467dbec Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 10:32:23 +0100 Subject: [PATCH 002/105] Cherry picked EEMAP/dev to avoid rewritten history --- intermediateFoodTests/Ex1.py | 63 + intermediateFoodTests/Ex1tespy070.csv | 3 + intermediateFoodTests/Ex4.py | 93 ++ intermediateFoodTests/Ex4tespy070.csv | 9 + intermediateFoodTests/Ex8.py | 155 ++ intermediateFoodTests/Ex8tespy070_1.csv | 14 + intermediateFoodTests/Ex8tespy070_2.csv | 14 + intermediateFoodTests/Ex9.py | 143 ++ intermediateFoodTests/Ex9tespy070.csv | 15 + .../energy-supply_energy-merge3.py | 67 + .../energy-supply_energy-split3.py | 67 + .../energy-supply_heat-pump3.py | 64 + .../energy-supply_loss-model3.py | 67 + .../initialFoodTests/food-properties.py | 228 +++ .../newComponentsTests/SpeciesFlowSplit.py | 69 + .../SpeciesFlowSplitWithDeltaT.py | 86 ++ .../SpeciesFlowSplitWithDeltaTAndPr.py | 84 ++ .../SpeciesFlowSplitWithPr.py | 83 ++ .../newComponentsTests/heatex+merge.py | 88 ++ .../newComponentsTests/heatex+merge_mrk.py | 112 ++ .../newComponentsTests/heatex_alone.py | 52 + .../newComponentsTests/heatex_alone_deltaP.py | 61 + .../heatex_alone_lossFactor.py | 61 + .../newComponentsTests/merge_mrk.py | 50 + .../simple_heatex_for_jorrit.py | 62 + pyproject.toml | 135 +- pyproject_.toml | 6 + src/tespy/components/__init__.py | 3 + src/tespy/components/component.py | 40 + src/tespy/components/newcomponents.py | 1247 +++++++++++++++++ src/tespy/components/nodes/base.py | 4 + src/tespy/networks/network.py | 11 +- src/tespy/tools/data_containers.py | 16 + 33 files changed, 3160 insertions(+), 112 deletions(-) create mode 100644 intermediateFoodTests/Ex1.py create mode 100644 intermediateFoodTests/Ex1tespy070.csv create mode 100644 intermediateFoodTests/Ex4.py create mode 100644 intermediateFoodTests/Ex4tespy070.csv create mode 100644 intermediateFoodTests/Ex8.py create mode 100644 intermediateFoodTests/Ex8tespy070_1.csv create mode 100644 intermediateFoodTests/Ex8tespy070_2.csv create mode 100644 intermediateFoodTests/Ex9.py create mode 100644 intermediateFoodTests/Ex9tespy070.csv create mode 100644 intermediateFoodTests/energy-supply_energy-merge3.py create mode 100644 intermediateFoodTests/energy-supply_energy-split3.py create mode 100644 intermediateFoodTests/energy-supply_heat-pump3.py create mode 100644 intermediateFoodTests/energy-supply_loss-model3.py create mode 100644 intermediateFoodTests/initialFoodTests/food-properties.py create mode 100644 intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py create mode 100644 intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py create mode 100644 intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py create mode 100644 intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py create mode 100644 intermediateFoodTests/newComponentsTests/heatex+merge.py create mode 100644 intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py create mode 100644 intermediateFoodTests/newComponentsTests/heatex_alone.py create mode 100644 intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py create mode 100644 intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py create mode 100644 intermediateFoodTests/newComponentsTests/merge_mrk.py create mode 100644 intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py create mode 100644 pyproject_.toml create mode 100644 src/tespy/components/newcomponents.py diff --git a/intermediateFoodTests/Ex1.py b/intermediateFoodTests/Ex1.py new file mode 100644 index 000000000..cb0fa137d --- /dev/null +++ b/intermediateFoodTests/Ex1.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Dec 22 12:00:18 2022 + +@author: mrk + +This model includes +- Boiler + + +""" + +from tespy.components import Sink, Source, HeatExchangerSimple +from tespy.connections import Connection +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + +import logging +#logging.basicConfig(level=logging.DEBUG) + + +#network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + + +# Objects +source = Source('source') +boiler = HeatExchangerSimple('boiler') +sink = Sink('sink') + +# Connections +c1 = Connection(source, 'out1', boiler, 'in1') +c2 = Connection(boiler, 'out1', sink, 'in1') + +network.add_conns(c1,c2) + +# set global guess values +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar + +# set conditions around boiler +c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, h=h0, p=p0) +c2.set_attr(h=h0,p=p0) + +# solve and print results +network.solve('design') +# c1.set_attr(T=40, h=None) +# c2.set_attr(T=60, h=None) +# network.solve('design') + +network.print_results() + + +print(network.results['Connection']) + +network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") \ No newline at end of file diff --git a/intermediateFoodTests/Ex1tespy070.csv b/intermediateFoodTests/Ex1tespy070.csv new file mode 100644 index 000000000..2c1c3b713 --- /dev/null +++ b/intermediateFoodTests/Ex1tespy070.csv @@ -0,0 +1,3 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_sink:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 diff --git a/intermediateFoodTests/Ex4.py b/intermediateFoodTests/Ex4.py new file mode 100644 index 000000000..f541e25d0 --- /dev/null +++ b/intermediateFoodTests/Ex4.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Dec 22 12:00:18 2022 + +@author: mrk + +This model includes +- Boiler +- Press +- Decanter (no steam is mixed into product in the pressWater) +- Centrifuge + +""" +from tespy.components import Sink, Source, HeatExchangerSimple +from tespy.connections import Connection +from tespy.networks import Network + + +from tespy.components import Separator,Merge,CycleCloser,Valve +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + +import logging +#logging.basicConfig(level=logging.DEBUG) + +fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + +# Objects +source = Source('source') +boiler = HeatExchangerSimple('boiler') +press = SeparatorWithSpeciesSplits('press', num_out=2) +#pressWater = Sink('pressWater') +presscake = Sink('presscake') +decanter = SeparatorWithSpeciesSplits('decanter', num_out=2) +grax = Sink('grax') +oil = Sink('oil') +centrifuge = SeparatorWithSpeciesSplits('centrifuge',num_out=2) +stickWater = Sink('stickWater') + +# Connections +c1 = Connection(source, 'out1', boiler, 'in1') +c2 = Connection(boiler, 'out1', press, 'in1') +c3 = Connection(press, 'out1', presscake, 'in1') +c4 = Connection(press, 'out2', decanter, 'in1') +c5 = Connection(decanter, 'out1', grax, 'in1') +c6 = Connection(decanter, 'out2', centrifuge, 'in1') +c7 = Connection(centrifuge, 'out1', stickWater, 'in1') +c8 = Connection(centrifuge, 'out2', oil, 'in1') + +network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8) + +# set global guess values +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar + +for c in network.conns['object']: +# n_fl = len(network.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/3, 'PHE': 1/3, 'S800': 1/3}) + +# set conditions around boiler +c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=100, h=h0, p=p0) +c2.set_attr(h=h0,p=p0) + + +# set conditions around press +press.set_attr(SFS={ + 'val': 0.7, 'is_set': True, + 'split_fluid' : 'S800', 'split_outlet' : "out1"}) +c3.set_attr(fluid={'Water': 0.50, 'PHE': 0.05, 'S800': 0.45}) + + +# set conditions around decanter +decanter.set_attr(SFS={ + 'val': 0.3, 'is_set': True, + 'split_fluid' : 'S800', 'split_outlet' : "out1"}) +c5.set_attr(fluid={'Water': 0.60, 'PHE': 0.05, 'S800': 0.35}) + +# set conditions around centrifuge +centrifuge.set_attr(SFS={ + 'val': 0.8, 'is_set': True, + 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) +c8.set_attr(fluid={'Water': 0,'PHE': 0.99, 'S800': 0.01}) + +# solve and print results +network.solve('design') + +# network.print_results() +print(network.results['Connection'].loc[:, [c for c in network.results["Connection"] if "unit" not in c]]) + +print(0.65 * c1.m.val_SI * c1.fluid.val["S800"] / c3.fluid.val["S800"] == network.results['Connection'].loc["press:out1_presscake:in1", "m"]) + +network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") \ No newline at end of file diff --git a/intermediateFoodTests/Ex4tespy070.csv b/intermediateFoodTests/Ex4tespy070.csv new file mode 100644 index 000000000..2e610c0f8 --- /dev/null +++ b/intermediateFoodTests/Ex4tespy070.csv @@ -0,0 +1,9 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_presscake:in1,7.777777777777778,2.0,78.66612649956119,46.945715802337304,0.008221058787004482,0.001056993272614862,256.3696338669351,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341097,46.94571580233952,0.09570564307860968,0.0010377720333825146,331.87502899705527,0.0,0.0,0.158433734939759,0.016265060240963854,0.8253012048192772 +decanter:out1_grax:in1,1.2857142857142856,2.0,85.51182358236238,46.94571580233941,0.0013476962897216462,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.02952353029265,46.94571580233952,0.09435794678888804,0.0010376244803106905,332.6266240381677,0.0,0.0,0.15996683539884796,0.011546517716879038,0.8284866468842731 +centrifuge:out1_stickWater:in1,79.18149751483085,2.0,109.46751182641472,46.945715802339464,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.03674299136386185,0.011776108371890536,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.9273942545358,46.945715802339464,0.013894775614785894,0.0011820300549596216,169.02088145066307,0.0,0.0,0.99,0.01,0.0 diff --git a/intermediateFoodTests/Ex8.py b/intermediateFoodTests/Ex8.py new file mode 100644 index 000000000..a0fb7ad80 --- /dev/null +++ b/intermediateFoodTests/Ex8.py @@ -0,0 +1,155 @@ + +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter + +import logging +#logging.basicConfig(level=logging.DEBUG) + +fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + +# Objects +source = Source('source') +boiler = HeatExchangerSimple('boiler') +press = SeparatorWithSpeciesSplits('press', num_out=2) +#presswater = Sink('presswater') +#presscake = Sink('presscake') +decanter = SeparatorWithSpeciesSplits('decanter', num_out=2) +#grax = Sink('grax') +oil = Sink('oil') +centrifuge = SeparatorWithSpeciesSplits('centrifuge',num_out=2) +thickener = SeparatorWithSpeciesSplits('thickener',num_out=2) +vapourextract1 = Sink('vapourextract1') +#solubles = Sink('solubles') +liquidmerge = MergeWithPressureLoss('liquidmerge', num_in = 3) +wetproduct = Sink('wetproduct') +drier = SeparatorWithSpeciesSplits('drier',num_out=2) +meal = Sink('meal') +vapourextract2 = Sink('vapourextract2') + +# Connections +c1 = Connection(source, 'out1', boiler, 'in1') +c2 = Connection(boiler, 'out1', press, 'in1') +c3 = Connection(press, 'out1', liquidmerge, 'in1') +c4 = Connection(press, 'out2', decanter, 'in1') +c5 = Connection(decanter, 'out1', liquidmerge, 'in2') +c6 = Connection(decanter, 'out2', centrifuge, 'in1') +c7 = Connection(centrifuge, 'out1', thickener, 'in1') +c8 = Connection(centrifuge, 'out2', oil, 'in1') +c9 = Connection(thickener, 'out1', liquidmerge, 'in3') +c10 = Connection(thickener, 'out2', vapourextract1, 'in1') +c11 = Connection(liquidmerge, 'out1', drier, 'in1') +c12 = Connection(drier, 'out1', meal, 'in1') +c13 = Connection(drier, 'out2', vapourextract2, 'in1') + +network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13) + +# set global guess values +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar + +for c in network.conns['object']: + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/3, 'PHE': 1/3, 'S800': 1/3}) + +# set conditions around boiler +c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, h=h0, p=p0) +c2.set_attr(h=h0,p=p0) + +# set conditions around press +press.set_attr(SFS={ + 'val': 0.7, 'is_set': True, + 'split_fluid' : 'S800', 'split_outlet' : "out1"}) +c3.set_attr(fluid={'Water': 0.50, 'PHE': 0.05, 'S800': 0.45}) + +# set conditions around decanter +decanter.set_attr(SFS={ + 'val': 0.3, 'is_set': True, + 'split_fluid' : 'S800', 'split_outlet' : "out1"}) +c5.set_attr(fluid={'Water': 0.60, 'PHE': 0.05, 'S800': 0.35}) + +# set conditions around centrifuge +centrifuge.set_attr(SFS={ + 'val': 0.8, 'is_set': True, + 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) +c8.set_attr(fluid={'Water': 0,'PHE': 0.99, 'S800': 0.01}) + +# set conditions around thickener +c10.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) +c9.set_attr(fluid={'PHE': 0.25}) + +# set conditions around liquidMerge +c11.set_attr(p=p0) + +# set conditions around drier +c12.set_attr(fluid={'Water': 0.1}) +c13.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) + +oilmassflow = c8.m.val +print(f"oil mass flow is {oilmassflow}") +network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070_1.csv") + +# import sys +# sys.exit() + +# %% oil cleansing + +fluid_list2 = ['INCOMP::Water','INCOMP::S800'] +network2 = Network(fluids=fluid_list2, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + +# Objects +sourceFat = Source('Fat') +sourceCitricAcid = Source('CitricAcid') +centimerge = MergeWithPressureLoss('centimerge', num_in=2) +T2 = SplitWithFlowSplitter('T2', num_out=2) +Oil1 = Sink('Oil1') +stripper = SplitWithFlowSplitter('stripper', num_out=2) +Oil2 = Sink('Oil2') +scrubOil = Sink('scrubOil') + +# Connections +c1 = Connection(sourceFat, 'out1', centimerge, 'in1') +c2 = Connection(sourceCitricAcid, 'out1', centimerge, 'in2') +c3 = Connection(centimerge, 'out1', T2, 'in1') +c4 = Connection(T2, 'out1', stripper, 'in1') +c5 = Connection(T2, 'out2', Oil1, 'in1') +c6 = Connection(stripper, 'out1', scrubOil, 'in1') +c7 = Connection(stripper, 'out2', Oil2, 'in1') + +network2.add_conns(c1,c2,c3,c4,c5,c6,c7) + +# set global guess values +m0 = oilmassflow # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar + +for c in network2.conns['object']: + c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::S800': 1/n_fl}) + +# set conditions around merge +c1.set_attr(fluid={'Water': 0,'S800': 1}, m=m0, h=h0, p=p0) +c2.set_attr(fluid={'Water': 1,'S800': 0}, m=0.7*m0/1000, h=h0, p=p0) +c3.set_attr(p=p0) + +T2.set_attr(FS={'val': 0.75, 'is_set': True, 'split_outlet' : "out1"}) +stripper.set_attr(FS={'val': 0.05, 'is_set': True, 'split_outlet' : "out1"}) + +# solve and print results +network2.solve('design') +network2.print_results() +print(network2.results['Connection']) + +network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070_2.csv") diff --git a/intermediateFoodTests/Ex8tespy070_1.csv b/intermediateFoodTests/Ex8tespy070_1.csv new file mode 100644 index 000000000..9d437a9d8 --- /dev/null +++ b/intermediateFoodTests/Ex8tespy070_1.csv @@ -0,0 +1,14 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 +decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 +centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 +thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 +thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 +drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 +drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex8tespy070_2.csv b/intermediateFoodTests/Ex8tespy070_2.csv new file mode 100644 index 000000000..9d437a9d8 --- /dev/null +++ b/intermediateFoodTests/Ex8tespy070_2.csv @@ -0,0 +1,14 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 +decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 +centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 +thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 +thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 +drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 +drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex9.py b/intermediateFoodTests/Ex9.py new file mode 100644 index 000000000..05b1153cc --- /dev/null +++ b/intermediateFoodTests/Ex9.py @@ -0,0 +1,143 @@ + +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter,SeparatorWithSpeciesSplitsAndDeltaT,SeparatorWithSpeciesSplitsAndDeltaTAndPr + +import logging +#logging.basicConfig(level=logging.DEBUG) + +fluid_list = ['HEOS::Water','INCOMP::PHE','INCOMP::S800'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + +# Objects +source = Source('source') +boiler = HeatExchangerSimple('boiler') +press = SeparatorWithSpeciesSplitsAndDeltaTAndPr('press', num_out=2) +#presswater = Sink('presswater') +#presscake = Sink('presscake') +decanter = SeparatorWithSpeciesSplitsAndDeltaTAndPr('decanter', num_out=2) +#grax = Sink('grax') +oil = Sink('oil') +centrifuge = SeparatorWithSpeciesSplitsAndDeltaTAndPr('centrifuge',num_out=2) +thickener = SeparatorWithSpeciesSplitsAndDeltaTAndPr('thickener',num_out=2) +vapourextract1 = Sink('vapourextract1') +#solubles = Sink('solubles') +liquidmerge = MergeWithPressureLoss('liquidmerge', num_in = 3) +wetproduct = Sink('wetproduct') +drier = SeparatorWithSpeciesSplitsAndDeltaTAndPr('drier',num_out=2) +meal = Sink('meal') +vapourextract2 = Sink('vapourextract2') + +presswaterheater = HeatExchangerSimple('presswaterheater') + +# Connections +c1 = Connection(source, 'out1', boiler, 'in1') +c2 = Connection(boiler, 'out1', press, 'in1') +c3 = Connection(press, 'out1', liquidmerge, 'in1') +#c4 = Connection(press, 'out2', decanter, 'in1') +c4a = Connection(press, 'out2', presswaterheater, 'in1') +c4b= Connection(presswaterheater, 'out1', decanter, 'in1') +c5 = Connection(decanter, 'out1', liquidmerge, 'in2') +c6 = Connection(decanter, 'out2', centrifuge, 'in1') +c7 = Connection(centrifuge, 'out1', thickener, 'in1') +c8 = Connection(centrifuge, 'out2', oil, 'in1') +c9 = Connection(thickener, 'out1', liquidmerge, 'in3') +c10 = Connection(thickener, 'out2', vapourextract1, 'in1') +c11 = Connection(liquidmerge, 'out1', drier, 'in1') +c12 = Connection(drier, 'out1', meal, 'in1') +c13 = Connection(drier, 'out2', vapourextract2, 'in1') + +network.add_conns(c1,c2,c3,c4a,c4b,c5,c6,c7,c8,c9,c10,c11,c12,c13) + +# set global guess values +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +for c in network.conns['object']: + n_fl = len(network.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/n_fl, 'S800': 1/n_fl, 'PHE': 1/n_fl}) + c.set_attr(p=p0) + +# set conditions around boiler +c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, T=5) +c2.set_attr(T=95) + +# set conditions around press +press.set_attr(SFS={ + 'val': 0.7, 'is_set': True, + 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) +c3.set_attr(fluid={'Water': 0.5, 'S800': 0.05, 'PHE': 0.45}) +c3.set_attr(T=85) +c4a.set_attr(T=85) +c4b.set_attr(T=95) +#c4b.set_attr(p0=1) + +# set conditions around decanter +decanter.set_attr(SFS={ + 'val': 0.3, 'is_set': True, + 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) +c5.set_attr(fluid={'Water': 0.60, 'S800': 0.05, 'PHE': 0.35}) +c5.set_attr(T=90) +c6.set_attr(T=90) + +# set conditions around centrifuge +centrifuge.set_attr(SFS={ + 'val': 0.8, 'is_set': True, + 'split_fluid' : 'S800', 'split_outlet' : "out2"}) +c8.set_attr(fluid={'Water': 0, 'S800': 0.99, 'PHE': 0.01}) +c7.set_attr(T=45) +c8.set_attr(T=80) + +# set conditions around thickener +c10.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) +c9.set_attr(fluid={'PHE': 0.25}) +c10.set_attr(T=105) +c9.set_attr(T=105) + +c10.set_attr(p=p0) + +# set conditions around liquidMerge +#c11.set_attr(p=p0) + +# set conditions around drier +c12.set_attr(fluid={'Water': 0.1}) +c13.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) +c12.set_attr(T=100) +c13.set_attr(T=100) + +c13.set_attr(p=None,x=1) + + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) + +oilmassflow = c8.m.val +print(f"oil mass flow is {oilmassflow}") +print(f"\n") +network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") + +# MJ to kwh +# +for o in network.comps['object']: + if isinstance(o,SeparatorWithSpeciesSplitsAndDeltaTAndPr): + print(f"heat exchange for {o.label} = {o.Q.val}") +print(f"\n") + +for o in network.comps['object']: + if isinstance(o,SeparatorWithSpeciesSplitsAndDeltaTAndPr): + print(f"Total heat for {o.label} = {o.Q.val / (3.6*1e6)}") +print(f"\n") + +print(f"Total heat for boiler is {boiler.Q.val/(3.6*1e6):.1f}") +print(f"Total heat for presswater heater is {presswaterheater.Q.val/(3.6*1e6):.1f}") + diff --git a/intermediateFoodTests/Ex9tespy070.csv b/intermediateFoodTests/Ex9tespy070.csv new file mode 100644 index 000000000..1de6f2543 --- /dev/null +++ b/intermediateFoodTests/Ex9tespy070.csv @@ -0,0 +1,15 @@ +,m,p,h,T,v,vol,s,x,Td_bp,Water,PHE,S800 +source:out1_boiler:in1,100.0,5.0,11.927817356454685,5.0,0.10244903431560166,0.0010244903431560167,42.17534307955257,0.0,0.0,0.8,0.15,0.05 +boiler:out1_press:in1,100.0,5.0,347.73276629402903,95.0,0.10731885384290359,0.0010731885384290358,1087.6845264098968,0.0,0.0,0.8,0.15,0.05 +press:out1_liquidmerge:in1,23.333333333333332,5.0,242.16768988793567,85.0,0.026160149686381976,0.0011211492722735133,763.1933790048553,0.0,0.0,0.49999999999999994,0.45,0.05 +press:out2_presswaterheater:in1,76.66666666666667,5.0,330.6883654544387,84.99999999999449,0.08038044079569369,0.0010484405321177436,1051.0286927193201,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 +presswaterheater:out1_decanter:in1,76.66666666666667,5.0,370.2784672443261,94.99999999999687,0.08096049019323474,0.0010560063938248009,1160.053457653331,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 +decanter:out1_liquidmerge:in2,3.857142857142857,5.0,281.54439230506006,90.0,0.0042684792118244125,0.001106642758621144,883.2089826934414,0.0,0.0,0.6,0.35,0.05 +decanter:out2_centrifuge:in1,72.80952380952381,5.0,354.12058245226905,89.99999999999864,0.07639654564835188,0.0010492658329727858,1117.6733425160928,0.0,0.0,0.9067364290385874,0.043263570961412694,0.04999999999999999 +centrifuge:out1_thickener:in1,69.86772486772487,5.0,181.05101285530006,44.99999999997766,0.07114264015923703,0.0010182475569932448,611.6350715142114,0.0,0.0,0.944914804998107,0.044664142370314276,0.010421052631578944 +centrifuge:out2_oil:in1,2.9417989417989414,5.0,100.0781863246528,80.0,0.003335242690945141,0.0011337425694040138,308.9315041090459,0.0,0.0,0.0,0.01,0.99 +thickener:out1_liquidmerge:in3,12.482328042328044,5.0,356.36268450896694,105.00000000000028,0.013748836912735783,0.0011014641552531674,1096.5687083290452,0.0,0.0,0.6916699164109263,0.25,0.058330083589074044 +thickener:out2_vapourextract1:in1,57.385396825396825,5.0,440.55426498775586,104.99999999999773,0.060096661478605574,0.0010472465958797524,1363.0390021793273,-1.0,,1.0,0.0,0.0 +liquidmerge:out1_drier:in1,39.67280423280423,5.0,281.9254277292509,92.28684488833795,0.044193935239153596,0.0011139604596594405,880.7937574528526,0.0,0.0,0.5700278468317561,0.37735124350507326,0.05262090966317069 +drier:out1_meal:in1,18.953556731334505,5.0,184.93088408428466,99.99999999999937,0.022841343955262234,0.001205121776299661,559.4856087856919,0.0,0.0,0.1,0.7898560794044667,0.11014392059553352 +drier:out2_vapourextract2:in1,20.719247501469727,1.0141799666808606,2675.5698844230105,100.00000000224776,34.637736274183936,1.6717661329991302,7354.119145674784,1.0,,1.0,0.0,0.0 diff --git a/intermediateFoodTests/energy-supply_energy-merge3.py b/intermediateFoodTests/energy-supply_energy-merge3.py new file mode 100644 index 000000000..6f5ba03dd --- /dev/null +++ b/intermediateFoodTests/energy-supply_energy-merge3.py @@ -0,0 +1,67 @@ +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection, Ref, Bus +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter +from tespy.components.newcomponents import * + +import logging +logging.basicConfig(level=logging.DEBUG) + +from CoolProp.CoolProp import PropsSI + + + + +fluid_list = ['INCOMP::FoodWater'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +# Objects +PurchasedNaturalGas1 = Source('PurchasedNaturalGas1') +PurchasedNaturalGas2 = Source('PurchasedNaturalGas2') + +Merge = MergeEnergySupply('Merge',num_in = 2) + +Consumer = Sink('Consumer') + + +# Connections +c1 = Connection(PurchasedNaturalGas1, 'out1', Merge, 'in1') +c2 = Connection(PurchasedNaturalGas2, 'out1', Merge, 'in2') +c3 = Connection(Merge, 'out1', Consumer, 'in1') + +network.add_conns(c1,c2,c3) + +m0 = 4.428 + +c1.set_attr(m=m0) +c2.set_attr(m=m0/4) + +# guess +for c in network.conns['object']: + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + +# arbitray values +c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c2.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c3.set_attr(h=0,p=1) +# merge already propergate h, p and fluid + +network.solve('design',init_only=True) + +for c in network.conns['object']: + print(c.p.val_SI) +for c in network.conns['object']: + print(c.h.val_SI) +for c in network.conns['object']: + print(c.T.val_SI) + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) + diff --git a/intermediateFoodTests/energy-supply_energy-split3.py b/intermediateFoodTests/energy-supply_energy-split3.py new file mode 100644 index 000000000..07d662bf1 --- /dev/null +++ b/intermediateFoodTests/energy-supply_energy-split3.py @@ -0,0 +1,67 @@ +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection, Ref, Bus +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter +from tespy.components.newcomponents import * + +import logging +logging.basicConfig(level=logging.DEBUG) + +from CoolProp.CoolProp import PropsSI + + + + +fluid_list = ['INCOMP::FoodWater'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +# Objects +PurchasedNaturalGas = Source('PurchasedNaturalGas') + +Splitter1 = SplitterEnergySupply('Splitter1',num_out = 2) + +Consumer1 = Sink('Consumer1') +Consumer2 = Sink('Consumer2') + + + +# Connections +c1 = Connection(PurchasedNaturalGas, 'out1', Splitter1, 'in1') +c2 = Connection(Splitter1, 'out1', Consumer1, 'in1') +c3 = Connection(Splitter1, 'out2', Consumer2, 'in1') + +network.add_conns(c1,c2,c3) + +m0 = 4.428 + +c1.set_attr(m=m0) +c2.set_attr(m=m0/4) + +# guess +for c in network.conns['object']: + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + +# arbitray values +c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c2.set_attr(h=0,p=1) +c3.set_attr(h=0,p=1) + +network.solve('design',init_only=True) + +for c in network.conns['object']: + print(c.p.val_SI) +for c in network.conns['object']: + print(c.h.val_SI) +for c in network.conns['object']: + print(c.T.val_SI) + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) + diff --git a/intermediateFoodTests/energy-supply_heat-pump3.py b/intermediateFoodTests/energy-supply_heat-pump3.py new file mode 100644 index 000000000..6e135ddbb --- /dev/null +++ b/intermediateFoodTests/energy-supply_heat-pump3.py @@ -0,0 +1,64 @@ +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection, Ref, Bus +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter +from tespy.components.newcomponents import * + +import logging +logging.basicConfig(level=logging.DEBUG) + +from CoolProp.CoolProp import PropsSI + + + + +fluid_list = ['INCOMP::FoodWater'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +# Objects +PurchasedElectricity = Source('PurchasedElectricity') +HeatPump = MassFactorVCCEnergySupply('HeatPump') +Heating = Sink('Consumer1') +Cooling = Sink('Consumer2') + +# Connections +c1 = Connection(PurchasedElectricity, 'out1', HeatPump, 'in1') +c2 = Connection(HeatPump, 'out1', Heating, 'in1') +c3 = Connection(HeatPump, 'out2', Cooling, 'in1') + +network.add_conns(c1,c2,c3) + +m0 = 4.428 +c1.set_attr(m=m0) +#c2.set_attr(m=m0*3.5) + +HeatPump.set_attr(COP=3) + + +# guess +for c in network.conns['object']: + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + +# arbitray values +c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c2.set_attr(h=0,p=1) +c3.set_attr(h=0,p=1) + +network.solve('design',init_only=True) + +for c in network.conns['object']: + print(c.p.val_SI) +for c in network.conns['object']: + print(c.h.val_SI) +for c in network.conns['object']: + print(c.T.val_SI) + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) diff --git a/intermediateFoodTests/energy-supply_loss-model3.py b/intermediateFoodTests/energy-supply_loss-model3.py new file mode 100644 index 000000000..715ff45bc --- /dev/null +++ b/intermediateFoodTests/energy-supply_loss-model3.py @@ -0,0 +1,67 @@ +from tespy.components import Sink, Source, HeatExchangerSimple, Splitter +from tespy.connections import Connection, Ref, Bus +from tespy.networks import Network +import shutil +import numpy as np +import matplotlib.pyplot as plt + +from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter +from tespy.components.newcomponents import * + +import logging +logging.basicConfig(level=logging.DEBUG) + +from CoolProp.CoolProp import PropsSI + + + + +fluid_list = ['INCOMP::FoodWater'] +network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +# Objects +PurchasedElectricity = Source('PurchasedElectricity') +LossModel = MassFactorLossModelEnergySupply('LossModel') +Heating = Sink('Consumer1') +Cooling = Sink('Consumer2') + +# Connections +c1 = Connection(PurchasedElectricity, 'out1', LossModel, 'in1') +c2 = Connection(LossModel, 'out1', Heating, 'in1') +c3 = Connection(LossModel, 'out2', Cooling, 'in1') + +network.add_conns(c1,c2,c3) + +m0 = 4.428 +c1.set_attr(m=m0) +#c2.set_attr(m=m0*0.9) +LossModel.set_attr(Loss=0.1) + + + +# guess +for c in network.conns['object']: + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + +# arbitray values +c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c2.set_attr(h=0,p=1) +c3.set_attr(h=0,p=1) + +# c2 as split already propergate h, p and fluid +# c3 as split already propergate h, p and fluid + +network.solve('design',init_only=True) + +for c in network.conns['object']: + print(c.p.val_SI) +for c in network.conns['object']: + print(c.h.val_SI) +for c in network.conns['object']: + print(c.T.val_SI) + +# solve and print results +network.solve('design') + +network.print_results() +print(network.results['Connection']) diff --git a/intermediateFoodTests/initialFoodTests/food-properties.py b/intermediateFoodTests/initialFoodTests/food-properties.py new file mode 100644 index 000000000..dbf17920c --- /dev/null +++ b/intermediateFoodTests/initialFoodTests/food-properties.py @@ -0,0 +1,228 @@ +# %% +# -*- coding: utf-8 -*- +""" +Created on Thu Dec 22 22:41:28 2022 + +@author: mrk +""" + +import CoolProp.CoolProp as CP +import numpy as np +import matplotlib.pyplot as plt +from decimal import Decimal + +print("loaded modules") + +# %% + +Temps = np.linspace(-40,150,50) + +cp = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +k = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +a = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +d = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +a2 = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } + +#Specific heat, kJ/(kg·K) +for T in Temps: + cp['Protein'] += [2.0082 + 1.2089 * 1e-3*T - 1.3129 * 1e-6*T**2] + cp['Fat'] += [1.9842 + 1.4733 * 1e-3*T - 4.8008 * 1e-6*T**2] + cp['Carbohydrate'] += [1.5488 + 1.9625 * 1e-3*T - 5.9399 * 1e-6*T**2] + cp['Fiber'] += [1.8459 + 1.8306 * 1e-3*T - 4.6509 * 1e-6*T**2] + cp['Ash'] += [1.0926 + 1.8896 * 1e-3*T - 3.6817 * 1e-6*T**2] + cp['Water'] += [4.1289 - 9.0864 * 1e-5*T + 5.4731 * 1e-6*T**2] + + k['Protein'] += [1.7881 * 1e-1 + 1.1958 * 1e-3*T - 2.7178 * 1e-6*T**2] + k['Fat'] += [1.8071 * 1e-1 - 2.7604 * 1e-4*T - 1.7749 * 1e-7*T**2] + k['Carbohydrate'] += [2.0141 * 1e-1 + 1.3874 * 1e-3*T - 4.3312 * 1e-6*T**2] + k['Fiber'] += [1.8331 * 1e-1 + 1.2497 * 1e-3*T - 3.1683 * 1e-6*T**2] + k['Ash'] += [3.2962 * 1e-1 + 1.4011 * 1e-3*T - 2.9069 * 1e-6*T**2] + k['Water'] += [5.7109 * 1e-1 + 1.7625 * 1e-3*T - 6.7036 * 1e-6*T**2] + + a['Protein'] += [6.8714 * 1e-8 + 4.7578 * 1e-10*T - 1.4646 * 1e-12*T**2] + a['Fat'] += [9.8777 * 1e-8 - 1.2569 * 1e-11*T - 3.8286 * 1e-14*T**2] + a['Carbohydrate'] += [8.0842 * 1e-8 + 5.3052 * 1e-10*T - 2.3218 * 1e-12*T**2] + a['Fiber'] += [7.3976 * 1e-8 + 5.1902 * 1e-10*T - 2.2202 * 1e-12*T**2] + a['Ash'] += [1.2461 * 1e-7 + 3.7321 * 1e-10*T - 1.2244 * 1e-12*T**2] + a['Water'] += [1.3168 * 1e-7 + 6.2477 * 1e-10*T - 2.4022 * 1e-12*T**2] + + d['Protein'] += [1.3299 * 1e3 - 5.1840 * 1e-1*T] + d['Fat'] += [9.2559 * 1e2 - 4.1757 * 1e-1*T] + d['Carbohydrate'] += [1.5991 * 1e3 - 3.1046 * 1e-1*T] + d['Fiber'] += [1.3115 * 1e3 - 3.6589 * 1e-1*T] + d['Ash'] += [2.4238 * 1e3 - 2.8063 * 1e-1*T] + d['Water'] += [9.9718 * 1e2 + 3.1439 * 1e-3*T - 3.7574 * 1e-3*T**2] + +a2['Protein'] = [k/(cp*d) for k,cp,d in zip(k['Protein'],cp['Protein'],d['Protein'])] +a2['Fat'] = [k/(cp*d) for k,cp,d in zip(k['Fat'],cp['Fat'],d['Fat'])] +a2['Carbohydrate'] = [k/(cp*d) for k,cp,d in zip(k['Carbohydrate'],cp['Carbohydrate'],d['Carbohydrate'])] +a2['Fiber'] = [k/(cp*d) for k,cp,d in zip(k['Fiber'],cp['Fiber'],d['Fiber'])] +a2['Ash'] = [k/(cp*d) for k,cp,d in zip(k['Ash'],cp['Ash'],d['Ash'])] +a2['Water'] = [k/(cp*d) for k,cp,d in zip(k['Water'],cp['Water'],d['Water'])] + + +fig, ax = plt.subplots(2, 2, figsize=(16, 8)) +ax = ax.flatten() +[a.grid() for a in ax] +[a.set_xlabel('temperature, C') for a in ax] + +for i,key in enumerate(cp): + ax[0].scatter(Temps, cp[key],label=str(key)) + +for i,key in enumerate(k): + ax[1].scatter(Temps, k[key],label=str(key)) + +for i,key in enumerate(a): + ax[2].scatter(Temps, [a/a2*1000 for a,a2 in zip(a[key],a2[key])],label=str(key)) + +for i,key in enumerate(d): + ax[3].scatter(Temps, d[key],label=str(key)) + +[a.legend() for a in ax] +ax[0].set_ylabel('cp') +ax[1].set_ylabel('k') +ax[2].set_ylabel('a') +ax[3].set_ylabel('d') + +fig.show + + +np.set_printoptions(precision=5,suppress=False) + +Temps +print('\n') + + +for key in [cp,k,d]: + print(np.array(key['Protein'])) +print('\n') +for key in [cp,k,d]: + print(np.array(key['Fat'])) +print('\n') +for key in [cp,k,d]: + print(np.array(key['Carbohydrate'])) +print('\n') +for key in [cp,k,d]: + print(np.array(key['Fiber'])) +print('\n') +for key in [cp,k,d]: + print(np.array(key['Ash'])) +print('\n') +for key in [cp,k,d]: + print(np.array(key['Water'])) + +# %% + + +CP.get_global_param_string("version") +fl = CP.get_global_param_string("FluidsList") + + +CP_cp = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +CP_k = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } +CP_d = {'Protein' : [], + 'Fat' : [], + 'Carbohydrate' : [], + 'Fiber' : [], + 'Ash' : [], + 'Water' : [] + } + +Temps[0] = Temps[0] +1e-4 +Temps[-1] = Temps[-1] -1e-4 + + +#Specific heat, kJ/(kg·K) +for T in Temps: + CP_cp['Protein'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] + CP_cp['Fat'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodFat')] + CP_cp['Carbohydrate'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] + CP_cp['Fiber'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] + CP_cp['Ash'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] + CP_cp['Water'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodWater')] + + CP_k['Protein'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] + CP_k['Fat'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodFat')] + CP_k['Carbohydrate'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] + CP_k['Fiber'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] + CP_k['Ash'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] + CP_k['Water'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodWater')] + + CP_d['Protein'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] + CP_d['Fat'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodFat')] + CP_d['Carbohydrate'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] + CP_d['Fiber'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] + CP_d['Ash'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] + CP_d['Water'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodWater')] + + + +fig, ax = plt.subplots(2, 2, figsize=(16, 8)) +ax = ax.flatten() +[a.grid() for a in ax] +[a.set_xlabel('temperature, C') for a in ax] + +for i,key in enumerate(CP_cp): + ax[0].scatter(Temps, CP_cp[key],label=str(key)) + +for i,key in enumerate(CP_k): + ax[1].scatter(Temps, CP_k[key],label=str(key)) + +# ax[2].scatter(Temps, [a/a2*1000 for a,a2 in zip(a[key],a2[key])],label=str(key)) + +for i,key in enumerate(CP_d): + ax[3].scatter(Temps, CP_d[key],label=str(key)) + +[a.legend() for a in ax] +ax[0].set_ylabel('cp') +ax[1].set_ylabel('k') +ax[3].set_ylabel('d') + + + +plt.show(block=True) + + + diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py new file mode 100644 index 000000000..3e7830047 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py @@ -0,0 +1,69 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +se = SeparatorWithSpeciesSplits("Separator") +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 0.9, "T66": 0.1}) + +# set compositions +c2.set_attr(fluid={"Water": 0.85, "T66": 0.15}) +# or others +#c3.set_attr(fluid={"Water": 0.85, "T66": 0.15}) +# or others +#c2.set_attr(fluid={"Water": 0.85}) +#c3.set_attr(fluid={"Water": 1}) + +# This one produce error because T66 is 0 and the equation cannot be solved.. +#c2.set_attr(fluid={"Water": 1, "T66": 0.0}) + +# specify this one to avoid using the species flow split : SFS +#c2.set_attr(m=0.5) +# set the species flow split, specify the fluid and the outlet too.. (we might need some checks of this) +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + +# add some guess values +c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) + +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] + +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") + +print(f"\n heat flows are {se.Q.val}") +print(f"\n") + + diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py new file mode 100644 index 000000000..384666539 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -0,0 +1,86 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsAndDeltaT + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsAndDeltaT("Separator",num_out=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +for c in nw.conns['object']: + n_fl = len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=50, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) +#c3.set_attr(fluid={"FoodProtein": 0.1}) + +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) + + +se.set_attr(deltaT=2) +#se.set_attr(Q_loss=0) + +# Now it is possible to set the temperatures out of the separator differently +# c2.set_attr(T=20) +# c3.set_attr(T=10) + +# Or to use a deltaT array instead +#se.set_attr(deltaT=[-10,-20]) +#se.set_attr(deltaT=[0,0]) + +# # add some guess values +# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) +# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) + +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + +m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] +m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] + + +print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") + +print(f"\n Q loss {se.Q_loss.val}") + + + +print(f"\n") + + + diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py new file mode 100644 index 000000000..1f5d5e67b --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py @@ -0,0 +1,84 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsAndDeltaTAndPr("Separator",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +for c in nw.conns['object']: + n_fl = len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) + +# set some generic data for starting values +c1.set_attr(m=1, p=5, h=h0, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) +#c3.set_attr(fluid={"FoodProtein": 0.1}) + +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) + + +# Now it is possible to set the temperatures out of the separator differently +c2.set_attr(T=20,p=5) +c3.set_attr(T=10,p=5) + +# se.set_attr(deltaT=2) +# se.set_attr(deltaP=1) + +# Or to use a deltaT array instead +#se.set_attr(deltaT=[-10,-20]) +#se.set_attr(deltaT=[0,0]) + +# # add some guess values +# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) +# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) + +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + +m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] +m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] + + +print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") + +print(f"\n heat flows are {se.Q_loss.val}") +print(f"\n") + + + + +# %% diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py new file mode 100644 index 000000000..911ccf279 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py @@ -0,0 +1,83 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr, SeparatorWithSpeciesSplitsAndPr + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsAndPr("Separator",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +for c in nw.conns['object']: + n_fl = len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) + +# set some generic data for starting values +c1.set_attr(m=1, p=5, h=h0, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) +#c3.set_attr(fluid={"FoodProtein": 0.1}) + +se.set_attr(SFS={ + 'val': 0.65, 'is_set': True, + 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) + + +# Now it is possible to set the temperatures out of the separator differently +# c2.set_attr(p=5) +# c3.set_attr(p=4) + +se.set_attr(deltaP=0) + +# Or to use a deltaT array instead +#se.set_attr(deltaT=[-10,-20]) +#se.set_attr(deltaT=[0,0]) + +# # add some guess values +# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) +# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) + +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + +m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] +m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] + + +print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") + +#print(f"\n heat flows are {se.Q.val}") +#print(se.Qout.val) + +print(f"\n") + + + diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge.py b/intermediateFoodTests/newComponentsTests/heatex+merge.py new file mode 100644 index 000000000..b08af68ae --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/heatex+merge.py @@ -0,0 +1,88 @@ +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] + + +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +so2 = Source("Source2") + +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta +he = DiabaticSimpleHeatExchanger("Heater") +me = MergeWithPressureLoss("Merge") +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", me, "in1", label="2") +c3 = Connection(so2, "out1", me, "in2", label="3") +c4 = Connection(me, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2, c3, c4) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"Water": 0.9, "T66": 0.1}) +c2.set_attr(h=2.2e5) +# mix with pure water +c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"Water": 1, "T66": 0}) + +# set pressure ratios of heater and merge +he.set_attr(pr=1) +me.set_attr(pr=0.9) + +nw.solve("design") + +# use temperature to make it relatable +c1.set_attr(h=None, T=30) +c2.set_attr(h=None, T=50) + +nw.solve("design") + +# add some heat +c2.set_attr(T=None) +# efficiency is used for postprocessing here +he.set_attr(Q=1e5, eta=0.9) + +nw.solve("design") +nw.print_results() + +c2.set_attr(T=50) + +# impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) +# In this case, efficiency decreases +he.set_attr(Q=None, Q_total=1.5e5, eta="var") + +nw.solve("design") +nw.print_results() + +# with set efficiency, temperature cannot be set anymore +c2.set_attr(T=None) +he.set_attr(Q_total=1.5e5, eta=.5) + +nw.solve("design") +nw.print_results() + +# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C +c2.set_attr(T=5) +he.set_attr(Q_total=None, eta=None) + +nw.solve("design") +nw.print_results() + +he.set_attr(Q_total=-.6e5, eta="var") + +nw.solve("design") +nw.print_results() diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py b/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py new file mode 100644 index 000000000..5f36bd050 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py @@ -0,0 +1,112 @@ +# %% +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] + + +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +so2 = Source("Source2") + +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta +he = DiabaticSimpleHeatExchanger("Heater") +me = MergeWithPressureLoss("Merge") +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", me, "in1", label="2") +c3 = Connection(so2, "out1", me, "in2", label="3") +c4 = Connection(me, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2, c3, c4) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"Water": 0.9, "T66": 0.1}) +c2.set_attr(h=2.2e5) +# mix with pure water +c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"Water": 1, "T66": 0}) + +# set pressure ratios of heater and merge +he.set_attr(pr=1) +me.set_attr(pr=0.9) + +nw.solve("design") + +print(nw.results['Connection']) +he.Q.val +he.Q_loss.val +he.Q_total.val + +# %% +# use temperature to make it relatable +c1.set_attr(h=None, T=30) +c2.set_attr(h=None, T=50) + +nw.solve("design") + +# %% +# add some heat +c2.set_attr(T=None) +# efficiency is used for postprocessing here +he.set_attr(Q=1e5, eta=0.9) # MRK so eta is (1-hlf) heat loss factor + +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + + +# %% + +c2.set_attr(T=50) + +# impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) +# In this case, efficiency decreases +he.set_attr(Q=None, Q_total=1.5e5, eta='var') +nw.solve("design") +nw.print_results() + +print(nw.results['Connection']) + + +# %% +# with set efficiency, temperature cannot be set anymore +c2.set_attr(T=None) +he.set_attr(Q_total=1.5e5, eta=.5) + +nw.solve("design") +nw.print_results() + + +# %% +# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C +c2.set_attr(T=5) +he.set_attr(Q_total=None, eta=None) + +#nw.solve("design") +#nw.print_results() + +he.set_attr(Q_total=-.6e5, eta="var") + +nw.solve("design") +nw.print_results() + +# %% diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone.py b/intermediateFoodTests/newComponentsTests/heatex_alone.py new file mode 100644 index 000000000..83c6a16ff --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/heatex_alone.py @@ -0,0 +1,52 @@ +# %% + +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta +he = DiabaticSimpleHeatExchanger("Heater") +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(T=50) + +# set pressure ratios of heater and merge +he.set_attr(pr=1) + +he.set_attr(eta=1) # MRK so eta is (1-hlf) heat loss factor + +nw.solve("design") +nw.print_results() + +# print(nw.results['Connection']) +# he.Q.val +# he.Q_loss.val +# he.Q_total.val + diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py new file mode 100644 index 000000000..01e6b7731 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py @@ -0,0 +1,61 @@ +# %% + +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import HeatExchangerSimpleDeltaP, HeatExchangerSimpleLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits + + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta + +#he = HeatExchangerSimpleLossFactor("Heater") +he = HeatExchangerSimpleDeltaP("Heater") + + +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2) + +# set some generic data for starting values +c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(T=50) + +# set pressure ratios of heater and merge +he.set_attr(deltaP=1) + +#he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor +#he.set_attr(Q_total=86371.13607253956) # MRK so eta is (1-hlf) heat loss factor +#he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor + +nw.solve("design") +nw.print_results() + +# print(nw.results['Connection']) +# he.Q.val +# he.Q_loss.val +# he.Q_total.val + +# print(he.LF.val) +# print(he.Q_total.val) +# print(he.Q_loss.val) diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py new file mode 100644 index 000000000..5e72ff762 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py @@ -0,0 +1,61 @@ +# %% + +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import HeatExchangerSimpleDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits + + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta + +he = HeatExchangerSimpleDeltaPLossFactor("Heater") +#he = HeatExchangerSimpleDeltaP("Heater") + + +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2) + +# set some generic data for starting values +c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c2.set_attr(T=50) + +# set pressure ratios of heater and merge +he.set_attr(deltaP=1) + +#he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(Q_total=86371.13607253956) # MRK so eta is (1-hlf) heat loss factor +#he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor + +nw.solve("design") +nw.print_results() + +# print(nw.results['Connection']) +# he.Q.val +# he.Q_loss.val +# he.Q_total.val + +print(he.LF.val) +print(he.Q_total.val) +print(he.Q_loss.val) diff --git a/intermediateFoodTests/newComponentsTests/merge_mrk.py b/intermediateFoodTests/newComponentsTests/merge_mrk.py new file mode 100644 index 000000000..6e6f3ded4 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/merge_mrk.py @@ -0,0 +1,50 @@ +# %% +import logging + + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits + + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] + + +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +so2 = Source("Source2") + +me = MergeWithPressureLoss("Merge") +si = Sink("Sink") + +c1 = Connection(so, "out1", me, "in1", label="2") +c3 = Connection(so2, "out1", me, "in2", label="3") +c4 = Connection(me, "out1", si, "in1", label="4") + +nw.add_conns(c1, c3, c4) + +# set some generic data for starting values +c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +# mix with pure water +c3.set_attr(m=0.05, p=2.2, h=0.5e5, fluid={"FoodWater": 1, "FoodProtein": 0}) + +# set pressure ratios of heater and merge +me.set_attr(deltaP=1) +#c4.set_attr(p=1) + +nw.solve("design") + +nw.print_results() +print(nw.results['Connection']) + diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py new file mode 100644 index 000000000..04a42c857 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py @@ -0,0 +1,62 @@ +# %% two fluids +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink +from tespy.connections import Connection +from tespy.networks import Network + +# fluid and network +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +# components +so = Source("Source") +he = HeatExchangerSimple("Heater") +si = Sink("Sink") + +# connections +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="4") +nw.add_conns(c1, c2) + +# set some conditions on connections +c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 0.9, "T66": 0.1}) +c2.set_attr(T=50) + +# set some conditions on component +he.set_attr(pr=1) + +nw.solve("design") +nw.print_results() + +# %% one fluid + +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink +from tespy.connections import Connection +from tespy.networks import Network + +# fluid and network +fluids = ["INCOMP::Water"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +# components +so = Source("Source") +he = HeatExchangerSimple("Heater") +si = Sink("Sink") + +# connections +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="2") +nw.add_conns(c1, c2) + +# set some conditions on connections +c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 1}) +c2.set_attr(T=50) + +# set some conditions on component +he.set_attr(pr=1) + +nw.solve("design") +nw.print_results() diff --git a/pyproject.toml b/pyproject.toml index 2249b03f0..d338ffb6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,116 +1,31 @@ -[build-system] -requires = ["flit_core >=3.2,<4"] -build-backend = "flit_core.buildapi" - -[tool.flit.sdist] -include = [ - "CHANGELOG.rst", - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.md", - "MANIFEST.in", - "LICENSE*", - "PULL_REQUEST_TEMPLATE.md", - ".coveragerc", - ".editorconfig", - ".pep8speaks.yml", - ".readthedocs.yml", - "paper.bib", - "paper.md", - "tox.ini", - "docs/", - "tests/", - "tutorial/", -] -exclude = ["docs/_build"] - -[project] +[tool.poetry] name = "tespy" -version = "0.7.0.dev0" -description = "Thermal Engineering Systems in Python (TESPy)" +version = "0.1.0" +description = "" +authors = ["mrk "] readme = "README.rst" -authors = [ - {name = "Francesco Witte", email = "tespy@witte.sh"}, -] -classifiers = [ - "Development Status :: 4 - Beta", - "Intended Audience :: Education", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: Microsoft :: Windows", - "Operating System :: POSIX", - "Operating System :: Unix", - "Programming Language :: Python", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Topic :: Scientific/Engineering", -] -requires-python = ">=3.9" -dependencies = [ - "CoolProp>=6.4,<7", - "jinja2", - "matplotlib>=3.2.1,<4", - "numpy>=1.13.3,<2", - "pandas>=1.3.0,<3", - "tabulate>=0.8.2,<0.9", -] -license = {text = "MIT"} -[project.urls] -Homepage = "https://github.com/oemof/tespy" -Documentation = "https://tespy.readthedocs.io/" -Changelog = "https://tespy.readthedocs.io/en/main/whats_new.html" -"Issue Tracker" = "https://github.com/oemof/tespy/issues" +[tool.poetry.dependencies] +python = "^3.9" +numpy = "^1.25.1" +matplotlib = "^3.7.2" +pandas = "^2.0.3" +tabulate = "^0.9.0" -[project.optional-dependencies] -dev = [ - "build", - "flit", - "furo", - "iapws", - "pyromat", - "pytest", - "sphinx>=7.2.2", - "sphinx-copybutton", - "sphinx-design", - "sphinxcontrib.bibtex", - "tox", -] - -[tool.pytest.ini_options] -python_files = [ - "test_*.py", - "*_test.py", - "tests.py", -] -addopts = """ - -ra - --strict-markers - --doctest-modules - --doctest-glob=/*.rst - --tb=short - --pyargs -""" -testpaths = [ - "tespy", - "tests/", -] +[tool.poetry.group.coolprop.dependencies] +cython = "^0.29.35" +setuptools = "^67.8.0" +wheel = "^0.40.0" +requests = "^2.31.0" +jinja2 = "^3.1.2" +pyyaml = "^6.0" -[tool.isort] -force_single_line = true -line_length = 120 -known_first_party = "tespy" -default_section = "THIRDPARTY" -forced_separate = "test_tespy" -not_skip = "__init__.py" -skip = "migrations" -[tool.coverage.run] -branch = true -source = ["src"] -parallel = true - -[tool.coverage.report] -show_missing = true -precision = 2 -omit = ["migrations"] +[build-system] +requires = [ + "poetry-core", + "setuptools>=30.3.0", + "wheel", + "setuptools_scm>=3.3.1", +] +build-backend = "poetry.core.masonry.api" diff --git a/pyproject_.toml b/pyproject_.toml new file mode 100644 index 000000000..23cf6d7e1 --- /dev/null +++ b/pyproject_.toml @@ -0,0 +1,6 @@ +[build-system] +requires = [ + "setuptools>=30.3.0", + "wheel", + "setuptools_scm>=3.3.1", +] diff --git a/src/tespy/components/__init__.py b/src/tespy/components/__init__.py index d459df9af..5d7705a85 100644 --- a/src/tespy/components/__init__.py +++ b/src/tespy/components/__init__.py @@ -27,3 +27,6 @@ from .turbomachinery.compressor import Compressor # noqa: F401 from .turbomachinery.pump import Pump # noqa: F401 from .turbomachinery.turbine import Turbine # noqa: F401 + +# New components +from .newcomponents import * \ No newline at end of file diff --git a/src/tespy/components/component.py b/src/tespy/components/component.py index 8b8bafd1c..0eaac894f 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -26,6 +26,7 @@ from tespy.tools.data_containers import GroupedComponentCharacteristics as dc_gcc from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.data_containers import SimpleDataContainer as dc_simple +from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa from tespy.tools.document_models import generate_latex_eq from tespy.tools.fluid_properties import v_mix_ph from tespy.tools.global_vars import ERR @@ -210,6 +211,45 @@ def set_attr(self, **kwargs): logger.error(msg) raise TypeError(msg) + elif isinstance(data, dc_cpa): + try: + for f in kwargs[key]: + float(f) + is_numeric = True + except (TypeError, ValueError): + is_numeric = False + + for f in kwargs[key]: + if (f == 'var'): + is_var = True + else: + is_var = False + break + + if is_numeric: + if np.isnan(kwargs[key]).any(): + data.set_attr(is_set=False) + if isinstance(data, dc_cpa): + data.set_attr(is_var=False) + else: + data.set_attr(val=kwargs[key], is_set=True) + if isinstance(data, dc_cpa): + data.set_attr(is_var=False) + data.set_attr(num_eq=len(kwargs[key])) + + elif is_var: + if isinstance(data, dc_cpa): + data.set_attr(is_set=True, is_var=True) + data.set_attr(num_eq=len(kwargs[key])) + + # invalid datatype for keyword + else: + msg = ( + 'Bad datatype for keyword argument ' + key + + ' at ' + self.label + '.') + logging.error(msg) + raise TypeError(msg) + elif key in ['design', 'offdesign']: if not isinstance(kwargs[key], list): msg = ( diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py new file mode 100644 index 000000000..7f17b6b33 --- /dev/null +++ b/src/tespy/components/newcomponents.py @@ -0,0 +1,1247 @@ +import logging + +from tespy.components import HeatExchangerSimple, Merge, Separator, Splitter +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp +from tespy.tools.fluid_properties import T_mix_ph + +from tespy.components.component import Component + +import numpy as np + +class DiabaticSimpleHeatExchanger(HeatExchangerSimple): + + @staticmethod + def component(): + return 'diabatic simple heat exchanger' + + def get_variables(self): + variables = super().get_variables() + variables["eta"] = dc_cp(min_val=1e-5, val=1, max_val=1) + variables["Q_loss"] = dc_cp(max_val=0, val=0, is_result=True) + variables["Q_total"] = dc_cp(is_result=True) + variables["energy_group"] = dc_gcp( + elements=['Q_total', 'eta'], + num_eq=1, + latex=self.energy_balance_func_doc, + func=self.energy_balance2_func, deriv=self.energy_balance2_deriv + ) + + return variables + + def energy_balance2_func(self): + r""" + Equation for pressure drop calculation. + + Returns + ------- + residual : float + Residual value of equation: + + .. math:: + + 0 =\dot{m}_{in}\cdot\left( h_{out}-h_{in}\right) -\dot{Q} + """ + if self.Q_total.val < 0: + return self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) * self.eta.val - self.Q_total.val + else: + return self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) - self.Q_total.val * self.eta.val + + def energy_balance2_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + self.jacobian[k, 0, 0] = ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI) + self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI + self.jacobian[k, 1, 2] = self.inl[0].m.val_SI + # custom variable Q + if self.Q_total.is_var: + if self.Q_total.val < 0: + self.jacobian[k, 2 + self.Q.var_pos, 0] = -1 + else: + self.jacobian[k, 2 + self.Q.var_pos, 0] = -self.eta.val + + if self.eta.is_var: + if self.Q_total.val < 0: + self.jacobian[k, 2 + self.eta.var_pos, 0] = self.inl[0].m.val_SI * ( + self.outl[0].h.val_SI - self.inl[0].h.val_SI + ) + else: + self.jacobian[k, 2 + self.eta.var_pos, 0] = -self.Q_total.val + + def calc_parameters(self): + super().calc_parameters() + + if self.eta.is_set: + if self.Q.val < 0: + self.Q_loss.val = self.Q.val * (1 - self.eta.val) + else: + self.Q_loss.val = -self.Q.val * (1 / self.eta.val - 1) + + self.Q_total.val = self.Q.val - self.Q_loss.val + + +class HeatExchangerSimpleDeltaP(HeatExchangerSimple): + + @staticmethod + def component(): + return 'diabatic simple heat exchanger' + + def get_variables(self): + variables = super().get_variables() + variables["deltaP"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1, + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + + return self.inl[0].p.val_SI - self.deltaP.val*1e5 - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k, 0, 1] = 1 #self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def calc_parameters(self): + super().calc_parameters() + self.deltaP.val = (self.inl[0].p.val_SI - self.outl[0].p.val_SI)/1e5 + + +class HeatExchangerSimpleDeltaPLossFactor(HeatExchangerSimpleDeltaP): + + @staticmethod + def component(): + return 'diabatic simple heat exchanger' + + def get_variables(self): + variables = super().get_variables() + variables["LF"] = dc_cp(min_val=0, val=0, max_val=1,is_result=True) + variables["Q_loss"] = dc_cp(is_result=True) + variables["Q_total"] = dc_cp(is_result=True) + variables["energy_group"] = dc_gcp( + elements=['Q_total', 'LF', 'Q_loss'], + num_eq=1, + latex=self.energy_balance_func_doc, + func=self.energy_balance2_func, deriv=self.energy_balance2_deriv + ) + + return variables + + def energy_balance2_func(self): + r""" + Equation for pressure drop calculation. + + Returns + ------- + residual : float + Residual value of equation: + + .. math:: + + 0 =\dot{m}_{in}\cdot\left( h_{out}-h_{in}\right) -\dot{Q} + """ + # self.Q_loss.val is negative and Q_total is positive (and vice versa) + if self.Q_loss.is_var: + self.LF.val = -self.Q_loss/self.Q.val + else: + return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val + + + def energy_balance2_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + if self.Q_loss.is_var: + self.LF.val = -self.Q_loss/self.Q.val + self.jacobian[k, 0, 0] = (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) + self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI*(1+self.LF.val) + self.jacobian[k, 1, 2] = self.inl[0].m.val_SI*(1+self.LF.val) + # custom variable Q + if self.Q_total.is_var: + self.jacobian[k, 2 + self.Q.var_pos, 0] = -1 + + if self.LF.is_var: + self.jacobian[k, 2 + self.LF.var_pos, 0] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) + + def calc_parameters(self): + super().calc_parameters() + + if self.Q_total.is_set: + self.Q_loss.val = self.Q.val-self.Q_total.val + self.LF.val = -self.Q_loss.val / self.Q.val + elif self.LF.is_set: + self.Q_total.val = self.Q.val * (1+self.LF.val) + self.Q_loss.val = self.Q.val-self.Q_total.val + else: + self.Q_total.val = self.Q.val-self.Q_loss.val + self.LF.val = -self.Q_loss.val/self.Q.val + + + +class MergeWithPressureLoss(Merge): + + @staticmethod + def component(): + return 'merge with pressure losses' + + def get_variables(self): + variables = super().get_variables() + variables["deltaP"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1, + ) + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} + } + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + p_in_min = min([i.p.val_SI for i in self.inl]) + return p_in_min - self.deltaP.val*1e5 - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + p_in = [i.p.val_SI for i in self.inl] + p_min_index = p_in.index(min(p_in)) + + self.jacobian[k, p_min_index, 1] = 1 #self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def calc_parameters(self): + super().calc_parameters() + Pmin = min([i.p.val_SI for i in self.inl]) + Pmax = max([i.p.val_SI for i in self.inl]) + if abs(self.outl[0].p.val_SI - Pmin) >= abs(self.outl[0].p.val_SI - Pmax): + self.deltaP.val = (Pmin - self.outl[0].p.val_SI)/1e5 + else: + self.deltaP.val = (Pmax - self.outl[0].p.val_SI)/1e5 + + +class SplitterWithPressureLoss(Splitter): + + @staticmethod + def component(): + return 'Splitter with pressure losses' + + def get_variables(self): + variables = super().get_variables() + variables["deltaP"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=self.num_out, + ) + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + } + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + residual = [] + p_in = self.inl[0].p.val_SI + for o in self.outl: + residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] + return residual + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + # self.jacobian[k, 0, 1] = self.pr.val + # self.jacobian[k, self.num_i, 1] = -1 + j = 0 + for c in self.outl: + self.jacobian[k, 0, 1] = 1 + self.jacobian[k, j + 1, 1] = -1 + j += 1 + k += 1 + + def calc_parameters(self): + super().calc_parameters() + + Pmin = min([i.p.val_SI for i in self.outl]) + Pmax = max([i.p.val_SI for i in self.outl]) + if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): + self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 + else: + self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 + + +class SeparatorWithSpeciesSplits(Separator): + + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + super().__init__(label, **kwargs) + + + + @staticmethod + def component(): + return 'separator with species flow splits' + + def get_variables(self): + variables = super().get_variables() + variables["SFS"] = dc_cp_SFS( + min_val=0, + deriv=self.SFS_deriv, + func=self.SFS_func, + latex=self.pr_func_doc, + num_eq=1, + ) + return variables + + def SFS_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + # residual = [] + # for fluid, x in self.inl[0].fluid.val.items(): + # res = x * self.inl[0].m.val_SI + # for o in self.outl: + # res -= o.fluid.val[fluid] * o.m.val_SI + # residual += [res] + # return residual + + fluid = self.SFS.split_fluid + out_i = int(self.SFS.split_outlet[3:]) - 1 + + res = self.inl[0].fluid.val[fluid] * self.inl[0].m.val_SI * self.SFS.val \ + - self.outl[out_i].fluid.val[fluid] * self.outl[out_i].m.val_SI + + #print(res) + return res + + def SFS_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + + # j=0 + # self.jacobian[k, j, 0] = self.inl[j].fluid.val[self.split_fluid] * self.TS.val + # self.jacobian[k, j, i + 3] = self.inl[j].m.val_SI * self.TS.val + + # i = 0 + # for fluid, x in self.outl[0].fluid.val.items(): + # j = 0 + # for inl in self.inl: + # self.jacobian[k, j, 0] = inl.fluid.val[fluid] + # self.jacobian[k, j, i + 3] = inl.m.val_SI + # j += 1 + # self.jacobian[k, j, 0] = -x + # self.jacobian[k, j, i + 3] = -self.outl[0].m.val_SI + # i += 1 + # k += 1 + + fluid_index = list(self.inl[0].fluid.val.keys()).index(self.SFS.split_fluid) + fluid = self.SFS.split_fluid + out_i = int(self.SFS.split_outlet[3:]) - 1 + + i = fluid_index + j = 0 + self.jacobian[k, j, 0] = self.inl[0].fluid.val[fluid] * self.SFS.val + self.jacobian[k, j, i + 3] = self.inl[0].m.val_SI * self.SFS.val + j = 1 + out_i + self.jacobian[k, j, 0] = -self.outl[out_i].fluid.val[fluid] + self.jacobian[k, j, i + 3] = -self.outl[out_i].m.val_SI + + #print(self.jacobian) + #print(self.jacobian[k,:,:]) + + + + +class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplits): + + + + @staticmethod + def component(): + return 'separator with species flow splits and dT on outlets' + + def get_variables(self): + variables = super().get_variables() + variables["deltaT"] = dc_cp( + deriv=self.energy_balance_deriv, # same as before + func=self.energy_balance_deltaT_func, + latex=self.pr_func_doc, + num_eq=self.num_out + ) + variables["Q"] = dc_cp(is_result=True) + #variables["Qout"] = dc_cpa() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + # 'energy_balance_constraints': { + # 'func': self.energy_balance_func, + # 'deriv': self.energy_balance_deriv, + # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + # 'num_eq': self.num_o}, + 'pressure_constraints': { + 'func': self.pressure_equality_func, + 'deriv': self.pressure_equality_deriv, + 'constant_deriv': True, + 'latex': self.pressure_equality_func_doc, + 'num_eq': self.num_i + self.num_o - 1} + } + + def energy_balance_deltaT_func(self): + r""" + Calculate energy balance. + + Returns + ------- + residual : list + Residual value of energy balance. + + .. math:: + + 0 = T_{in} - T_{out,j}\\ + \forall j \in \text{outlets} + """ + residual = [] + T_in = T_mix_ph(self.inl[0].get_flow(), T0=self.inl[0].T.val_SI) + i=0 + for o in self.outl: + residual += [T_in - self.deltaT.val - T_mix_ph(o.get_flow(), T0=o.T.val_SI)] + i+=1 + return residual + + def calc_parameters(self): + super().calc_parameters() + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) + + Tmin = min([i.T.val_SI for i in self.outl]) + Tmax = max([i.T.val_SI for i in self.outl]) + if abs(self.inl[0].T.val_SI - Tmin) >= abs(self.inl[0].T.val_SI - Tmax): + self.deltaT.val = self.inl[0].T.val_SI - Tmin + else: + self.deltaT.val = self.inl[0].T.val_SI - Tmax + # self.inl[0].T.val_SI - min([i.T.val_SI for i in self.outl]) + +class SeparatorWithSpeciesSplitsAndPr(SeparatorWithSpeciesSplits): + + @staticmethod + def component(): + return 'separator with species flow splits and dT and Pr on outlets' + + def get_variables(self): + variables = super().get_variables() + variables["deltaP"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=self.num_out, + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + residual = [] + p_in = self.inl[0].p.val_SI + for o in self.outl: + residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] + return residual + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + j = 0 + for c in self.outl: + self.jacobian[k, 0, 1] = 1 + self.jacobian[k, j + 1, 1] = -1 + j += 1 + k += 1 + + def calc_parameters(self): + super().calc_parameters() + + Pmin = min([i.p.val_SI for i in self.outl]) + Pmax = max([i.p.val_SI for i in self.outl]) + if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): + self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 + else: + self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 + + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + # 'pressure_constraints': { + # 'func': self.pressure_equality_func, + # 'deriv': self.pressure_equality_deriv, + # 'constant_deriv': True, + # 'latex': self.pressure_equality_func_doc, + # 'num_eq': self.num_i + self.num_o - 1} + } + + +class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndPr): + + @staticmethod + def component(): + return 'separator with species flow splits and dT and Pr on outlets' + + def get_variables(self): + variables = super().get_variables() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + # 'energy_balance_constraints': { + # 'func': self.energy_balance_func, + # 'deriv': self.energy_balance_deriv, + # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + # 'num_eq': self.num_o}, + # 'pressure_constraints': { + # 'func': self.pressure_equality_func, + # 'deriv': self.pressure_equality_deriv, + # 'constant_deriv': True, + # 'latex': self.pressure_equality_func_doc, + # 'num_eq': self.num_i + self.num_o - 1} + } + + +class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsAndDeltaTAndPr): + + @staticmethod + def component(): + return 'separator with species flow splits and dT and Pr on outlets + Bus connection on Q' + + def get_variables(self): + variables = super().get_variables() + return variables + + def bus_func(self, bus): + r""" + Calculate the value of the bus function. + + Parameters + ---------- + bus : tespy.connections.bus.Bus + TESPy bus object. + + Returns + ------- + val : float + Value of energy transfer :math:`\dot{E}`. This value is passed to + :py:meth:`tespy.components.component.Component.calc_bus_value` + for value manipulation according to the specified characteristic + line of the bus. + + .. math:: + + \dot{E} = \dot{m}_{in} \cdot \left( h_{out} - h_{in} \right) + """ + return np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) + + def bus_func_doc(self, bus): + r""" + Return LaTeX string of the bus function. + + Parameters + ---------- + bus : tespy.connections.bus.Bus + TESPy bus object. + + Returns + ------- + latex : str + LaTeX string of bus function. + """ + return ( + r'\dot{m}_\mathrm{in} \cdot \left(h_\mathrm{out} - ' + r'h_\mathrm{in} \right)') + + def bus_deriv(self, bus): + r""" + Calculate partial derivatives of the bus function. + + Parameters + ---------- + bus : tespy.connections.bus.Bus + TESPy bus object. + + Returns + ------- + deriv : ndarray + Matrix of partial derivatives. + """ +# for o in self.outl: +# self.Qout.val += [o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI)] +# return np.sum(self.Qout.val) + + deriv = np.zeros((1, len(self.outl)+1, self.num_nw_vars)) + f = self.calc_bus_value + deriv[0, 0, 2] = self.numeric_deriv(f, 'h', 0, bus=bus) + i = 0 + for o in self.outl: + i = i+1 + deriv[0, i, 0] = self.numeric_deriv(f, 'm', i, bus=bus) + deriv[0, i, 2] = self.numeric_deriv(f, 'h', i, bus=bus) + return deriv + + + + +class SplitWithFlowSplitter(Splitter): + + @staticmethod + def component(): + return 'splitter with flow split ratios' + + def get_variables(self): + variables = super().get_variables() + variables["FS"] = dc_cp_FS( + min_val=0, + deriv=self.FS_deriv, + func=self.FS_func, + latex=self.pr_func_doc, + num_eq=1, + ) + return variables + + def FS_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + + out_i = int(self.FS.split_outlet[3:]) - 1 + res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI + + #print(res) + return res + + def FS_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + + out_i = int(self.FS.split_outlet[3:]) - 1 + + j = 0 + self.jacobian[k, j, 0] = self.FS.val + j = 1 + out_i + self.jacobian[k, j, 0] = -1 + + #print(self.jacobian) + #print(self.jacobian[k,:,:]) + + +#%% Class containers + +class dc_cp_SFS(dc_cp): + """ + Data container for simple properties. + + SFS_fluid + + SFS_outlet + """ + @staticmethod + def attr(): + attributes = dc_cp.attr() + attributes.update({'split_fluid' : str, 'split_outlet' : str}) + return attributes + +class dc_cp_FS(dc_cp): + """ + Data container for component properties. + + FS_outlet + """ + @staticmethod + def attr(): + attributes = dc_cp.attr() + attributes.update({'split_outlet' : str}) + return attributes + + + +class MassFactorVCC(Splitter): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_variables(self): + variables = super().get_variables() + variables["COP"] = dc_cp( + min_val=0, + deriv=self.COP_deriv, + func=self.COP_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + 'pressure_constraints': { + 'func': self.pressure_equality_func, + 'deriv': self.pressure_equality_deriv, + 'constant_deriv': True, + 'latex': self.pressure_equality_func_doc, + 'num_eq': self.num_i + self.num_o - 1} + } + + + def COP_func(self): + r""" + Equation for COP. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI + + def COP_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k , 0, 0] = self.COP.val + self.jacobian[k , self.num_i, 0] = -1 + + def calc_parameters(self): + super().calc_parameters() + self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) + + + +class MassFactorVCCWithPressureLoss(MassFactorVCC): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_variables(self): + variables = super().get_variables() + variables["pr"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1 + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k, 0, 1] = self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + } + + def calc_parameters(self): + super().calc_parameters() + self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI + for i in range(self.num_i): + if self.inl[i].p.val < self.outl[0].p.val: + msg = ( + f"The pressure at inlet {i + 1} is lower than the pressure " + f"at the outlet of component {self.label}." + ) + logging.warning(msg) + + + + +class MassFactorLossModel(Splitter): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' + + def get_variables(self): + variables = super().get_variables() + variables["Loss"] = dc_cp( + min_val=0, + deriv=self.Loss_deriv, + func=self.Loss_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + 'pressure_constraints': { + 'func': self.pressure_equality_func, + 'deriv': self.pressure_equality_deriv, + 'constant_deriv': True, + 'latex': self.pressure_equality_func_doc, + 'num_eq': self.num_i + self.num_o - 1} + } + + + def Loss_func(self): + return self.inl[0].m.val_SI * (1-self.Loss.val) - self.outl[0].m.val_SI + + def Loss_deriv(self, increment_filter, k): + self.jacobian[k , 0, 0] = (1-self.Loss.val) + self.jacobian[k , self.num_i, 0] = -1 + + def calc_parameters(self): + super().calc_parameters() + self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI + + + +class MassFactorLossModelWithPressureLoss(MassFactorLossModel): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' + + def get_variables(self): + variables = super().get_variables() + variables["pr"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1 + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k, 0, 1] = self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + } + + def calc_parameters(self): + super().calc_parameters() + self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI + for i in range(self.num_i): + if self.inl[i].p.val < self.outl[0].p.val: + msg = ( + f"The pressure at inlet {i + 1} is lower than the pressure " + f"at the outlet of component {self.label}." + ) + logging.warning(msg) + + + + + + +class MergeEnergySupply(Merge): + + @staticmethod + def component(): + return 'merge without pressure/energy constraints' + + def get_variables(self): + variables = super().get_variables() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + } + +class SplitterEnergySupply(Splitter): + + @staticmethod + def component(): + return 'Splitter without pressure/energy constraints' + + def get_variables(self): + variables = super().get_variables() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + } + + + +class MassFactorVCCEnergySupply(MassFactorVCC): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances, without pressure/enthalpy constraints)' + + def get_variables(self): + variables = super().get_variables() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + } + + +class MassFactorLossModelEnergySupply(MassFactorLossModel): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances, without pressure/enthalpy constraints)' + + def get_variables(self): + variables = super().get_variables() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + } diff --git a/src/tespy/components/nodes/base.py b/src/tespy/components/nodes/base.py index 55a22b82d..9a85ed428 100644 --- a/src/tespy/components/nodes/base.py +++ b/src/tespy/components/nodes/base.py @@ -171,6 +171,8 @@ def initialise_source(c, key): return 1e5 elif key == 'h': return 5e5 + elif key == 'T': # maybe add more parameters + return 300 @staticmethod def initialise_target(c, key): @@ -201,6 +203,8 @@ def initialise_target(c, key): return 1e5 elif key == 'h': return 5e5 + elif key == 'T': # maybe add more parameters + return 300 def propagate_to_target(self, branch): diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 103e1c9e9..30e60c8a0 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1667,7 +1667,7 @@ def init_properties(self): 'network.') logger.warning(msg) - for key in ['m', 'p', 'h']: + for key in ['m', 'p', 'h', 'T']: # maybe add all properties to be initialized (maybe also initialize those from init_path) if c.get_attr(key).is_var: if not c.good_starting_values: self.init_val0(c, key) @@ -1767,7 +1767,7 @@ def init_precalc_properties(self, c): except ValueError: pass - def init_val0(self, c, key): + def init_val0(self, c: con.Connection, key: str): r""" Set starting values for fluid properties. @@ -1791,11 +1791,18 @@ def init_val0(self, c, key): val_s = c.source.initialise_source(c, key) val_t = c.target.initialise_target(c, key) + if val_s is None: + val_s = 0 + if val_t is None: + val_t = 0 + if val_s == 0 and val_t == 0: if key == 'p': c.get_attr(key).val0 = 1e5 elif key == 'h': c.get_attr(key).val0 = 1e6 + elif key == 'T': # should probably add other paratemeter too ? + c.get_attr(key).val0 = 300 elif val_s == 0: c.get_attr(key).val0 = val_t diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index 00168670d..c5683d132 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -583,3 +583,19 @@ def attr(): def serialize(self): return {"val": self.val, "is_set": self.is_set} + +class ComponentPropertiesArray(DataContainer): + """ + Data container for arrays. + """ + @staticmethod + def attr(): + """ + """ + return { + 'val': [], 'val_SI': [], 'is_set': False, 'd': 1e-4, + 'min_val': -1e12, 'max_val': 1e12, 'is_var': False, + 'val_ref': 1, 'design': np.nan, 'is_result': False, + 'num_eq': 0, 'func_params': {}, 'func': None, 'deriv': None, + 'latex': None} + \ No newline at end of file From a260449e0267a2206dd2f55f5da644b91aeff493 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 09:28:47 +0100 Subject: [PATCH 003/105] register nested root for coolprop (cherry picked from commit c06cdebd5cb460ef5856ea48d38c7daaae89a0a8) --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 0900bbae3..e10b5a8ba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "externals/CoolProp"] path = externals/CoolProp - url = ../CoolProp.git + url = git@github.com:IPUdk/CoolProp.git From 6712c5e4ee715b912827ea9963e1074d96f20229 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 12:00:49 +0100 Subject: [PATCH 004/105] updating examples (cherry picked from commit 56eb349a08758bf479d3afb34878dbfe4a8e1bb5) --- intermediateFoodTests/Ex1.py | 8 +- intermediateFoodTests/Ex1EEMAP_ref.csv | 3 + intermediateFoodTests/Ex1tespy070.csv | 6 +- intermediateFoodTests/Ex4.py | 29 ++- intermediateFoodTests/Ex4EEMAP_ref.csv | 9 + intermediateFoodTests/Ex4tespy070.csv | 18 +- intermediateFoodTests/Ex8.py | 36 +-- intermediateFoodTests/Ex8EEMAP_ref_1.csv | 14 ++ intermediateFoodTests/Ex8EEMAP_ref_2.csv | 14 ++ intermediateFoodTests/Ex8tespy070_1.csv | 28 +-- intermediateFoodTests/Ex8tespy070_2.csv | 28 +-- intermediateFoodTests/Ex9.py | 23 +- intermediateFoodTests/Ex9EEMAP_ref.csv | 15 ++ intermediateFoodTests/Ex9tespy070.csv | 30 +-- intermediateFoodTests/diff.ipynb | 215 ++++++++++++++++++ .../energy-supply_energy-merge3.py | 0 .../energy-supply_energy-split3.py | 0 .../energy-supply_heat-pump3.py | 0 .../energy-supply_loss-model3.py | 0 19 files changed, 370 insertions(+), 106 deletions(-) create mode 100644 intermediateFoodTests/Ex1EEMAP_ref.csv create mode 100644 intermediateFoodTests/Ex4EEMAP_ref.csv create mode 100644 intermediateFoodTests/Ex8EEMAP_ref_1.csv create mode 100644 intermediateFoodTests/Ex8EEMAP_ref_2.csv create mode 100644 intermediateFoodTests/Ex9EEMAP_ref.csv create mode 100644 intermediateFoodTests/diff.ipynb rename intermediateFoodTests/{ => energySupply}/energy-supply_energy-merge3.py (100%) rename intermediateFoodTests/{ => energySupply}/energy-supply_energy-split3.py (100%) rename intermediateFoodTests/{ => energySupply}/energy-supply_heat-pump3.py (100%) rename intermediateFoodTests/{ => energySupply}/energy-supply_loss-model3.py (100%) diff --git a/intermediateFoodTests/Ex1.py b/intermediateFoodTests/Ex1.py index cb0fa137d..189054665 100644 --- a/intermediateFoodTests/Ex1.py +++ b/intermediateFoodTests/Ex1.py @@ -24,10 +24,7 @@ #logging.basicConfig(level=logging.DEBUG) -#network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) -fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - +network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) # Objects source = Source('source') @@ -46,7 +43,8 @@ p0 = 2 # global guess value in bar # set conditions around boiler -c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, h=h0, p=p0) +# fluid_back_ends={'Water': "INCOMP", "PHE": "INCOMP", "S800": "INCOMP"} +c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=100, h=h0, p=p0, mixing_rule="incompressible") c2.set_attr(h=h0,p=p0) # solve and print results diff --git a/intermediateFoodTests/Ex1EEMAP_ref.csv b/intermediateFoodTests/Ex1EEMAP_ref.csv new file mode 100644 index 000000000..2c1c3b713 --- /dev/null +++ b/intermediateFoodTests/Ex1EEMAP_ref.csv @@ -0,0 +1,3 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_sink:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 diff --git a/intermediateFoodTests/Ex1tespy070.csv b/intermediateFoodTests/Ex1tespy070.csv index 2c1c3b713..f5ff45442 100644 --- a/intermediateFoodTests/Ex1tespy070.csv +++ b/intermediateFoodTests/Ex1tespy070.csv @@ -1,3 +1,3 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_sink:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,PHE,S800 +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 +boiler:out1_sink:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 diff --git a/intermediateFoodTests/Ex4.py b/intermediateFoodTests/Ex4.py index f541e25d0..f52660d71 100644 --- a/intermediateFoodTests/Ex4.py +++ b/intermediateFoodTests/Ex4.py @@ -11,7 +11,7 @@ - Centrifuge """ -from tespy.components import Sink, Source, HeatExchangerSimple +from tespy.components import Sink, Source, SimpleHeatExchanger from tespy.connections import Connection from tespy.networks import Network @@ -22,18 +22,17 @@ import logging #logging.basicConfig(level=logging.DEBUG) -fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=False) # Objects source = Source('source') -boiler = HeatExchangerSimple('boiler') +boiler = SimpleHeatExchanger('boiler') press = SeparatorWithSpeciesSplits('press', num_out=2) -#pressWater = Sink('pressWater') +#pressWater = Sink('pressWater') presscake = Sink('presscake') decanter = SeparatorWithSpeciesSplits('decanter', num_out=2) grax = Sink('grax') -oil = Sink('oil') +oil = Sink('oil') centrifuge = SeparatorWithSpeciesSplits('centrifuge',num_out=2) stickWater = Sink('stickWater') @@ -50,37 +49,35 @@ network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8) # set global guess values -m0 = 100 # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar for c in network.conns['object']: # n_fl = len(network.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/3, 'PHE': 1/3, 'S800': 1/3}) + c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/3, 'INCOMP::PHE': 1/3, 'INCOMP::S800': 1/3}) # set conditions around boiler -c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=100, h=h0, p=p0) +c1.set_attr(fluid={'INCOMP::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, h=h0, p=p0, mixing_rule="incompressible") c2.set_attr(h=h0,p=p0) - # set conditions around press press.set_attr(SFS={ 'val': 0.7, 'is_set': True, 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'Water': 0.50, 'PHE': 0.05, 'S800': 0.45}) - +c3.set_attr(fluid={'INCOMP::Water': 0.50, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.45}) # set conditions around decanter decanter.set_attr(SFS={ 'val': 0.3, 'is_set': True, 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'Water': 0.60, 'PHE': 0.05, 'S800': 0.35}) +c5.set_attr(fluid={'INCOMP::Water': 0.6, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.35}) # set conditions around centrifuge centrifuge.set_attr(SFS={ 'val': 0.8, 'is_set': True, 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'Water': 0,'PHE': 0.99, 'S800': 0.01}) +c8.set_attr(fluid={'INCOMP::PHE': 0.99, 'INCOMP::S800': 0.01}) # solve and print results network.solve('design') diff --git a/intermediateFoodTests/Ex4EEMAP_ref.csv b/intermediateFoodTests/Ex4EEMAP_ref.csv new file mode 100644 index 000000000..2e610c0f8 --- /dev/null +++ b/intermediateFoodTests/Ex4EEMAP_ref.csv @@ -0,0 +1,9 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_presscake:in1,7.777777777777778,2.0,78.66612649956119,46.945715802337304,0.008221058787004482,0.001056993272614862,256.3696338669351,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341097,46.94571580233952,0.09570564307860968,0.0010377720333825146,331.87502899705527,0.0,0.0,0.158433734939759,0.016265060240963854,0.8253012048192772 +decanter:out1_grax:in1,1.2857142857142856,2.0,85.51182358236238,46.94571580233941,0.0013476962897216462,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.02952353029265,46.94571580233952,0.09435794678888804,0.0010376244803106905,332.6266240381677,0.0,0.0,0.15996683539884796,0.011546517716879038,0.8284866468842731 +centrifuge:out1_stickWater:in1,79.18149751483085,2.0,109.46751182641472,46.945715802339464,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.03674299136386185,0.011776108371890536,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.9273942545358,46.945715802339464,0.013894775614785894,0.0011820300549596216,169.02088145066307,0.0,0.0,0.99,0.01,0.0 diff --git a/intermediateFoodTests/Ex4tespy070.csv b/intermediateFoodTests/Ex4tespy070.csv index 2e610c0f8..4d56de368 100644 --- a/intermediateFoodTests/Ex4tespy070.csv +++ b/intermediateFoodTests/Ex4tespy070.csv @@ -1,9 +1,9 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_presscake:in1,7.777777777777778,2.0,78.66612649956119,46.945715802337304,0.008221058787004482,0.001056993272614862,256.3696338669351,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341097,46.94571580233952,0.09570564307860968,0.0010377720333825146,331.87502899705527,0.0,0.0,0.158433734939759,0.016265060240963854,0.8253012048192772 -decanter:out1_grax:in1,1.2857142857142856,2.0,85.51182358236238,46.94571580233941,0.0013476962897216462,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.02952353029265,46.94571580233952,0.09435794678888804,0.0010376244803106905,332.6266240381677,0.0,0.0,0.15996683539884796,0.011546517716879038,0.8284866468842731 -centrifuge:out1_stickWater:in1,79.18149751483085,2.0,109.46751182641472,46.945715802339464,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.03674299136386185,0.011776108371890536,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.9273942545358,46.945715802339464,0.013894775614785894,0.0011820300549596216,169.02088145066307,0.0,0.0,0.99,0.01,0.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,PHE,S800 +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 +press:out1_presscake:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.6661264995547,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.5,0.05,0.45 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.8253012048192772,0.158433734939759,0.016265060240963854 +decanter:out1_grax:in1,1.2857142857142856,kg / s,0.0013476962897216462,m3 / s,2.0,bar,85.51182358236194,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.6,0.05,0.35 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.828486646884273,0.15996683539884796,0.011546517716879038 +centrifuge:out1_stickWater:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.91496499562584,J / kgK,0.9514809002642476,0.036742991363861846,0.011776108371890536 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.0,0.99,0.01 diff --git a/intermediateFoodTests/Ex8.py b/intermediateFoodTests/Ex8.py index a0fb7ad80..a6105074f 100644 --- a/intermediateFoodTests/Ex8.py +++ b/intermediateFoodTests/Ex8.py @@ -12,8 +12,7 @@ import logging #logging.basicConfig(level=logging.DEBUG) -fluid_list = ['INCOMP::Water','INCOMP::PHE','INCOMP::S800'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) # Objects source = Source('source') @@ -52,45 +51,47 @@ network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13) # set global guess values -m0 = 100 # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar +m0 = 100 # transform unit at some point +h0 = 1e2 # global guess value in kJ/kg +p0 = 2 # global guess value in bar for c in network.conns['object']: - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/3, 'PHE': 1/3, 'S800': 1/3}) +# n_fl = len(network.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/3, 'INCOMP::PHE': 1/3, 'INCOMP::S800': 1/3}) # set conditions around boiler -c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, h=h0, p=p0) +c1.set_attr(fluid={'INCOMP::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, h=h0, p=p0, mixing_rule="incompressible") c2.set_attr(h=h0,p=p0) # set conditions around press press.set_attr(SFS={ 'val': 0.7, 'is_set': True, 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'Water': 0.50, 'PHE': 0.05, 'S800': 0.45}) +c3.set_attr(fluid={'INCOMP::Water': 0.50, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.45}) # set conditions around decanter decanter.set_attr(SFS={ 'val': 0.3, 'is_set': True, 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'Water': 0.60, 'PHE': 0.05, 'S800': 0.35}) +c5.set_attr(fluid={'INCOMP::Water': 0.6, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.35}) # set conditions around centrifuge centrifuge.set_attr(SFS={ 'val': 0.8, 'is_set': True, 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'Water': 0,'PHE': 0.99, 'S800': 0.01}) +c8.set_attr(fluid={'INCOMP::PHE': 0.99, 'INCOMP::S800': 0.01}) # set conditions around thickener -c10.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) -c9.set_attr(fluid={'PHE': 0.25}) +c10.set_attr(fluid={'INCOMP::Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) +c9.set_attr(fluid={'INCOMP::PHE': 0.25}) # set conditions around liquidMerge c11.set_attr(p=p0) # set conditions around drier -c12.set_attr(fluid={'Water': 0.1}) -c13.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) +c12.set_attr(fluid={'INCOMP::Water': 0.1}) +c13.set_attr(fluid={'INCOMP::Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) + # solve and print results network.solve('design') @@ -107,8 +108,7 @@ # %% oil cleansing -fluid_list2 = ['INCOMP::Water','INCOMP::S800'] -network2 = Network(fluids=fluid_list2, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +network2 = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) # Objects sourceFat = Source('Fat') @@ -140,8 +140,8 @@ c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::S800': 1/n_fl}) # set conditions around merge -c1.set_attr(fluid={'Water': 0,'S800': 1}, m=m0, h=h0, p=p0) -c2.set_attr(fluid={'Water': 1,'S800': 0}, m=0.7*m0/1000, h=h0, p=p0) +c1.set_attr(fluid={'INCOMP::S800': 1}, m=m0, h=h0, p=p0, mixing_rule="incompressible") +c2.set_attr(fluid={'INCOMP::Water': 1}, m=0.7*m0/1000, h=h0, p=p0) c3.set_attr(p=p0) T2.set_attr(FS={'val': 0.75, 'is_set': True, 'split_outlet' : "out1"}) diff --git a/intermediateFoodTests/Ex8EEMAP_ref_1.csv b/intermediateFoodTests/Ex8EEMAP_ref_1.csv new file mode 100644 index 000000000..9d437a9d8 --- /dev/null +++ b/intermediateFoodTests/Ex8EEMAP_ref_1.csv @@ -0,0 +1,14 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 +decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 +centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 +thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 +thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 +drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 +drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex8EEMAP_ref_2.csv b/intermediateFoodTests/Ex8EEMAP_ref_2.csv new file mode 100644 index 000000000..9d437a9d8 --- /dev/null +++ b/intermediateFoodTests/Ex8EEMAP_ref_2.csv @@ -0,0 +1,14 @@ +,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water +source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 +press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 +press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 +decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 +centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 +thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 +thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 +drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 +drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex8tespy070_1.csv b/intermediateFoodTests/Ex8tespy070_1.csv index 9d437a9d8..c6192b528 100644 --- a/intermediateFoodTests/Ex8tespy070_1.csv +++ b/intermediateFoodTests/Ex8tespy070_1.csv @@ -1,14 +1,14 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 -decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 -centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 -thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 -thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 -drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 -drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 +press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955468,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.5,0.05 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.8253012048192772,0.158433734939759 +decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236196,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.6,0.05 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.011546517716879036,0.828486646884273,0.15996683539884796 +centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410211,m3 / s,2.0,bar,109.46751182641476,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754611,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890531,0.9514809002642475,0.03674299136386184 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453577,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.0,0.99 +thickener:out1_liquidmerge:in3,11.637460317460313,kg / s,0.012327881012709239,m3 / s,2.0,bar,91.88882840645772,kJ / kg,46.94571580233952,C,0.0,C,0.001059327437122432,m3 / kg,0.0,-,299.5182167574656,J / kgK,0.08012486146863373,0.6698751385313659,0.25 +thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757952,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 +liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.52471562494758,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.0143891477573,J / kgK,0.23585629327256138,0.6017096495565393,0.16243405717089932 +drier:out1_meal:in1,9.161099531469914,kg / s,0.010255768072889382,m3 / s,2.0,bar,53.80949985561704,kJ / kg,46.94571580233958,C,0.0,C,0.0011194909560428962,m3 / kg,0.0,-,175.2083414222269,J / kgK,0.532954573739888,0.1,0.36704542626011183 +drier:out2_vapourextract2:in1,11.539852849482465,kg / s,0.011640868016546005,m3 / s,2.0,bar,112.49622078757943,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 diff --git a/intermediateFoodTests/Ex8tespy070_2.csv b/intermediateFoodTests/Ex8tespy070_2.csv index 9d437a9d8..c6192b528 100644 --- a/intermediateFoodTests/Ex8tespy070_2.csv +++ b/intermediateFoodTests/Ex8tespy070_2.csv @@ -1,14 +1,14 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 -decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 -centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 -thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 -thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 -drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 -drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 +press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955468,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.5,0.05 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.8253012048192772,0.158433734939759 +decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236196,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.6,0.05 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.011546517716879036,0.828486646884273,0.15996683539884796 +centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410211,m3 / s,2.0,bar,109.46751182641476,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754611,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890531,0.9514809002642475,0.03674299136386184 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453577,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.0,0.99 +thickener:out1_liquidmerge:in3,11.637460317460313,kg / s,0.012327881012709239,m3 / s,2.0,bar,91.88882840645772,kJ / kg,46.94571580233952,C,0.0,C,0.001059327437122432,m3 / kg,0.0,-,299.5182167574656,J / kgK,0.08012486146863373,0.6698751385313659,0.25 +thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757952,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 +liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.52471562494758,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.0143891477573,J / kgK,0.23585629327256138,0.6017096495565393,0.16243405717089932 +drier:out1_meal:in1,9.161099531469914,kg / s,0.010255768072889382,m3 / s,2.0,bar,53.80949985561704,kJ / kg,46.94571580233958,C,0.0,C,0.0011194909560428962,m3 / kg,0.0,-,175.2083414222269,J / kgK,0.532954573739888,0.1,0.36704542626011183 +drier:out2_vapourextract2:in1,11.539852849482465,kg / s,0.011640868016546005,m3 / s,2.0,bar,112.49622078757943,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 diff --git a/intermediateFoodTests/Ex9.py b/intermediateFoodTests/Ex9.py index 05b1153cc..dea057026 100644 --- a/intermediateFoodTests/Ex9.py +++ b/intermediateFoodTests/Ex9.py @@ -12,8 +12,7 @@ import logging #logging.basicConfig(level=logging.DEBUG) -fluid_list = ['HEOS::Water','INCOMP::PHE','INCOMP::S800'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) # Objects source = Source('source') @@ -56,24 +55,24 @@ network.add_conns(c1,c2,c3,c4a,c4b,c5,c6,c7,c8,c9,c10,c11,c12,c13) # set global guess values -m0 = 100 # transform unit at some point +m0 = 100 # transform unit at some point [this is kt/yr] h0 = 1e2 # global guess value in kJ/kg p0 = 5 # global guess value in bar for c in network.conns['object']: - n_fl = len(network.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'Water': 1/n_fl, 'S800': 1/n_fl, 'PHE': 1/n_fl}) + # n_fl = len(network.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'Water': 1/n_fl, 'INCOMP::S800': 1/n_fl, 'INCOMP::PHE': 1/n_fl}) c.set_attr(p=p0) # set conditions around boiler -c1.set_attr(fluid={'Water': 0.80,'PHE': 0.15,'S800': 0.05}, m=m0, T=5) +c1.set_attr(fluid={'Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, T=5, mixing_rule="incompressible") c2.set_attr(T=95) # set conditions around press press.set_attr(SFS={ 'val': 0.7, 'is_set': True, 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'Water': 0.5, 'S800': 0.05, 'PHE': 0.45}) +c3.set_attr(fluid={'Water': 0.50, 'INCOMP::S800': 0.05, 'INCOMP::PHE': 0.45}) c3.set_attr(T=85) c4a.set_attr(T=85) c4b.set_attr(T=95) @@ -83,7 +82,7 @@ decanter.set_attr(SFS={ 'val': 0.3, 'is_set': True, 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'Water': 0.60, 'S800': 0.05, 'PHE': 0.35}) +c5.set_attr(fluid={'Water': 0.60, 'INCOMP::S800': 0.05, 'INCOMP::PHE': 0.35}) c5.set_attr(T=90) c6.set_attr(T=90) @@ -91,13 +90,13 @@ centrifuge.set_attr(SFS={ 'val': 0.8, 'is_set': True, 'split_fluid' : 'S800', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'Water': 0, 'S800': 0.99, 'PHE': 0.01}) +c8.set_attr(fluid={'Water': 0, 'INCOMP::S800': 0.99, 'INCOMP::PHE': 0.01}) c7.set_attr(T=45) c8.set_attr(T=80) # set conditions around thickener -c10.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) -c9.set_attr(fluid={'PHE': 0.25}) +c10.set_attr(fluid={'Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) +c9.set_attr(fluid={'INCOMP::PHE': 0.25}) c10.set_attr(T=105) c9.set_attr(T=105) @@ -108,7 +107,7 @@ # set conditions around drier c12.set_attr(fluid={'Water': 0.1}) -c13.set_attr(fluid={'Water': 1, 'S800': 0, 'PHE': 0}) +c13.set_attr(fluid={'Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) c12.set_attr(T=100) c13.set_attr(T=100) diff --git a/intermediateFoodTests/Ex9EEMAP_ref.csv b/intermediateFoodTests/Ex9EEMAP_ref.csv new file mode 100644 index 000000000..1de6f2543 --- /dev/null +++ b/intermediateFoodTests/Ex9EEMAP_ref.csv @@ -0,0 +1,15 @@ +,m,p,h,T,v,vol,s,x,Td_bp,Water,PHE,S800 +source:out1_boiler:in1,100.0,5.0,11.927817356454685,5.0,0.10244903431560166,0.0010244903431560167,42.17534307955257,0.0,0.0,0.8,0.15,0.05 +boiler:out1_press:in1,100.0,5.0,347.73276629402903,95.0,0.10731885384290359,0.0010731885384290358,1087.6845264098968,0.0,0.0,0.8,0.15,0.05 +press:out1_liquidmerge:in1,23.333333333333332,5.0,242.16768988793567,85.0,0.026160149686381976,0.0011211492722735133,763.1933790048553,0.0,0.0,0.49999999999999994,0.45,0.05 +press:out2_presswaterheater:in1,76.66666666666667,5.0,330.6883654544387,84.99999999999449,0.08038044079569369,0.0010484405321177436,1051.0286927193201,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 +presswaterheater:out1_decanter:in1,76.66666666666667,5.0,370.2784672443261,94.99999999999687,0.08096049019323474,0.0010560063938248009,1160.053457653331,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 +decanter:out1_liquidmerge:in2,3.857142857142857,5.0,281.54439230506006,90.0,0.0042684792118244125,0.001106642758621144,883.2089826934414,0.0,0.0,0.6,0.35,0.05 +decanter:out2_centrifuge:in1,72.80952380952381,5.0,354.12058245226905,89.99999999999864,0.07639654564835188,0.0010492658329727858,1117.6733425160928,0.0,0.0,0.9067364290385874,0.043263570961412694,0.04999999999999999 +centrifuge:out1_thickener:in1,69.86772486772487,5.0,181.05101285530006,44.99999999997766,0.07114264015923703,0.0010182475569932448,611.6350715142114,0.0,0.0,0.944914804998107,0.044664142370314276,0.010421052631578944 +centrifuge:out2_oil:in1,2.9417989417989414,5.0,100.0781863246528,80.0,0.003335242690945141,0.0011337425694040138,308.9315041090459,0.0,0.0,0.0,0.01,0.99 +thickener:out1_liquidmerge:in3,12.482328042328044,5.0,356.36268450896694,105.00000000000028,0.013748836912735783,0.0011014641552531674,1096.5687083290452,0.0,0.0,0.6916699164109263,0.25,0.058330083589074044 +thickener:out2_vapourextract1:in1,57.385396825396825,5.0,440.55426498775586,104.99999999999773,0.060096661478605574,0.0010472465958797524,1363.0390021793273,-1.0,,1.0,0.0,0.0 +liquidmerge:out1_drier:in1,39.67280423280423,5.0,281.9254277292509,92.28684488833795,0.044193935239153596,0.0011139604596594405,880.7937574528526,0.0,0.0,0.5700278468317561,0.37735124350507326,0.05262090966317069 +drier:out1_meal:in1,18.953556731334505,5.0,184.93088408428466,99.99999999999937,0.022841343955262234,0.001205121776299661,559.4856087856919,0.0,0.0,0.1,0.7898560794044667,0.11014392059553352 +drier:out2_vapourextract2:in1,20.719247501469727,1.0141799666808606,2675.5698844230105,100.00000000224776,34.637736274183936,1.6717661329991302,7354.119145674784,1.0,,1.0,0.0,0.0 diff --git a/intermediateFoodTests/Ex9tespy070.csv b/intermediateFoodTests/Ex9tespy070.csv index 1de6f2543..41f931d61 100644 --- a/intermediateFoodTests/Ex9tespy070.csv +++ b/intermediateFoodTests/Ex9tespy070.csv @@ -1,15 +1,15 @@ -,m,p,h,T,v,vol,s,x,Td_bp,Water,PHE,S800 -source:out1_boiler:in1,100.0,5.0,11.927817356454685,5.0,0.10244903431560166,0.0010244903431560167,42.17534307955257,0.0,0.0,0.8,0.15,0.05 -boiler:out1_press:in1,100.0,5.0,347.73276629402903,95.0,0.10731885384290359,0.0010731885384290358,1087.6845264098968,0.0,0.0,0.8,0.15,0.05 -press:out1_liquidmerge:in1,23.333333333333332,5.0,242.16768988793567,85.0,0.026160149686381976,0.0011211492722735133,763.1933790048553,0.0,0.0,0.49999999999999994,0.45,0.05 -press:out2_presswaterheater:in1,76.66666666666667,5.0,330.6883654544387,84.99999999999449,0.08038044079569369,0.0010484405321177436,1051.0286927193201,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 -presswaterheater:out1_decanter:in1,76.66666666666667,5.0,370.2784672443261,94.99999999999687,0.08096049019323474,0.0010560063938248009,1160.053457653331,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 -decanter:out1_liquidmerge:in2,3.857142857142857,5.0,281.54439230506006,90.0,0.0042684792118244125,0.001106642758621144,883.2089826934414,0.0,0.0,0.6,0.35,0.05 -decanter:out2_centrifuge:in1,72.80952380952381,5.0,354.12058245226905,89.99999999999864,0.07639654564835188,0.0010492658329727858,1117.6733425160928,0.0,0.0,0.9067364290385874,0.043263570961412694,0.04999999999999999 -centrifuge:out1_thickener:in1,69.86772486772487,5.0,181.05101285530006,44.99999999997766,0.07114264015923703,0.0010182475569932448,611.6350715142114,0.0,0.0,0.944914804998107,0.044664142370314276,0.010421052631578944 -centrifuge:out2_oil:in1,2.9417989417989414,5.0,100.0781863246528,80.0,0.003335242690945141,0.0011337425694040138,308.9315041090459,0.0,0.0,0.0,0.01,0.99 -thickener:out1_liquidmerge:in3,12.482328042328044,5.0,356.36268450896694,105.00000000000028,0.013748836912735783,0.0011014641552531674,1096.5687083290452,0.0,0.0,0.6916699164109263,0.25,0.058330083589074044 -thickener:out2_vapourextract1:in1,57.385396825396825,5.0,440.55426498775586,104.99999999999773,0.060096661478605574,0.0010472465958797524,1363.0390021793273,-1.0,,1.0,0.0,0.0 -liquidmerge:out1_drier:in1,39.67280423280423,5.0,281.9254277292509,92.28684488833795,0.044193935239153596,0.0011139604596594405,880.7937574528526,0.0,0.0,0.5700278468317561,0.37735124350507326,0.05262090966317069 -drier:out1_meal:in1,18.953556731334505,5.0,184.93088408428466,99.99999999999937,0.022841343955262234,0.001205121776299661,559.4856087856919,0.0,0.0,0.1,0.7898560794044667,0.11014392059553352 -drier:out2_vapourextract2:in1,20.719247501469727,1.0141799666808606,2675.5698844230105,100.00000000224776,34.637736274183936,1.6717661329991302,7354.119145674784,1.0,,1.0,0.0,0.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,S800,PHE +source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,0.0,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.8,0.05,0.15 +boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,0.0,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.8,0.05,0.15 +press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,0.0,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.5,0.05,0.45 +press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.08038044079569365,m3 / s,5.0,bar,330.688365454369,kJ / kg,85.00000000000176,C,0.0,C,0.0010484405321177432,m3 / kg,0.0,-,1051.0286927193572,J / kgK,0.8913043478260869,0.04999999999999999,0.058695652173913045 +presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.0809604901932347,m3 / s,5.0,bar,370.2784672442884,kJ / kg,95.00000000000011,C,0.0,C,0.0010560063938248004,m3 / kg,0.0,-,1160.0534576533219,J / kgK,0.8913043478260869,0.04999999999999999,0.058695652173913045 +decanter:out1_liquidmerge:in2,3.857142857142857,kg / s,0.004268479211824417,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,0.0,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.6,0.05,0.35 +decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.07639654564835228,m3 / s,5.0,bar,354.12058245226115,kJ / kg,90.00000000000074,C,0.0,C,0.0010492658329727914,m3 / kg,0.0,-,1117.673342516109,J / kgK,0.9067364290385873,0.05,0.0432635709614127 +centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015923824,m3 / s,5.0,bar,181.05101285503065,kJ / kg,44.999999999999375,C,0.0,C,0.0010182475569932622,m3 / kg,0.0,-,611.6350715143549,J / kgK,0.9449148049981069,0.010421052631578942,0.04466414237031428 +centrifuge:out2_oil:in1,2.9417989417989414,kg / s,0.00333524269094514,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,0.0,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.0,0.99,0.01 +thickener:out1_liquidmerge:in3,12.482328042328044,kg / s,0.013748836912735814,m3 / s,5.0,bar,356.36268450897313,kJ / kg,104.99999999999943,C,0.0,C,0.00110146415525317,m3 / kg,0.0,-,1096.568708329052,J / kgK,0.6916699164109258,0.05833008358907408,0.25 +thickener:out2_vapourextract1:in1,57.385396825396825,kg / s,0.060096661478604874,m3 / s,5.0,bar,440.55426498767247,kJ / kg,104.99999999999773,C,-46.83107910307007,C,0.0010472465958797402,m3 / kg,-1.0,-,1363.039002179117,J / kgK,1.0,0.0,0.0 +liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153485,m3 / s,5.0,bar,281.9254277292528,kJ / kg,92.28684488833858,C,0.0,C,0.0011139604596594377,m3 / kg,0.0,-,880.793757452899,J / kgK,0.570027846831756,0.052620909663170706,0.3773512435050733 +drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262258,m3 / s,5.0,bar,184.9308840842808,kJ / kg,99.99999999999989,C,0.0,C,0.0012051217762996612,m3 / kg,0.0,-,559.4856087856896,J / kgK,0.1,0.11014392059553348,0.7898560794044664 +drier:out2_vapourextract2:in1,20.719247501469713,kg / s,34.63773627778022,m3 / s,1.0141799665682765,bar,2675.569884418101,kJ / kg,99.999999999137,C,0.0,C,1.6717661331727036,m3 / kg,1.0,-,7354.1191457120685,J / kgK,1.0,0.0,0.0 diff --git a/intermediateFoodTests/diff.ipynb b/intermediateFoodTests/diff.ipynb new file mode 100644 index 000000000..0a127bf5f --- /dev/null +++ b/intermediateFoodTests/diff.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m 0.000000e+00\n", + "p 0.000000e+00\n", + "h 6.494361e-12\n", + "T 2.223999e-12\n", + "v 0.000000e+00\n", + "vol 0.000000e+00\n", + "s 1.830358e-11\n", + "x 0.000000e+00\n", + "Td_bp 0.000000e+00\n", + "PHE 0.000000e+00\n", + "S800 0.000000e+00\n", + "Water 1.110223e-16\n", + "dtype: float64" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"Ex4tespy070.csv\", index_col=0)\n", + "df.index = df.index.str.lower()\n", + "df_ref = pd.read_csv(\"Ex4EEMAP_ref.csv\", index_col=0)\n", + "df_ref.index = df_ref.index.str.lower()\n", + "(df.loc[:, df_ref.columns] - df_ref).abs().max()" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m 0.000000e+00\n", + "p 0.000000e+00\n", + "h 0.000000e+00\n", + "T 5.684342e-14\n", + "v 0.000000e+00\n", + "vol 0.000000e+00\n", + "s 0.000000e+00\n", + "x 0.000000e+00\n", + "Td_bp 0.000000e+00\n", + "PHE 0.000000e+00\n", + "S800 0.000000e+00\n", + "Water 0.000000e+00\n", + "dtype: float64" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"Ex1tespy070.csv\", index_col=0)\n", + "df.index = df.index.str.lower()\n", + "df_ref = pd.read_csv(\"Ex1EEMAP_ref.csv\", index_col=0)\n", + "df_ref.index = df_ref.index.str.lower()\n", + "(df.loc[:, df_ref.columns] - df_ref).abs().max()" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m 7.105427e-15\n", + "p 0.000000e+00\n", + "h 1.131468e-10\n", + "T 1.203944e-10\n", + "v 8.985868e-16\n", + "vol 9.996344e-17\n", + "s 1.285571e-09\n", + "x 0.000000e+00\n", + "Td_bp 0.000000e+00\n", + "PHE 8.326673e-17\n", + "S800 2.220446e-16\n", + "Water 1.110223e-16\n", + "dtype: float64" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"Ex8tespy070_1.csv\", index_col=0)\n", + "df.index = df.index.str.lower()\n", + "df_ref = pd.read_csv(\"Ex8EEMAP_ref_1.csv\", index_col=0)\n", + "df_ref.index = df_ref.index.str.lower()\n", + "(df.loc[:, df_ref.columns] - df_ref).abs().max()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m 7.105427e-15\n", + "p 0.000000e+00\n", + "h 1.131468e-10\n", + "T 1.203944e-10\n", + "v 8.985868e-16\n", + "vol 9.996344e-17\n", + "s 1.285571e-09\n", + "x 0.000000e+00\n", + "Td_bp 0.000000e+00\n", + "PHE 8.326673e-17\n", + "S800 2.220446e-16\n", + "Water 1.110223e-16\n", + "dtype: float64" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"Ex8tespy070_2.csv\", index_col=0)\n", + "df.index = df.index.str.lower()\n", + "df_ref = pd.read_csv(\"Ex8EEMAP_ref_2.csv\", index_col=0)\n", + "df_ref.index = df_ref.index.str.lower()\n", + "(df.loc[:, df_ref.columns] - df_ref).abs().max()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "m 1.421085e-14\n", + "p 1.125842e-10\n", + "h 4.909452e-09\n", + "T 3.110756e-09\n", + "v 3.596284e-09\n", + "vol 1.735734e-10\n", + "s 3.728383e-08\n", + "x 0.000000e+00\n", + "Td_bp 0.000000e+00\n", + "Water 5.551115e-16\n", + "PHE 2.220446e-16\n", + "S800 1.040834e-16\n", + "dtype: float64" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.read_csv(\"Ex9tespy070.csv\", index_col=0)\n", + "df.index = df.index.str.lower()\n", + "df_ref = pd.read_csv(\"Ex9EEMAP_ref.csv\", index_col=0)\n", + "df_ref.index = df_ref.index.str.lower()\n", + "(df.loc[:, df_ref.columns] - df_ref).abs().max()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "tespy-env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.15" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/intermediateFoodTests/energy-supply_energy-merge3.py b/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py similarity index 100% rename from intermediateFoodTests/energy-supply_energy-merge3.py rename to intermediateFoodTests/energySupply/energy-supply_energy-merge3.py diff --git a/intermediateFoodTests/energy-supply_energy-split3.py b/intermediateFoodTests/energySupply/energy-supply_energy-split3.py similarity index 100% rename from intermediateFoodTests/energy-supply_energy-split3.py rename to intermediateFoodTests/energySupply/energy-supply_energy-split3.py diff --git a/intermediateFoodTests/energy-supply_heat-pump3.py b/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py similarity index 100% rename from intermediateFoodTests/energy-supply_heat-pump3.py rename to intermediateFoodTests/energySupply/energy-supply_heat-pump3.py diff --git a/intermediateFoodTests/energy-supply_loss-model3.py b/intermediateFoodTests/energySupply/energy-supply_loss-model3.py similarity index 100% rename from intermediateFoodTests/energy-supply_loss-model3.py rename to intermediateFoodTests/energySupply/energy-supply_loss-model3.py From 99dbc576f98e84fd2bb0349fde0de38400a9e25a Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 13:03:01 +0100 Subject: [PATCH 005/105] successfully runing examples 1,4,8,9 (cherry picked from commit 81c4fe2d2165c49d00327090cff18d84d52a24c8) --- intermediateFoodTests/Ex4tespy070.csv | 18 +- intermediateFoodTests/Ex8tespy070_1.csv | 28 +-- intermediateFoodTests/Ex8tespy070_2.csv | 28 +-- intermediateFoodTests/Ex9tespy070.csv | 30 +-- pyproject.toml | 4 + src/tespy/components/newcomponents.py | 234 +++++++++++++----------- 6 files changed, 184 insertions(+), 158 deletions(-) diff --git a/intermediateFoodTests/Ex4tespy070.csv b/intermediateFoodTests/Ex4tespy070.csv index 4d56de368..5c9d84019 100644 --- a/intermediateFoodTests/Ex4tespy070.csv +++ b/intermediateFoodTests/Ex4tespy070.csv @@ -1,9 +1,9 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,PHE,S800 -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 -press:out1_presscake:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.6661264995547,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.5,0.05,0.45 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.8253012048192772,0.158433734939759,0.016265060240963854 -decanter:out1_grax:in1,1.2857142857142856,kg / s,0.0013476962897216462,m3 / s,2.0,bar,85.51182358236194,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.6,0.05,0.35 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.828486646884273,0.15996683539884796,0.011546517716879038 -centrifuge:out1_stickWater:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.91496499562584,J / kgK,0.9514809002642476,0.036742991363861846,0.011776108371890536 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.0,0.99,0.01 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,PHE,S800,Water +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.15,0.05,0.8 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.15,0.05,0.8 +press:out1_presscake:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.6661264995547,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.05,0.45,0.5 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.158433734939759,0.016265060240963854,0.8253012048192772 +decanter:out1_grax:in1,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236194,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.05,0.35,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.15996683539884796,0.011546517716879038,0.828486646884273 +centrifuge:out1_stickWater:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.91496499562584,J / kgK,0.036742991363861846,0.011776108371890534,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.99,0.01,0.0 diff --git a/intermediateFoodTests/Ex8tespy070_1.csv b/intermediateFoodTests/Ex8tespy070_1.csv index c6192b528..e92e0c1ba 100644 --- a/intermediateFoodTests/Ex8tespy070_1.csv +++ b/intermediateFoodTests/Ex8tespy070_1.csv @@ -1,14 +1,14 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 -press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955468,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.5,0.05 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.8253012048192772,0.158433734939759 -decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236196,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.6,0.05 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.011546517716879036,0.828486646884273,0.15996683539884796 -centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410211,m3 / s,2.0,bar,109.46751182641476,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754611,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890531,0.9514809002642475,0.03674299136386184 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453577,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.0,0.99 -thickener:out1_liquidmerge:in3,11.637460317460313,kg / s,0.012327881012709239,m3 / s,2.0,bar,91.88882840645772,kJ / kg,46.94571580233952,C,0.0,C,0.001059327437122432,m3 / kg,0.0,-,299.5182167574656,J / kgK,0.08012486146863373,0.6698751385313659,0.25 -thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757952,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 -liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.52471562494758,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.0143891477573,J / kgK,0.23585629327256138,0.6017096495565393,0.16243405717089932 -drier:out1_meal:in1,9.161099531469914,kg / s,0.010255768072889382,m3 / s,2.0,bar,53.80949985561704,kJ / kg,46.94571580233958,C,0.0,C,0.0011194909560428962,m3 / kg,0.0,-,175.2083414222269,J / kgK,0.532954573739888,0.1,0.36704542626011183 -drier:out2_vapourextract2:in1,11.539852849482465,kg / s,0.011640868016546005,m3 / s,2.0,bar,112.49622078757943,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,PHE,Water +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 +press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955471,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.05,0.5 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.158433734939759,0.8253012048192772 +decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236197,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.05,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888804,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106905,m3 / kg,0.0,-,332.6266240381677,J / kgK,0.011546517716879038,0.15996683539884796,0.8284866468842731 +centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890534,0.03674299136386185,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.99,0.0 +thickener:out1_liquidmerge:in3,11.637460317460315,kg / s,0.012327881012709246,m3 / s,2.0,bar,91.88882840645775,kJ / kg,46.94571580233952,C,0.0,C,0.0010593274371224325,m3 / kg,0.0,-,299.5182167574658,J / kgK,0.08012486146863364,0.25,0.6698751385313665 +thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757946,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.5247156249476,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.01438914775736,J / kgK,0.23585629327256122,0.16243405717089926,0.6017096495565396 +drier:out1_meal:in1,9.1610995314699,kg / s,0.010255768072889368,m3 / s,2.0,bar,53.809499855616984,kJ / kg,46.94571580233952,C,0.0,C,0.0011194909560428964,m3 / kg,0.0,-,175.20834142222498,J / kgK,0.5329545737398881,0.367045426260112,0.1 +drier:out2_vapourextract2:in1,11.53985284948248,kg / s,0.01164086801654602,m3 / s,2.0,bar,112.49622078757945,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex8tespy070_2.csv b/intermediateFoodTests/Ex8tespy070_2.csv index c6192b528..e92e0c1ba 100644 --- a/intermediateFoodTests/Ex8tespy070_2.csv +++ b/intermediateFoodTests/Ex8tespy070_2.csv @@ -1,14 +1,14 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.8,0.15 -press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955468,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.5,0.05 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.8253012048192772,0.158433734939759 -decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236196,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.6,0.05 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.011546517716879036,0.828486646884273,0.15996683539884796 -centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410211,m3 / s,2.0,bar,109.46751182641476,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754611,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890531,0.9514809002642475,0.03674299136386184 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453577,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.0,0.99 -thickener:out1_liquidmerge:in3,11.637460317460313,kg / s,0.012327881012709239,m3 / s,2.0,bar,91.88882840645772,kJ / kg,46.94571580233952,C,0.0,C,0.001059327437122432,m3 / kg,0.0,-,299.5182167574656,J / kgK,0.08012486146863373,0.6698751385313659,0.25 -thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757952,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 -liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.52471562494758,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.0143891477573,J / kgK,0.23585629327256138,0.6017096495565393,0.16243405717089932 -drier:out1_meal:in1,9.161099531469914,kg / s,0.010255768072889382,m3 / s,2.0,bar,53.80949985561704,kJ / kg,46.94571580233958,C,0.0,C,0.0011194909560428962,m3 / kg,0.0,-,175.2083414222269,J / kgK,0.532954573739888,0.1,0.36704542626011183 -drier:out2_vapourextract2:in1,11.539852849482465,kg / s,0.011640868016546005,m3 / s,2.0,bar,112.49622078757943,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,1.0,0.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,PHE,Water +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 +boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 +press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955471,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.05,0.5 +press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.158433734939759,0.8253012048192772 +decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236197,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.05,0.6 +decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888804,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106905,m3 / kg,0.0,-,332.6266240381677,J / kgK,0.011546517716879038,0.15996683539884796,0.8284866468842731 +centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890534,0.03674299136386185,0.9514809002642476 +centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.99,0.0 +thickener:out1_liquidmerge:in3,11.637460317460315,kg / s,0.012327881012709246,m3 / s,2.0,bar,91.88882840645775,kJ / kg,46.94571580233952,C,0.0,C,0.0010593274371224325,m3 / kg,0.0,-,299.5182167574658,J / kgK,0.08012486146863364,0.25,0.6698751385313665 +thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757946,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 +liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.5247156249476,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.01438914775736,J / kgK,0.23585629327256122,0.16243405717089926,0.6017096495565396 +drier:out1_meal:in1,9.1610995314699,kg / s,0.010255768072889368,m3 / s,2.0,bar,53.809499855616984,kJ / kg,46.94571580233952,C,0.0,C,0.0011194909560428964,m3 / kg,0.0,-,175.20834142222498,J / kgK,0.5329545737398881,0.367045426260112,0.1 +drier:out2_vapourextract2:in1,11.53985284948248,kg / s,0.01164086801654602,m3 / s,2.0,bar,112.49622078757945,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 diff --git a/intermediateFoodTests/Ex9tespy070.csv b/intermediateFoodTests/Ex9tespy070.csv index 41f931d61..697fd605d 100644 --- a/intermediateFoodTests/Ex9tespy070.csv +++ b/intermediateFoodTests/Ex9tespy070.csv @@ -1,15 +1,15 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,S800,PHE -source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,0.0,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.8,0.05,0.15 -boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,0.0,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.8,0.05,0.15 -press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,0.0,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.5,0.05,0.45 -press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.08038044079569365,m3 / s,5.0,bar,330.688365454369,kJ / kg,85.00000000000176,C,0.0,C,0.0010484405321177432,m3 / kg,0.0,-,1051.0286927193572,J / kgK,0.8913043478260869,0.04999999999999999,0.058695652173913045 -presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.0809604901932347,m3 / s,5.0,bar,370.2784672442884,kJ / kg,95.00000000000011,C,0.0,C,0.0010560063938248004,m3 / kg,0.0,-,1160.0534576533219,J / kgK,0.8913043478260869,0.04999999999999999,0.058695652173913045 -decanter:out1_liquidmerge:in2,3.857142857142857,kg / s,0.004268479211824417,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,0.0,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.6,0.05,0.35 -decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.07639654564835228,m3 / s,5.0,bar,354.12058245226115,kJ / kg,90.00000000000074,C,0.0,C,0.0010492658329727914,m3 / kg,0.0,-,1117.673342516109,J / kgK,0.9067364290385873,0.05,0.0432635709614127 -centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015923824,m3 / s,5.0,bar,181.05101285503065,kJ / kg,44.999999999999375,C,0.0,C,0.0010182475569932622,m3 / kg,0.0,-,611.6350715143549,J / kgK,0.9449148049981069,0.010421052631578942,0.04466414237031428 -centrifuge:out2_oil:in1,2.9417989417989414,kg / s,0.00333524269094514,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,0.0,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.0,0.99,0.01 -thickener:out1_liquidmerge:in3,12.482328042328044,kg / s,0.013748836912735814,m3 / s,5.0,bar,356.36268450897313,kJ / kg,104.99999999999943,C,0.0,C,0.00110146415525317,m3 / kg,0.0,-,1096.568708329052,J / kgK,0.6916699164109258,0.05833008358907408,0.25 -thickener:out2_vapourextract1:in1,57.385396825396825,kg / s,0.060096661478604874,m3 / s,5.0,bar,440.55426498767247,kJ / kg,104.99999999999773,C,-46.83107910307007,C,0.0010472465958797402,m3 / kg,-1.0,-,1363.039002179117,J / kgK,1.0,0.0,0.0 -liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153485,m3 / s,5.0,bar,281.9254277292528,kJ / kg,92.28684488833858,C,0.0,C,0.0011139604596594377,m3 / kg,0.0,-,880.793757452899,J / kgK,0.570027846831756,0.052620909663170706,0.3773512435050733 -drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262258,m3 / s,5.0,bar,184.9308840842808,kJ / kg,99.99999999999989,C,0.0,C,0.0012051217762996612,m3 / kg,0.0,-,559.4856087856896,J / kgK,0.1,0.11014392059553348,0.7898560794044664 -drier:out2_vapourextract2:in1,20.719247501469713,kg / s,34.63773627778022,m3 / s,1.0141799665682765,bar,2675.569884418101,kJ / kg,99.999999999137,C,0.0,C,1.6717661331727036,m3 / kg,1.0,-,7354.1191457120685,J / kgK,1.0,0.0,0.0 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,PHE,Water,S800 +source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,0.0,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.15,0.8,0.05 +boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,0.0,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.15,0.8,0.05 +press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,0.0,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.45,0.5,0.05 +press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.0803804407956944,m3 / s,5.0,bar,330.6883654543774,kJ / kg,85.0000000000012,C,0.0,C,0.001048440532117753,m3 / kg,0.0,-,1051.028692719397,J / kgK,0.058695652173913045,0.8913043478260869,0.049999999999999996 +presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.0809604901932347,m3 / s,5.0,bar,370.2784672442943,kJ / kg,95.0,C,0.0,C,0.0010560063938248004,m3 / kg,0.0,-,1160.0534576533798,J / kgK,0.058695652173913045,0.8913043478260869,0.049999999999999996 +decanter:out1_liquidmerge:in2,3.857142857142857,kg / s,0.004268479211824417,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,0.0,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.35,0.6,0.05 +decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.0763965456483523,m3 / s,5.0,bar,354.1205824522718,kJ / kg,90.0000000000029,C,0.0,C,0.0010492658329727916,m3 / kg,0.0,-,1117.673342516117,J / kgK,0.0432635709614127,0.9067364290385873,0.05 +centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015924088,m3 / s,5.0,bar,181.05101285505833,kJ / kg,45.00000000000182,C,0.0,C,0.0010182475569933,m3 / kg,0.0,-,611.6350715142552,J / kgK,0.044664142370314276,0.9449148049981068,0.010421052631578944 +centrifuge:out2_oil:in1,2.9417989417989414,kg / s,0.00333524269094514,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,0.0,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.01,0.0,0.99 +thickener:out1_liquidmerge:in3,12.482328042328044,kg / s,0.013748836912735755,m3 / s,5.0,bar,356.36268450896904,kJ / kg,104.99999999999955,C,0.0,C,0.0011014641552531653,m3 / kg,0.0,-,1096.5687083290422,J / kgK,0.25,0.6916699164109257,0.0583300835890741 +thickener:out2_vapourextract1:in1,57.385396825396825,kg / s,0.060096661478604874,m3 / s,5.0,bar,440.55426498767247,kJ / kg,104.99999999999773,C,-46.83107910307007,C,0.0010472465958797402,m3 / kg,-1.0,-,1363.039002179117,J / kgK,0.0,1.0,0.0 +liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153215,m3 / s,5.0,bar,281.9254277292515,kJ / kg,92.28684488833767,C,0.0,C,0.0011139604596594307,m3 / kg,0.0,-,880.7937574528975,J / kgK,0.3773512435050734,0.5700278468317559,0.05262090966317071 +drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262272,m3 / s,5.0,bar,184.93088408428227,kJ / kg,99.99999999999994,C,0.0,C,0.0012051217762996621,m3 / kg,0.0,-,559.4856087856979,J / kgK,0.7898560794044664,0.1,0.11014392059553348 +drier:out2_vapourextract2:in1,20.719247501469713,kg / s,34.63773627778022,m3 / s,1.0141799665682765,bar,2675.569884418101,kJ / kg,99.999999999137,C,0.0,C,1.6717661331727036,m3 / kg,1.0,-,7354.1191457120685,J / kgK,0.0,1.0,0.0 diff --git a/pyproject.toml b/pyproject.toml index d338ffb6a..558aa0138 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,10 @@ jinja2 = "^3.1.2" pyyaml = "^6.0" + +[tool.poetry.group.dev.dependencies] +ipykernel = "^6.26.0" + [build-system] requires = [ "poetry-core", diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 7f17b6b33..0bbb0133a 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -2,7 +2,6 @@ from tespy.components import HeatExchangerSimple, Merge, Separator, Splitter from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.fluid_properties import T_mix_ph @@ -16,8 +15,8 @@ class DiabaticSimpleHeatExchanger(HeatExchangerSimple): def component(): return 'diabatic simple heat exchanger' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["eta"] = dc_cp(min_val=1e-5, val=1, max_val=1) variables["Q_loss"] = dc_cp(max_val=0, val=0, is_result=True) variables["Q_total"] = dc_cp(is_result=True) @@ -101,17 +100,17 @@ class HeatExchangerSimpleDeltaP(HeatExchangerSimple): def component(): return 'diabatic simple heat exchanger' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=1, - ) + ) return variables - + def pr_func(self): r""" Equation for pressure drop. @@ -125,7 +124,7 @@ def pr_func(self): 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ - + return self.inl[0].p.val_SI - self.deltaP.val*1e5 - self.outl[0].p.val_SI def pr_deriv(self, increment_filter, k): @@ -146,7 +145,7 @@ def pr_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() self.deltaP.val = (self.inl[0].p.val_SI - self.outl[0].p.val_SI)/1e5 - + class HeatExchangerSimpleDeltaPLossFactor(HeatExchangerSimpleDeltaP): @@ -154,8 +153,8 @@ class HeatExchangerSimpleDeltaPLossFactor(HeatExchangerSimpleDeltaP): def component(): return 'diabatic simple heat exchanger' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["LF"] = dc_cp(min_val=0, val=0, max_val=1,is_result=True) variables["Q_loss"] = dc_cp(is_result=True) variables["Q_total"] = dc_cp(is_result=True) @@ -186,7 +185,7 @@ def energy_balance2_func(self): self.LF.val = -self.Q_loss/self.Q.val else: return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val - + def energy_balance2_deriv(self, increment_filter, k): r""" @@ -224,7 +223,7 @@ def calc_parameters(self): else: self.Q_total.val = self.Q.val-self.Q_loss.val self.LF.val = -self.Q_loss.val/self.Q.val - + class MergeWithPressureLoss(Merge): @@ -233,27 +232,40 @@ class MergeWithPressureLoss(Merge): def component(): return 'merge with pressure losses' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=1, - ) + ) return variables + def get_mandatory_constraints(self): + + + variable_fluids = set( + [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] + ) + num_fluid_eq = len(variable_fluids) + + if num_fluid_eq == 0: + num_fluid_eq = len(self.inl[0].fluid.val) + num_m_eq = 0 + else: + num_m_eq = 1 return { 'mass_flow_constraints': { 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, + 'num_eq': num_m_eq}, 'fluid_constraints': { 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, + 'num_eq': num_fluid_eq}, 'energy_balance_constraints': { 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, @@ -311,15 +323,15 @@ class SplitterWithPressureLoss(Splitter): def component(): return 'Splitter with pressure losses' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=self.num_out, - ) + ) return variables def get_mandatory_constraints(self): @@ -357,7 +369,7 @@ def pr_func(self): p_in = self.inl[0].p.val_SI for o in self.outl: residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] - return residual + return residual def pr_deriv(self, increment_filter, k): r""" @@ -376,9 +388,9 @@ def pr_deriv(self, increment_filter, k): j = 0 for c in self.outl: self.jacobian[k, 0, 1] = 1 - self.jacobian[k, j + 1, 1] = -1 + self.jacobian[k, j + 1, 1] = -1 j += 1 - k += 1 + k += 1 def calc_parameters(self): super().calc_parameters() @@ -407,8 +419,8 @@ def __init__(self, label, **kwargs): def component(): return 'separator with species flow splits' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["SFS"] = dc_cp_SFS( min_val=0, deriv=self.SFS_deriv, @@ -441,9 +453,11 @@ def SFS_func(self): fluid = self.SFS.split_fluid out_i = int(self.SFS.split_outlet[3:]) - 1 + inl = self.inl[0] + outl = self.outl[out_i] - res = self.inl[0].fluid.val[fluid] * self.inl[0].m.val_SI * self.SFS.val \ - - self.outl[out_i].fluid.val[fluid] * self.outl[out_i].m.val_SI + res = inl.fluid.val[fluid] * inl.m.val_SI * self.SFS.val \ + - outl.fluid.val[fluid] * outl.m.val_SI #print(res) return res @@ -461,9 +475,9 @@ def SFS_deriv(self, increment_filter, k): Position of equation in Jacobian matrix. """ - # j=0 + # j=0 # self.jacobian[k, j, 0] = self.inl[j].fluid.val[self.split_fluid] * self.TS.val - # self.jacobian[k, j, i + 3] = self.inl[j].m.val_SI * self.TS.val + # self.jacobian[k, j, i + 3] = self.inl[j].m.val_SI * self.TS.val # i = 0 # for fluid, x in self.outl[0].fluid.val.items(): @@ -482,13 +496,20 @@ def SFS_deriv(self, increment_filter, k): out_i = int(self.SFS.split_outlet[3:]) - 1 i = fluid_index - j = 0 - self.jacobian[k, j, 0] = self.inl[0].fluid.val[fluid] * self.SFS.val - self.jacobian[k, j, i + 3] = self.inl[0].m.val_SI * self.SFS.val - j = 1 + out_i - self.jacobian[k, j, 0] = -self.outl[out_i].fluid.val[fluid] - self.jacobian[k, j, i + 3] = -self.outl[out_i].m.val_SI - + j = 0 + inl = self.inl[0] + outl = self.outl[out_i] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = inl.fluid.val[fluid] * self.SFS.val + + if fluid in inl.fluid.is_var: + self.jacobian[k, inl.fluid.J_col[fluid]] = inl.m.val_SI * self.SFS.val + + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -outl.fluid.val[fluid] + if fluid in outl.fluid.is_var: + self.jacobian[k, outl.fluid.J_col[fluid]] = -outl.m.val_SI + #print(self.jacobian) #print(self.jacobian[k,:,:]) @@ -503,19 +524,26 @@ class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplits): def component(): return 'separator with species flow splits and dT on outlets' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["deltaT"] = dc_cp( deriv=self.energy_balance_deriv, # same as before func=self.energy_balance_deltaT_func, latex=self.pr_func_doc, num_eq=self.num_out ) - variables["Q"] = dc_cp(is_result=True) - #variables["Qout"] = dc_cpa() + variables["Q"] = dc_cp(is_result=True) + #variables["Qout"] = dc_cpa() return variables def get_mandatory_constraints(self): + self.variable_fluids = set( + [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] + ) + num_fluid_eq = len(self.variable_fluids) + if num_fluid_eq == 0: + num_fluid_eq = 1 + self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] return { 'mass_flow_constraints': { 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, @@ -524,7 +552,7 @@ def get_mandatory_constraints(self): 'fluid_constraints': { 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, + 'num_eq': num_fluid_eq}, # 'energy_balance_constraints': { # 'func': self.energy_balance_func, # 'deriv': self.energy_balance_deriv, @@ -563,7 +591,7 @@ def energy_balance_deltaT_func(self): def calc_parameters(self): super().calc_parameters() self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) - + Tmin = min([i.T.val_SI for i in self.outl]) Tmax = max([i.T.val_SI for i in self.outl]) if abs(self.inl[0].T.val_SI - Tmin) >= abs(self.inl[0].T.val_SI - Tmax): @@ -578,15 +606,15 @@ class SeparatorWithSpeciesSplitsAndPr(SeparatorWithSpeciesSplits): def component(): return 'separator with species flow splits and dT and Pr on outlets' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=self.num_out, - ) + ) return variables def pr_func(self): @@ -623,7 +651,7 @@ def pr_deriv(self, increment_filter, k): j = 0 for c in self.outl: self.jacobian[k, 0, 1] = 1 - self.jacobian[k, j + 1, 1] = -1 + self.jacobian[k, j + 1, 1] = -1 j += 1 k += 1 @@ -668,11 +696,18 @@ class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsAndDelt def component(): return 'separator with species flow splits and dT and Pr on outlets' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables def get_mandatory_constraints(self): + self.variable_fluids = set( + [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] + ) + num_fluid_eq = len(self.variable_fluids) + if num_fluid_eq == 0: + num_fluid_eq = 1 + self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] return { 'mass_flow_constraints': { 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, @@ -681,7 +716,7 @@ def get_mandatory_constraints(self): 'fluid_constraints': { 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, + 'num_eq': num_fluid_eq}, # 'energy_balance_constraints': { # 'func': self.energy_balance_func, # 'deriv': self.energy_balance_deriv, @@ -702,8 +737,8 @@ class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsA def component(): return 'separator with species flow splits and dT and Pr on outlets + Bus connection on Q' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables def bus_func(self, bus): @@ -762,8 +797,8 @@ def bus_deriv(self, bus): Matrix of partial derivatives. """ # for o in self.outl: -# self.Qout.val += [o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI)] -# return np.sum(self.Qout.val) +# self.Qout.val += [o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI)] +# return np.sum(self.Qout.val) deriv = np.zeros((1, len(self.outl)+1, self.num_nw_vars)) f = self.calc_bus_value @@ -784,8 +819,8 @@ class SplitWithFlowSplitter(Splitter): def component(): return 'splitter with flow split ratios' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["FS"] = dc_cp_FS( min_val=0, deriv=self.FS_deriv, @@ -810,7 +845,7 @@ def FS_func(self): """ out_i = int(self.FS.split_outlet[3:]) - 1 - res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI + res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI #print(res) return res @@ -830,11 +865,14 @@ def FS_deriv(self, increment_filter, k): out_i = int(self.FS.split_outlet[3:]) - 1 - j = 0 - self.jacobian[k, j, 0] = self.FS.val - j = 1 + out_i - self.jacobian[k, j, 0] = -1 - + inl = self.inl[0] + outl = self.outl[out_i] + j = 0 + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.FS.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + #print(self.jacobian) #print(self.jacobian[k,:,:]) @@ -843,7 +881,7 @@ def FS_deriv(self, increment_filter, k): class dc_cp_SFS(dc_cp): """ - Data container for simple properties. + Data container for simple properties. + SFS_fluid + SFS_outlet """ @@ -855,7 +893,7 @@ def attr(): class dc_cp_FS(dc_cp): """ - Data container for component properties. + Data container for component properties. + FS_outlet """ @staticmethod @@ -872,8 +910,8 @@ class MassFactorVCC(Splitter): def component(): return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["COP"] = dc_cp( min_val=0, deriv=self.COP_deriv, @@ -885,14 +923,6 @@ def get_variables(self): def get_mandatory_constraints(self): return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, 'energy_balance_constraints': { 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, @@ -934,8 +964,12 @@ def COP_deriv(self, increment_filter, k): k : int Position of equation in Jacobian matrix. """ - self.jacobian[k , 0, 0] = self.COP.val - self.jacobian[k , self.num_i, 0] = -1 + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.COP.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 def calc_parameters(self): super().calc_parameters() @@ -949,15 +983,15 @@ class MassFactorVCCWithPressureLoss(MassFactorVCC): def component(): return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["pr"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=1 - ) + ) return variables def pr_func(self): @@ -1016,7 +1050,7 @@ def calc_parameters(self): f"The pressure at inlet {i + 1} is lower than the pressure " f"at the outlet of component {self.label}." ) - logging.warning(msg) + logging.warning(msg) @@ -1027,8 +1061,8 @@ class MassFactorLossModel(Splitter): def component(): return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["Loss"] = dc_cp( min_val=0, deriv=self.Loss_deriv, @@ -1081,15 +1115,15 @@ class MassFactorLossModelWithPressureLoss(MassFactorLossModel): def component(): return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() variables["pr"] = dc_cp( min_val=0, deriv=self.pr_deriv, func=self.pr_func, latex=self.pr_func_doc, num_eq=1 - ) + ) return variables def pr_func(self): @@ -1148,7 +1182,7 @@ def calc_parameters(self): f"The pressure at inlet {i + 1} is lower than the pressure " f"at the outlet of component {self.label}." ) - logging.warning(msg) + logging.warning(msg) @@ -1161,8 +1195,8 @@ class MergeEnergySupply(Merge): def component(): return 'merge without pressure/energy constraints' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables def get_mandatory_constraints(self): @@ -1183,8 +1217,8 @@ class SplitterEnergySupply(Splitter): def component(): return 'Splitter without pressure/energy constraints' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables def get_mandatory_constraints(self): @@ -1207,22 +1241,10 @@ class MassFactorVCCEnergySupply(MassFactorVCC): def component(): return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances, without pressure/enthalpy constraints)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - } - class MassFactorLossModelEnergySupply(MassFactorLossModel): @@ -1230,8 +1252,8 @@ class MassFactorLossModelEnergySupply(MassFactorLossModel): def component(): return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances, without pressure/enthalpy constraints)' - def get_variables(self): - variables = super().get_variables() + def get_parameters(self): + variables = super().get_parameters() return variables def get_mandatory_constraints(self): From 4a92f6ef69f25247a9275ec5502c03b07d19524d Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:35:59 +0100 Subject: [PATCH 006/105] testing heat exchangers (cherry picked from commit a22f2679ef70adf87e12bca9687e4be0100bfbab) --- intermediateFoodTests/Ex1.py | 6 ++-- intermediateFoodTests/Ex1tespy070.csv | 6 ++-- intermediateFoodTests/diff.ipynb | 48 +++++++++++++-------------- 3 files changed, 31 insertions(+), 29 deletions(-) diff --git a/intermediateFoodTests/Ex1.py b/intermediateFoodTests/Ex1.py index 189054665..15dfd0789 100644 --- a/intermediateFoodTests/Ex1.py +++ b/intermediateFoodTests/Ex1.py @@ -18,7 +18,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SimpleHeatExchanger import logging #logging.basicConfig(level=logging.DEBUG) @@ -45,7 +45,9 @@ # set conditions around boiler # fluid_back_ends={'Water': "INCOMP", "PHE": "INCOMP", "S800": "INCOMP"} c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=100, h=h0, p=p0, mixing_rule="incompressible") -c2.set_attr(h=h0,p=p0) +#c2.set_attr(h=h0,p=p0) +c2.set_attr(h=h0) +boiler.set_attr(pr=1) # solve and print results network.solve('design') diff --git a/intermediateFoodTests/Ex1tespy070.csv b/intermediateFoodTests/Ex1tespy070.csv index f5ff45442..91593cccb 100644 --- a/intermediateFoodTests/Ex1tespy070.csv +++ b/intermediateFoodTests/Ex1tespy070.csv @@ -1,3 +1,3 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,PHE,S800 -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 -boiler:out1_sink:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.15,0.05 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,S800,PHE +source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.05,0.15 +boiler:out1_sink:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.05,0.15 diff --git a/intermediateFoodTests/diff.ipynb b/intermediateFoodTests/diff.ipynb index 0a127bf5f..e003dabae 100644 --- a/intermediateFoodTests/diff.ipynb +++ b/intermediateFoodTests/diff.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 27, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -11,13 +11,13 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "m 0.000000e+00\n", + "m 2.220446e-16\n", "p 0.000000e+00\n", "h 6.494361e-12\n", "T 2.223999e-12\n", @@ -32,7 +32,7 @@ "dtype: float64" ] }, - "execution_count": 28, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -47,7 +47,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -68,7 +68,7 @@ "dtype: float64" ] }, - "execution_count": 29, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -83,28 +83,28 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "m 7.105427e-15\n", + "m 1.065814e-14\n", "p 0.000000e+00\n", "h 1.131468e-10\n", "T 1.203944e-10\n", "v 8.985868e-16\n", "vol 9.996344e-17\n", - "s 1.285571e-09\n", + "s 1.285741e-09\n", "x 0.000000e+00\n", "Td_bp 0.000000e+00\n", - "PHE 8.326673e-17\n", - "S800 2.220446e-16\n", - "Water 1.110223e-16\n", + "PHE 2.775558e-16\n", + "S800 3.330669e-16\n", + "Water 6.661338e-16\n", "dtype: float64" ] }, - "execution_count": 30, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -119,28 +119,28 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "m 7.105427e-15\n", + "m 1.065814e-14\n", "p 0.000000e+00\n", "h 1.131468e-10\n", "T 1.203944e-10\n", "v 8.985868e-16\n", "vol 9.996344e-17\n", - "s 1.285571e-09\n", + "s 1.285741e-09\n", "x 0.000000e+00\n", "Td_bp 0.000000e+00\n", - "PHE 8.326673e-17\n", - "S800 2.220446e-16\n", - "Water 1.110223e-16\n", + "PHE 2.775558e-16\n", + "S800 3.330669e-16\n", + "Water 6.661338e-16\n", "dtype: float64" ] }, - "execution_count": 31, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -155,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -170,13 +170,13 @@ "s 3.728383e-08\n", "x 0.000000e+00\n", "Td_bp 0.000000e+00\n", - "Water 5.551115e-16\n", + "Water 6.661338e-16\n", "PHE 2.220446e-16\n", "S800 1.040834e-16\n", "dtype: float64" ] }, - "execution_count": 32, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -206,7 +206,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.15" + "version": "3.10.11" }, "orig_nbformat": 4 }, From f2cbc5704b8f314677f70079ff4508f3dba926f1 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:46:37 +0100 Subject: [PATCH 007/105] solving P > Psat for incompressible "water" :: I believe there is no way to access TminPsat internally (cherry picked from commit 1a64bd6d456644ad8f442264b952711cc5a61a14) --- src/tespy/tools/fluid_properties/wrappers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 0f65b03aa..22fa90c56 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -149,6 +149,8 @@ def h_ps(self, p, s): def h_pT(self, p, T): if self.back_end == "INCOMP": + if self.fluid == "Water": + T = min(T,CP.CoolProp.PropsSI("T","P",p,"Q",0,"HEOS::"+self.fluid)) if T == (self._T_max + self._T_min) / 2: T += ERR self.AS.update(CP.PT_INPUTS, p, T) From b6867c79044fc521169f7374b1afa97bf4871d25 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:47:28 +0100 Subject: [PATCH 008/105] updating SimpleHeatExchangerDeltaP with new jacobian structure (cherry picked from commit cc22938969cb327d8bdcc885346d973cb36fcab1) --- .../newComponentsTests/heatex_alone_deltaP.py | 25 ++++++----- src/tespy/components/newcomponents.py | 43 +++++++++++++------ 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py index 01e6b7731..a8bdb96d8 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py @@ -3,7 +3,7 @@ import logging -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator from tespy.tools import ComponentProperties from tespy.connections import Connection from tespy.networks import Network @@ -12,22 +12,24 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import HeatExchangerSimpleDeltaP, HeatExchangerSimpleLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits - +from tespy.components.newcomponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +logging.basicConfig(level=logging.DEBUG) # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") +#fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +#nw = Network(p_unit="bar", T_unit="C", iterinfo=True) +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + so = Source("Source") # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system # boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -#he = HeatExchangerSimpleLossFactor("Heater") -he = HeatExchangerSimpleDeltaP("Heater") +#he = SimpleHeatExchangerLossFactor("Heater") +he = SimpleHeatExchangerDeltaP("Heater") si = Sink("Sink") @@ -38,11 +40,14 @@ nw.add_conns(c1, c2) # set some generic data for starting values -c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) -c2.set_attr(T=50) +c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=1, T=30, p=1, mixing_rule="incompressible") +#c1.set_attr(m=1, p=2.2, T=30, fluid={"INCOMP::FoodWater": 0.9, "INCOMP::FoodProtein": 0.1}, mixing_rule="incompressible") +c2.set_attr(T=95) #,p=1) # set pressure ratios of heater and merge -he.set_attr(deltaP=1) +he.set_attr(deltaP=0.1) +#he.set_attr(pr=1.1) + #he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor #he.set_attr(Q_total=86371.13607253956) # MRK so eta is (1-hlf) heat loss factor diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 0bbb0133a..ff2c3e324 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -1,6 +1,6 @@ import logging -from tespy.components import HeatExchangerSimple, Merge, Separator, Splitter +from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.fluid_properties import T_mix_ph @@ -9,7 +9,7 @@ import numpy as np -class DiabaticSimpleHeatExchanger(HeatExchangerSimple): +class DiabaticSimpleHeatExchanger(SimpleHeatExchanger): @staticmethod def component(): @@ -94,24 +94,24 @@ def calc_parameters(self): self.Q_total.val = self.Q.val - self.Q_loss.val -class HeatExchangerSimpleDeltaP(HeatExchangerSimple): +class SimpleHeatExchangerDeltaP(SimpleHeatExchanger): @staticmethod def component(): - return 'diabatic simple heat exchanger' + return 'simple heat exchanger with pressure drop' def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=1, ) return variables - def pr_func(self): + def deltaP_func(self): r""" Equation for pressure drop. @@ -127,9 +127,9 @@ def pr_func(self): return self.inl[0].p.val_SI - self.deltaP.val*1e5 - self.outl[0].p.val_SI - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k, pr='', inconn=0, outconn=0): r""" - Calculate the partial derivatives for combustion pressure ratio. + Calculate the partial derivatives for pressure drop. Parameters ---------- @@ -138,16 +138,35 @@ def pr_deriv(self, increment_filter, k): k : int Position of equation in Jacobian matrix. + + pr : str + Component parameter to evaluate the pr_func on, e.g. + :code:`pr1`. + + inconn : int + Connection index of inlet. + + outconn : int + Connection index of outlet. """ - self.jacobian[k, 0, 1] = 1 #self.pr.val - self.jacobian[k, self.num_i, 1] = -1 + + deltaP = self.get_attr("deltaP") + i = self.inl[inconn] + o = self.outl[inconn] + if i.p.is_var: + self.jacobian[k, i.p.J_col] = 1 + if o.p.is_var: + self.jacobian[k, o.p.J_col] = -1 + if deltaP.is_var: + self.jacobian[k, self.pr.J_col] = 1 + def calc_parameters(self): super().calc_parameters() self.deltaP.val = (self.inl[0].p.val_SI - self.outl[0].p.val_SI)/1e5 -class HeatExchangerSimpleDeltaPLossFactor(HeatExchangerSimpleDeltaP): +class SimpleHeatExchangerDeltaPLossFactor(SimpleHeatExchangerDeltaP): @staticmethod def component(): From 022d5f3b8baa1f13d0eb4cbff6fad0a0e9938cf4 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 20:56:28 +0100 Subject: [PATCH 009/105] heat exchanger with loss updated with new jacobian structure (cherry picked from commit 1a766a17d2dcd366ba0398c8edd981143fe32d4d) --- .../newComponentsTests/heatex_alone_deltaP.py | 9 ++- .../heatex_alone_lossFactor.py | 22 +++--- src/tespy/components/newcomponents.py | 75 +++++++------------ 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py index a8bdb96d8..2da6fb661 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py @@ -28,8 +28,8 @@ # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system # boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -#he = SimpleHeatExchangerLossFactor("Heater") he = SimpleHeatExchangerDeltaP("Heater") +#he = SimpleHeatExchangerDeltaPLossFactor("Heater") si = Sink("Sink") @@ -48,9 +48,14 @@ he.set_attr(deltaP=0.1) #he.set_attr(pr=1.1) +#he.set_attr(Tamb=10) +#he.set_attr(L=10) +#he.set_attr(D=0.3) + +#he.set_attr(Q=74000) #he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor -#he.set_attr(Q_total=86371.13607253956) # MRK so eta is (1-hlf) heat loss factor +#he.set_attr(Q_total=8.16e4) # MRK so eta is (1-hlf) heat loss factor #he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor nw.solve("design") diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py index 5e72ff762..506a37b9a 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py @@ -3,7 +3,7 @@ import logging -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator from tespy.tools import ComponentProperties from tespy.connections import Connection from tespy.networks import Network @@ -12,8 +12,9 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import HeatExchangerSimpleDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +logging.basicConfig(level=logging.DEBUG) # %% @@ -26,8 +27,8 @@ # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system # boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -he = HeatExchangerSimpleDeltaPLossFactor("Heater") -#he = HeatExchangerSimpleDeltaP("Heater") +he = SimpleHeatExchangerDeltaPLossFactor("Heater") +#he = SimpleHeatExchangerDeltaP("Heater") si = Sink("Sink") @@ -38,14 +39,17 @@ nw.add_conns(c1, c2) # set some generic data for starting values -c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) -c2.set_attr(T=50) +#c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") +c1.set_attr(m=1, p=2.2, T=30) + +#c2.set_attr(T=50) # set pressure ratios of heater and merge he.set_attr(deltaP=1) -#he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor -he.set_attr(Q_total=86371.13607253956) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(Q_total=8.16e+04) # MRK so eta is (1-hlf) heat loss factor #he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor nw.solve("design") @@ -58,4 +62,4 @@ print(he.LF.val) print(he.Q_total.val) -print(he.Q_loss.val) +#print(he.Q_loss.val) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index ff2c3e324..3400ab4ea 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -174,75 +174,52 @@ def component(): def get_parameters(self): variables = super().get_parameters() - variables["LF"] = dc_cp(min_val=0, val=0, max_val=1,is_result=True) - variables["Q_loss"] = dc_cp(is_result=True) - variables["Q_total"] = dc_cp(is_result=True) + variables["LF"] = dc_cp(min_val=0, val=0, max_val=1, is_result=True) + variables["Q_total"] = dc_cp(is_result=True) variables["energy_group"] = dc_gcp( - elements=['Q_total', 'LF', 'Q_loss'], - num_eq=1, - latex=self.energy_balance_func_doc, - func=self.energy_balance2_func, deriv=self.energy_balance2_deriv - ) - + elements=['LF', 'Q_total'], + func=self.Q_total_func, + deriv=self.Q_total_deriv, + latex=self.energy_balance_func_doc, num_eq=1) return variables - def energy_balance2_func(self): + def Q_total_func(self): r""" - Equation for pressure drop calculation. + Equation for total heat flow rate - Returns - ------- - residual : float - Residual value of equation: - - .. math:: - - 0 =\dot{m}_{in}\cdot\left( h_{out}-h_{in}\right) -\dot{Q} """ - # self.Q_loss.val is negative and Q_total is positive (and vice versa) - if self.Q_loss.is_var: - self.LF.val = -self.Q_loss/self.Q.val - else: - return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val + # self.Q_loss.val is negative and Q_total is positive (and vice versa) + return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val - def energy_balance2_deriv(self, increment_filter, k): + def Q_total_deriv(self, increment_filter, k): r""" - Calculate partial derivatives of energy balance. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. + Calculate partial derivatives of Q_total - k : int - Position of derivatives in Jacobian matrix (k-th equation). """ - if self.Q_loss.is_var: - self.LF.val = -self.Q_loss/self.Q.val - self.jacobian[k, 0, 0] = (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI*(1+self.LF.val) - self.jacobian[k, 1, 2] = self.inl[0].m.val_SI*(1+self.LF.val) + + i = self.inl[0] + o = self.outl[0] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) + if i.h.is_var: + self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) + if o.h.is_var: + self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) # custom variable Q if self.Q_total.is_var: - self.jacobian[k, 2 + self.Q.var_pos, 0] = -1 - + self.jacobian[k, self.Q.J_col] = -1 if self.LF.is_var: - self.jacobian[k, 2 + self.LF.var_pos, 0] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) + self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) def calc_parameters(self): super().calc_parameters() if self.Q_total.is_set: - self.Q_loss.val = self.Q.val-self.Q_total.val - self.LF.val = -self.Q_loss.val / self.Q.val - elif self.LF.is_set: + self.LF.val = (self.Q_total.val-self.Q.val) / self.Q.val + if self.LF.is_set: self.Q_total.val = self.Q.val * (1+self.LF.val) - self.Q_loss.val = self.Q.val-self.Q_total.val - else: - self.Q_total.val = self.Q.val-self.Q_loss.val - self.LF.val = -self.Q_loss.val/self.Q.val - + class MergeWithPressureLoss(Merge): From e24e4a72a043c98d76384fb1055289c9d09db89a Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 21:42:47 +0100 Subject: [PATCH 010/105] Finally happy with all combinations of LF, Q_loss an Q_total working (cherry picked from commit d97dcd7e5515cf050c8317622bec2403b448f97a) --- .../heatex_alone_lossFactor.py | 4 +-- src/tespy/components/newcomponents.py | 36 +++++++++++++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py index 506a37b9a..77f23ff07 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py @@ -49,8 +49,8 @@ he.set_attr(deltaP=1) he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor -he.set_attr(Q_total=8.16e+04) # MRK so eta is (1-hlf) heat loss factor -#he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor +#he.set_attr(Q_total=8.16e+04) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(Q_loss=-7.42e+03) # MRK so eta is (1-hlf) heat loss factor nw.solve("design") nw.print_results() diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 3400ab4ea..b7893e778 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -175,12 +175,23 @@ def component(): def get_parameters(self): variables = super().get_parameters() variables["LF"] = dc_cp(min_val=0, val=0, max_val=1, is_result=True) + variables["Q_loss"] = dc_cp(is_result=True) variables["Q_total"] = dc_cp(is_result=True) - variables["energy_group"] = dc_gcp( + variables["energy_group1"] = dc_gcp( elements=['LF', 'Q_total'], func=self.Q_total_func, deriv=self.Q_total_deriv, latex=self.energy_balance_func_doc, num_eq=1) + variables["energy_group2"] = dc_gcp( + elements=['Q_loss', 'Q_total'], + func=self.Q_total_func, + deriv=self.Q_total_deriv, + latex=self.energy_balance_func_doc, num_eq=1) + variables["energy_group3"] = dc_gcp( + elements=['Q_loss', 'LF'], + func=self.Q_total_func, + deriv=self.Q_total_deriv, + latex=self.energy_balance_func_doc, num_eq=1) return variables def Q_total_func(self): @@ -188,10 +199,17 @@ def Q_total_func(self): Equation for total heat flow rate """ - # self.Q_loss.val is negative and Q_total is positive (and vice versa) + + if self.energy_group2.is_set: + self.LF.val = -self.Q_loss.val/(self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)) + if self.energy_group3.is_set: + self.Q_total.val = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - self.Q_loss.val + return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val + + def Q_total_deriv(self, increment_filter, k): r""" Calculate partial derivatives of Q_total @@ -206,20 +224,24 @@ def Q_total_deriv(self, increment_filter, k): self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) if o.h.is_var: self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) - # custom variable Q if self.Q_total.is_var: self.jacobian[k, self.Q.J_col] = -1 - if self.LF.is_var: + if self.LF.is_var or self.Q_loss.is_var: # if Q_loss solve LF equation self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) def calc_parameters(self): super().calc_parameters() + # repeat calculations to ensure variables are assigned if self.Q_total.is_set: - self.LF.val = (self.Q_total.val-self.Q.val) / self.Q.val - if self.LF.is_set: + self.Q_loss.val = self.Q.val-self.Q_total.val + self.LF.val = -self.Q_loss.val / self.Q.val + elif self.LF.is_set: self.Q_total.val = self.Q.val * (1+self.LF.val) - + self.Q_loss.val = self.Q.val-self.Q_total.val + else: + self.Q_total.val = self.Q.val-self.Q_loss.val + self.LF.val = -self.Q_loss.val/self.Q.val class MergeWithPressureLoss(Merge): From 54895981cfd4f2ab2a03ba36ee6bfbb12edf52dd Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 11:56:03 +0100 Subject: [PATCH 011/105] solving P > Psat more elegantly :: INCOMP pressure is now limited by Psat - removing use of PropsSI (cherry picked from commit 4d2458ee5068bcfc25b94a2a6474f192f3fb0a62) --- src/tespy/tools/fluid_properties/wrappers.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 22fa90c56..be6c01b55 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -147,12 +147,17 @@ def h_ps(self, p, s): self.AS.update(CP.PSmass_INPUTS, p, s) return self.AS.hmass() + def _ensure_incomp_is_liquid(self,p,T): + self.AS.update(CP.QT_INPUTS, 0, T) + psat = self.AS.p() # pressure must always be greater than saturation for incompressibles + p = max(p,psat*(1+ERR)) + if T == (self._T_max + self._T_min) / 2: + T += ERR + return p,T + def h_pT(self, p, T): if self.back_end == "INCOMP": - if self.fluid == "Water": - T = min(T,CP.CoolProp.PropsSI("T","P",p,"Q",0,"HEOS::"+self.fluid)) - if T == (self._T_max + self._T_min) / 2: - T += ERR + p,T = self._ensure_incomp_is_liquid(p,T) self.AS.update(CP.PT_INPUTS, p, T) return self.AS.hmass() @@ -186,6 +191,8 @@ def d_ph(self, p, h): return self.AS.rhomass() def d_pT(self, p, T): + if self.back_end == "INCOMP": + p,T = self._ensure_incomp_is_liquid(p,T) self.AS.update(CP.PT_INPUTS, p, T) return self.AS.rhomass() @@ -198,6 +205,8 @@ def viscosity_ph(self, p, h): return self.AS.viscosity() def viscosity_pT(self, p, T): + if self.back_end == "INCOMP": + p,T = self._ensure_incomp_is_liquid(p,T) self.AS.update(CP.PT_INPUTS, p, T) return self.AS.viscosity() @@ -206,6 +215,8 @@ def s_ph(self, p, h): return self.AS.smass() def s_pT(self, p, T): + if self.back_end == "INCOMP": + p,T = self._ensure_incomp_is_liquid(p,T) self.AS.update(CP.PT_INPUTS, p, T) return self.AS.smass() From 54196b84b5b97cf9f02f340e3aeb360afd8987b6 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 12:01:30 +0100 Subject: [PATCH 012/105] updating some errors in jacobian derrivatives (cherry picked from commit d615ba64f4b5032cc63f11246884f3dda2cbd40b) --- src/tespy/components/newcomponents.py | 64 ++++++++++++--------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index b7893e778..7c1a3c4e1 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -63,24 +63,30 @@ def energy_balance2_deriv(self, increment_filter, k): k : int Position of derivatives in Jacobian matrix (k-th equation). """ - self.jacobian[k, 0, 0] = ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI) - self.jacobian[k, 0, 2] = -self.inl[0].m.val_SI - self.jacobian[k, 1, 2] = self.inl[0].m.val_SI + + + i = self.inl[0] + o = self.outl[0] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI) + if i.h.is_var: + self.jacobian[k, i.h.J_col] = -i.m.val_SI + if o.h.is_var: + self.jacobian[k, o.h.J_col] = i.m.val_SI # custom variable Q if self.Q_total.is_var: if self.Q_total.val < 0: - self.jacobian[k, 2 + self.Q.var_pos, 0] = -1 + self.jacobian[k, self.Q_total.J_col] = -1 else: - self.jacobian[k, 2 + self.Q.var_pos, 0] = -self.eta.val + self.jacobian[k, self.Q_total.J_col] = -self.eta.val if self.eta.is_var: if self.Q_total.val < 0: - self.jacobian[k, 2 + self.eta.var_pos, 0] = self.inl[0].m.val_SI * ( + self.jacobian[k, self.eta.J_col] = self.inl[0].m.val_SI * ( self.outl[0].h.val_SI - self.inl[0].h.val_SI ) else: - self.jacobian[k, 2 + self.eta.var_pos, 0] = -self.Q_total.val + self.jacobian[k, self.eta.J_col] = -self.Q_total.val def calc_parameters(self): super().calc_parameters() @@ -204,11 +210,10 @@ def Q_total_func(self): if self.energy_group2.is_set: self.LF.val = -self.Q_loss.val/(self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)) if self.energy_group3.is_set: - self.Q_total.val = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - self.Q_loss.val + self.Q_total.val = -self.Q_loss.val*(1+self.LF.val)/self.LF.val return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val - - + def Q_total_deriv(self, increment_filter, k): r""" @@ -225,9 +230,11 @@ def Q_total_deriv(self, increment_filter, k): if o.h.is_var: self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) if self.Q_total.is_var: - self.jacobian[k, self.Q.J_col] = -1 - if self.LF.is_var or self.Q_loss.is_var: # if Q_loss solve LF equation + self.jacobian[k, self.Q_total.J_col] = -1 + if self.LF.is_var: self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) + if self.Q_loss.is_var: + self.jacobian[k, self.Q_loss.J_col] = -(1+self.LF.val)/self.LF.val def calc_parameters(self): super().calc_parameters() @@ -254,8 +261,8 @@ def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=1, ) @@ -291,39 +298,26 @@ def get_mandatory_constraints(self): 'num_eq': 1} } - def pr_func(self): + def deltaP_func(self): r""" Equation for pressure drop. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ p_in_min = min([i.p.val_SI for i in self.inl]) return p_in_min - self.deltaP.val*1e5 - self.outl[0].p.val_SI - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. + Calculate the partial derivatives for pressure drop. - k : int - Position of equation in Jacobian matrix. """ p_in = [i.p.val_SI for i in self.inl] p_min_index = p_in.index(min(p_in)) - self.jacobian[k, p_min_index, 1] = 1 #self.pr.val - self.jacobian[k, self.num_i, 1] = -1 + if self.inl[p_min_index].p.is_var: + self.jacobian[k, self.inl[p_min_index].p.J_col] = 1 #self.pr.val + if self.outl[0].p.is_var: + self.jacobian[k, self.outl[0].p.J_col] = -1 def calc_parameters(self): super().calc_parameters() From 8017ffad1d91798be3aace99b9fd8248c4060830 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 12:04:21 +0100 Subject: [PATCH 013/105] updating heat exchanger and merge tests (cherry picked from commit 1f0a2b31b2008c04e58b69c36af2929c5a0463f4) --- .../newComponentsTests/heatex+merge.py | 46 +++++-- .../newComponentsTests/heatex+merge_mrk.py | 112 ------------------ .../newComponentsTests/heatex_alone.py | 13 +- .../newComponentsTests/heatex_alone_deltaP.py | 15 ++- .../heatex_alone_lossFactor.py | 31 ++++- .../newComponentsTests/merge_mrk.py | 23 ++-- 6 files changed, 97 insertions(+), 143 deletions(-) delete mode 100644 intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge.py b/intermediateFoodTests/newComponentsTests/heatex+merge.py index b08af68ae..3d0e20fa0 100644 --- a/intermediateFoodTests/newComponentsTests/heatex+merge.py +++ b/intermediateFoodTests/newComponentsTests/heatex+merge.py @@ -1,6 +1,5 @@ import logging - from tespy.components import HeatExchangerSimple, Source, Sink, Merge from tespy.connections import Connection from tespy.networks import Network @@ -11,6 +10,8 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +logging.basicConfig(level=logging.DEBUG) + # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? fluids = ["INCOMP::Water", "INCOMP::T66"] @@ -34,45 +35,70 @@ nw.add_conns(c1, c2, c3, c4) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"Water": 0.9, "T66": 0.1}) +c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) c2.set_attr(h=2.2e5) # mix with pure water -c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"Water": 1, "T66": 0}) +c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) # set pressure ratios of heater and merge -he.set_attr(pr=1) -me.set_attr(pr=0.9) +he.set_attr(pr=0.9) +me.set_attr(deltaP=0.15) +#c2.set_attr(p=2.2) +#c4.set_attr(p=2.2) nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() # use temperature to make it relatable c1.set_attr(h=None, T=30) c2.set_attr(h=None, T=50) nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() # add some heat c2.set_attr(T=None) -# efficiency is used for postprocessing here +# # efficiency is used for postprocessing here he.set_attr(Q=1e5, eta=0.9) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + +he.set_attr(Q=1e5, Q_total=1.1e5, eta=None) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +he.set_attr(Q=1e5, Q_total=1.5e5) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() c2.set_attr(T=50) # impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) # In this case, efficiency decreases -he.set_attr(Q=None, Q_total=1.5e5, eta="var") +he.set_attr(Q=None, Q_total=1.1e5, eta=None) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() # with set efficiency, temperature cannot be set anymore c2.set_attr(T=None) -he.set_attr(Q_total=1.5e5, eta=.5) +he.set_attr(Q_total=1.1e5, eta=.5) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() # now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C @@ -80,9 +106,13 @@ he.set_attr(Q_total=None, eta=None) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() he.set_attr(Q_total=-.6e5, eta="var") nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py b/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py deleted file mode 100644 index 5f36bd050..000000000 --- a/intermediateFoodTests/newComponentsTests/heatex+merge_mrk.py +++ /dev/null @@ -1,112 +0,0 @@ -# %% -import logging - - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits - - - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] - - -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -so = Source("Source") -so2 = Source("Source2") - -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -he = DiabaticSimpleHeatExchanger("Heater") -me = MergeWithPressureLoss("Merge") -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", me, "in1", label="2") -c3 = Connection(so2, "out1", me, "in2", label="3") -c4 = Connection(me, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2, c3, c4) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"Water": 0.9, "T66": 0.1}) -c2.set_attr(h=2.2e5) -# mix with pure water -c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"Water": 1, "T66": 0}) - -# set pressure ratios of heater and merge -he.set_attr(pr=1) -me.set_attr(pr=0.9) - -nw.solve("design") - -print(nw.results['Connection']) -he.Q.val -he.Q_loss.val -he.Q_total.val - -# %% -# use temperature to make it relatable -c1.set_attr(h=None, T=30) -c2.set_attr(h=None, T=50) - -nw.solve("design") - -# %% -# add some heat -c2.set_attr(T=None) -# efficiency is used for postprocessing here -he.set_attr(Q=1e5, eta=0.9) # MRK so eta is (1-hlf) heat loss factor - -nw.solve("design") -nw.print_results() - -print(nw.results['Connection']) - - -# %% - -c2.set_attr(T=50) - -# impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) -# In this case, efficiency decreases -he.set_attr(Q=None, Q_total=1.5e5, eta='var') -nw.solve("design") -nw.print_results() - -print(nw.results['Connection']) - - -# %% -# with set efficiency, temperature cannot be set anymore -c2.set_attr(T=None) -he.set_attr(Q_total=1.5e5, eta=.5) - -nw.solve("design") -nw.print_results() - - -# %% -# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C -c2.set_attr(T=5) -he.set_attr(Q_total=None, eta=None) - -#nw.solve("design") -#nw.print_results() - -he.set_attr(Q_total=-.6e5, eta="var") - -nw.solve("design") -nw.print_results() - -# %% diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone.py b/intermediateFoodTests/newComponentsTests/heatex_alone.py index 83c6a16ff..ade3218ee 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone.py @@ -14,13 +14,12 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits - +logging.basicConfig(level=logging.DEBUG) # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) so = Source("Source") # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system @@ -34,16 +33,20 @@ nw.add_conns(c1, c2) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}) c2.set_attr(T=50) # set pressure ratios of heater and merge he.set_attr(pr=1) -he.set_attr(eta=1) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(eta=0.9) # MRK so eta is (1-hlf) heat loss factor nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() +print(nw.results['Connection']) + # print(nw.results['Connection']) # he.Q.val diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py index 2da6fb661..a07e72bff 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py @@ -2,7 +2,6 @@ import logging - from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator from tespy.tools import ComponentProperties from tespy.connections import Connection @@ -19,11 +18,8 @@ # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -#fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] -#nw = Network(p_unit="bar", T_unit="C", iterinfo=True) nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - so = Source("Source") # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system # boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta @@ -59,9 +55,18 @@ #he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() -# print(nw.results['Connection']) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + # he.Q.val # he.Q_loss.val # he.Q_total.val diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py index 77f23ff07..77818c5e7 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py @@ -20,8 +20,8 @@ # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) so = Source("Source") # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system @@ -48,13 +48,34 @@ # set pressure ratios of heater and merge he.set_attr(deltaP=1) -he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor -#he.set_attr(Q_total=8.16e+04) # MRK so eta is (1-hlf) heat loss factor -he.set_attr(Q_loss=-7.42e+03) # MRK so eta is (1-hlf) heat loss factor +he.set_attr(LF=0.1) +he.set_attr(Q_total=8.16e+04) +#he.set_attr(Q_loss=-7.42e+03) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + +he.set_attr(LF=None) +he.set_attr(Q_total=8.16e+04) +he.set_attr(Q_loss=-7.42e+03) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +he.set_attr(LF=0.1) +he.set_attr(Q_total=None) +he.set_attr(Q_loss=-7.42e+03) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() + + + + # print(nw.results['Connection']) # he.Q.val # he.Q_loss.val diff --git a/intermediateFoodTests/newComponentsTests/merge_mrk.py b/intermediateFoodTests/newComponentsTests/merge_mrk.py index 6e6f3ded4..d081bd7a0 100644 --- a/intermediateFoodTests/newComponentsTests/merge_mrk.py +++ b/intermediateFoodTests/newComponentsTests/merge_mrk.py @@ -1,7 +1,6 @@ # %% import logging - from tespy.components import HeatExchangerSimple, Source, Sink, Merge from tespy.connections import Connection from tespy.networks import Network @@ -12,15 +11,13 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits - +logging.basicConfig(level=logging.DEBUG) # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] - -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") +nw = Network(p_unit="bar", T_unit="C") so = Source("Source") so2 = Source("Source2") @@ -35,16 +32,26 @@ nw.add_conns(c1, c3, c4) # set some generic data for starting values -c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) +c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) # mix with pure water -c3.set_attr(m=0.05, p=2.2, h=0.5e5, fluid={"FoodWater": 1, "FoodProtein": 0}) +c3.set_attr(m=0.05, p=2.2, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) # set pressure ratios of heater and merge me.set_attr(deltaP=1) #c4.set_attr(p=1) nw.solve("design") - +if not nw.converged: + raise Exception("not converged") nw.print_results() print(nw.results['Connection']) + +me.set_attr(deltaP=None) +c4.set_attr(p=1) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) \ No newline at end of file From 6302fabdff6befd960c76dd70f95a292d5787c5e Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:11:10 +0100 Subject: [PATCH 014/105] constraints are now inherited and deleted if necessary. Added SplitterWithPressureLoss example (cherry picked from commit b5206a890c4b92a8a5c8acece7a4a18d18d9ac38) --- .../newComponentsTests/SplitterWithDeltaP.py | 57 +++++ .../simple_heatex_for_jorrit.py | 4 +- src/tespy/components/newcomponents.py | 242 ++++-------------- 3 files changed, 104 insertions(+), 199 deletions(-) create mode 100644 intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py diff --git a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py new file mode 100644 index 000000000..582b88c91 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py @@ -0,0 +1,57 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitterWithPressureLoss + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +se = SplitterWithPressureLoss("Splitter",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c2.set_attr(m=0.6) + +c2.set_attr(p=1.1) +c3.set_attr(p=1.0) + +# add some guess values +#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# use delta P +c2.set_attr(p=None) +c3.set_attr(p=None) +se.set_attr(deltaP=0.25) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py index 04a42c857..548c57893 100644 --- a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py +++ b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py @@ -20,7 +20,7 @@ nw.add_conns(c1, c2) # set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 0.9, "T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) c2.set_attr(T=50) # set some conditions on component @@ -52,7 +52,7 @@ nw.add_conns(c1, c2) # set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 1}) c2.set_attr(T=50) # set some conditions on component diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 7c1a3c4e1..ae1464e1b 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -268,35 +268,10 @@ def get_parameters(self): ) return variables - def get_mandatory_constraints(self): - - - variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(variable_fluids) - - if num_fluid_eq == 0: - num_fluid_eq = len(self.inl[0].fluid.val) - num_m_eq = 0 - else: - num_m_eq = 1 - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': num_m_eq}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints def deltaP_func(self): r""" @@ -331,6 +306,14 @@ def calc_parameters(self): class SplitterWithPressureLoss(Splitter): + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + super().__init__(label, **kwargs) + @staticmethod def component(): return 'Splitter with pressure losses' @@ -339,42 +322,22 @@ def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=self.num_out, ) return variables def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints - def pr_func(self): + def deltaP_func(self): r""" Equation for pressure drop. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI residual = [] @@ -383,25 +346,18 @@ def pr_func(self): residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] return residual - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k): r""" Calculate the partial derivatives for combustion pressure ratio. - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. """ - # self.jacobian[k, 0, 1] = self.pr.val - # self.jacobian[k, self.num_i, 1] = -1 - j = 0 - for c in self.outl: - self.jacobian[k, 0, 1] = 1 - self.jacobian[k, j + 1, 1] = -1 - j += 1 + + i = self.inl[0] + for o in self.outl: + if i.p.is_var: + self.jacobian[k, i.p.J_col] = 1 + if o.p.is_var: + self.jacobian[k, o.p.J_col] = -1 k += 1 def calc_parameters(self): @@ -426,7 +382,6 @@ def __init__(self, label, **kwargs): super().__init__(label, **kwargs) - @staticmethod def component(): return 'separator with species flow splits' @@ -444,16 +399,8 @@ def get_parameters(self): def SFS_func(self): r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: + Equation for SFS. - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ # residual = [] # for fluid, x in self.inl[0].fluid.val.items(): @@ -476,15 +423,8 @@ def SFS_func(self): def SFS_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. + Calculate the partial derivatives for SFS. - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. """ # j=0 @@ -549,48 +489,14 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - self.variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(self.variable_fluids) - if num_fluid_eq == 0: - num_fluid_eq = 1 - self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - # 'energy_balance_constraints': { - # 'func': self.energy_balance_func, - # 'deriv': self.energy_balance_deriv, - # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - # 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } + constraints = super().get_mandatory_constraints() + del constraints['energy_balance_constraints'] + return constraints def energy_balance_deltaT_func(self): r""" - Calculate energy balance. - - Returns - ------- - residual : list - Residual value of energy balance. + Calculate delta T derivatives. - .. math:: - - 0 = T_{in} - T_{out,j}\\ - \forall j \in \text{outlets} """ residual = [] T_in = T_mix_ph(self.inl[0].get_flow(), T0=self.inl[0].T.val_SI) @@ -622,25 +528,22 @@ def get_parameters(self): variables = super().get_parameters() variables["deltaP"] = dc_cp( min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, + deriv=self.deltaP_deriv, + func=self.deltaP_func, latex=self.pr_func_doc, num_eq=self.num_out, ) return variables - def pr_func(self): + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints + + def deltaP_func(self): r""" Equation for pressure drop. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ residual = [] p_in = self.inl[0].p.val_SI @@ -648,17 +551,10 @@ def pr_func(self): residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] return residual - def pr_deriv(self, increment_filter, k): + def deltaP_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. + Calculate the partial derivatives for pressure drop - k : int - Position of equation in Jacobian matrix. """ j = 0 for c in self.outl: @@ -678,30 +574,6 @@ def calc_parameters(self): self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - # 'pressure_constraints': { - # 'func': self.pressure_equality_func, - # 'deriv': self.pressure_equality_deriv, - # 'constant_deriv': True, - # 'latex': self.pressure_equality_func_doc, - # 'num_eq': self.num_i + self.num_o - 1} - } - - class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndPr): @staticmethod @@ -713,34 +585,10 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - self.variable_fluids = set( - [fluid for c in self.inl + self.outl for fluid in c.fluid.is_var] - ) - num_fluid_eq = len(self.variable_fluids) - if num_fluid_eq == 0: - num_fluid_eq = 1 - self.variable_fluids = [list(self.inl[0].fluid.is_set)[0]] - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq}, - # 'energy_balance_constraints': { - # 'func': self.energy_balance_func, - # 'deriv': self.energy_balance_deriv, - # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - # 'num_eq': self.num_o}, - # 'pressure_constraints': { - # 'func': self.pressure_equality_func, - # 'deriv': self.pressure_equality_deriv, - # 'constant_deriv': True, - # 'latex': self.pressure_equality_func_doc, - # 'num_eq': self.num_i + self.num_o - 1} - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsAndDeltaTAndPr): From a2b4624a907d0f93b8428827023afaa7c332e1d7 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:32:59 +0100 Subject: [PATCH 015/105] Flow splitter working and added flow splitter with pressure drop (cherry picked from commit 6d8a34fcaf1c40b63046e2154db3b14087e3a032) --- .../SplitWithFlowSplitter.py | 69 +++++++++++++++++++ .../SplitWithFlowSplitterDeltaP.py | 69 +++++++++++++++++++ src/tespy/components/newcomponents.py | 46 +++++-------- 3 files changed, 156 insertions(+), 28 deletions(-) create mode 100644 intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py create mode 100644 intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py new file mode 100644 index 000000000..671f35725 --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py @@ -0,0 +1,69 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +se = SplitWithFlowSplitter("Splitter",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c2.set_attr(m=0.6) + +#c2.set_attr(p=1.1) +#c3.set_attr(p=1.0) + +# add some guess values +#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# use FS +c2.set_attr(m=None) +se.set_attr(FS={ + 'val': 0.65, 'is_set': True, + 'split_outlet' : "out1"}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# # use delta P +# c2.set_attr(p=None) +# c3.set_attr(p=None) +# se.set_attr(deltaP=0.25) + +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() +# print(nw.results['Connection']) diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py new file mode 100644 index 000000000..dd6e43b1d --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py @@ -0,0 +1,69 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter,SplitWithFlowSplitterDeltaP + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, p_unit="bar", T_unit="C") + +so = Source("Source") +se = SplitWithFlowSplitterDeltaP("Splitter",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c2.set_attr(m=0.6) + +c2.set_attr(p=1.1) +c3.set_attr(p=1.0) + +# add some guess values +#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# use FS +c2.set_attr(m=None) +se.set_attr(FS={ + 'val': 0.65, 'is_set': True, + 'split_outlet' : "out1"}) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +# use delta P +c2.set_attr(p=None) +c3.set_attr(p=None) +se.set_attr(deltaP=0.25) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index ae1464e1b..44a6b4d9c 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -692,49 +692,39 @@ def get_parameters(self): def FS_func(self): r""" - Equation for pressure drop. + Equation for flow split. - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} """ out_i = int(self.FS.split_outlet[3:]) - 1 res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI - - #print(res) return res def FS_deriv(self, increment_filter, k): r""" - Calculate the partial derivatives for combustion pressure ratio. + Calculate the partial derivatives for flow split - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. """ out_i = int(self.FS.split_outlet[3:]) - 1 - inl = self.inl[0] - outl = self.outl[out_i] - j = 0 - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.FS.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 + i = self.inl[0] + o = self.outl[out_i] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = self.FS.val + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 - #print(self.jacobian) - #print(self.jacobian[k,:,:]) + +class SplitWithFlowSplitterDeltaP(SplitWithFlowSplitter, SplitterWithPressureLoss): + + @staticmethod + def component(): + return 'splitter with flow split ratios and pressure drop' + + def get_parameters(self): + variables = super().get_parameters() + return variables #%% Class containers From 5d647a658dc0e96e0cd3d58e9df23beb31bb4e40 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:34:28 +0100 Subject: [PATCH 016/105] reorganizing splitters (cherry picked from commit ecb718cdf82e8da671854d91043de190b67bbb3c) --- src/tespy/components/newcomponents.py | 131 +++++++++++++------------- 1 file changed, 64 insertions(+), 67 deletions(-) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 44a6b4d9c..780b46a95 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -304,73 +304,6 @@ def calc_parameters(self): self.deltaP.val = (Pmax - self.outl[0].p.val_SI)/1e5 -class SplitterWithPressureLoss(Splitter): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - super().__init__(label, **kwargs) - - @staticmethod - def component(): - return 'Splitter with pressure losses' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaP"] = dc_cp( - min_val=0, - deriv=self.deltaP_deriv, - func=self.deltaP_func, - latex=self.pr_func_doc, - num_eq=self.num_out, - ) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - return constraints - - def deltaP_func(self): - r""" - Equation for pressure drop. - - """ - #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - residual = [] - p_in = self.inl[0].p.val_SI - for o in self.outl: - residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] - return residual - - def deltaP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - """ - - i = self.inl[0] - for o in self.outl: - if i.p.is_var: - self.jacobian[k, i.p.J_col] = 1 - if o.p.is_var: - self.jacobian[k, o.p.J_col] = -1 - k += 1 - - def calc_parameters(self): - super().calc_parameters() - - Pmin = min([i.p.val_SI for i in self.outl]) - Pmax = max([i.p.val_SI for i in self.outl]) - if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): - self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 - else: - self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 - - class SeparatorWithSpeciesSplits(Separator): def __init__(self, label, **kwargs): @@ -671,7 +604,71 @@ def bus_deriv(self, bus): return deriv +class SplitterWithPressureLoss(Splitter): + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + super().__init__(label, **kwargs) + + @staticmethod + def component(): + return 'Splitter with pressure losses' + + def get_parameters(self): + variables = super().get_parameters() + variables["deltaP"] = dc_cp( + min_val=0, + deriv=self.deltaP_deriv, + func=self.deltaP_func, + latex=self.pr_func_doc, + num_eq=self.num_out, + ) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + return constraints + + def deltaP_func(self): + r""" + Equation for pressure drop. + + """ + #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + residual = [] + p_in = self.inl[0].p.val_SI + for o in self.outl: + residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] + return residual + + def deltaP_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + """ + + i = self.inl[0] + for o in self.outl: + if i.p.is_var: + self.jacobian[k, i.p.J_col] = 1 + if o.p.is_var: + self.jacobian[k, o.p.J_col] = -1 + k += 1 + + def calc_parameters(self): + super().calc_parameters() + + Pmin = min([i.p.val_SI for i in self.outl]) + Pmax = max([i.p.val_SI for i in self.outl]) + if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): + self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 + else: + self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 class SplitWithFlowSplitter(Splitter): From de6c045669c9d2481be8b6012f0772e09e7028c9 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 16:53:25 +0100 Subject: [PATCH 017/105] working on SFS (cherry picked from commit 9143f092f07f0773de0ba1f47ec17939710bf5d7) --- .../newComponentsTests/SpeciesFlowSplit.py | 40 ++----- .../SpeciesFlowSplitWithDeltaT.py | 58 +++++---- .../SpeciesFlowSplitWithDeltaTAndPr.py | 90 +++++++++++--- .../SpeciesFlowSplitWithPr.py | 12 +- .../SplitWithFlowSplitter.py | 2 +- .../SplitWithFlowSplitterDeltaP.py | 2 +- .../newComponentsTests/SplitterWithDeltaP.py | 2 +- .../newComponentsTests/heatex+merge.py | 2 +- .../newComponentsTests/heatex_alone.py | 2 +- .../newComponentsTests/merge_mrk.py | 2 +- .../simple_heatex_for_jorrit.py | 2 +- src/tespy/components/newcomponents.py | 113 +++++++----------- src/tespy/tools/fluid_properties/helpers.py | 1 + 13 files changed, 168 insertions(+), 160 deletions(-) diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py index 3e7830047..afc50483f 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py @@ -29,41 +29,25 @@ nw.add_conns(c1, c2, c3) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"Water": 0.9, "T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") # set compositions -c2.set_attr(fluid={"Water": 0.85, "T66": 0.15}) -# or others -#c3.set_attr(fluid={"Water": 0.85, "T66": 0.15}) -# or others -#c2.set_attr(fluid={"Water": 0.85}) -#c3.set_attr(fluid={"Water": 1}) +c2.set_attr(fluid={"INCOMP::Water": 0.85, "INCOMP::T66": 0.15}) -# This one produce error because T66 is 0 and the equation cannot be solved.. -#c2.set_attr(fluid={"Water": 1, "T66": 0.0}) - -# specify this one to avoid using the species flow split : SFS -#c2.set_attr(m=0.5) -# set the species flow split, specify the fluid and the outlet too.. (we might need some checks of this) se.set_attr(SFS={ 'val': 0.6, 'is_set': True, 'split_fluid' : 'T66', 'split_outlet' : "out1"}) - -# add some guess values -c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) - nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() - print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] - -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") - -print(f"\n heat flows are {se.Q.val}") -print(f"\n") - - +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'Water', 'split_outlet' : "out1"}) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py index 384666539..e6f2d0452 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -16,7 +16,7 @@ # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +fluids = ["INCOMP::Water", "INCOMP::T66"] nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") @@ -36,50 +36,46 @@ h0 = 1e2 # global guess value in kJ/kg p0 = 5 # global guess value in bar -for c in nw.conns['object']: - n_fl = len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) +# for c in nw.conns['object']: +# c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/3, 'INCOMP::FoodFat': 1/3, 'INCOMP::T66': 1/3}, mixing_rule="incompressible") # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=50, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) -c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) -#c3.set_attr(fluid={"FoodProtein": 0.1}) +c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +#c1.set_attr(T0=10) # it seems guess values are SI + +c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) + 'split_fluid' : 'T66', 'split_outlet' : "out1"}) +se.set_attr(deltaT=5) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") -se.set_attr(deltaT=2) -#se.set_attr(Q_loss=0) # Now it is possible to set the temperatures out of the separator differently -# c2.set_attr(T=20) -# c3.set_attr(T=10) - -# Or to use a deltaT array instead -#se.set_attr(deltaT=[-10,-20]) -#se.set_attr(deltaT=[0,0]) +se.set_attr(deltaT=None) +c2.set_attr(T=20) +c3.set_attr(T=10) -# # add some guess values -# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) -# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() - print(nw.results['Connection']) - -m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] -m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] - - -print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") - -print(f"\n Q loss {se.Q_loss.val}") - - - +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") print(f"\n") diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py index 1f5d5e67b..d3d2aa1d8 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py @@ -16,7 +16,7 @@ # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +fluids = ["INCOMP::Water", "INCOMP::T66"] nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") @@ -36,23 +36,77 @@ p0 = 5 # global guess value in bar for c in nw.conns['object']: - n_fl = len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) + n_fl = 2 # len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) # set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) -c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) -#c3.set_attr(fluid={"FoodProtein": 0.1}) +c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) - + 'split_fluid' : 'T66', 'split_outlet' : "out1"}) # Now it is possible to set the temperatures out of the separator differently c2.set_attr(T=20,p=5) c3.set_attr(T=10,p=5) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +# deltaT +se.set_attr(deltaT=0) +c2.set_attr(T=None) +c3.set_attr(T=None) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +# deltaT and different pressures +se.set_attr(deltaT=5) +c2.set_attr(p=4) +c3.set_attr(p=3) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +# deltaP +se.set_attr(deltaT=5,deltaP=1.2) +c2.set_attr(p=None) +c3.set_attr(p=None) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + # se.set_attr(deltaT=2) # se.set_attr(deltaP=1) @@ -61,22 +115,22 @@ #se.set_attr(deltaT=[0,0]) # # add some guess values -# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) -# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) +# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) +# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -nw.solve("design") -nw.print_results() +# nw.solve("design") +# nw.print_results() -print(nw.results['Connection']) +# print(nw.results['Connection']) -m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] -m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] +# m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +# m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") +# print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n heat flows are {se.Q_loss.val}") -print(f"\n") +# print(f"\n heat flows are {se.Q_loss.val}") +# print(f"\n") diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py index 911ccf279..18c2348ae 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py @@ -36,12 +36,12 @@ p0 = 5 # global guess value in bar for c in nw.conns['object']: - n_fl = len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'FoodWater': 1/n_fl, 'FoodFat': 1/n_fl, 'FoodProtein': 1/n_fl}) + n_fl = 2 # len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::FoodWater': 1/n_fl, 'INCOMP::FoodProtein': 1/n_fl}) # set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) -c2.set_attr(fluid={"FoodWater": 0.8, "FoodProtein": 0.2}) +c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::FoodWater": 0.9, "INCOMP::FoodProtein": 0.1}, mixing_rule="incompressible") +c2.set_attr(fluid={"INCOMP::FoodWater": 0.8, "INCOMP::FoodProtein": 0.2}) #c3.set_attr(fluid={"FoodProtein": 0.1}) se.set_attr(SFS={ @@ -50,8 +50,8 @@ # Now it is possible to set the temperatures out of the separator differently -# c2.set_attr(p=5) -# c3.set_attr(p=4) +#c2.set_attr(p=5) +#c3.set_attr(p=5) se.set_attr(deltaP=0) diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py index 671f35725..4cbef27bb 100644 --- a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py @@ -29,7 +29,7 @@ nw.add_conns(c1, c2, c3) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(m=0.6) #c2.set_attr(p=1.1) diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py index dd6e43b1d..82950592d 100644 --- a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py @@ -29,7 +29,7 @@ nw.add_conns(c1, c2, c3) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(m=0.6) c2.set_attr(p=1.1) diff --git a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py index 582b88c91..467804022 100644 --- a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py +++ b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py @@ -29,7 +29,7 @@ nw.add_conns(c1, c2, c3) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(m=0.6) c2.set_attr(p=1.1) diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge.py b/intermediateFoodTests/newComponentsTests/heatex+merge.py index 3d0e20fa0..eba35bcbd 100644 --- a/intermediateFoodTests/newComponentsTests/heatex+merge.py +++ b/intermediateFoodTests/newComponentsTests/heatex+merge.py @@ -35,7 +35,7 @@ nw.add_conns(c1, c2, c3, c4) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(h=2.2e5) # mix with pure water c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone.py b/intermediateFoodTests/newComponentsTests/heatex_alone.py index ade3218ee..158946be9 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone.py @@ -33,7 +33,7 @@ nw.add_conns(c1, c2) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}) +c1.set_attr(m=1, p=1.2, T=30, fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") c2.set_attr(T=50) # set pressure ratios of heater and merge diff --git a/intermediateFoodTests/newComponentsTests/merge_mrk.py b/intermediateFoodTests/newComponentsTests/merge_mrk.py index d081bd7a0..d0d1211c2 100644 --- a/intermediateFoodTests/newComponentsTests/merge_mrk.py +++ b/intermediateFoodTests/newComponentsTests/merge_mrk.py @@ -32,7 +32,7 @@ nw.add_conns(c1, c3, c4) # set some generic data for starting values -c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") # mix with pure water c3.set_attr(m=0.05, p=2.2, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py index 548c57893..b6d484695 100644 --- a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py +++ b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py @@ -20,7 +20,7 @@ nw.add_conns(c1, c2) # set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(T=50) # set some conditions on component diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 780b46a95..e25aa66f8 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -335,23 +335,15 @@ def SFS_func(self): Equation for SFS. """ - # residual = [] - # for fluid, x in self.inl[0].fluid.val.items(): - # res = x * self.inl[0].m.val_SI - # for o in self.outl: - # res -= o.fluid.val[fluid] * o.m.val_SI - # residual += [res] - # return residual fluid = self.SFS.split_fluid out_i = int(self.SFS.split_outlet[3:]) - 1 - inl = self.inl[0] - outl = self.outl[out_i] + i = self.inl[0] + o = self.outl[out_i] - res = inl.fluid.val[fluid] * inl.m.val_SI * self.SFS.val \ - - outl.fluid.val[fluid] * outl.m.val_SI + res = i.fluid.val[fluid] * i.m.val_SI * self.SFS.val \ + - o.fluid.val[fluid] * o.m.val_SI - #print(res) return res def SFS_deriv(self, increment_filter, k): @@ -360,51 +352,23 @@ def SFS_deriv(self, increment_filter, k): """ - # j=0 - # self.jacobian[k, j, 0] = self.inl[j].fluid.val[self.split_fluid] * self.TS.val - # self.jacobian[k, j, i + 3] = self.inl[j].m.val_SI * self.TS.val - - # i = 0 - # for fluid, x in self.outl[0].fluid.val.items(): - # j = 0 - # for inl in self.inl: - # self.jacobian[k, j, 0] = inl.fluid.val[fluid] - # self.jacobian[k, j, i + 3] = inl.m.val_SI - # j += 1 - # self.jacobian[k, j, 0] = -x - # self.jacobian[k, j, i + 3] = -self.outl[0].m.val_SI - # i += 1 - # k += 1 - - fluid_index = list(self.inl[0].fluid.val.keys()).index(self.SFS.split_fluid) fluid = self.SFS.split_fluid out_i = int(self.SFS.split_outlet[3:]) - 1 - i = fluid_index - j = 0 - inl = self.inl[0] - outl = self.outl[out_i] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = inl.fluid.val[fluid] * self.SFS.val - - if fluid in inl.fluid.is_var: - self.jacobian[k, inl.fluid.J_col[fluid]] = inl.m.val_SI * self.SFS.val - - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -outl.fluid.val[fluid] - if fluid in outl.fluid.is_var: - self.jacobian[k, outl.fluid.J_col[fluid]] = -outl.m.val_SI - - #print(self.jacobian) - #print(self.jacobian[k,:,:]) - - + i = self.inl[0] + o = self.outl[out_i] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] * self.SFS.val + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI * self.SFS.val + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplits): - - @staticmethod def component(): return 'separator with species flow splits and dT on outlets' @@ -428,28 +392,35 @@ def get_mandatory_constraints(self): def energy_balance_deltaT_func(self): r""" - Calculate delta T derivatives. + Calculate deltaT residuals. """ + i = self.inl[0] + if i.T.is_set: + T_in = i.T.val_SI + else: + # calculate T_in + if i.T.val0 > 0: + T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule,i.T.val0) + else: + T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule) + residual = [] - T_in = T_mix_ph(self.inl[0].get_flow(), T0=self.inl[0].T.val_SI) - i=0 for o in self.outl: - residual += [T_in - self.deltaT.val - T_mix_ph(o.get_flow(), T0=o.T.val_SI)] - i+=1 + residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess return residual def calc_parameters(self): super().calc_parameters() - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) + i = self.inl[0] + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - Tmin = min([i.T.val_SI for i in self.outl]) - Tmax = max([i.T.val_SI for i in self.outl]) - if abs(self.inl[0].T.val_SI - Tmin) >= abs(self.inl[0].T.val_SI - Tmax): - self.deltaT.val = self.inl[0].T.val_SI - Tmin + Tmin = min([o.T.val_SI for o in self.outl]) + Tmax = max([o.T.val_SI for o in self.outl]) + if abs(i.T.val_SI - Tmin) >= abs(i.T.val_SI - Tmax): + self.deltaT.val = i.T.val_SI - Tmin else: - self.deltaT.val = self.inl[0].T.val_SI - Tmax - # self.inl[0].T.val_SI - min([i.T.val_SI for i in self.outl]) + self.deltaT.val = i.T.val_SI - Tmax class SeparatorWithSpeciesSplitsAndPr(SeparatorWithSpeciesSplits): @@ -489,12 +460,14 @@ def deltaP_deriv(self, increment_filter, k): Calculate the partial derivatives for pressure drop """ - j = 0 - for c in self.outl: - self.jacobian[k, 0, 1] = 1 - self.jacobian[k, j + 1, 1] = -1 - j += 1 - k += 1 + + i = self.inl[0] + for o in self.outl: + if i.p.is_var: + self.jacobian[k, i.p.J_col] = 1 + if o.p.is_var: + self.jacobian[k, o.p.J_col] = -1 + k += 1 def calc_parameters(self): super().calc_parameters() @@ -519,8 +492,8 @@ def get_parameters(self): def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] + #del constraints['pressure_constraints'] + #del constraints['energy_balance_constraints'] return constraints diff --git a/src/tespy/tools/fluid_properties/helpers.py b/src/tespy/tools/fluid_properties/helpers.py index 8bf433d7a..c94576b84 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -97,6 +97,7 @@ def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=N valmin, valmax = get_mixture_temperature_range(fluid_data) if T0 is None: T0 = (valmin + valmax) / 2.0 + T0 = max(valmin,min(valmax,T0)) function_kwargs = { "p": p, "fluid_data": fluid_data, "T": T0, From 0c3fbeb24efe3541eb8238e400748b62e613a413 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:29:58 +0100 Subject: [PATCH 018/105] fixing tespy separator model (is_var on the jacobian outlets ) (cherry picked from commit acb41ef9cec7c2649d4036a025fcb90cf1a2aed8) --- src/tespy/components/nodes/separator.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index c826f022c..dea3f3f04 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -350,8 +350,10 @@ def energy_balance_deriv(self, increment_filter, k): # for fluid in i.fluid.is_var: # self.jacobian[k, i.fluid.J_col[fluid]] = dT_dfluid_in[fluid] args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule) - self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) - self.jacobian[k, o.h.J_col] = -dT_mix_pdh(*args) + if self.is_variable(o.p): + self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -dT_mix_pdh(*args) # for fluid in o.fluid.is_var: # self.jacobian[k, o.fluid.J_col[fluid]] = -dT_mix_ph_dfluid(o) k += 1 From 2ac4f23a22a70591745297d03cd41a296dbc2a6c Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:31:14 +0100 Subject: [PATCH 019/105] cleaning test files for not using Food properties (cherry picked from commit c8415d6b65b0cee14e19705522fb918b987c3c04) --- .../newComponentsTests/SpeciesFlowSplit.py | 2 + .../SpeciesFlowSplitWithDeltaT.py | 5 +- .../SpeciesFlowSplitWithDeltaTAndPr.py | 33 +---------- .../SpeciesFlowSplitWithPr.py | 57 +++++++++---------- .../SplitWithFlowSplitter.py | 2 + .../SplitWithFlowSplitterDeltaP.py | 2 + .../newComponentsTests/SplitterWithDeltaP.py | 2 + .../newComponentsTests/heatex_alone_deltaP.py | 1 - .../heatex_alone_lossFactor.py | 1 - .../simple_heatex_for_jorrit.py | 2 + 10 files changed, 42 insertions(+), 65 deletions(-) diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py index afc50483f..95a7d1ef7 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py @@ -11,6 +11,8 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py index e6f2d0452..02ee540ea 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -13,6 +13,8 @@ DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsAndDeltaT +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? @@ -36,9 +38,6 @@ h0 = 1e2 # global guess value in kJ/kg p0 = 5 # global guess value in bar -# for c in nw.conns['object']: -# c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/3, 'INCOMP::FoodFat': 1/3, 'INCOMP::T66': 1/3}, mixing_rule="incompressible") - # set some generic data for starting values c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") #c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py index d3d2aa1d8..8538d196f 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py @@ -13,6 +13,8 @@ DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? @@ -62,7 +64,7 @@ print(f"\n") # deltaT -se.set_attr(deltaT=0) +se.set_attr(deltaT=5) c2.set_attr(T=None) c3.set_attr(T=None) @@ -107,32 +109,3 @@ print(f"\n") -# se.set_attr(deltaT=2) -# se.set_attr(deltaP=1) - -# Or to use a deltaT array instead -#se.set_attr(deltaT=[-10,-20]) -#se.set_attr(deltaT=[0,0]) - -# # add some guess values -# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) - -# nw.solve("design") -# nw.print_results() - -# print(nw.results['Connection']) - -# m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -# m_T66_c2 = c2.m.val * c2.fluid.val['T66'] - - -# print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") - -# print(f"\n heat flows are {se.Q_loss.val}") -# print(f"\n") - - - - -# %% diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py index 18c2348ae..e7f86e88e 100644 --- a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py @@ -13,10 +13,12 @@ DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr, SeparatorWithSpeciesSplitsAndPr +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodProtein"] +fluids = ["INCOMP::Water", "INCOMP::T66"] nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") @@ -37,47 +39,42 @@ for c in nw.conns['object']: n_fl = 2 # len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::FoodWater': 1/n_fl, 'INCOMP::FoodProtein': 1/n_fl}) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) # set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::FoodWater": 0.9, "INCOMP::FoodProtein": 0.1}, mixing_rule="incompressible") -c2.set_attr(fluid={"INCOMP::FoodWater": 0.8, "INCOMP::FoodProtein": 0.2}) -#c3.set_attr(fluid={"FoodProtein": 0.1}) +c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) +#c3.set_attr(fluid={"T66": 0.1}) se.set_attr(SFS={ 'val': 0.65, 'is_set': True, - 'split_fluid' : 'FoodProtein', 'split_outlet' : "out1"}) - - -# Now it is possible to set the temperatures out of the separator differently -#c2.set_attr(p=5) -#c3.set_attr(p=5) - -se.set_attr(deltaP=0) + 'split_fluid' : 'T66', 'split_outlet' : "out1"}) -# Or to use a deltaT array instead -#se.set_attr(deltaT=[-10,-20]) -#se.set_attr(deltaT=[0,0]) -# # add some guess values -# c2.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) -# c3.set_attr(m0=0.5,p0=1.2,T0=50,fluid0={"FoodWater": 0.5, "FoodProtein": 0.5}) +se.set_attr(deltaP=1.2) nw.solve("design") +if not nw.converged: + raise Exception("not converged") nw.print_results() - print(nw.results['Connection']) - -m_FoodProtein_c1 = c1.m.val * c1.fluid.val['FoodProtein'] -m_FoodProtein_c2 = c2.m.val * c2.fluid.val['FoodProtein'] - - -print(f"\n Species flow split is {m_FoodProtein_c2/m_FoodProtein_c1}") - -#print(f"\n heat flows are {se.Q.val}") -#print(se.Qout.val) - +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") print(f"\n") +# Now it is possible to set the pressures +c2.set_attr(p=4) +c3.set_attr(p=3) +se.set_attr(deltaP=None) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") \ No newline at end of file diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py index 4cbef27bb..bf263a188 100644 --- a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py @@ -11,6 +11,8 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py index 82950592d..1c4a41fde 100644 --- a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py +++ b/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py @@ -11,6 +11,8 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter,SplitWithFlowSplitterDeltaP +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? diff --git a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py index 467804022..6607a403b 100644 --- a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py +++ b/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py @@ -11,6 +11,8 @@ from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitterWithPressureLoss +logging.basicConfig(level=logging.DEBUG) + # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py index a07e72bff..1f47169a4 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py @@ -37,7 +37,6 @@ # set some generic data for starting values c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=1, T=30, p=1, mixing_rule="incompressible") -#c1.set_attr(m=1, p=2.2, T=30, fluid={"INCOMP::FoodWater": 0.9, "INCOMP::FoodProtein": 0.1}, mixing_rule="incompressible") c2.set_attr(T=95) #,p=1) # set pressure ratios of heater and merge diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py index 77818c5e7..95e801631 100644 --- a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py @@ -39,7 +39,6 @@ nw.add_conns(c1, c2) # set some generic data for starting values -#c1.set_attr(m=1, p=2.2, T=30, fluid={"FoodWater": 0.9, "FoodProtein": 0.1}) c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") c1.set_attr(m=1, p=2.2, T=30) diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py index b6d484695..c4c9917ff 100644 --- a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py +++ b/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py @@ -5,6 +5,8 @@ from tespy.connections import Connection from tespy.networks import Network +logging.basicConfig(level=logging.DEBUG) + # fluid and network fluids = ["INCOMP::Water", "INCOMP::T66"] nw = Network(fluids=fluids, p_unit="bar", T_unit="C") From 5182217663f81b0416e600176a91c5344e10f39f Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:33:03 +0100 Subject: [PATCH 020/105] And the BUS is running (cherry picked from commit 537c7f52c3cf9845d628230e0222da433ae78de3) --- .../SpeciesFlowSplitWithDeltaTAndPrAndBus.py | 78 +++++++++++++++++++ src/tespy/components/newcomponents.py | 53 +++++-------- 2 files changed, 96 insertions(+), 35 deletions(-) create mode 100644 intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py new file mode 100644 index 000000000..be3d5e71b --- /dev/null +++ b/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py @@ -0,0 +1,78 @@ +import logging + +from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection, Bus +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr, SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus,SimpleHeatExchangerDeltaP + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus("Separator",num_out=2) +si1 = Sink("Sink 1") +hx = SimpleHeatExchangerDeltaP("HX") +si2 = Sink("Sink 2") + + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", hx, "in1", label="3") +c4 = Connection(hx, "out1", si2, "in1", label="4") + +nw.add_conns(c1, c2, c3, c4) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +for c in nw.conns['object']: + n_fl = 2 # len(nw.fluids) + c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) + +# set some generic data for starting values +c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) + +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + +# Now it is possible to set the temperatures out of the separator differently +c2.set_attr(T=20,p=5) +c3.set_attr(T=10,p=5) + +#c4.set_attr(p=1) +hx.set_attr(deltaP=1) + + +heat_bus = Bus('total heat input', P=0) +heat_bus.add_comps({'comp': se, 'char': 1}, {'comp': hx, 'char': 1}) +nw.add_busses(heat_bus) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + + diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index e25aa66f8..fb2e7fda7 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -511,22 +511,6 @@ def bus_func(self, bus): r""" Calculate the value of the bus function. - Parameters - ---------- - bus : tespy.connections.bus.Bus - TESPy bus object. - - Returns - ------- - val : float - Value of energy transfer :math:`\dot{E}`. This value is passed to - :py:meth:`tespy.components.component.Component.calc_bus_value` - for value manipulation according to the specified characteristic - line of the bus. - - .. math:: - - \dot{E} = \dot{m}_{in} \cdot \left( h_{out} - h_{in} \right) """ return np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) @@ -552,29 +536,28 @@ def bus_deriv(self, bus): r""" Calculate partial derivatives of the bus function. - Parameters - ---------- - bus : tespy.connections.bus.Bus - TESPy bus object. - - Returns - ------- - deriv : ndarray - Matrix of partial derivatives. """ -# for o in self.outl: -# self.Qout.val += [o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI)] -# return np.sum(self.Qout.val) - deriv = np.zeros((1, len(self.outl)+1, self.num_nw_vars)) f = self.calc_bus_value - deriv[0, 0, 2] = self.numeric_deriv(f, 'h', 0, bus=bus) - i = 0 + if self.inl[0].m.is_var: + if self.inl[0].m.J_col not in bus.jacobian: + bus.jacobian[self.inl[0].m.J_col] = 0 + bus.jacobian[self.inl[0].m.J_col] -= self.numeric_deriv(f, 'm', self.inl[0], bus=bus) + + if self.inl[0].h.is_var: + if self.inl[0].h.J_col not in bus.jacobian: + bus.jacobian[self.inl[0].h.J_col] = 0 + bus.jacobian[self.inl[0].h.J_col] -= self.numeric_deriv(f, 'h', self.inl[0], bus=bus) + for o in self.outl: - i = i+1 - deriv[0, i, 0] = self.numeric_deriv(f, 'm', i, bus=bus) - deriv[0, i, 2] = self.numeric_deriv(f, 'h', i, bus=bus) - return deriv + if o.h.is_var: + if o.h.J_col not in bus.jacobian: + bus.jacobian[o.h.J_col] = 0 + bus.jacobian[o.h.J_col] -= self.numeric_deriv(f, 'h', o, bus=bus) + if o.m.is_var: + if o.m.J_col not in bus.jacobian: + bus.jacobian[o.m.J_col] = 0 + bus.jacobian[o.m.J_col] -= self.numeric_deriv(f, 'm', o, bus=bus) class SplitterWithPressureLoss(Splitter): From 5cd4b9a82bea555ce307f99c0065ea61ebc945bd Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:42:30 +0100 Subject: [PATCH 021/105] splitting energySupplyComponents from newComponents.. Energy Supply models are not very useful for tespy I believe (cherry picked from commit bed22e1da7fdaacc77462c70bd004102c4c3b5b1) --- .../energy-supply_energy-merge3.py | 2 +- src/tespy/components/__init__.py | 3 +- .../components/energySupplyComponents.py | 372 ++++++++++++++++++ src/tespy/components/newcomponents.py | 365 ----------------- 4 files changed, 375 insertions(+), 367 deletions(-) create mode 100644 src/tespy/components/energySupplyComponents.py diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py b/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py index 6f5ba03dd..1da8859b4 100644 --- a/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py +++ b/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.newcomponents import * +from tespy.components.energySupplyComponents import * import logging logging.basicConfig(level=logging.DEBUG) diff --git a/src/tespy/components/__init__.py b/src/tespy/components/__init__.py index 5d7705a85..d7f99362d 100644 --- a/src/tespy/components/__init__.py +++ b/src/tespy/components/__init__.py @@ -29,4 +29,5 @@ from .turbomachinery.turbine import Turbine # noqa: F401 # New components -from .newcomponents import * \ No newline at end of file +from .newcomponents import * +from .energySupplyComponents import * \ No newline at end of file diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py new file mode 100644 index 000000000..a5fe20223 --- /dev/null +++ b/src/tespy/components/energySupplyComponents.py @@ -0,0 +1,372 @@ +import logging + +from tespy.components import Merge, Splitter +from tespy.tools.data_containers import ComponentProperties as dc_cp + + +# Fictious Energy Supply models (energy flows modelled as mass flows) +# No real use for tespy I guess + +class MassFactorVCC(Splitter): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["COP"] = dc_cp( + min_val=0, + deriv=self.COP_deriv, + func=self.COP_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + return { + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + 'pressure_constraints': { + 'func': self.pressure_equality_func, + 'deriv': self.pressure_equality_deriv, + 'constant_deriv': True, + 'latex': self.pressure_equality_func_doc, + 'num_eq': self.num_i + self.num_o - 1} + } + + + def COP_func(self): + r""" + Equation for COP. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI + + def COP_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.COP.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) + + + +class MassFactorVCCWithPressureLoss(MassFactorVCC): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["pr"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1 + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k, 0, 1] = self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + } + + def calc_parameters(self): + super().calc_parameters() + self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI + for i in range(self.num_i): + if self.inl[i].p.val < self.outl[0].p.val: + msg = ( + f"The pressure at inlet {i + 1} is lower than the pressure " + f"at the outlet of component {self.label}." + ) + logging.warning(msg) + + + + +class MassFactorLossModel(Splitter): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["Loss"] = dc_cp( + min_val=0, + deriv=self.Loss_deriv, + func=self.Loss_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + 'pressure_constraints': { + 'func': self.pressure_equality_func, + 'deriv': self.pressure_equality_deriv, + 'constant_deriv': True, + 'latex': self.pressure_equality_func_doc, + 'num_eq': self.num_i + self.num_o - 1} + } + + + def Loss_func(self): + return self.inl[0].m.val_SI * (1-self.Loss.val) - self.outl[0].m.val_SI + + def Loss_deriv(self, increment_filter, k): + self.jacobian[k , 0, 0] = (1-self.Loss.val) + self.jacobian[k , self.num_i, 0] = -1 + + def calc_parameters(self): + super().calc_parameters() + self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI + + + +class MassFactorLossModelWithPressureLoss(MassFactorLossModel): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["pr"] = dc_cp( + min_val=0, + deriv=self.pr_deriv, + func=self.pr_func, + latex=self.pr_func_doc, + num_eq=1 + ) + return variables + + def pr_func(self): + r""" + Equation for pressure drop. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI + + def pr_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + self.jacobian[k, 0, 1] = self.pr.val + self.jacobian[k, self.num_i, 1] = -1 + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + 'energy_balance_constraints': { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': True, 'latex': self.energy_balance_func_doc, + 'num_eq': self.num_o}, + } + + def calc_parameters(self): + super().calc_parameters() + self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI + for i in range(self.num_i): + if self.inl[i].p.val < self.outl[0].p.val: + msg = ( + f"The pressure at inlet {i + 1} is lower than the pressure " + f"at the outlet of component {self.label}." + ) + logging.warning(msg) + + + + + + +class MergeEnergySupply(Merge): + + @staticmethod + def component(): + return 'merge without pressure/energy constraints' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': self.num_nw_fluids}, + } + +class SplitterEnergySupply(Splitter): + + @staticmethod + def component(): + return 'Splitter without pressure/energy constraints' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + } + + + +class MassFactorVCCEnergySupply(MassFactorVCC): + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances, without pressure/enthalpy constraints)' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + +class MassFactorLossModelEnergySupply(MassFactorLossModel): + + @staticmethod + def component(): + return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances, without pressure/enthalpy constraints)' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + def get_mandatory_constraints(self): + return { + 'mass_flow_constraints': { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1}, + 'fluid_constraints': { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': True, 'latex': self.fluid_func_doc, + 'num_eq': self.num_o * self.num_nw_fluids}, + } diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index fb2e7fda7..0a6f2fb31 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -705,368 +705,3 @@ def attr(): attributes.update({'split_outlet' : str}) return attributes - - -class MassFactorVCC(Splitter): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["COP"] = dc_cp( - min_val=0, - deriv=self.COP_deriv, - func=self.COP_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - return variables - - def get_mandatory_constraints(self): - return { - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } - - - def COP_func(self): - r""" - Equation for COP. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI - - def COP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.COP.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) - - - -class MassFactorVCCWithPressureLoss(MassFactorVCC): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["pr"] = dc_cp( - min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def pr_func(self): - r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - - def pr_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - self.jacobian[k, 0, 1] = self.pr.val - self.jacobian[k, self.num_i, 1] = -1 - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } - - def calc_parameters(self): - super().calc_parameters() - self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI - for i in range(self.num_i): - if self.inl[i].p.val < self.outl[0].p.val: - msg = ( - f"The pressure at inlet {i + 1} is lower than the pressure " - f"at the outlet of component {self.label}." - ) - logging.warning(msg) - - - - -class MassFactorLossModel(Splitter): - - @staticmethod - def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["Loss"] = dc_cp( - min_val=0, - deriv=self.Loss_deriv, - func=self.Loss_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - return variables - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } - - - def Loss_func(self): - return self.inl[0].m.val_SI * (1-self.Loss.val) - self.outl[0].m.val_SI - - def Loss_deriv(self, increment_filter, k): - self.jacobian[k , 0, 0] = (1-self.Loss.val) - self.jacobian[k , self.num_i, 0] = -1 - - def calc_parameters(self): - super().calc_parameters() - self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI - - - -class MassFactorLossModelWithPressureLoss(MassFactorLossModel): - - @staticmethod - def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["pr"] = dc_cp( - min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def pr_func(self): - r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - - def pr_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - self.jacobian[k, 0, 1] = self.pr.val - self.jacobian[k, self.num_i, 1] = -1 - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } - - def calc_parameters(self): - super().calc_parameters() - self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI - for i in range(self.num_i): - if self.inl[i].p.val < self.outl[0].p.val: - msg = ( - f"The pressure at inlet {i + 1} is lower than the pressure " - f"at the outlet of component {self.label}." - ) - logging.warning(msg) - - - - - - -class MergeEnergySupply(Merge): - - @staticmethod - def component(): - return 'merge without pressure/energy constraints' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, - } - -class SplitterEnergySupply(Splitter): - - @staticmethod - def component(): - return 'Splitter without pressure/energy constraints' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - } - - - -class MassFactorVCCEnergySupply(MassFactorVCC): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances, without pressure/enthalpy constraints)' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - -class MassFactorLossModelEnergySupply(MassFactorLossModel): - - @staticmethod - def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances, without pressure/enthalpy constraints)' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - } From 7448aa3e8bd08dc5be26213a8e5494347e179ac3 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:25:14 +0100 Subject: [PATCH 022/105] working energy models and examples (cherry picked from commit f76274647c97e44b50b0c3ce59567bf105de2289) --- .../energy-supply_energy-merge3.py | 8 +- .../energy-supply_energy-split3.py | 8 +- .../energySupply/energy-supply_heat-pump3.py | 8 +- .../energySupply/energy-supply_loss-model3.py | 10 +- .../components/energySupplyComponents.py | 103 ++++-------------- 5 files changed, 40 insertions(+), 97 deletions(-) diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py b/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py index 1da8859b4..951d291f5 100644 --- a/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py +++ b/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py @@ -16,7 +16,7 @@ -fluid_list = ['INCOMP::FoodWater'] +fluid_list = ['INCOMP::Water'] network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) # Objects @@ -42,11 +42,11 @@ # guess for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}, mixing_rule="incompressible") # arbitray values -c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) -c2.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) +c2.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) c3.set_attr(h=0,p=1) # merge already propergate h, p and fluid diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-split3.py b/intermediateFoodTests/energySupply/energy-supply_energy-split3.py index 07d662bf1..85558efbc 100644 --- a/intermediateFoodTests/energySupply/energy-supply_energy-split3.py +++ b/intermediateFoodTests/energySupply/energy-supply_energy-split3.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.newcomponents import * +from tespy.components.energySupplyComponents import * import logging logging.basicConfig(level=logging.DEBUG) @@ -16,7 +16,7 @@ -fluid_list = ['INCOMP::FoodWater'] +fluid_list = ['INCOMP::Water'] network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) # Objects @@ -43,10 +43,10 @@ # guess for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}, mixing_rule="incompressible") # arbitray values -c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) c2.set_attr(h=0,p=1) c3.set_attr(h=0,p=1) diff --git a/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py b/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py index 6e135ddbb..8a0825f97 100644 --- a/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py +++ b/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.newcomponents import * +from tespy.components.energySupplyComponents import * import logging logging.basicConfig(level=logging.DEBUG) @@ -16,7 +16,7 @@ -fluid_list = ['INCOMP::FoodWater'] +fluid_list = ['INCOMP::Water'] network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) # Objects @@ -41,10 +41,10 @@ # guess for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}) # arbitray values -c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}, mixing_rule="incompressible") c2.set_attr(h=0,p=1) c3.set_attr(h=0,p=1) diff --git a/intermediateFoodTests/energySupply/energy-supply_loss-model3.py b/intermediateFoodTests/energySupply/energy-supply_loss-model3.py index 715ff45bc..eed49cfdc 100644 --- a/intermediateFoodTests/energySupply/energy-supply_loss-model3.py +++ b/intermediateFoodTests/energySupply/energy-supply_loss-model3.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.newcomponents import * +from tespy.components.energySupplyComponents import * import logging logging.basicConfig(level=logging.DEBUG) @@ -16,7 +16,7 @@ -fluid_list = ['INCOMP::FoodWater'] +fluid_list = ['INCOMP::Water'] network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) # Objects @@ -37,14 +37,12 @@ #c2.set_attr(m=m0*0.9) LossModel.set_attr(Loss=0.1) - - # guess for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'FoodWater': 1}) + c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}) # arbitray values -c1.set_attr(h=0,p=1,fluid={'FoodWater': 1}) +c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}, mixing_rule="incompressible") c2.set_attr(h=0,p=1) c3.set_attr(h=0,p=1) diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index a5fe20223..36df6a2f1 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -25,20 +25,11 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - return { - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } - + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + #del constraints['mass_flow_constraints'] + return constraints def COP_func(self): r""" @@ -176,42 +167,27 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - 'pressure_constraints': { - 'func': self.pressure_equality_func, - 'deriv': self.pressure_equality_deriv, - 'constant_deriv': True, - 'latex': self.pressure_equality_func_doc, - 'num_eq': self.num_i + self.num_o - 1} - } - + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints def Loss_func(self): return self.inl[0].m.val_SI * (1-self.Loss.val) - self.outl[0].m.val_SI def Loss_deriv(self, increment_filter, k): - self.jacobian[k , 0, 0] = (1-self.Loss.val) - self.jacobian[k , self.num_i, 0] = -1 + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = (1-self.Loss.val) + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 def calc_parameters(self): super().calc_parameters() self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI - class MassFactorLossModelWithPressureLoss(MassFactorLossModel): @staticmethod @@ -287,11 +263,6 @@ def calc_parameters(self): ) logging.warning(msg) - - - - - class MergeEnergySupply(Merge): @staticmethod @@ -303,16 +274,10 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': self.num_nw_fluids}, - } + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints class SplitterEnergySupply(Splitter): @@ -325,18 +290,10 @@ def get_parameters(self): return variables def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - } - - + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints class MassFactorVCCEnergySupply(MassFactorVCC): @@ -348,7 +305,6 @@ def get_parameters(self): variables = super().get_parameters() return variables - class MassFactorLossModelEnergySupply(MassFactorLossModel): @staticmethod @@ -358,15 +314,4 @@ def component(): def get_parameters(self): variables = super().get_parameters() return variables - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - } + \ No newline at end of file From 45b57fce278bf56e70e5a60f7d7a130f1dc1e416 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:31:47 +0100 Subject: [PATCH 023/105] renaming example files (cherry picked from commit 33c76cc9f6eeba38629da57876cee4b183f317bf) --- ...ergy-supply_energy-merge3.py => energy-supply_energy-merge.py} | 0 ...ergy-supply_energy-split3.py => energy-supply_energy-split.py} | 0 .../{energy-supply_heat-pump3.py => energy-supply_heat-pump.py} | 0 .../{energy-supply_loss-model3.py => energy-supply_loss.py} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename intermediateFoodTests/energySupply/{energy-supply_energy-merge3.py => energy-supply_energy-merge.py} (100%) rename intermediateFoodTests/energySupply/{energy-supply_energy-split3.py => energy-supply_energy-split.py} (100%) rename intermediateFoodTests/energySupply/{energy-supply_heat-pump3.py => energy-supply_heat-pump.py} (100%) rename intermediateFoodTests/energySupply/{energy-supply_loss-model3.py => energy-supply_loss.py} (100%) diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-merge3.py b/intermediateFoodTests/energySupply/energy-supply_energy-merge.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_energy-merge3.py rename to intermediateFoodTests/energySupply/energy-supply_energy-merge.py diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-split3.py b/intermediateFoodTests/energySupply/energy-supply_energy-split.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_energy-split3.py rename to intermediateFoodTests/energySupply/energy-supply_energy-split.py diff --git a/intermediateFoodTests/energySupply/energy-supply_heat-pump3.py b/intermediateFoodTests/energySupply/energy-supply_heat-pump.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_heat-pump3.py rename to intermediateFoodTests/energySupply/energy-supply_heat-pump.py diff --git a/intermediateFoodTests/energySupply/energy-supply_loss-model3.py b/intermediateFoodTests/energySupply/energy-supply_loss.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_loss-model3.py rename to intermediateFoodTests/energySupply/energy-supply_loss.py From 9e2df2fd68d81202f8d041ffed4af60bf985bea9 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:34:03 +0100 Subject: [PATCH 024/105] deleting old energy supply models, updating names and examples (cherry picked from commit 68eadb09533caf18746069bb1173a36592d16287) --- .../energySupply/energy-supply_heat-pump.py | 2 +- .../energySupply/energy-supply_loss.py | 2 +- .../components/energySupplyComponents.py | 184 +----------------- 3 files changed, 6 insertions(+), 182 deletions(-) diff --git a/intermediateFoodTests/energySupply/energy-supply_heat-pump.py b/intermediateFoodTests/energySupply/energy-supply_heat-pump.py index 8a0825f97..fe84b6f73 100644 --- a/intermediateFoodTests/energySupply/energy-supply_heat-pump.py +++ b/intermediateFoodTests/energySupply/energy-supply_heat-pump.py @@ -21,7 +21,7 @@ # Objects PurchasedElectricity = Source('PurchasedElectricity') -HeatPump = MassFactorVCCEnergySupply('HeatPump') +HeatPump = MassFactorEnergySupply('HeatPump') Heating = Sink('Consumer1') Cooling = Sink('Consumer2') diff --git a/intermediateFoodTests/energySupply/energy-supply_loss.py b/intermediateFoodTests/energySupply/energy-supply_loss.py index eed49cfdc..1012f701e 100644 --- a/intermediateFoodTests/energySupply/energy-supply_loss.py +++ b/intermediateFoodTests/energySupply/energy-supply_loss.py @@ -21,7 +21,7 @@ # Objects PurchasedElectricity = Source('PurchasedElectricity') -LossModel = MassFactorLossModelEnergySupply('LossModel') +LossModel = MassLossEnergySupply('LossModel') Heating = Sink('Consumer1') Cooling = Sink('Consumer2') diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index 36df6a2f1..32b88e1a5 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -7,7 +7,7 @@ # Fictious Energy Supply models (energy flows modelled as mass flows) # No real use for tespy I guess -class MassFactorVCC(Splitter): +class MassFactorEnergySupply(Splitter): @staticmethod def component(): @@ -70,90 +70,11 @@ def calc_parameters(self): self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) - -class MassFactorVCCWithPressureLoss(MassFactorVCC): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["pr"] = dc_cp( - min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def pr_func(self): - r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - - def pr_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - self.jacobian[k, 0, 1] = self.pr.val - self.jacobian[k, self.num_i, 1] = -1 - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } - - def calc_parameters(self): - super().calc_parameters() - self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI - for i in range(self.num_i): - if self.inl[i].p.val < self.outl[0].p.val: - msg = ( - f"The pressure at inlet {i + 1} is lower than the pressure " - f"at the outlet of component {self.label}." - ) - logging.warning(msg) - - - - -class MassFactorLossModel(Splitter): +class MassLossEnergySupply(Splitter): @staticmethod def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' + return 'mass loss model for splitting energy flows (modelled using tespy mass balances)' def get_parameters(self): variables = super().get_parameters() @@ -187,82 +108,6 @@ def calc_parameters(self): super().calc_parameters() self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI - -class MassFactorLossModelWithPressureLoss(MassFactorLossModel): - - @staticmethod - def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["pr"] = dc_cp( - min_val=0, - deriv=self.pr_deriv, - func=self.pr_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def pr_func(self): - r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - - def pr_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - self.jacobian[k, 0, 1] = self.pr.val - self.jacobian[k, self.num_i, 1] = -1 - - def get_mandatory_constraints(self): - return { - 'mass_flow_constraints': { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1}, - 'fluid_constraints': { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': True, 'latex': self.fluid_func_doc, - 'num_eq': self.num_o * self.num_nw_fluids}, - 'energy_balance_constraints': { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': True, 'latex': self.energy_balance_func_doc, - 'num_eq': self.num_o}, - } - - def calc_parameters(self): - super().calc_parameters() - self.pr.val = self.outl[0].p.val_SI / self.inl[0].p.val_SI - for i in range(self.num_i): - if self.inl[i].p.val < self.outl[0].p.val: - msg = ( - f"The pressure at inlet {i + 1} is lower than the pressure " - f"at the outlet of component {self.label}." - ) - logging.warning(msg) - class MergeEnergySupply(Merge): @staticmethod @@ -293,25 +138,4 @@ def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() del constraints['pressure_constraints'] del constraints['energy_balance_constraints'] - return constraints - -class MassFactorVCCEnergySupply(MassFactorVCC): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances, without pressure/enthalpy constraints)' - - def get_parameters(self): - variables = super().get_parameters() - return variables - -class MassFactorLossModelEnergySupply(MassFactorLossModel): - - @staticmethod - def component(): - return 'mass factor loss model for splitting energy flows (modelled using tespy mass balances, without pressure/enthalpy constraints)' - - def get_parameters(self): - variables = super().get_parameters() - return variables - \ No newline at end of file + return constraints \ No newline at end of file From 31234c2e30e2b313db8729555155c4097e22c834 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 13:33:40 +0100 Subject: [PATCH 025/105] new folder names --- {intermediateFoodTests => incompressiblesTests}/Ex1.py | 0 {intermediateFoodTests => incompressiblesTests}/Ex1EEMAP_ref.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex1tespy070.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex4.py | 0 {intermediateFoodTests => incompressiblesTests}/Ex4EEMAP_ref.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex4tespy070.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex8.py | 0 .../Ex8EEMAP_ref_1.csv | 0 .../Ex8EEMAP_ref_2.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex8tespy070_1.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex8tespy070_2.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex9.py | 0 {intermediateFoodTests => incompressiblesTests}/Ex9EEMAP_ref.csv | 0 {intermediateFoodTests => incompressiblesTests}/Ex9tespy070.csv | 0 {intermediateFoodTests => incompressiblesTests}/diff.ipynb | 0 .../energySupply/energy-supply_energy-merge.py | 0 .../energySupply/energy-supply_energy-split.py | 0 .../energySupply/energy-supply_heat-pump.py | 0 .../energySupply/energy-supply_loss.py | 0 .../initialFoodTests/food-properties.py | 0 .../newComponentsTests/SpeciesFlowSplit.py | 0 .../newComponentsTests/SpeciesFlowSplitWithDeltaT.py | 0 .../newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py | 0 .../newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py | 0 .../newComponentsTests/SpeciesFlowSplitWithPr.py | 0 .../newComponentsTests/SplitWithFlowSplitter.py | 0 .../newComponentsTests/SplitWithFlowSplitterDeltaP.py | 0 .../newComponentsTests/SplitterWithDeltaP.py | 0 .../newComponentsTests/heatex+merge.py | 0 .../newComponentsTests/heatex_alone.py | 0 .../newComponentsTests/heatex_alone_deltaP.py | 0 .../newComponentsTests/heatex_alone_lossFactor.py | 0 .../newComponentsTests/merge_mrk.py | 0 .../newComponentsTests/simple_heatex_for_jorrit.py | 0 34 files changed, 0 insertions(+), 0 deletions(-) rename {intermediateFoodTests => incompressiblesTests}/Ex1.py (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex1EEMAP_ref.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex1tespy070.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex4.py (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex4EEMAP_ref.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex4tespy070.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex8.py (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex8EEMAP_ref_1.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex8EEMAP_ref_2.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex8tespy070_1.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex8tespy070_2.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex9.py (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex9EEMAP_ref.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/Ex9tespy070.csv (100%) rename {intermediateFoodTests => incompressiblesTests}/diff.ipynb (100%) rename {intermediateFoodTests => incompressiblesTests}/energySupply/energy-supply_energy-merge.py (100%) rename {intermediateFoodTests => incompressiblesTests}/energySupply/energy-supply_energy-split.py (100%) rename {intermediateFoodTests => incompressiblesTests}/energySupply/energy-supply_heat-pump.py (100%) rename {intermediateFoodTests => incompressiblesTests}/energySupply/energy-supply_loss.py (100%) rename {intermediateFoodTests => incompressiblesTests}/initialFoodTests/food-properties.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SpeciesFlowSplit.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SpeciesFlowSplitWithDeltaT.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SpeciesFlowSplitWithPr.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SplitWithFlowSplitter.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SplitWithFlowSplitterDeltaP.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/SplitterWithDeltaP.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/heatex+merge.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/heatex_alone.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/heatex_alone_deltaP.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/heatex_alone_lossFactor.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/merge_mrk.py (100%) rename {intermediateFoodTests => incompressiblesTests}/newComponentsTests/simple_heatex_for_jorrit.py (100%) diff --git a/intermediateFoodTests/Ex1.py b/incompressiblesTests/Ex1.py similarity index 100% rename from intermediateFoodTests/Ex1.py rename to incompressiblesTests/Ex1.py diff --git a/intermediateFoodTests/Ex1EEMAP_ref.csv b/incompressiblesTests/Ex1EEMAP_ref.csv similarity index 100% rename from intermediateFoodTests/Ex1EEMAP_ref.csv rename to incompressiblesTests/Ex1EEMAP_ref.csv diff --git a/intermediateFoodTests/Ex1tespy070.csv b/incompressiblesTests/Ex1tespy070.csv similarity index 100% rename from intermediateFoodTests/Ex1tespy070.csv rename to incompressiblesTests/Ex1tespy070.csv diff --git a/intermediateFoodTests/Ex4.py b/incompressiblesTests/Ex4.py similarity index 100% rename from intermediateFoodTests/Ex4.py rename to incompressiblesTests/Ex4.py diff --git a/intermediateFoodTests/Ex4EEMAP_ref.csv b/incompressiblesTests/Ex4EEMAP_ref.csv similarity index 100% rename from intermediateFoodTests/Ex4EEMAP_ref.csv rename to incompressiblesTests/Ex4EEMAP_ref.csv diff --git a/intermediateFoodTests/Ex4tespy070.csv b/incompressiblesTests/Ex4tespy070.csv similarity index 100% rename from intermediateFoodTests/Ex4tespy070.csv rename to incompressiblesTests/Ex4tespy070.csv diff --git a/intermediateFoodTests/Ex8.py b/incompressiblesTests/Ex8.py similarity index 100% rename from intermediateFoodTests/Ex8.py rename to incompressiblesTests/Ex8.py diff --git a/intermediateFoodTests/Ex8EEMAP_ref_1.csv b/incompressiblesTests/Ex8EEMAP_ref_1.csv similarity index 100% rename from intermediateFoodTests/Ex8EEMAP_ref_1.csv rename to incompressiblesTests/Ex8EEMAP_ref_1.csv diff --git a/intermediateFoodTests/Ex8EEMAP_ref_2.csv b/incompressiblesTests/Ex8EEMAP_ref_2.csv similarity index 100% rename from intermediateFoodTests/Ex8EEMAP_ref_2.csv rename to incompressiblesTests/Ex8EEMAP_ref_2.csv diff --git a/intermediateFoodTests/Ex8tespy070_1.csv b/incompressiblesTests/Ex8tespy070_1.csv similarity index 100% rename from intermediateFoodTests/Ex8tespy070_1.csv rename to incompressiblesTests/Ex8tespy070_1.csv diff --git a/intermediateFoodTests/Ex8tespy070_2.csv b/incompressiblesTests/Ex8tespy070_2.csv similarity index 100% rename from intermediateFoodTests/Ex8tespy070_2.csv rename to incompressiblesTests/Ex8tespy070_2.csv diff --git a/intermediateFoodTests/Ex9.py b/incompressiblesTests/Ex9.py similarity index 100% rename from intermediateFoodTests/Ex9.py rename to incompressiblesTests/Ex9.py diff --git a/intermediateFoodTests/Ex9EEMAP_ref.csv b/incompressiblesTests/Ex9EEMAP_ref.csv similarity index 100% rename from intermediateFoodTests/Ex9EEMAP_ref.csv rename to incompressiblesTests/Ex9EEMAP_ref.csv diff --git a/intermediateFoodTests/Ex9tespy070.csv b/incompressiblesTests/Ex9tespy070.csv similarity index 100% rename from intermediateFoodTests/Ex9tespy070.csv rename to incompressiblesTests/Ex9tespy070.csv diff --git a/intermediateFoodTests/diff.ipynb b/incompressiblesTests/diff.ipynb similarity index 100% rename from intermediateFoodTests/diff.ipynb rename to incompressiblesTests/diff.ipynb diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-merge.py b/incompressiblesTests/energySupply/energy-supply_energy-merge.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_energy-merge.py rename to incompressiblesTests/energySupply/energy-supply_energy-merge.py diff --git a/intermediateFoodTests/energySupply/energy-supply_energy-split.py b/incompressiblesTests/energySupply/energy-supply_energy-split.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_energy-split.py rename to incompressiblesTests/energySupply/energy-supply_energy-split.py diff --git a/intermediateFoodTests/energySupply/energy-supply_heat-pump.py b/incompressiblesTests/energySupply/energy-supply_heat-pump.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_heat-pump.py rename to incompressiblesTests/energySupply/energy-supply_heat-pump.py diff --git a/intermediateFoodTests/energySupply/energy-supply_loss.py b/incompressiblesTests/energySupply/energy-supply_loss.py similarity index 100% rename from intermediateFoodTests/energySupply/energy-supply_loss.py rename to incompressiblesTests/energySupply/energy-supply_loss.py diff --git a/intermediateFoodTests/initialFoodTests/food-properties.py b/incompressiblesTests/initialFoodTests/food-properties.py similarity index 100% rename from intermediateFoodTests/initialFoodTests/food-properties.py rename to incompressiblesTests/initialFoodTests/food-properties.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SpeciesFlowSplit.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py diff --git a/intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SpeciesFlowSplitWithPr.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py b/incompressiblesTests/newComponentsTests/SplitWithFlowSplitter.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SplitWithFlowSplitter.py rename to incompressiblesTests/newComponentsTests/SplitWithFlowSplitter.py diff --git a/intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py b/incompressiblesTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py rename to incompressiblesTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py diff --git a/intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/SplitterWithDeltaP.py rename to incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py diff --git a/intermediateFoodTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/heatex+merge.py rename to incompressiblesTests/newComponentsTests/heatex+merge.py diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone.py b/incompressiblesTests/newComponentsTests/heatex_alone.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/heatex_alone.py rename to incompressiblesTests/newComponentsTests/heatex_alone.py diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/heatex_alone_deltaP.py rename to incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py diff --git a/intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/heatex_alone_lossFactor.py rename to incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py diff --git a/intermediateFoodTests/newComponentsTests/merge_mrk.py b/incompressiblesTests/newComponentsTests/merge_mrk.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/merge_mrk.py rename to incompressiblesTests/newComponentsTests/merge_mrk.py diff --git a/intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py b/incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py similarity index 100% rename from intermediateFoodTests/newComponentsTests/simple_heatex_for_jorrit.py rename to incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py From 086991e9344c38fd44c183b0b1719b6be56af041 Mon Sep 17 00:00:00 2001 From: mrk Date: Sun, 5 Nov 2023 20:35:41 +0100 Subject: [PATCH 026/105] I think we should always include and fluid composition equations for a separator. And I think we should also not use sum to 1 concentration, only when one fluid is remaining in some connector.. --- .../SpeciesFlowSplitWithDeltaTAndPr.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py index 8538d196f..53f9e2ebb 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py @@ -45,9 +45,12 @@ c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'T66', 'split_outlet' : "out1"}) +# se.set_attr(SFS={ +# 'val': 0.6, 'is_set': True, +# 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + +c3.set_attr(fluid={"INCOMP::Water": 0.95}) +#c3.set_attr(m=0.5) # Now it is possible to set the temperatures out of the separator differently c2.set_attr(T=20,p=5) From ab0c8f5c001dc5291ed8b2f06c0ec9e68daf17eb Mon Sep 17 00:00:00 2001 From: mrk Date: Sun, 5 Nov 2023 20:36:13 +0100 Subject: [PATCH 027/105] I think we should always include and fluid composition equations for a separator. And I think we should also not use sum to 1 concentration, only when one fluid is remaining in some connector.. --- src/tespy/components/newcomponents.py | 12 ++++++++++++ src/tespy/networks/network.py | 22 +++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 0a6f2fb31..4f5d4ae4f 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -387,6 +387,12 @@ def get_parameters(self): def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() + self.variable_fluids = self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} del constraints['energy_balance_constraints'] return constraints @@ -441,6 +447,12 @@ def get_parameters(self): def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() + self.variable_fluids = self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} del constraints['pressure_constraints'] return constraints diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 30e60c8a0..204929582 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1046,17 +1046,17 @@ def presolve_fluid_topology(self): # remaining fluids are variable, create wrappers for them all_fluids = main_conn.fluid.val.keys() num_remaining_fluids = len(all_fluids) - len(fixed_fractions) - if num_remaining_fluids == 1: - missing_fluid = list( - main_conn.fluid.val.keys() - fixed_fractions.keys() - )[0] - fixed_fractions[missing_fluid] = 1 - mass_fraction_sum - variable = set() - else: - missing_fluids = ( - main_conn.fluid.val.keys() - fixed_fractions.keys() - ) - variable = {f for f in missing_fluids} + # if num_remaining_fluids == 1: + # missing_fluid = list( + # main_conn.fluid.val.keys() - fixed_fractions.keys() + # )[0] + # fixed_fractions[missing_fluid] = 1 - mass_fraction_sum + # variable = set() + # else: + missing_fluids = ( + main_conn.fluid.val.keys() - fixed_fractions.keys() + ) + variable = {f for f in missing_fluids} else: # fluid mass fraction is 100 %, all other fluids are 0 % From bbcb7213459166745704a56e8afc9b7abb33cd75 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 6 Nov 2023 11:40:20 +0100 Subject: [PATCH 028/105] let's syncronize the way fluids are specified, also for the split_fluid --- .../newComponentsTests/SpeciesFlowSplit.py | 4 ++-- .../newComponentsTests/SpeciesFlowSplitWithDeltaT.py | 2 +- .../newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py | 8 ++++---- .../SpeciesFlowSplitWithDeltaTAndPrAndBus.py | 2 +- .../newComponentsTests/SpeciesFlowSplitWithPr.py | 2 +- src/tespy/tools/data_containers.py | 7 +++++-- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py index 95a7d1ef7..154d4c17f 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py @@ -38,7 +38,7 @@ se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -47,7 +47,7 @@ se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'Water', 'split_outlet' : "out1"}) + 'split_fluid' : 'INCOMP::Water', 'split_outlet' : "out1"}) nw.solve("design") if not nw.converged: raise Exception("not converged") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py index 02ee540ea..c5cad4b93 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -47,7 +47,7 @@ se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) se.set_attr(deltaT=5) nw.solve("design") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py index 53f9e2ebb..4b5026e36 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py @@ -45,11 +45,11 @@ c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) -# se.set_attr(SFS={ -# 'val': 0.6, 'is_set': True, -# 'split_fluid' : 'T66', 'split_outlet' : "out1"}) +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) -c3.set_attr(fluid={"INCOMP::Water": 0.95}) +#c3.set_attr(fluid={"INCOMP::Water": 0.95}) #c3.set_attr(m=0.5) # Now it is possible to set the temperatures out of the separator differently diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py index be3d5e71b..62ed0ddef 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py @@ -50,7 +50,7 @@ se.set_attr(SFS={ 'val': 0.6, 'is_set': True, - 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) # Now it is possible to set the temperatures out of the separator differently c2.set_attr(T=20,p=5) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py index e7f86e88e..881d85e79 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py @@ -48,7 +48,7 @@ se.set_attr(SFS={ 'val': 0.65, 'is_set': True, - 'split_fluid' : 'T66', 'split_outlet' : "out1"}) + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) se.set_attr(deltaP=1.2) diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index c5683d132..866e1707e 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -115,8 +115,11 @@ def set_attr(self, **kwargs): # specify values for key in kwargs: if key in var: - self.__dict__.update({key: kwargs[key]}) - + if key == "split_fluid": + back_end, fluid = kwargs[key].split("::") + self.__dict__.update({key: fluid}) + else: + self.__dict__.update({key: kwargs[key]}) else: msg = ( f"Datacontainer of type {self.__class__.__name__} has no " From 1046dd5ce62f9fd3b8c6710e600218ecdc70cb33 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 6 Nov 2023 11:45:07 +0100 Subject: [PATCH 029/105] let's keep backward compatibility --- src/tespy/tools/data_containers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index 866e1707e..fbee9a19f 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -116,7 +116,10 @@ def set_attr(self, **kwargs): for key in kwargs: if key in var: if key == "split_fluid": - back_end, fluid = kwargs[key].split("::") + if "::" in kwargs[key]: + _, fluid = kwargs[key].split("::") + else: + fluid = kwargs[key] self.__dict__.update({key: fluid}) else: self.__dict__.update({key: kwargs[key]}) From 14fb14fcbd29aff304bab10742ba477d7f3927f1 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 16:12:11 +0100 Subject: [PATCH 030/105] need force_state, limit_increments and RobustRelax --- src/tespy/components/newcomponents.py | 17 +++- src/tespy/connections/connection.py | 37 ++++--- src/tespy/networks/network.py | 99 ++++++++++++++----- src/tespy/networks/network_reader.py | 16 ++- src/tespy/tools/data_containers.py | 2 +- src/tespy/tools/fluid_properties/functions.py | 56 +++++------ src/tespy/tools/fluid_properties/helpers.py | 6 +- src/tespy/tools/fluid_properties/mixtures.py | 10 +- src/tespy/tools/fluid_properties/wrappers.py | 56 ++++++----- 9 files changed, 195 insertions(+), 104 deletions(-) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 4f5d4ae4f..5c94f7998 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -309,6 +309,7 @@ class SeparatorWithSpeciesSplits(Separator): def __init__(self, label, **kwargs): #self.set_attr(**kwargs) # need to assign the number of outlets before the variables are set + self.num_out = 2 # default for key in kwargs: if key == 'num_out': self.num_out=kwargs[key] @@ -703,8 +704,15 @@ class dc_cp_SFS(dc_cp): @staticmethod def attr(): attributes = dc_cp.attr() - attributes.update({'split_fluid' : str, 'split_outlet' : str}) + attributes.update({'split_fluid' : None, 'split_outlet' : None}) return attributes + + @staticmethod + def _serializable_keys(): + keys = dc_cp._serializable_keys() + keys.append("split_fluid") + keys.append("split_outlet") + return keys class dc_cp_FS(dc_cp): """ @@ -714,6 +722,11 @@ class dc_cp_FS(dc_cp): @staticmethod def attr(): attributes = dc_cp.attr() - attributes.update({'split_outlet' : str}) + attributes.update({'split_outlet' : None}) return attributes + @staticmethod + def _serializable_keys(): + keys = dc_cp._serializable_keys() + keys.append("split_outlet") + return keys diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index e402bb6bc..a7210d23f 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -263,6 +263,9 @@ def __init__(self, source, outlet_id, target, inlet_id, self.local_offdesign = False self.printout = True + self.force_state = None + self.good_starting_values = None + # set default values for kwargs self.property_data = self.get_parameters() self.parameters = { @@ -462,6 +465,12 @@ def set_attr(self, **kwargs): elif key == "mixing_rule": self.mixing_rule = kwargs[key] + elif key == "force_state": + self.force_state = kwargs[key] + + elif key == "good_starting_values": + self.good_starting_values = kwargs[key] + # invalid keyword else: msg = 'Connection has no attribute ' + key + '.' @@ -596,7 +605,7 @@ def _serializable(): return [ "source_id", "target_id", "design_path", "design", "offdesign", "local_design", "local_design", - "printout", "mixing_rule" + "printout", "mixing_rule","good_starting_values","force_state" ] def _create_fluid_wrapper(self): @@ -654,12 +663,12 @@ def simplify_specifications(self): if not self.h.is_set and self.p.is_set: if self.T.is_set: - self.h.val_SI = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule) + self.h.val_SI = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule, self.force_state) self.h.solved = True self.T.solved = True elif self.Td_bp.is_set: T_sat = T_sat_p(self.p.val_SI, self.fluid_data) - self.h.val_SI = h_mix_pT(self.p.val_SI, T_sat + self.Td_bp.val, self.fluid_data) + self.h.val_SI = h_mix_pT(self.p.val_SI, T_sat + self.Td_bp.val, self.fluid_data, self.force_state) self.h.solved = True self.Td_bp.solved = True elif self.x.is_set: @@ -737,7 +746,7 @@ def primary_ref_deriv(self, k, **kwargs): self.jacobian[k, ref.obj.get_attr(variable).J_col] = -ref.factor def calc_T(self, T0=None): - return T_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0) + return T_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0, force_state=self.force_state) def T_func(self, k, **kwargs): self.residual[k] = self.calc_T() - self.T.val_SI @@ -745,16 +754,16 @@ def T_func(self, k, **kwargs): def T_deriv(self, k, **kwargs): if self.p.is_var: self.jacobian[k, self.p.J_col] = ( - dT_mix_dph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, self.T.val_SI) + dT_mix_dph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, self.T.val_SI, force_state=self.force_state) ) if self.h.is_var: self.jacobian[k, self.h.J_col] = ( - dT_mix_pdh(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, self.T.val_SI) + dT_mix_pdh(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, self.T.val_SI, force_state=self.force_state) ) for fluid in self.fluid.is_var: # if not self._increment_filter[self.fluid.J_col[fluid]]: self.jacobian[k, self.fluid.J_col[fluid]] = dT_mix_ph_dfluid( - self.p.val_SI, self.h.val_SI, fluid, self.fluid_data, self.mixing_rule + self.p.val_SI, self.h.val_SI, fluid, self.fluid_data, self.mixing_rule, force_state=self.force_state ) def T_ref_func(self, k, **kwargs): @@ -790,7 +799,7 @@ def calc_viscosity(self, T0=None): def calc_vol(self, T0=None): try: - return v_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0) + return v_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0, force_state=self.force_state) except NotImplementedError: return np.nan @@ -876,7 +885,7 @@ def Td_bp_deriv(self, k, **kwargs): ) def calc_s(self): - return s_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=self.T.val_SI) + return s_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=self.T.val_SI, force_state=self.force_state) def calc_Q(self): return Q_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data) @@ -893,7 +902,7 @@ def calc_results(self): number_fluids = get_number_of_fluids(self.fluid_data) _converged = True if number_fluids > 1: - h_from_T = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule) + h_from_T = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule, force_state=self.force_state) if abs(h_from_T - self.h.val_SI) > ERR ** .5: self.T.val_SI = np.nan self.vol.val_SI = np.nan @@ -953,7 +962,7 @@ def check_enthalpy_bounds(self, fluid): # enthalpy try: hmin = self.fluid.wrapper[fluid].h_pT( - self.p.val_SI, self.fluid.wrapper[fluid]._T_min + 1e-1 + self.p.val_SI, self.fluid.wrapper[fluid]._T_min + 1e-1,force_state=self.force_state ) except ValueError: f = 1.05 @@ -971,7 +980,7 @@ def check_enthalpy_bounds(self, fluid): T = self.fluid.wrapper[fluid]._T_max while True: try: - hmax = self.fluid.wrapper[fluid].h_pT(self.p.val_SI, T) + hmax = self.fluid.wrapper[fluid].h_pT(self.p.val_SI, T, force_state=self.force_state) break except ValueError as e: T *= 0.99 @@ -1010,8 +1019,8 @@ def check_temperature_bounds(self): Tmax = min( [w._T_max for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR] ) * 0.99 - hmin = h_mix_pT(self.p.val_SI, Tmin, self.fluid_data, self.mixing_rule) - hmax = h_mix_pT(self.p.val_SI, Tmax, self.fluid_data, self.mixing_rule) + hmin = h_mix_pT(self.p.val_SI, Tmin, self.fluid_data, self.mixing_rule, force_state=self.force_state) + hmax = h_mix_pT(self.p.val_SI, Tmax, self.fluid_data, self.mixing_rule, force_state=self.force_state) if self.h.val_SI < hmin: self.h.val_SI = hmin diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 204929582..21d0ae52b 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1667,7 +1667,7 @@ def init_properties(self): 'network.') logger.warning(msg) - for key in ['m', 'p', 'h', 'T']: # maybe add all properties to be initialized (maybe also initialize those from init_path) + for key in ['m', 'p', 'h']: if c.get_attr(key).is_var: if not c.good_starting_values: self.init_val0(c, key) @@ -1763,7 +1763,7 @@ def init_precalc_properties(self, c): if c.T.is_set: try: - c.h.val_SI = fp.h_mix_pT(c.p.val_SI, c.T.val_SI, c.fluid_data, c.mixing_rule) + c.h.val_SI = fp.h_mix_pT(c.p.val_SI, c.T.val_SI, c.fluid_data, c.mixing_rule, force_state=c.force_state) except ValueError: pass @@ -1791,18 +1791,11 @@ def init_val0(self, c: con.Connection, key: str): val_s = c.source.initialise_source(c, key) val_t = c.target.initialise_target(c, key) - if val_s is None: - val_s = 0 - if val_t is None: - val_t = 0 - if val_s == 0 and val_t == 0: if key == 'p': c.get_attr(key).val0 = 1e5 elif key == 'h': c.get_attr(key).val0 = 1e6 - elif key == 'T': # should probably add other paratemeter too ? - c.get_attr(key).val0 = 300 elif val_s == 0: c.get_attr(key).val0 = val_t @@ -2226,36 +2219,92 @@ def matrix_inversion(self): except np.linalg.linalg.LinAlgError: self.increment = self.residual * 0 + def _limit_increments(self,valmin,valmax,val,increment): + inc_min = valmin-val + inc_max = valmax-val + + if increment < inc_min: + # need to limit the increment + if inc_min < -0.01/(valmax-valmin): + # if we are not close the the bound we limit it half way to the bound + increment = inc_min/2 + else: + # othervice we set the increment to the bound + increment = inc_min + + if increment > inc_max: + # need to limit the increment + if inc_max > 0.01/(valmax-valmin): + # if we are not close the the bound we limit it half way to the bound + increment = inc_max/2 + else: + # othervice we set the increment to the bound + increment = inc_max + return increment + def update_variables(self): + + if self.iter < 2: + RobustRelax = 0.1 + elif self.iter < 4: + RobustRelax = 0.25 + elif self.iter < 6: + RobustRelax = 0.5 + else: + RobustRelax = 1 + + #RobustRelax = 1 + # add the increment for data in self.variables_dict.values(): - if data["variable"] in ["m", "h"]: + if data["variable"] == "m": + container = data["obj"].get_attr(data["variable"]) + increment = self.increment[container.J_col] + container.val_SI += RobustRelax * self._limit_increments(self.m_range_SI[0],self.m_range_SI[1],container.val_SI,increment) + #print(container.val_SI) + elif data["variable"] == "h": container = data["obj"].get_attr(data["variable"]) - container.val_SI += self.increment[container.J_col] + increment = self.increment[container.J_col] + container.val_SI += RobustRelax * self._limit_increments(self.h_range_SI[0],self.h_range_SI[1],container.val_SI,increment) + #print(container.val_SI) elif data["variable"] == "p": container = data["obj"].p increment = self.increment[container.J_col] relax = max(1, -2 * increment / container.val_SI) - container.val_SI += increment / relax + container.val_SI += RobustRelax * increment / relax + # increment = self.increment[container.J_col] + # container.val_SI += self._limit_increments(self.p_range_SI[0],self.p_range_SI[1],container.val_SI,increment) + #print(container.val_SI) elif data["variable"] == "fluid": container = data["obj"].fluid - container.val[data["fluid"]] += self.increment[ - container.J_col[data["fluid"]] - ] - if container.val[data["fluid"]] < ERR : - container.val[data["fluid"]] = 0 - elif container.val[data["fluid"]] > 1 - ERR : - container.val[data["fluid"]] = 1 + increment = self.increment[container.J_col[data["fluid"]]] + val = container.val[data["fluid"]] + container.val[data["fluid"]] += RobustRelax * self._limit_increments(0,1,val,increment) + + #print(container.val[data["fluid"]]) + + # if container.val[data["fluid"]] < ERR : + # container.val[data["fluid"]] = 0 + # elif container.val[data["fluid"]] > 1 - ERR : + # container.val[data["fluid"]] = 1 else: # add increment - data["obj"].val += self.increment[data["obj"].J_col] + + increment = self.increment[data["obj"].J_col] + val = data["obj"].val + data["obj"].val += RobustRelax * self._limit_increments(data["obj"].min_val,data["obj"].max_val,val,increment) + + #data["obj"].val += RobustRelax * self.increment[data["obj"].J_col] + + + - # keep value within specified value range - if data["obj"].val < data["obj"].min_val: - data["obj"].val = data["obj"].min_val - elif data["obj"].val > data["obj"].max_val: - data["obj"].val = data["obj"].max_val + # # keep value within specified value range + # if data["obj"].val < data["obj"].min_val: + # data["obj"].val = data["obj"].min_val + # elif data["obj"].val > data["obj"].max_val: + # data["obj"].val = data["obj"].max_val def check_variable_bounds(self): diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index ecbe2bbac..94f79f141 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -41,6 +41,7 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer +from tespy.components.newcomponents import * from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref @@ -81,7 +82,14 @@ 'WaterElectrolyzer': WaterElectrolyzer, 'Compressor': Compressor, 'Pump': Pump, - 'Turbine': Turbine + 'Turbine': Turbine, + 'MergeWithPressureLoss' :MergeWithPressureLoss, + 'SeparatorWithSpeciesSplits' : SeparatorWithSpeciesSplits, + 'SeparatorWithSpeciesSplitsAndDeltaT' : SeparatorWithSpeciesSplitsAndDeltaT, + 'SeparatorWithSpeciesSplitsAndDeltaTAndPr' : SeparatorWithSpeciesSplitsAndDeltaTAndPr, + 'SeparatorWithSpeciesSplitsAndPr' : SeparatorWithSpeciesSplitsAndPr, + 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, + 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, } ENGINE_TARGET_CLASSES = { @@ -336,9 +344,11 @@ def construct_components(component, data): container = instances[cp].get_attr(param) if isinstance(container, dc): if isinstance(container, dc_cc): - param_data["char_func"] = CharLine(**param_data["char_func"]) + if 'char_func' in param_data.keys(): + param_data["char_func"] = CharLine(**param_data["char_func"]) elif isinstance(container, dc_cm): - param_data["char_func"] = CharMap(**param_data["char_func"]) + if 'char_func' in param_data.keys(): + param_data["char_func"] = CharMap(**param_data["char_func"]) if isinstance(container, dc_prop): param_data["val0"] = param_data["val"] container.set_attr(**param_data) diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index fbee9a19f..0a7a70e11 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -115,7 +115,7 @@ def set_attr(self, **kwargs): # specify values for key in kwargs: if key in var: - if key == "split_fluid": + if key == "split_fluid" and kwargs[key]: if "::" in kwargs[key]: _, fluid = kwargs[key].split("::") else: diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index 9ae4c1a52..42a1482c2 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -72,7 +72,7 @@ def calc_chemical_exergy(pamb, Tamb, fluid_data, Chem_Ex, mixing_rule=None, T0=N return EXERGY_CHEMICAL[mixing_rule](pamb, Tamb, fluid_data, Chem_Ex) -def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): +def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_ph(p, h) @@ -80,42 +80,42 @@ def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): _check_mixing_rule(mixing_rule, T_MIX_PH_REVERSE, "temperature (from enthalpy)") kwargs = { "p": p, "target_value": h, "fluid_data": fluid_data, "T0": T0, - "f": T_MIX_PH_REVERSE[mixing_rule] + "f": T_MIX_PH_REVERSE[mixing_rule], "force_state" : force_state, } return inverse_temperature_mixture(**kwargs) -def dT_mix_pdh(p, h, fluid_data, mixing_rule=None, T0=None): +def dT_mix_pdh(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): d = 1e-1 - upper = T_mix_ph(p, h + d, fluid_data, mixing_rule=mixing_rule, T0=T0) - lower = T_mix_ph(p, h - d, fluid_data, mixing_rule=mixing_rule, T0=upper) + upper = T_mix_ph(p, h + d, fluid_data, mixing_rule=mixing_rule, T0=T0, force_state=force_state) + lower = T_mix_ph(p, h - d, fluid_data, mixing_rule=mixing_rule, T0=upper, force_state=force_state) return (upper - lower) / (2 * d) -def dT_mix_dph(p, h, fluid_data, mixing_rule=None, T0=None): +def dT_mix_dph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): d = 1e-1 - upper = T_mix_ph(p + d, h, fluid_data, mixing_rule=mixing_rule, T0=T0) - lower = T_mix_ph(p - d, h, fluid_data, mixing_rule=mixing_rule, T0=upper) + upper = T_mix_ph(p + d, h, fluid_data, mixing_rule=mixing_rule, T0=T0, force_state=force_state) + lower = T_mix_ph(p - d, h, fluid_data, mixing_rule=mixing_rule, T0=upper, force_state=force_state) return (upper - lower) / (2 * d) -def dT_mix_ph_dfluid(p, h, fluid, fluid_data, mixing_rule=None, T0=None): +def dT_mix_ph_dfluid(p, h, fluid, fluid_data, mixing_rule=None, T0=None, force_state=None): d = 1e-5 fluid_data[fluid]["mass_fraction"] += d - upper = T_mix_ph(p, h, fluid_data, mixing_rule=mixing_rule, T0=T0) + upper = T_mix_ph(p, h, fluid_data, mixing_rule=mixing_rule, T0=T0, force_state=force_state) fluid_data[fluid]["mass_fraction"] -= 2 * d - lower = T_mix_ph(p, h, fluid_data, mixing_rule=mixing_rule, T0=upper) + lower = T_mix_ph(p, h, fluid_data, mixing_rule=mixing_rule, T0=upper, force_state=force_state) fluid_data[fluid]["mass_fraction"] += d return (upper - lower) / (2 * d) -def h_mix_pT(p, T, fluid_data, mixing_rule=None): +def h_mix_pT(p, T, fluid_data, mixing_rule=None, force_state = None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) - return pure_fluid["wrapper"].h_pT(p, T) + return pure_fluid["wrapper"].h_pT(p, T, force_state=force_state) else: _check_mixing_rule(mixing_rule, H_MIX_PT_DIRECT, "enthalpy") - return H_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data) + return H_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data, force_state=force_state) def h_mix_pQ(p, Q, fluid_data, mixing_rule=None): @@ -168,26 +168,26 @@ def dT_sat_dp(p, fluid_data, mixing_rule=None): return (upper - lower) / (2 * d) -def s_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): +def s_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].s_ph(p, h) else: - T = T_mix_ph(p, h , fluid_data, mixing_rule, T0) - return s_mix_pT(p, T, fluid_data, mixing_rule) + T = T_mix_ph(p, h , fluid_data, mixing_rule, T0, force_state=force_state) + return s_mix_pT(p, T, fluid_data, mixing_rule, force_state=force_state) -def s_mix_pT(p, T, fluid_data, mixing_rule=None): +def s_mix_pT(p, T, fluid_data, mixing_rule=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].s_pT(p, T) else: _check_mixing_rule(mixing_rule, S_MIX_PT_DIRECT, "entropy") - return S_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data) + return S_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data, force_state=force_state) -def T_mix_ps(p, s, fluid_data, mixing_rule=None, T0=None): +def T_mix_ps(p, s, fluid_data, mixing_rule=None, T0=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_ps(p, s) @@ -195,18 +195,18 @@ def T_mix_ps(p, s, fluid_data, mixing_rule=None, T0=None): _check_mixing_rule(mixing_rule, T_MIX_PS_REVERSE, "temperature (from entropy)") kwargs = { "p": p, "target_value": s, "fluid_data": fluid_data, "T0": T0, - "f": T_MIX_PS_REVERSE[mixing_rule] + "f": T_MIX_PS_REVERSE[mixing_rule], "force_state" : force_state, } return inverse_temperature_mixture(**kwargs) -def v_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): +def v_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return 1 / pure_fluid["wrapper"].d_ph(p, h) else: - T = T_mix_ph(p, h , fluid_data, mixing_rule, T0) - return v_mix_pT(p, T, fluid_data, mixing_rule) + T = T_mix_ph(p, h , fluid_data, mixing_rule, T0, force_state=force_state) + return v_mix_pT(p, T, fluid_data, mixing_rule, force_state=force_state) def dv_mix_dph(p, h, fluid_data, mixing_rule=None, T0=None): @@ -223,13 +223,13 @@ def dv_mix_pdh(p, h, fluid_data, mixing_rule=None, T0=None): return (upper - lower) / (2 * d) -def v_mix_pT(p, T, fluid_data, mixing_rule=None): +def v_mix_pT(p, T, fluid_data, mixing_rule=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return 1 / pure_fluid["wrapper"].d_pT(p, T) else: _check_mixing_rule(mixing_rule, V_MIX_PT_DIRECT, "specific volume") - return V_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data) + return V_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data, force_state=force_state) def viscosity_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): @@ -241,10 +241,10 @@ def viscosity_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None): return viscosity_mix_pT(p, T, fluid_data, mixing_rule) -def viscosity_mix_pT(p, T, fluid_data, mixing_rule=None): +def viscosity_mix_pT(p, T, fluid_data, mixing_rule=None, force_state=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].viscosity_pT(p, T) else: _check_mixing_rule(mixing_rule, V_MIX_PT_DIRECT, "viscosity") - return VISCOSITY_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data) + return VISCOSITY_MIX_PT_DIRECT[mixing_rule](p, T, fluid_data, force_state=force_state) diff --git a/src/tespy/tools/fluid_properties/helpers.py b/src/tespy/tools/fluid_properties/helpers.py index c94576b84..53875f78a 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -92,17 +92,17 @@ def central_difference(function=None, parameter=None, delta=None, **kwargs): return (function(**upper) - function(**lower)) / (2 * delta) -def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=None, f=None): +def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=None, f=None, **function_kwargs): # calculate the fluid properties for fluid mixtures valmin, valmax = get_mixture_temperature_range(fluid_data) if T0 is None: T0 = (valmin + valmax) / 2.0 T0 = max(valmin,min(valmax,T0)) - function_kwargs = { + function_kwargs.update({ "p": p, "fluid_data": fluid_data, "T": T0, "function": f, "parameter": "T" , "delta": 0.01 - } + }) return newton_with_kwargs( central_difference, target_value, diff --git a/src/tespy/tools/fluid_properties/mixtures.py b/src/tespy/tools/fluid_properties/mixtures.py index 53c9ba020..3dabe6996 100644 --- a/src/tespy/tools/fluid_properties/mixtures.py +++ b/src/tespy/tools/fluid_properties/mixtures.py @@ -67,8 +67,8 @@ def h_mix_pT_incompressible(p, T, fluid_data, **kwargs): h = 0 for data in fluid_data.values(): if _is_larger_than_precision(data["mass_fraction"]): - h += data["wrapper"].h_pT(p, T) * data["mass_fraction"] - + h += data["wrapper"].h_pT(p, T, **kwargs) * data["mass_fraction"] + return h @@ -113,7 +113,7 @@ def s_mix_pT_incompressible(p=None, T=None, fluid_data=None, **kwargs): for data in fluid_data.values(): if _is_larger_than_precision(data["mass_fraction"]): - s += data["wrapper"].s_pT(p, T) * data["mass_fraction"] + s += data["wrapper"].s_pT(p, T, **kwargs) * data["mass_fraction"] return s @@ -158,7 +158,7 @@ def v_mix_pT_incompressible(p=None, T=None, fluid_data=None, **kwargs): v = 0 for data in fluid_data.values(): if _is_larger_than_precision(data["mass_fraction"]): - v += 1 / data["wrapper"].d_pT(p, T) * data["mass_fraction"] + v += 1 / data["wrapper"].d_pT(p, T, **kwargs) * data["mass_fraction"] return v @@ -214,7 +214,7 @@ def viscosity_mix_pT_incompressible(p=None, T=None, fluid_data=None, **kwargs): viscosity = 0 for data in fluid_data.values(): if _is_larger_than_precision(data["mass_fraction"]): - viscosity += data["wrapper"].viscosity_pT(p, T) * data["mass_fraction"] + viscosity += data["wrapper"].viscosity_pT(p, T, **kwargs) * data["mass_fraction"] return viscosity diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index be6c01b55..33c3c791b 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -147,18 +147,34 @@ def h_ps(self, p, s): self.AS.update(CP.PSmass_INPUTS, p, s) return self.AS.hmass() - def _ensure_incomp_is_liquid(self,p,T): - self.AS.update(CP.QT_INPUTS, 0, T) - psat = self.AS.p() # pressure must always be greater than saturation for incompressibles - p = max(p,psat*(1+ERR)) - if T == (self._T_max + self._T_min) / 2: - T += ERR - return p,T - - def h_pT(self, p, T): + def _check_imposed_state(self,p,T,**kwargs): + # correct INCOMP interpolation origin if self.back_end == "INCOMP": - p,T = self._ensure_incomp_is_liquid(p,T) - self.AS.update(CP.PT_INPUTS, p, T) + if T == (self._T_max + self._T_min) / 2: + T += ERR + if kwargs['force_state'] == "l" or self.back_end == "INCOMP": # incomp is always liquid + self.AS.update(CP.QT_INPUTS, 0, T) + if p > self.AS.p(): + try: + self.AS.update(CP.PT_INPUTS, p, T) + except: + print("allowing state to move up on the liquid saturation curve") + self.AS.update(CP.QT_INPUTS, 0, T) + pass + elif kwargs['force_state'] == "g": + self.AS.update(CP.QT_INPUTS, 0, T) + if p < self.AS.p(): + try: + self.AS.update(CP.PT_INPUTS, p, T) + except: + print("allowing state to move further down on the gas curve") + self.AS.update(CP.QT_INPUTS, 0, T) + pass + else: + self.AS.update(CP.PT_INPUTS, p, T) + + def h_pT(self, p, T, **kwargs): + self._check_imposed_state(p,T,**kwargs) return self.AS.hmass() def h_QT(self, Q, T): @@ -190,10 +206,8 @@ def d_ph(self, p, h): self.AS.update(CP.HmassP_INPUTS, h, p) return self.AS.rhomass() - def d_pT(self, p, T): - if self.back_end == "INCOMP": - p,T = self._ensure_incomp_is_liquid(p,T) - self.AS.update(CP.PT_INPUTS, p, T) + def d_pT(self, p, T, **kwargs): + self._check_imposed_state(p,T, **kwargs) return self.AS.rhomass() def d_QT(self, Q, T): @@ -204,20 +218,16 @@ def viscosity_ph(self, p, h): self.AS.update(CP.HmassP_INPUTS, h, p) return self.AS.viscosity() - def viscosity_pT(self, p, T): - if self.back_end == "INCOMP": - p,T = self._ensure_incomp_is_liquid(p,T) - self.AS.update(CP.PT_INPUTS, p, T) + def viscosity_pT(self, p, T, **kwargs): + self._check_imposed_state(p,T, **kwargs) return self.AS.viscosity() def s_ph(self, p, h): self.AS.update(CP.HmassP_INPUTS, h, p) return self.AS.smass() - def s_pT(self, p, T): - if self.back_end == "INCOMP": - p,T = self._ensure_incomp_is_liquid(p,T) - self.AS.update(CP.PT_INPUTS, p, T) + def s_pT(self, p, T, **kwargs): + self._check_imposed_state(p,T, **kwargs) return self.AS.smass() From 9b2d71990c1b8c95b42b6bbd529fc892ac3de537 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 16:12:29 +0100 Subject: [PATCH 031/105] more examples --- ...esFlowSplitWithDeltaTAndPr-decanterTest.py | 120 ++++++++++++++++++ .../newComponentsTests/heatex+merge.py | 6 +- 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py new file mode 100644 index 000000000..e5aaca693 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py @@ -0,0 +1,120 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::FoodWater", "INCOMP::FoodFat", "INCOMP::FoodProtein"] +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsAndDeltaTAndPr("Separator",num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 76 # transform unit at some point [this is kt/yr] +h0 = 119 # global guess value in kJ/kg +p0 = 1 # global guess value in bar + +#water = 'INCOMP::FoodWater' +water = 'Water' + +for c in nw.conns['object']: + n_fl = 3 # len(nw.fluids) + c.set_attr(m0=80,h0=h0,p0=p0,fluid0={water: 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) + +# set some generic data for starting values +c1.set_attr(m=1, p=p0, T=95, fluid={water: 0.902, "INCOMP::FoodFat": 0.023, "INCOMP::FoodProtein": 0.075}, mixing_rule="incompressible") +c2.set_attr(fluid={water: 0.648, "INCOMP::FoodFat": 0.022, "INCOMP::FoodProtein": 0.33}) + +c3.set_attr(force_state='l') + +se.set_attr(SFS={ + 'val': 0.35, 'is_set': True, + 'split_fluid' : 'INCOMP::FoodProtein', 'split_outlet' : "out1"}) + + +# Now it is possible to set the temperatures out of the separator differently +c2.set_attr(T=90,p=p0) +c3.set_attr(T=90,p=p0) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +else: + nw.print_results() + print(nw.results['Connection']) + print(f"\n converged ") + + + +import sys +sys.exit() + +# deltaT +se.set_attr(deltaT=5) +c2.set_attr(T=None) +c3.set_attr(T=None) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +# deltaT and different pressures +se.set_attr(deltaT=5) +c2.set_attr(p=4) +c3.set_attr(p=3) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +# deltaP +se.set_attr(deltaT=5,deltaP=1.2) +c2.set_attr(p=None) +c3.set_attr(p=None) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py index eba35bcbd..20f244029 100644 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ b/incompressiblesTests/newComponentsTests/heatex+merge.py @@ -102,9 +102,13 @@ nw.print_results() # now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C + + + c2.set_attr(T=5) -he.set_attr(Q_total=None, eta=None) +he.set_attr(Q_total=None, eta=1) +#nw.solve("design",init_only=True) nw.solve("design") if not nw.converged: raise Exception("not converged") From 7fc24847939284e79ece9d6101bd55c9df9d5780 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 20:46:56 +0100 Subject: [PATCH 032/105] models working again --- .../newComponentsTests/heatex+merge.py | 45 ++++++++++++------- src/tespy/tools/fluid_properties/mixtures.py | 6 +-- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py index 20f244029..ab78f7078 100644 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ b/incompressiblesTests/newComponentsTests/heatex+merge.py @@ -8,7 +8,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) @@ -16,14 +16,13 @@ fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") +nw = Network(fluids=fluids, p_unit="bar", T_unit="C",h_range=[-5.e5, 3.e+06]) so = Source("Source") so2 = Source("Source2") -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -he = DiabaticSimpleHeatExchanger("Heater") +# Variant 2: Q is m (h_2 - h_1), Q_total is taking loss factor into account and represents the heat transfer over system +he = SimpleHeatExchangerDeltaPLossFactor("Heater") me = MergeWithPressureLoss("Merge") si = Sink("Sink") @@ -34,15 +33,20 @@ nw.add_conns(c1, c2, c3, c4) +for c in nw.conns['object']: + n_fl=2 + c.set_attr(m0=0.1,h0=0.5e5,p0=1.2,fluid0={"INCOMP::Water": 1/n_fl, 'INCOMP::T66': 1/n_fl}, mixing_rule="incompressible") + c.set_attr(force_state='l') + # set some generic data for starting values c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") c2.set_attr(h=2.2e5) # mix with pure water -c3.set_attr(m=0.05, p=1.1, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) +c3.set_attr(m=0.05, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) # set pressure ratios of heater and merge -he.set_attr(pr=0.9) -me.set_attr(deltaP=0.15) +he.set_attr(deltaP=0) +me.set_attr(deltaP=0) #c2.set_attr(p=2.2) #c4.set_attr(p=2.2) @@ -51,6 +55,7 @@ raise Exception("not converged") nw.print_results() + # use temperature to make it relatable c1.set_attr(h=None, T=30) c2.set_attr(h=None, T=50) @@ -63,13 +68,13 @@ # add some heat c2.set_attr(T=None) # # efficiency is used for postprocessing here -he.set_attr(Q=1e5, eta=0.9) +he.set_attr(Q=1e5, LF=0.1) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() -he.set_attr(Q=1e5, Q_total=1.1e5, eta=None) +he.set_attr(Q=1e5, Q_total=1.1e5, LF=None) nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -82,10 +87,9 @@ nw.print_results() c2.set_attr(T=50) - # impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) # In this case, efficiency decreases -he.set_attr(Q=None, Q_total=1.1e5, eta=None) +he.set_attr(Q=None, Q_total=1.1e5, LF=None) nw.solve("design") if not nw.converged: @@ -94,19 +98,28 @@ # with set efficiency, temperature cannot be set anymore c2.set_attr(T=None) -he.set_attr(Q_total=1.1e5, eta=.5) +he.set_attr(Q_total=1.1e5, LF=.5) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() -# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C +# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C +#c2.set_attr(T0=5) +c2.set_attr(h=-1e3) +he.set_attr(Q=None, LF=0.1, Q_total=None) +#nw.solve("design",init_only=True) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +c2.set_attr(h=None) c2.set_attr(T=5) -he.set_attr(Q_total=None, eta=1) +he.set_attr(Q_total=None, LF=0.1) #nw.solve("design",init_only=True) nw.solve("design") @@ -114,7 +127,7 @@ raise Exception("not converged") nw.print_results() -he.set_attr(Q_total=-.6e5, eta="var") +he.set_attr(Q_total=-.6e5, LF=None) nw.solve("design") if not nw.converged: diff --git a/src/tespy/tools/fluid_properties/mixtures.py b/src/tespy/tools/fluid_properties/mixtures.py index 3dabe6996..b858cf67a 100644 --- a/src/tespy/tools/fluid_properties/mixtures.py +++ b/src/tespy/tools/fluid_properties/mixtures.py @@ -16,7 +16,7 @@ def h_mix_pT_ideal(p=None, T=None, fluid_data=None, **kwargs): if _is_larger_than_precision(data["mass_fraction"]): pp = p * molar_fractions[fluid] - h += data["wrapper"].h_pT(pp, T) * data["mass_fraction"] + h += data["wrapper"].h_pT(pp, T, **kwargs) * data["mass_fraction"] return h @@ -80,7 +80,7 @@ def s_mix_pT_ideal(p=None, T=None, fluid_data=None, **kwargs): if _is_larger_than_precision(data["mass_fraction"]): pp = p * molar_fractions[fluid] - s += data["wrapper"].s_pT(pp, T) * data["mass_fraction"] + s += data["wrapper"].s_pT(pp, T, **kwargs) * data["mass_fraction"] return s @@ -126,7 +126,7 @@ def v_mix_pT_ideal(p=None, T=None, fluid_data=None, **kwargs): if _is_larger_than_precision(data["mass_fraction"]): pp = p * molar_fractions[fluid] - d += data["wrapper"].d_pT(pp, T) + d += data["wrapper"].d_pT(pp, T, **kwargs) return 1 / d From 35c5f8083cd23e4050984150733a3664c4433c1b Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 09:30:41 +0100 Subject: [PATCH 033/105] Ensure seeing that enthalpy is limited --- incompressiblesTests/newComponentsTests/heatex+merge.py | 1 + src/tespy/connections/connection.py | 8 ++++---- src/tespy/networks/network.py | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py index ab78f7078..4837af3e3 100644 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ b/incompressiblesTests/newComponentsTests/heatex+merge.py @@ -16,6 +16,7 @@ fluids = ["INCOMP::Water", "INCOMP::T66"] +#nw = Network(fluids=fluids, p_unit="bar", T_unit="C",h_range=[1.e3, 3.e+06]) nw = Network(fluids=fluids, p_unit="bar", T_unit="C",h_range=[-5.e5, 3.e+06]) so = Source("Source") diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index a7210d23f..04cb2d77b 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1014,11 +1014,11 @@ def check_temperature_bounds(self): Connection to check fluid properties. """ Tmin = max( - [w._T_min for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR] - ) * 1.01 + [w._T_min for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR] + ) * (1+ERR) Tmax = min( - [w._T_max for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR] - ) * 0.99 + [w._T_max for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR] + ) * (1-ERR) hmin = h_mix_pT(self.p.val_SI, Tmin, self.fluid_data, self.mixing_rule, force_state=self.force_state) hmax = h_mix_pT(self.p.val_SI, Tmax, self.fluid_data, self.mixing_rule, force_state=self.force_state) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 21d0ae52b..a94806eed 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -2375,7 +2375,7 @@ def check_connection_properties(self, c): c.check_two_phase_bounds(fl) # mixture - elif self.iter < 4 and not c.good_starting_values: + else: #if self.iter < 4 and not c.good_starting_values: # pressure if c.p.is_var: if c.p.val_SI <= self.p_range_SI[0]: @@ -2388,11 +2388,11 @@ def check_connection_properties(self, c): # enthalpy if c.h.is_var: - if c.h.val_SI < self.h_range_SI[0]: + if c.h.val_SI <= self.h_range_SI[0]: c.h.val_SI = self.h_range_SI[0] logger.debug(c._property_range_message('h')) - elif c.h.val_SI > self.h_range_SI[1]: + elif c.h.val_SI >= self.h_range_SI[1]: c.h.val_SI = self.h_range_SI[1] logger.debug(c._property_range_message('h')) From 655e82ab1dec4f3d6e8592de05460a4bf0b2581e Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 10:24:32 +0100 Subject: [PATCH 034/105] Renamed new components --- incompressiblesTests/Ex1.py | 2 +- incompressiblesTests/Ex4.py | 2 +- incompressiblesTests/Ex8.py | 10 +- incompressiblesTests/Ex9.py | 18 +-- .../newComponentsTests/SpeciesFlowSplit.py | 2 +- ...litWithPr.py => SpeciesFlowSplitDeltaP.py} | 6 +- .../SpeciesFlowSplitWithDeltaT.py | 6 +- ...FlowSplitWithDeltaTDeltaP-decanterTest.py} | 6 +- ...py => SpeciesFlowSplitWithDeltaTDeltaP.py} | 6 +- ...=> SpeciesFlowSplitWithDeltaTDeltaPBus.py} | 6 +- .../newComponentsTests/SplitterWithDeltaP.py | 4 +- ...plitter.py => SplitterWithFlowSplitter.py} | 4 +- ...P.py => SplitterWithFlowSplitterDeltaP.py} | 4 +- .../newComponentsTests/heatex+merge.py | 4 +- .../newComponentsTests/heatex_alone.py | 2 +- .../newComponentsTests/heatex_alone_deltaP.py | 2 +- .../heatex_alone_lossFactor.py | 2 +- .../newComponentsTests/merge_mrk.py | 4 +- src/tespy/components/newcomponents.py | 105 ++++++++++++++++-- src/tespy/networks/network_reader.py | 8 +- 20 files changed, 146 insertions(+), 57 deletions(-) rename incompressiblesTests/newComponentsTests/{SpeciesFlowSplitWithPr.py => SpeciesFlowSplitDeltaP.py} (89%) rename incompressiblesTests/newComponentsTests/{SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py => SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py} (93%) rename incompressiblesTests/newComponentsTests/{SpeciesFlowSplitWithDeltaTAndPr.py => SpeciesFlowSplitWithDeltaTDeltaP.py} (93%) rename incompressiblesTests/newComponentsTests/{SpeciesFlowSplitWithDeltaTAndPrAndBus.py => SpeciesFlowSplitWithDeltaTDeltaPBus.py} (87%) rename incompressiblesTests/newComponentsTests/{SplitWithFlowSplitter.py => SplitterWithFlowSplitter.py} (93%) rename incompressiblesTests/newComponentsTests/{SplitWithFlowSplitterDeltaP.py => SplitterWithFlowSplitterDeltaP.py} (92%) diff --git a/incompressiblesTests/Ex1.py b/incompressiblesTests/Ex1.py index 15dfd0789..1e7bc20b1 100644 --- a/incompressiblesTests/Ex1.py +++ b/incompressiblesTests/Ex1.py @@ -18,7 +18,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SimpleHeatExchanger +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SimpleHeatExchanger import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/Ex4.py b/incompressiblesTests/Ex4.py index f52660d71..ae211b371 100644 --- a/incompressiblesTests/Ex4.py +++ b/incompressiblesTests/Ex4.py @@ -85,6 +85,6 @@ # network.print_results() print(network.results['Connection'].loc[:, [c for c in network.results["Connection"] if "unit" not in c]]) -print(0.65 * c1.m.val_SI * c1.fluid.val["S800"] / c3.fluid.val["S800"] == network.results['Connection'].loc["press:out1_presscake:in1", "m"]) +print(0.7 * c1.m.val_SI * c1.fluid.val["S800"] / c3.fluid.val["S800"] == network.results['Connection'].loc["press:out1_presscake:in1", "m"]) network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") \ No newline at end of file diff --git a/incompressiblesTests/Ex8.py b/incompressiblesTests/Ex8.py index a6105074f..403431daf 100644 --- a/incompressiblesTests/Ex8.py +++ b/incompressiblesTests/Ex8.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter import logging #logging.basicConfig(level=logging.DEBUG) @@ -27,7 +27,7 @@ thickener = SeparatorWithSpeciesSplits('thickener',num_out=2) vapourextract1 = Sink('vapourextract1') #solubles = Sink('solubles') -liquidmerge = MergeWithPressureLoss('liquidmerge', num_in = 3) +liquidmerge = MergeDeltaP('liquidmerge', num_in = 3) wetproduct = Sink('wetproduct') drier = SeparatorWithSpeciesSplits('drier',num_out=2) meal = Sink('meal') @@ -113,10 +113,10 @@ # Objects sourceFat = Source('Fat') sourceCitricAcid = Source('CitricAcid') -centimerge = MergeWithPressureLoss('centimerge', num_in=2) -T2 = SplitWithFlowSplitter('T2', num_out=2) +centimerge = MergeDeltaP('centimerge', num_in=2) +T2 = SplitterWithFlowSplitter('T2', num_out=2) Oil1 = Sink('Oil1') -stripper = SplitWithFlowSplitter('stripper', num_out=2) +stripper = SplitterWithFlowSplitter('stripper', num_out=2) Oil2 = Sink('Oil2') scrubOil = Sink('scrubOil') diff --git a/incompressiblesTests/Ex9.py b/incompressiblesTests/Ex9.py index dea057026..dea719ab6 100644 --- a/incompressiblesTests/Ex9.py +++ b/incompressiblesTests/Ex9.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter,SeparatorWithSpeciesSplitsAndDeltaT,SeparatorWithSpeciesSplitsAndDeltaTAndPr +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaTDeltaP import logging #logging.basicConfig(level=logging.DEBUG) @@ -17,19 +17,19 @@ # Objects source = Source('source') boiler = HeatExchangerSimple('boiler') -press = SeparatorWithSpeciesSplitsAndDeltaTAndPr('press', num_out=2) +press = SeparatorWithSpeciesSplitsDeltaTDeltaP('press', num_out=2) #presswater = Sink('presswater') #presscake = Sink('presscake') -decanter = SeparatorWithSpeciesSplitsAndDeltaTAndPr('decanter', num_out=2) +decanter = SeparatorWithSpeciesSplitsDeltaTDeltaP('decanter', num_out=2) #grax = Sink('grax') oil = Sink('oil') -centrifuge = SeparatorWithSpeciesSplitsAndDeltaTAndPr('centrifuge',num_out=2) -thickener = SeparatorWithSpeciesSplitsAndDeltaTAndPr('thickener',num_out=2) +centrifuge = SeparatorWithSpeciesSplitsDeltaTDeltaP('centrifuge',num_out=2) +thickener = SeparatorWithSpeciesSplitsDeltaTDeltaP('thickener',num_out=2) vapourextract1 = Sink('vapourextract1') #solubles = Sink('solubles') -liquidmerge = MergeWithPressureLoss('liquidmerge', num_in = 3) +liquidmerge = MergeDeltaP('liquidmerge', num_in = 3) wetproduct = Sink('wetproduct') -drier = SeparatorWithSpeciesSplitsAndDeltaTAndPr('drier',num_out=2) +drier = SeparatorWithSpeciesSplitsDeltaTDeltaP('drier',num_out=2) meal = Sink('meal') vapourextract2 = Sink('vapourextract2') @@ -128,12 +128,12 @@ # MJ to kwh # for o in network.comps['object']: - if isinstance(o,SeparatorWithSpeciesSplitsAndDeltaTAndPr): + if isinstance(o,SeparatorWithSpeciesSplitsDeltaTDeltaP): print(f"heat exchange for {o.label} = {o.Q.val}") print(f"\n") for o in network.comps['object']: - if isinstance(o,SeparatorWithSpeciesSplitsAndDeltaTAndPr): + if isinstance(o,SeparatorWithSpeciesSplitsDeltaTDeltaP): print(f"Total heat for {o.label} = {o.Q.val / (3.6*1e6)}") print(f"\n") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py index 154d4c17f..dd0761214 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py similarity index 89% rename from incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py index 881d85e79..d97520770 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithPr.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py @@ -10,8 +10,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.components.newcomponents import \ - DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr, SeparatorWithSpeciesSplitsAndPr + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaP logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") -se = SeparatorWithSpeciesSplitsAndPr("Separator",num_out=2) +se = SeparatorWithSpeciesSplitsDeltaP("Separator",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py index c5cad4b93..2c30a614a 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -10,8 +10,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.components.newcomponents import \ - DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsAndDeltaT + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") -se = SeparatorWithSpeciesSplitsAndDeltaT("Separator",num_out=2) +se = SeparatorWithSpeciesSplitsDeltaT("Separator",num_out=2) #se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py similarity index 93% rename from incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py index e5aaca693..506480013 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr-decanterTest.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py @@ -10,8 +10,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.components.newcomponents import \ - DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") -se = SeparatorWithSpeciesSplitsAndDeltaTAndPr("Separator",num_out=2) +se = SeparatorWithSpeciesSplitsDeltaTDeltaP("Separator",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py similarity index 93% rename from incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py index 4b5026e36..3dc3815e8 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPr.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py @@ -10,8 +10,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.components.newcomponents import \ - DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") -se = SeparatorWithSpeciesSplitsAndDeltaTAndPr("Separator",num_out=2) +se = SeparatorWithSpeciesSplitsDeltaTDeltaP("Separator",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py similarity index 87% rename from incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py index 62ed0ddef..3a0a91f40 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTAndPrAndBus.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py @@ -10,8 +10,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.components.newcomponents import \ - DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndDeltaTAndPr, SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus,SimpleHeatExchangerDeltaP + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaTDeltaPBus,SimpleHeatExchangerDeltaP logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") -se = SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus("Separator",num_out=2) +se = SeparatorWithSpeciesSplitsDeltaTDeltaPBus("Separator",num_out=2) si1 = Sink("Sink 1") hx = SimpleHeatExchangerDeltaP("HX") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py index 6607a403b..4c121aea2 100644 --- a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitterWithPressureLoss +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterDeltaP logging.basicConfig(level=logging.DEBUG) @@ -20,7 +20,7 @@ nw = Network(fluids=fluids, p_unit="bar", T_unit="C") so = Source("Source") -se = SplitterWithPressureLoss("Splitter",num_out=2) +se = SplitterDeltaP("Splitter",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SplitWithFlowSplitter.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py similarity index 93% rename from incompressiblesTests/newComponentsTests/SplitWithFlowSplitter.py rename to incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py index bf263a188..666db85bf 100644 --- a/incompressiblesTests/newComponentsTests/SplitWithFlowSplitter.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter logging.basicConfig(level=logging.DEBUG) @@ -20,7 +20,7 @@ nw = Network(fluids=fluids, p_unit="bar", T_unit="C") so = Source("Source") -se = SplitWithFlowSplitter("Splitter",num_out=2) +se = SplitterWithFlowSplitter("Splitter",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py similarity index 92% rename from incompressiblesTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py rename to incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py index 1c4a41fde..aa1894037 100644 --- a/incompressiblesTests/newComponentsTests/SplitWithFlowSplitterDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits,SplitWithFlowSplitter,SplitWithFlowSplitterDeltaP +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SplitterWithFlowSplitterDeltaP logging.basicConfig(level=logging.DEBUG) @@ -20,7 +20,7 @@ nw = Network(fluids=fluids, p_unit="bar", T_unit="C") so = Source("Source") -se = SplitWithFlowSplitterDeltaP("Splitter",num_out=2) +se = SplitterWithFlowSplitterDeltaP("Splitter",num_out=2) si1 = Sink("Sink 1") si2 = Sink("Sink 2") diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py index 4837af3e3..67c24ef3a 100644 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ b/incompressiblesTests/newComponentsTests/heatex+merge.py @@ -8,7 +8,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) @@ -24,7 +24,7 @@ # Variant 2: Q is m (h_2 - h_1), Q_total is taking loss factor into account and represents the heat transfer over system he = SimpleHeatExchangerDeltaPLossFactor("Heater") -me = MergeWithPressureLoss("Merge") +me = MergeDeltaP("Merge") si = Sink("Sink") c1 = Connection(so, "out1", he, "in1", label="1") diff --git a/incompressiblesTests/newComponentsTests/heatex_alone.py b/incompressiblesTests/newComponentsTests/heatex_alone.py index 158946be9..c8516c6fe 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone.py @@ -12,7 +12,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py index 1f47169a4..3e3f348fd 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py @@ -11,7 +11,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py index 95e801631..e2bce867c 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py @@ -12,7 +12,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/merge_mrk.py b/incompressiblesTests/newComponentsTests/merge_mrk.py index d0d1211c2..632154ae5 100644 --- a/incompressiblesTests/newComponentsTests/merge_mrk.py +++ b/incompressiblesTests/newComponentsTests/merge_mrk.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) @@ -22,7 +22,7 @@ so = Source("Source") so2 = Source("Source2") -me = MergeWithPressureLoss("Merge") +me = MergeDeltaP("Merge") si = Sink("Sink") c1 = Connection(so, "out1", me, "in1", label="2") diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 5c94f7998..89d9553bb 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -7,6 +7,9 @@ from tespy.components.component import Component + +import warnings + import numpy as np class DiabaticSimpleHeatExchanger(SimpleHeatExchanger): @@ -251,7 +254,7 @@ def calc_parameters(self): self.LF.val = -self.Q_loss.val/self.Q.val -class MergeWithPressureLoss(Merge): +class MergeDeltaP(Merge): @staticmethod def component(): @@ -368,7 +371,7 @@ def SFS_deriv(self, increment_filter, k): self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI -class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplits): +class SeparatorWithSpeciesSplitsDeltaT(SeparatorWithSpeciesSplits): @staticmethod def component(): @@ -429,7 +432,7 @@ def calc_parameters(self): else: self.deltaT.val = i.T.val_SI - Tmax -class SeparatorWithSpeciesSplitsAndPr(SeparatorWithSpeciesSplits): +class SeparatorWithSpeciesSplitsDeltaP(SeparatorWithSpeciesSplits): @staticmethod def component(): @@ -493,7 +496,7 @@ def calc_parameters(self): self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 -class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsAndDeltaT, SeparatorWithSpeciesSplitsAndPr): +class SeparatorWithSpeciesSplitsDeltaTDeltaP(SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaP): @staticmethod def component(): @@ -510,7 +513,7 @@ def get_mandatory_constraints(self): return constraints -class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsAndDeltaTAndPr): +class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): @staticmethod def component(): @@ -573,7 +576,7 @@ def bus_deriv(self, bus): bus.jacobian[o.m.J_col] -= self.numeric_deriv(f, 'm', o, bus=bus) -class SplitterWithPressureLoss(Splitter): +class SplitterDeltaP(Splitter): def __init__(self, label, **kwargs): #self.set_attr(**kwargs) @@ -639,7 +642,7 @@ def calc_parameters(self): else: self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 -class SplitWithFlowSplitter(Splitter): +class SplitterWithFlowSplitter(Splitter): @staticmethod def component(): @@ -682,7 +685,7 @@ def FS_deriv(self, increment_filter, k): self.jacobian[k, o.m.J_col] = -1 -class SplitWithFlowSplitterDeltaP(SplitWithFlowSplitter, SplitterWithPressureLoss): +class SplitterWithFlowSplitterDeltaP(SplitterWithFlowSplitter, SplitterDeltaP): @staticmethod def component(): @@ -730,3 +733,89 @@ def _serializable_keys(): keys = dc_cp._serializable_keys() keys.append("split_outlet") return keys + + +# class MergeWithPressureLoss(MergeDeltaP): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component MergeWithPressureLoss will change with " +# "the next major release, please import MergeDeltaP instead." +# ) +# warnings.warn(msg, FutureWarning) + +# class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplitsDeltaT): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SeparatorWithSpeciesSplitsAndDeltaT will change with " +# "the next major release, please import SeparatorWithSpeciesSplitsDeltaT instead." +# ) +# warnings.warn(msg, FutureWarning) + +# class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsDeltaTDeltaP): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPr will change with " +# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaP instead." +# ) +# warnings.warn(msg, FutureWarning) + +# class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsDeltaTDeltaPBus): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus will change with " +# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaPBus instead." +# ) +# warnings.warn(msg, FutureWarning) + + +# class SplitterWithPressureLoss(SplitterDeltaP): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPr will change with " +# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaP instead." +# ) +# warnings.warn(msg, FutureWarning) + +# class SplitterWithPressureLoss(SplitterDeltaP): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SplitterWithPressureLoss will change with " +# "the next major release, please import SplitterDeltaP instead." +# ) +# warnings.warn(msg, FutureWarning) + + + + +# class SplitWithFlowSplitter(SplitterWithFlowSplitter): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SplitWithFlowSplitter will change with " +# "the next major release, please import SplitterWithFlowSplitter instead." +# ) +# warnings.warn(msg, FutureWarning) + + +# class SplitWithFlowSplitterDeltaP(SplitterWithFlowSplitterDeltaP): + +# def __init__(self, label, **kwargs): +# super().__init__(label, **kwargs) +# msg = ( +# "The API for the component SplitWithFlowSplitterDeltaP will change with " +# "the next major release, please import SplitterWithFlowSplitterDeltaP instead." +# ) +# warnings.warn(msg, FutureWarning) diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 94f79f141..217459abf 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -83,11 +83,11 @@ 'Compressor': Compressor, 'Pump': Pump, 'Turbine': Turbine, - 'MergeWithPressureLoss' :MergeWithPressureLoss, + 'MergeWithPressureLoss' :MergeDeltaP, 'SeparatorWithSpeciesSplits' : SeparatorWithSpeciesSplits, - 'SeparatorWithSpeciesSplitsAndDeltaT' : SeparatorWithSpeciesSplitsAndDeltaT, - 'SeparatorWithSpeciesSplitsAndDeltaTAndPr' : SeparatorWithSpeciesSplitsAndDeltaTAndPr, - 'SeparatorWithSpeciesSplitsAndPr' : SeparatorWithSpeciesSplitsAndPr, + 'SeparatorWithSpeciesSplitsAndDeltaT' : SeparatorWithSpeciesSplitsDeltaT, + 'SeparatorWithSpeciesSplitsAndDeltaTAndPr' : SeparatorWithSpeciesSplitsDeltaTDeltaP, + 'SeparatorWithSpeciesSplitsAndPr' : SeparatorWithSpeciesSplitsDeltaP, 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, } From 62370e3faf1eeb33b01642106b9bce4b9c7279c0 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 13:42:06 +0100 Subject: [PATCH 035/105] Updating check_temperatures to ensure force_state --- incompressiblesTests/Ex4.py | 2 +- src/tespy/connections/connection.py | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/incompressiblesTests/Ex4.py b/incompressiblesTests/Ex4.py index ae211b371..2735fdea6 100644 --- a/incompressiblesTests/Ex4.py +++ b/incompressiblesTests/Ex4.py @@ -17,7 +17,7 @@ from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeWithPressureLoss,SeparatorWithSpeciesSplits +from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 04cb2d77b..cae977bca 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1013,12 +1013,28 @@ def check_temperature_bounds(self): c : tespy.connections.connection.Connection Connection to check fluid properties. """ - Tmin = max( - [w._T_min for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR] - ) * (1+ERR) - Tmax = min( - [w._T_max for f, w in self.fluid.wrapper.items() if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR] - ) * (1-ERR) + Tminlist=[] + Tmaxlist=[] + for f, w in self.fluid.wrapper.items(): + if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR: + if self.force_state == 'l': + Tminlist.append(w._T_min) + if not w.back_end == 'INCOMP': + Tmaxlist.append(w.T_sat(self.p.val_SI)) + else: + Tmaxlist.append(w._T_max) + elif self.force_state == 'g': + Tmaxlist.append(w._T_max) + if not w.back_end == 'INCOMP': + Tminlist.append(w.T_sat(self.p.val_SI)) + else: + Tminlist.append(w._T_min) + else: + Tminlist.append(w._T_min) + Tmaxlist.append(w._T_max) + + Tmin = max(Tminlist) * (1+ERR) + Tmax = min(Tmaxlist) * (1-ERR) hmin = h_mix_pT(self.p.val_SI, Tmin, self.fluid_data, self.mixing_rule, force_state=self.force_state) hmax = h_mix_pT(self.p.val_SI, Tmax, self.fluid_data, self.mixing_rule, force_state=self.force_state) From 413a8fec74128c6d3b6bfcd6e2698a49adc96cc4 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 14:28:02 +0100 Subject: [PATCH 036/105] correct check_temperature back again... use iter > 8 to force closer limit --- src/tespy/connections/connection.py | 27 +++++++++------------------ src/tespy/networks/network.py | 2 +- src/tespy/networks/network_reader.py | 8 ++++---- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index cae977bca..086697c3e 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1004,7 +1004,7 @@ def check_two_phase_bounds(self, fluid): self.h.val_SI = h * 0.99 logger.debug(self._property_range_message('h')) - def check_temperature_bounds(self): + def check_temperature_bounds(self, iter): r""" Check if temperature is within user specified limits. @@ -1017,24 +1017,15 @@ def check_temperature_bounds(self): Tmaxlist=[] for f, w in self.fluid.wrapper.items(): if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR: - if self.force_state == 'l': - Tminlist.append(w._T_min) - if not w.back_end == 'INCOMP': - Tmaxlist.append(w.T_sat(self.p.val_SI)) - else: - Tmaxlist.append(w._T_max) - elif self.force_state == 'g': - Tmaxlist.append(w._T_max) - if not w.back_end == 'INCOMP': - Tminlist.append(w.T_sat(self.p.val_SI)) - else: - Tminlist.append(w._T_min) - else: - Tminlist.append(w._T_min) - Tmaxlist.append(w._T_max) + Tminlist.append(w._T_min) + Tmaxlist.append(w._T_max) - Tmin = max(Tminlist) * (1+ERR) - Tmax = min(Tmaxlist) * (1-ERR) + if iter < 8: + Tmin = max(Tminlist) * 1.01 + Tmax = min(Tmaxlist) * 0.99 + else: + Tmin = max(Tminlist) * (1+ERR) + Tmax = min(Tmaxlist) * (1-ERR) hmin = h_mix_pT(self.p.val_SI, Tmin, self.fluid_data, self.mixing_rule, force_state=self.force_state) hmax = h_mix_pT(self.p.val_SI, Tmax, self.fluid_data, self.mixing_rule, force_state=self.force_state) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index a94806eed..c02464505 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -2398,7 +2398,7 @@ def check_connection_properties(self, c): # temperature if c.T.is_set: - c.check_temperature_bounds() + c.check_temperature_bounds(self.iter) # mass flow if c.m.val_SI <= self.m_range_SI[0] and c.m.is_var: diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 217459abf..ccd31f337 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -83,11 +83,11 @@ 'Compressor': Compressor, 'Pump': Pump, 'Turbine': Turbine, - 'MergeWithPressureLoss' :MergeDeltaP, + 'MergeDeltaP' :MergeDeltaP, 'SeparatorWithSpeciesSplits' : SeparatorWithSpeciesSplits, - 'SeparatorWithSpeciesSplitsAndDeltaT' : SeparatorWithSpeciesSplitsDeltaT, - 'SeparatorWithSpeciesSplitsAndDeltaTAndPr' : SeparatorWithSpeciesSplitsDeltaTDeltaP, - 'SeparatorWithSpeciesSplitsAndPr' : SeparatorWithSpeciesSplitsDeltaP, + 'SeparatorWithSpeciesSplitsDeltaT' : SeparatorWithSpeciesSplitsDeltaT, + 'SeparatorWithSpeciesSplitsDeltaTDeltaP' : SeparatorWithSpeciesSplitsDeltaTDeltaP, + 'SeparatorWithSpeciesSplitsDeltaP' : SeparatorWithSpeciesSplitsDeltaP, 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, } From c3fcc9cc85ef78572297a5072a8d63680c7d3061 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 17:43:37 +0100 Subject: [PATCH 037/105] lets make heat exchanger model simpler with only options of LF+KPI and LF+Q (Q is Q_total now) and LF+Tout/hout --- .../heatex_alone_DeltaPLfKpi.py | 122 ++++++++++++++++++ src/tespy/components/newcomponents.py | 79 ++++++++++++ 2 files changed, 201 insertions(+) create mode 100644 incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py b/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py new file mode 100644 index 000000000..e99f216a0 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py @@ -0,0 +1,122 @@ +# %% + +import logging + + +from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLfKpi,MergeDeltaP,SeparatorWithSpeciesSplits + +logging.basicConfig(level=logging.DEBUG) + + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? + +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) + +so = Source("Source") +# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system +# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta + +he = SimpleHeatExchangerDeltaPLfKpi("Heater") +#he = SimpleHeatExchangerDeltaP("Heater") + + +si = Sink("Sink") + +c1 = Connection(so, "out1", he, "in1", label="1") +c2 = Connection(he, "out1", si, "in1", label="4") + +nw.add_conns(c1, c2) + +# set some generic data for starting values +c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") +c1.set_attr(m=1, p=2.2, T=30) + +c2.set_attr(T=50) + +# set pressure ratios of heater and merge +he.set_attr(deltaP=1) +he.set_attr(LF=0.1) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + + +c2.set_attr(T=None) + +he.set_attr(LF=0.1) +#he.set_attr(KPI=74e3) +he.set_attr(Q=7.0e+04) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + +he.set_attr(LF=0.1) +he.set_attr(KPI=60e3) +he.set_attr(Q=None) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + + +# he.set_attr(LF=None) +# he.set_attr(Q_total=8.16e+04) +# he.set_attr(Q_loss=-7.42e+03) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() + +# he.set_attr(LF=0.1) +# he.set_attr(Q_total=None) +# he.set_attr(Q_loss=-7.42e+03) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() + + + +# c2.set_attr(T=50) +# he.set_attr(LF=0.1) +# he.set_attr(Q_total=None) +# he.set_attr(Q_loss=None) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() + +# c2.set_attr(T=None) +# he.set_attr(Q=70e3) +# he.set_attr(LF=0.1) +# he.set_attr(Q_total=None) +# he.set_attr(Q_loss=None) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() + + +# he.set_attr(KPI=70e3) +# he.set_attr(Q=None) +# he.set_attr(LF=0.1) +# he.set_attr(Q_total=None) +# he.set_attr(Q_loss=None) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() + diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 89d9553bb..218cac660 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -254,6 +254,85 @@ def calc_parameters(self): self.LF.val = -self.Q_loss.val/self.Q.val +class SimpleHeatExchangerDeltaPLfKpi(SimpleHeatExchangerDeltaP): + + @staticmethod + def component(): + return 'simple heat exchanger with loss factor and KPI' + + def get_parameters(self): + variables = super().get_parameters() + variables["LF"] = dc_cp(min_val=0, val=0, max_val=1, is_result=True) + variables["Q_loss"] = dc_cp(is_result=True) + variables["KPI"] = dc_cp( + deriv=self.KPI_deriv, + func=self.KPI_func, + latex=self.pr_func_doc, + num_eq=1) + return variables + + def energy_balance_func(self): + r""" + Equation for total heat flow rate + + """ + + return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q.val + + def energy_balance_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of Q_total + + """ + + i = self.inl[0] + o = self.outl[0] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) + if i.h.is_var: + self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) + if o.h.is_var: + self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) + if self.Q.is_var: + self.jacobian[k, self.Q.J_col] = -1 + if self.LF.is_var: + self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) + + def KPI_func(self): + r""" + Equation for total heat flow rate + + """ + return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.KPI.val * self.inl[0].m.val_SI + + def KPI_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of Q_total + + """ + i = self.inl[0] + o = self.outl[0] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) - self.KPI.val + if i.h.is_var: + self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) + if o.h.is_var: + self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) + if self.LF.is_var: + self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) + if self.KPI.is_var: + self.jacobian[k, self.Q_loss.J_col] = -self.inl[0].m.val_SI + + def calc_parameters(self): + super().calc_parameters() + self.Q.val = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) + # repeat calculations to ensure variables are assigned + if self.KPI.is_set: + self.Q.val = self.KPI.val * self.inl[0].m.val_SI + else: + self.KPI.val = self.Q.val / self.inl[0].m.val_SI + self.Q_loss.val = - self.LF.val * self.Q.val + class MergeDeltaP(Merge): @staticmethod From 8ddf6b1b3785bf772901797b77223d1ea35a1bd7 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 9 Nov 2023 10:03:53 +0100 Subject: [PATCH 038/105] Added pinch temperature calculation for heat exchanger --- .../newComponentsTests/2streamHX.py | 82 +++++++++++++++++++ src/tespy/components/newcomponents.py | 67 ++++++++++++++- 2 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 incompressiblesTests/newComponentsTests/2streamHX.py diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py new file mode 100644 index 000000000..2f382a555 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/2streamHX.py @@ -0,0 +1,82 @@ +from tespy.components import Sink, Source, HeatExchanger +from tespy.components.newcomponents import TwoStreamHeatExchanger + +from tespy.connections import Connection +from tespy.networks import Network +from tespy.tools import document_model +import shutil + +import logging +logging.basicConfig(level=logging.DEBUG) + + +nw = Network(T_unit='C', p_unit='bar', h_unit='kJ / kg', iterinfo=True) + + + +hot_i = Source('hot in') +hot_o = Sink('hot out') + +cold_i = Source('cold in') +cold_o = Sink('cold out') + +he = TwoStreamHeatExchanger('heat exchanger') +#he.component() + +hot_in_he = Connection(hot_i, 'out1', he, 'in1') +hot_he_out = Connection(he, 'out1', hot_o, 'in1') +cold_in_he = Connection(cold_i, 'out1', he, 'in2') +cold_he_out = Connection(he, 'out2', cold_o, 'in1') +nw.add_conns(hot_in_he, hot_he_out, cold_in_he, cold_he_out) + + +he.set_attr(pr1=1, pr2=1) +cold_in_he.set_attr(fluid={'water': 1}, T=10, m=1, p=3) +hot_in_he.set_attr(fluid={'water': 1}, T=35, m=0.5, p=3) +hot_he_out.set_attr(T=30) + +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) + +# play with terminal +he.set_attr(ttd_l = 3) +hot_he_out.set_attr(T=None) +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) + +# play with terminal +#he.set_attr(ttd_l = None,ttd_u = 3) # this is not possible because cold stream has lower capacitance flow +he.set_attr(ttd_l = None,ttd_min = 15) # using new model with pinch +hot_he_out.set_attr(T=None) +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) + + + + + + + + +# nw.save('tmp') + +# round(ex_he.T.val - he_cw.T.val, 0) +# ex_he.set_attr(v=0.075) +# nw.solve('offdesign', design_path='tmp') +# round(he_cw.T.val, 1) +# round(he_ex.T.val, 1) +# ex_he.set_attr(v=0.1, T=40) +# nw.solve('offdesign', design_path='tmp') +# document_model(nw) +# round(he_cw.T.val, 1) +# round(he_ex.T.val, 1) +# shutil.rmtree('./tmp', ignore_errors=True) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 218cac660..e65426b56 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -1,6 +1,6 @@ import logging -from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter +from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter, HeatExchanger from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.fluid_properties import T_mix_ph @@ -333,6 +333,71 @@ def calc_parameters(self): self.KPI.val = self.Q.val / self.inl[0].m.val_SI self.Q_loss.val = - self.LF.val * self.Q.val + +class TwoStreamHeatExchanger(HeatExchanger): + + @staticmethod + def component(): + return 'two stream heat exchanger with min ttd (pinch)' + + def get_parameters(self): + variables = super().get_parameters() + variables['ttd_min'] = dc_cp( + min_val=0, num_eq=1, func=self.ttd_min_func, + deriv=self.ttd_min_deriv, latex=self.ttd_u_func_doc) + return variables + + def _calc_dTs(self): + i1 = self.inl[0] + o1 = self.outl[0] + i2 = self.inl[1] + o2 = self.outl[1] + + T_i1 = i1.calc_T(T0=i1.T.val_SI) + T_o1 = o1.calc_T(T0=o1.T.val_SI) + T_i2 = i2.calc_T(T0=i2.T.val_SI) + T_o2 = o2.calc_T(T0=o2.T.val_SI) + + dTa = abs(T_i1-T_o2) + dTb = abs(T_i2-T_o1) + return dTa,dTb + + def ttd_min_func(self): + r""" + Equation for minimum terminal temperature difference. + """ + + dTa,dTb = self._calc_dTs() + + if dTa < dTb: + return self.ttd_min.val - dTa + else: + return self.ttd_min.val - dTb + + # T_o2 = o.calc_T(T0=o.T.val_SI) + # return self.ttd_u.val - T_i1 + T_o2 + + + def ttd_min_deriv(self, increment_filter, k): + """ + Calculate partial derivates for minimum terminal temperature difference.. + + """ + f = self.ttd_min_func + for c in [self.inl[0], self.inl[1], self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(f, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c) + + def calc_parameters(self): + super().calc_parameters() + if not self.ttd_min.is_set: + self.ttd_min.val = min(self._calc_dTs()) + + + + class MergeDeltaP(Merge): @staticmethod From 804421ccb51cc986713c4a2da73c2e747048eb44 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 9 Nov 2023 12:06:44 +0100 Subject: [PATCH 039/105] setting lower bounds, and typo fix --- .../newComponentsTests/2streamHX.py | 38 ++++++++++++++++++- src/tespy/networks/network.py | 6 +-- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py index 2f382a555..603000381 100644 --- a/incompressiblesTests/newComponentsTests/2streamHX.py +++ b/incompressiblesTests/newComponentsTests/2streamHX.py @@ -29,10 +29,17 @@ cold_he_out = Connection(he, 'out2', cold_o, 'in1') nw.add_conns(hot_in_he, hot_he_out, cold_in_he, cold_he_out) +for c in nw.conns['object']: + n_fl=3 + c.set_attr(m0=0.5,h0=1e2,p0=3, mixing_rule="incompressible") + c.set_attr(fluid0={"HEOS::Water": 1/n_fl, 'INCOMP::PHE': 1/n_fl, 'INCOMP::S800': 1/n_fl}) + #c.set_attr(fluid0={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}) + c.set_attr(force_state='l') + c.set_attr(good_starting_values=True) he.set_attr(pr1=1, pr2=1) -cold_in_he.set_attr(fluid={'water': 1}, T=10, m=1, p=3) -hot_in_he.set_attr(fluid={'water': 1}, T=35, m=0.5, p=3) +cold_in_he.set_attr(fluid={'HEOS::Water': 1,'INCOMP::PHE': 0,'INCOMP::S800': 0}, T=1, m=1, p=3,mixing_rule="incompressible") +hot_in_he.set_attr(fluid={'HEOS::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, T=35, m=0.5, p=3) hot_he_out.set_attr(T=30) nw.solve("design",print_results=True) @@ -60,9 +67,36 @@ nw.print_results(colored=True, print_results=False) print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) +he.set_attr(ttd_l = None,ttd_min = None,kA=10e3) # using new model with pinch +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) +# switch hot and cold +cold_in_he.set_attr(T=50, m=1, p=3,mixing_rule="incompressible") +hot_in_he.set_attr(T=20, m=0.5, p=3) +hot_he_out.set_attr(T=25) +he.set_attr(ttd_l = None,ttd_min = None,kA=None) # using new model with pinch +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) + +# why negative Q and ttd_u and ttd_l +cold_in_he.set_attr(T=50, m=1, p=3,mixing_rule="incompressible") +hot_in_he.set_attr(T=20, m=0.5, p=3) +hot_he_out.set_attr(T=None) +he.set_attr(ttd_l = None,ttd_min = 5) # using new model with pinch +nw.solve("design",print_results=True) +if not nw.converged: + raise Exception("not converged") +nw.print_results(colored=True, print_results=False) +print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index c02464505..a38a46631 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -222,7 +222,7 @@ def set_defaults(self): # generic value range self.m_range_SI = np.array([-1e12, 1e12]) self.p_range_SI = np.array([2e2, 300e5]) - self.h_range_SI = np.array([1e3, 7e6]) + self.h_range_SI = np.array([-5e5, 7e6]) for prop in ['m', 'p', 'h']: limits = self.get_attr(prop + '_range_SI') @@ -2225,7 +2225,7 @@ def _limit_increments(self,valmin,valmax,val,increment): if increment < inc_min: # need to limit the increment - if inc_min < -0.01/(valmax-valmin): + if inc_min < -0.01*(valmax-valmin): # if we are not close the the bound we limit it half way to the bound increment = inc_min/2 else: @@ -2234,7 +2234,7 @@ def _limit_increments(self,valmin,valmax,val,increment): if increment > inc_max: # need to limit the increment - if inc_max > 0.01/(valmax-valmin): + if inc_max > 0.01*(valmax-valmin): # if we are not close the the bound we limit it half way to the bound increment = inc_max/2 else: From dbdeb0b198ce35c7653d85357d913f211f04fbca Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 10 Nov 2023 13:37:22 +0100 Subject: [PATCH 040/105] a drier model --- ...SpeciesFlowSplitWithDeltaT-drierWithAir.py | 62 +++++++ src/tespy/components/newcomponents.py | 169 +++++++++++++++++- 2 files changed, 230 insertions(+), 1 deletion(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py new file mode 100644 index 000000000..486efb6e8 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py @@ -0,0 +1,62 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT,DrierWithAir + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +#fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +soAir = Source("SourceAir") +se = DrierWithAir("Separator",num_out=2,num_in=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") +c4 = Connection(soAir, "out1", se, "in2", label="4") + +nw.add_conns(c1, c2, c3, c4) + + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") +c4.set_attr(m=10, p=1.2, T=80, fluid={"INCOMP::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") + +c2.set_attr(fluid={"INCOMP::T66": 0}) +c3.set_attr(fluid={"INCOMP::Water": 0.08, "HEOS::Air": 0}) + +c2.set_attr(p=1.2,T=60) +c3.set_attr(p=1.2,T=60) + + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + + + diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index e65426b56..18c01e34b 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -2,6 +2,7 @@ from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter, HeatExchanger from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import SimpleDataContainer as dc_simple from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.fluid_properties import T_mix_ph @@ -535,7 +536,7 @@ def get_parameters(self): def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() - self.variable_fluids = self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) num_fluid_eq = len(self.variable_fluids) constraints['fluid_constraints'] = { 'func': self.fluid_func, 'deriv': self.fluid_deriv, @@ -657,6 +658,172 @@ def get_mandatory_constraints(self): return constraints +class DrierWithAir(SeparatorWithSpeciesSplitsDeltaP): + + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + self.num_out = 2 # default + self.num_in = 2 # default + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + if key == 'num_in': + self.num_in=kwargs[key] + super().__init__(label, **kwargs) + + @staticmethod + def component(): + return 'separator with species flow splits and dT on outlets' + + @staticmethod + def inlets(): + return ['in1'] + + def inlets(self): + if self.num_in.is_set: + return ['in' + str(i + 1) for i in range(self.num_in.val)] + else: + self.set_attr(num_in=2) + return self.inlets() + + def get_parameters(self): + variables = super().get_parameters() + variables["num_in"] = dc_simple() + variables["deltaT"] = dc_cp( + deriv=self.energy_balance_deriv, # same as before + func=self.energy_balance_deltaT_func, + latex=self.pr_func_doc, + num_eq=self.num_out + ) + variables["Q"] = dc_cp(is_result=True) + #variables["Qout"] = dc_cpa() + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids)+1 + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + del constraints['energy_balance_constraints'] + return constraints + + def fluid_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + + Returns + ------- + residual : list + Vector of residual values for component's fluid balance. + + .. math:: + + 0 = \dot{m}_{in} \cdot x_{fl,in} - \dot {m}_{out,j} + \cdot x_{fl,out,j}\\ + \forall fl \in \text{network fluids,} + \; \forall j \in \text{outlets} + """ + #i = self.inl[0] + residual = [] + for fluid in self.variable_fluids: + res = 0 + for i in self.inl: + res += i.fluid.val[fluid] * i.m.val_SI + for o in self.outl: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + + # additional equation for air conservation + i = self.inl[1] + o = self.outl[0] + # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + residual += [(o.m.val_SI - i.m.val_SI*i.fluid.val['Air']) - o.fluid.val['Water'] * o.m.val_SI] + return residual + + def fluid_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of derivatives in Jacobian matrix (k-th equation). + """ + #i = self.inl[0] + for fluid in self.variable_fluids: + for o in self.outl: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + + for i in self.inl: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + # if fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + k += 1 + + i = self.inl[1] + o = self.outl[0] + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + + def energy_balance_deltaT_func(self): + r""" + Calculate deltaT residuals based on in[0] solely. + + """ + i = self.inl[0] + if i.T.is_set: + T_in = i.T.val_SI + else: + # calculate T_in + if i.T.val0 > 0: + T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule,i.T.val0) + else: + T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule) + + residual = [] + for o in self.outl: + residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess + return residual + + def calc_parameters(self): + super().calc_parameters() + + self.Q.val = sum([o.m.val_SI * o.h.val_SI for o in self.outl]) \ + - sum([i.m.val_SI * i.h.val_SI for i in self.inl]) + + i = self.inl[0] + if not i.T.is_set: + Tmin = min([o.T.val_SI for o in self.outl]) + Tmax = max([o.T.val_SI for o in self.outl]) + if abs(i.T.val_SI - Tmin) >= abs(i.T.val_SI - Tmax): + self.deltaT.val = i.T.val_SI - Tmin + else: + self.deltaT.val = i.T.val_SI - Tmax + + class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): @staticmethod From 6ca446483b812ed9bd91041942efa45f1574b234 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 10 Nov 2023 18:50:13 +0100 Subject: [PATCH 041/105] two-phase state results with HEOS::WATER --- src/tespy/connections/connection.py | 6 +- src/tespy/tools/fluid_properties/functions.py | 128 +++++++++++++++--- src/tespy/tools/fluid_properties/wrappers.py | 2 +- 3 files changed, 116 insertions(+), 20 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 086697c3e..2b594f9fc 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -843,7 +843,7 @@ def v_ref_deriv(self, k, **kwargs): def calc_x(self): try: - return Q_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data) + return Q_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, self.force_state) except NotImplementedError: return np.nan @@ -901,7 +901,7 @@ def calc_results(self): self.T.val_SI = self.calc_T() number_fluids = get_number_of_fluids(self.fluid_data) _converged = True - if number_fluids > 1: + if number_fluids > 1 and not "HEOS" in [self.fluid_data[f]["wrapper"].back_end for f in self.fluid_data] and not "Water" in [self.fluid_data[f]["wrapper"].fluid for f in self.fluid_data]: h_from_T = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule, force_state=self.force_state) if abs(h_from_T - self.h.val_SI) > ERR ** .5: self.T.val_SI = np.nan @@ -926,7 +926,7 @@ def calc_results(self): if not self.Td_bp.is_set: self.Td_bp.val_SI = self.calc_Td_bp() except ValueError: - self.x.val_SI = np.nan + self.Td_bp.val_SI = np.nan if _converged: self.vol.val_SI = self.calc_vol() diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index 42a1482c2..e2abf6cb1 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -77,12 +77,34 @@ def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_ph(p, h) else: - _check_mixing_rule(mixing_rule, T_MIX_PH_REVERSE, "temperature (from enthalpy)") - kwargs = { - "p": p, "target_value": h, "fluid_data": fluid_data, "T0": T0, - "f": T_MIX_PH_REVERSE[mixing_rule], "force_state" : force_state, - } - return inverse_temperature_mixture(**kwargs) + back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] + if "HEOS" in back_ends and not force_state: + fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] + if not "Water" in fluids: + msg = "Saturation function cannot be called on mixtures, unless there is water" + raise ValueError(msg) + else: + fluid = fluids[fluids.index("Water")] + Tsat = fluid_data[fluid]["wrapper"].T_sat(p) + hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') + hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') + x = (h-hL)/(hV-hL) + if h>hL and h=hV: + x = 1.0 + else: + x = (h-hL)/(hV-hL) + return x + + #msg = "Saturation function cannot be called on mixtures." + #raise ValueError(msg) def p_sat_T(T, fluid_data, mixing_rule=None): @@ -157,8 +203,19 @@ def T_sat_p(p, fluid_data, mixing_rule=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_sat(p) else: - msg = "Saturation function cannot be called on mixtures." - raise ValueError(msg) + back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] + if "HEOS" in back_ends: + fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] + if not "Water" in fluids: + msg = "Saturation function cannot be called on mixtures, unless there is HEOS::water" + raise ValueError(msg) + else: + fluid = fluids[fluids.index("Water")] + Tsat = fluid_data[fluid]["wrapper"].T_sat(p) + return Tsat + else: + msg = "Saturation function cannot be called on mixtures, unless there is HEOS::water" + raise ValueError(msg) def dT_sat_dp(p, fluid_data, mixing_rule=None): @@ -173,9 +230,28 @@ def s_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].s_ph(p, h) else: - T = T_mix_ph(p, h , fluid_data, mixing_rule, T0, force_state=force_state) - return s_mix_pT(p, T, fluid_data, mixing_rule, force_state=force_state) - + back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] + if "HEOS" in back_ends and not force_state: + fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] + if not "Water" in fluids: + msg = "Saturation function cannot be called on mixtures, unless there is water" + raise ValueError(msg) + else: + fluid = fluids[fluids.index("Water")] + Tsat = fluid_data[fluid]["wrapper"].T_sat(p) + hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') + hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') + if h>hL and hhL and h Date: Mon, 13 Nov 2023 13:14:06 +0100 Subject: [PATCH 042/105] calculate incompressible two-phase states based on HEOS::Water --- ...sFlowSplitWithDeltaTDeltaP-decanterTest.py | 2 +- src/tespy/connections/connection.py | 9 +- src/tespy/networks/network_reader.py | 1 + src/tespy/tools/fluid_properties/functions.py | 178 +++++++----------- 4 files changed, 73 insertions(+), 117 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py index 506480013..d1190a737 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py @@ -38,7 +38,7 @@ p0 = 1 # global guess value in bar #water = 'INCOMP::FoodWater' -water = 'Water' +water = 'Water' # wrapper gets HEOS backend for c in nw.conns['object']: n_fl = 3 # len(nw.fluids) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 2b594f9fc..40d368e89 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -667,19 +667,18 @@ def simplify_specifications(self): self.h.solved = True self.T.solved = True elif self.Td_bp.is_set: - T_sat = T_sat_p(self.p.val_SI, self.fluid_data) + T_sat = T_sat_p(self.p.val_SI, self.fluid_data, self.mixing_rule) self.h.val_SI = h_mix_pT(self.p.val_SI, T_sat + self.Td_bp.val, self.fluid_data, self.force_state) self.h.solved = True self.Td_bp.solved = True elif self.x.is_set: - self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data) + self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) self.h.solved = True self.x.solved = True - elif not self.h.is_set and not self.p.is_set: if self.T.is_set and self.x.is_set: - self.p.val_SI = p_sat_T(self.T.val_SI, self.fluid_data) - self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data) + self.p.val_SI = p_sat_T(self.T.val_SI, self.fluid_data, self.mixing_rule) + self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) self.T.solved = True self.x.solved = True self.p.solved = True diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index ccd31f337..2f8ee465e 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -90,6 +90,7 @@ 'SeparatorWithSpeciesSplitsDeltaP' : SeparatorWithSpeciesSplitsDeltaP, 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, + 'SimpleHeatExchangerDeltaPLfKpi' : SimpleHeatExchangerDeltaPLfKpi, } ENGINE_TARGET_CLASSES = { diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index e2abf6cb1..7eb851ea8 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -77,34 +77,20 @@ def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_ph(p, h) else: - back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] - if "HEOS" in back_ends and not force_state: - fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] - if not "Water" in fluids: - msg = "Saturation function cannot be called on mixtures, unless there is water" - raise ValueError(msg) - else: - fluid = fluids[fluids.index("Water")] - Tsat = fluid_data[fluid]["wrapper"].T_sat(p) - hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') - hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') - x = (h-hL)/(hV-hL) - if h>hL and hhL and h=hV: - x = 1.0 + return 1.0 else: - x = (h-hL)/(hV-hL) - return x - - #msg = "Saturation function cannot be called on mixtures." - #raise ValueError(msg) - + return (h-hL)/(hV-hL) + if force_state == 'l': + return 0.0 + elif force_state == 'g': + return 1.0 + msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" + raise ValueError(msg) def p_sat_T(T, fluid_data, mixing_rule=None): if get_number_of_fluids(fluid_data) == 1: pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].p_sat(T) else: - msg = "Saturation function cannot be called on mixtures." - raise ValueError(msg) + if "Water" in fluid_data: + if fluid_data["Water"]["wrapper"].back_end == "HEOS": + return fluid_data["Water"]["wrapper"].p_sat(T) + msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" + raise ValueError(msg) def T_sat_p(p, fluid_data, mixing_rule=None): @@ -203,19 +187,11 @@ def T_sat_p(p, fluid_data, mixing_rule=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].T_sat(p) else: - back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] - if "HEOS" in back_ends: - fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] - if not "Water" in fluids: - msg = "Saturation function cannot be called on mixtures, unless there is HEOS::water" - raise ValueError(msg) - else: - fluid = fluids[fluids.index("Water")] - Tsat = fluid_data[fluid]["wrapper"].T_sat(p) - return Tsat - else: - msg = "Saturation function cannot be called on mixtures, unless there is HEOS::water" - raise ValueError(msg) + if "Water" in fluid_data: + if fluid_data["Water"]["wrapper"].back_end == "HEOS": + return fluid_data["Water"]["wrapper"].T_sat(p) + msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" + raise ValueError(msg) def dT_sat_dp(p, fluid_data, mixing_rule=None): @@ -230,28 +206,18 @@ def s_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): pure_fluid = get_pure_fluid(fluid_data) return pure_fluid["wrapper"].s_ph(p, h) else: - back_ends = [fluid_data[f]["wrapper"].back_end for f in fluid_data] - if "HEOS" in back_ends and not force_state: - fluids = [fluid_data[f]["wrapper"].fluid for f in fluid_data] - if not "Water" in fluids: - msg = "Saturation function cannot be called on mixtures, unless there is water" - raise ValueError(msg) - else: - fluid = fluids[fluids.index("Water")] - Tsat = fluid_data[fluid]["wrapper"].T_sat(p) - hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') - hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') - if h>hL and hhL and hhL and hhL and h Date: Mon, 13 Nov 2023 16:14:12 +0100 Subject: [PATCH 043/105] fixing typo --- src/tespy/tools/fluid_properties/wrappers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 73b9c90a9..17a609455 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -158,7 +158,7 @@ def _check_imposed_state(self,p,T,**kwargs): try: self.AS.update(CP.PT_INPUTS, p, T) except: - print("allowing state to move up on the liquid saturation curve") + #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) pass elif kwargs['force_state'] == "g": @@ -167,8 +167,8 @@ def _check_imposed_state(self,p,T,**kwargs): try: self.AS.update(CP.PT_INPUTS, p, T) except: - print("allowing state to move further down on the gas curve") - self.AS.update(CP.QT_INPUTS, 0, T) + #print("allowing state to move further down on the gas curve") + self.AS.update(CP.QT_INPUTS, 1, T) pass else: self.AS.update(CP.PT_INPUTS, p, T) From db6cfeb70bbc493a2ed454edcd30c23fedf6b27c Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 13 Nov 2023 16:15:02 +0100 Subject: [PATCH 044/105] ensuring pT functions work at Tsat > Tmax --- src/tespy/tools/fluid_properties/functions.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index 7eb851ea8..afc8c67d0 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -80,9 +80,9 @@ def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if "Water" in fluid_data and not force_state: if fluid_data["Water"]["wrapper"].back_end == "HEOS": Tsat = fluid_data["Water"]["wrapper"].T_sat(p) - hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') - hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') - x = (h-hL)/(hV-hL) + T = min([fluid_data[f]["wrapper"]._T_max for f in fluid_data]+[Tsat]) + hL = h_mix_pT(p, T, fluid_data, mixing_rule, force_state = 'l') + hV = h_mix_pT(p, T, fluid_data, mixing_rule, force_state = 'g') if h>hL and h Date: Wed, 22 Nov 2023 12:35:28 +0100 Subject: [PATCH 045/105] possibility to set mass flow out of a species --- src/tespy/components/newcomponents.py | 47 +++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 18c01e34b..8aa99320d 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -477,7 +477,44 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=1, ) + variables["SF"] = dc_cp_SFS( + min_val=0, + deriv=self.SF_deriv, + func=self.SF_func, + latex=self.pr_func_doc, + num_eq=1, + ) return variables + + def SF_func(self): + r""" + Equation for SF. + + """ + + fluid = self.SF.split_fluid + out_i = int(self.SF.split_outlet[3:]) - 1 + i = self.inl[0] + o = self.outl[out_i] + + res = self.SF.val - o.fluid.val[fluid] * o.m.val_SI + + return res + + def SF_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for SF. + + """ + + fluid = self.SF.split_fluid + out_i = int(self.SF.split_outlet[3:]) - 1 + + o = self.outl[out_i] + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI def SFS_func(self): r""" @@ -515,6 +552,16 @@ def SFS_deriv(self, increment_filter, k): if fluid in o.fluid.is_var: self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + def calc_parameters(self): + super().calc_parameters() + + i = self.inl[0] + if self.SFS.is_set: + fluid = self.SFS.split_fluid + self.SF.val = self.SFS.val* i.fluid.val[fluid] * i.m.val_SI + if self.SF.is_set: + fluid = self.SF.split_fluid + self.SFS.val = self.SF.val / (i.fluid.val[fluid] * i.m.val_SI) class SeparatorWithSpeciesSplitsDeltaT(SeparatorWithSpeciesSplits): From c747bc0051b8ee48ff5794d43f2e7f61ece21175 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 22 Nov 2023 22:41:27 +0100 Subject: [PATCH 046/105] missing rule --- src/tespy/connections/connection.py | 4 ++-- src/tespy/tools/fluid_properties/functions.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 40d368e89..ce74ee12f 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -848,11 +848,11 @@ def calc_x(self): def x_func(self, k, **kwargs): # saturated steam fraction - self.residual[k] = self.h.val_SI - h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data) + self.residual[k] = self.h.val_SI - h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) def x_deriv(self, k, **kwargs): if self.p.is_var: - self.jacobian[k, self.p.J_col] = -dh_mix_dpQ(self.p.val_SI, self.x.val_SI, self.fluid_data) + self.jacobian[k, self.p.J_col] = -dh_mix_dpQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) if self.h.is_var: self.jacobian[k, self.h.J_col] = 1 diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index afc8c67d0..9c386bae5 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -142,8 +142,8 @@ def h_mix_pQ(p, Q, fluid_data, mixing_rule=None): def dh_mix_dpQ(p, Q, fluid_data, mixing_rule=None): d = 0.1 - upper = h_mix_pQ(p + d, Q, fluid_data) - lower = h_mix_pQ(p - d, Q, fluid_data) + upper = h_mix_pQ(p + d, Q, fluid_data, mixing_rule) + lower = h_mix_pQ(p - d, Q, fluid_data, mixing_rule) return (upper - lower) / (2 * d) From 1e5ed1fcc68e99f2dd79de9fa98f1a568658d013 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 23 Nov 2023 09:47:01 +0100 Subject: [PATCH 047/105] validating ttd_min and kA --- .../newComponentsTests/2streamHX.py | 14 ++++++++++++++ src/tespy/components/newcomponents.py | 9 +++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py index 603000381..dcc243bb5 100644 --- a/incompressiblesTests/newComponentsTests/2streamHX.py +++ b/incompressiblesTests/newComponentsTests/2streamHX.py @@ -67,6 +67,20 @@ nw.print_results(colored=True, print_results=False) print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) +Ti1 = nw.results['Connection']['T'][0] +To1 = nw.results['Connection']['T'][1] +Ti2 = nw.results['Connection']['T'][2] +To2 = nw.results['Connection']['T'][3] + +dTA = (Ti1-To2) +dTB = (To1-Ti2) +import numpy as np +LMDT = (dTA-dTB)/np.log(dTA/dTB) +UA = -he.Q.val/LMDT + +if not he.kA.val == UA: + raise Exception("UA did not compare") + he.set_attr(ttd_l = None,ttd_min = None,kA=10e3) # using new model with pinch nw.solve("design",print_results=True) if not nw.converged: diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 8aa99320d..f07652e93 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -359,8 +359,13 @@ def _calc_dTs(self): T_i2 = i2.calc_T(T0=i2.T.val_SI) T_o2 = o2.calc_T(T0=o2.T.val_SI) - dTa = abs(T_i1-T_o2) - dTb = abs(T_i2-T_o1) + if T_i1 > T_i2: + dTa = T_i1-T_o2 + dTb = T_o1-T_i2 + else: + dTa = -T_i1+T_o2 + dTb = -T_o1+T_i2 + return dTa,dTb def ttd_min_func(self): From d7c8262e1a65e7e987602d51377803c5a369a067 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 23 Nov 2023 15:45:01 +0100 Subject: [PATCH 048/105] updating tespy issues with saturation --- src/tespy/components/nodes/separator.py | 10 ++++-- src/tespy/connections/connection.py | 2 +- src/tespy/networks/network.py | 5 ++- src/tespy/networks/network_reader.py | 1 + src/tespy/tools/fluid_properties/wrappers.py | 33 +++++++++++++------- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index dea3f3f04..66f89ae7b 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -337,8 +337,8 @@ def energy_balance_deriv(self, increment_filter, k): Position of derivatives in Jacobian matrix (k-th equation). """ i = self.inl[0] - dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule) - dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule) + dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) + dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) # dT_dfluid_in = {} # for fluid in i.fluid.is_var: # dT_dfluid_in[fluid] = dT_mix_ph_dfluid(i) @@ -349,7 +349,7 @@ def energy_balance_deriv(self, increment_filter, k): self.jacobian[k, i.h.J_col] = dT_dh_in # for fluid in i.fluid.is_var: # self.jacobian[k, i.fluid.J_col[fluid]] = dT_dfluid_in[fluid] - args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule) + args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule,i.T.val_SI,o.force_state) if self.is_variable(o.p): self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) if self.is_variable(o.h): @@ -357,3 +357,7 @@ def energy_balance_deriv(self, increment_filter, k): # for fluid in o.fluid.is_var: # self.jacobian[k, o.fluid.J_col[fluid]] = -dT_mix_ph_dfluid(o) k += 1 + + # deriv = [d for d in self.jacobian.items()] + # [print(d) for d in deriv] + # deriv diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index ce74ee12f..218466f9d 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -748,7 +748,7 @@ def calc_T(self, T0=None): return T_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=T0, force_state=self.force_state) def T_func(self, k, **kwargs): - self.residual[k] = self.calc_T() - self.T.val_SI + self.residual[k] = self.calc_T(T0=self.T.val_SI) - self.T.val_SI def T_deriv(self, k, **kwargs): if self.p.is_var: diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index a38a46631..475055c3d 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1086,7 +1086,7 @@ def presolve_fluid_topology(self): main_conn.fluid.is_var = variable num_var = len(variable) for f in variable: - main_conn.fluid.val[f]: (1 - mass_fraction_sum) / num_var + main_conn.fluid.val[f] = (1 - mass_fraction_sum) / num_var [c.build_fluid_data() for c in all_connections] for fluid in main_conn.fluid.is_var: @@ -2298,6 +2298,9 @@ def update_variables(self): #data["obj"].val += RobustRelax * self.increment[data["obj"].J_col] + #print(data["obj"].val) + + # # keep value within specified value range diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 2f8ee465e..c74843a1d 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -91,6 +91,7 @@ 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, 'SimpleHeatExchangerDeltaPLfKpi' : SimpleHeatExchangerDeltaPLfKpi, + 'DrierWithAir' : DrierWithAir, } ENGINE_TARGET_CLASSES = { diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 17a609455..31ecb8ff4 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -152,7 +152,7 @@ def _check_imposed_state(self,p,T,**kwargs): if self.back_end == "INCOMP": if T == (self._T_max + self._T_min) / 2: T += ERR - if kwargs['force_state'] == "l" or self.back_end == "INCOMP": # incomp is always liquid + if self.back_end == "INCOMP": self.AS.update(CP.QT_INPUTS, 0, T) if p > self.AS.p(): try: @@ -160,18 +160,27 @@ def _check_imposed_state(self,p,T,**kwargs): except: #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) - pass - elif kwargs['force_state'] == "g": - self.AS.update(CP.QT_INPUTS, 1, T) - if p < self.AS.p(): - try: - self.AS.update(CP.PT_INPUTS, p, T) - except: - #print("allowing state to move further down on the gas curve") - self.AS.update(CP.QT_INPUTS, 1, T) - pass + else: + self.AS.update(CP.PT_INPUTS, p, T) else: - self.AS.update(CP.PT_INPUTS, p, T) + if (kwargs['force_state'] == "l") and not (T > self.AS.T_critical()): + self.AS.update(CP.QT_INPUTS, 0, T) + if p > self.AS.p(): + try: + self.AS.update(CP.PT_INPUTS, p, T) + except: + #print("allowing state to move up on the liquid saturation curve") + self.AS.update(CP.QT_INPUTS, 0, T) + elif kwargs['force_state'] == "g" and not (T > self.AS.T_critical()): + self.AS.update(CP.QT_INPUTS, 1, T) + if p < self.AS.p(): + try: + self.AS.update(CP.PT_INPUTS, p, T) + except: + #print("allowing state to move further down on the gas curve") + self.AS.update(CP.QT_INPUTS, 1, T) + else: + self.AS.update(CP.PT_INPUTS, p, T) def h_pT(self, p, T, **kwargs): self._check_imposed_state(p,T,**kwargs) From 5c71b12c34f15fa4c4cda9914af74834b67de3fb Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 24 Nov 2023 08:51:11 +0100 Subject: [PATCH 049/105] Revert "Auxiliary commit to revert individual files from d7c8262e1a65e7e987602d51377803c5a369a067" This reverts commit a60004bcdf5b1bc24c2204cbb4412c800ec22ad6. --- src/tespy/components/nodes/separator.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index 66f89ae7b..dea3f3f04 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -337,8 +337,8 @@ def energy_balance_deriv(self, increment_filter, k): Position of derivatives in Jacobian matrix (k-th equation). """ i = self.inl[0] - dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) - dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) + dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule) + dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule) # dT_dfluid_in = {} # for fluid in i.fluid.is_var: # dT_dfluid_in[fluid] = dT_mix_ph_dfluid(i) @@ -349,7 +349,7 @@ def energy_balance_deriv(self, increment_filter, k): self.jacobian[k, i.h.J_col] = dT_dh_in # for fluid in i.fluid.is_var: # self.jacobian[k, i.fluid.J_col[fluid]] = dT_dfluid_in[fluid] - args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule,i.T.val_SI,o.force_state) + args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule) if self.is_variable(o.p): self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) if self.is_variable(o.h): @@ -357,7 +357,3 @@ def energy_balance_deriv(self, increment_filter, k): # for fluid in o.fluid.is_var: # self.jacobian[k, o.fluid.J_col[fluid]] = -dT_mix_ph_dfluid(o) k += 1 - - # deriv = [d for d in self.jacobian.items()] - # [print(d) for d in deriv] - # deriv From 592441afb9057c70203cdc9a3548cd0b0ab9bf8a Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 24 Nov 2023 15:48:59 +0100 Subject: [PATCH 050/105] possibility to set delta H --- incompressiblesTests/Ex9tespy070.csv | 26 +- .../SpeciesFlowSplitWithDeltaH.py | 96 +++++++ src/tespy/components/newcomponents.py | 234 +++++++++++++----- src/tespy/tools/fluid_properties/wrappers.py | 2 +- 4 files changed, 285 insertions(+), 73 deletions(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py diff --git a/incompressiblesTests/Ex9tespy070.csv b/incompressiblesTests/Ex9tespy070.csv index 697fd605d..73eee03f7 100644 --- a/incompressiblesTests/Ex9tespy070.csv +++ b/incompressiblesTests/Ex9tespy070.csv @@ -1,15 +1,15 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,PHE,Water,S800 -source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,0.0,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.15,0.8,0.05 -boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,0.0,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.15,0.8,0.05 -press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,0.0,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.45,0.5,0.05 -press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.0803804407956944,m3 / s,5.0,bar,330.6883654543774,kJ / kg,85.0000000000012,C,0.0,C,0.001048440532117753,m3 / kg,0.0,-,1051.028692719397,J / kgK,0.058695652173913045,0.8913043478260869,0.049999999999999996 -presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.0809604901932347,m3 / s,5.0,bar,370.2784672442943,kJ / kg,95.0,C,0.0,C,0.0010560063938248004,m3 / kg,0.0,-,1160.0534576533798,J / kgK,0.058695652173913045,0.8913043478260869,0.049999999999999996 -decanter:out1_liquidmerge:in2,3.857142857142857,kg / s,0.004268479211824417,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,0.0,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.35,0.6,0.05 -decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.0763965456483523,m3 / s,5.0,bar,354.1205824522718,kJ / kg,90.0000000000029,C,0.0,C,0.0010492658329727916,m3 / kg,0.0,-,1117.673342516117,J / kgK,0.0432635709614127,0.9067364290385873,0.05 -centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015924088,m3 / s,5.0,bar,181.05101285505833,kJ / kg,45.00000000000182,C,0.0,C,0.0010182475569933,m3 / kg,0.0,-,611.6350715142552,J / kgK,0.044664142370314276,0.9449148049981068,0.010421052631578944 -centrifuge:out2_oil:in1,2.9417989417989414,kg / s,0.00333524269094514,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,0.0,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.01,0.0,0.99 -thickener:out1_liquidmerge:in3,12.482328042328044,kg / s,0.013748836912735755,m3 / s,5.0,bar,356.36268450896904,kJ / kg,104.99999999999955,C,0.0,C,0.0011014641552531653,m3 / kg,0.0,-,1096.5687083290422,J / kgK,0.25,0.6916699164109257,0.0583300835890741 +,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE +source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,-146.8310791030812,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.05,0.8,0.15 +boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,-56.83107910306518,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.05,0.8,0.15 +press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,-66.83107910306722,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.05,0.5,0.45 +press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.0803804407956943,m3 / s,5.0,bar,330.68836545439535,kJ / kg,85.00000000000426,C,-66.83107910306353,C,0.0010484405321177516,m3 / kg,0.0,-,1051.0286927194445,J / kgK,0.04999999999999999,0.8913043478260869,0.05869565217391304 +presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.08096049019323556,m3 / s,5.0,bar,370.27846724430117,kJ / kg,95.00000000000495,C,-56.83107910306285,C,0.0010560063938248117,m3 / kg,0.0,-,1160.053457653377,J / kgK,0.04999999999999999,0.8913043478260869,0.05869565217391304 +decanter:out1_liquidmerge:in2,3.8571428571428577,kg / s,0.004268479211824418,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,-61.831079103067964,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.05,0.6,0.35 +decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.07639654564835216,m3 / s,5.0,bar,354.12058245225813,kJ / kg,90.00000000000034,C,-61.83107910306745,C,0.0010492658329727897,m3 / kg,0.0,-,1117.6733425160814,J / kgK,0.05,0.9067364290385873,0.0432635709614127 +centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015923918,m3 / s,5.0,bar,181.05101285511884,kJ / kg,45.000000000011994,C,-106.8310791030558,C,0.0010182475569932756,m3 / kg,0.0,-,611.6350715146631,J / kgK,0.010421052631578945,0.9449148049981068,0.04466414237031428 +centrifuge:out2_oil:in1,2.941798941798942,kg / s,0.0033352426909451405,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,-71.83107910306785,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.99,0.0,0.01 +thickener:out1_liquidmerge:in3,12.482328042328042,kg / s,0.013748836912735735,m3 / s,5.0,bar,356.3626845089672,kJ / kg,104.99999999999858,C,-46.831079103069214,C,0.0011014641552531638,m3 / kg,0.0,-,1096.5687083290277,J / kgK,0.05833008358907411,0.6916699164109258,0.25 thickener:out2_vapourextract1:in1,57.385396825396825,kg / s,0.060096661478604874,m3 / s,5.0,bar,440.55426498767247,kJ / kg,104.99999999999773,C,-46.83107910307007,C,0.0010472465958797402,m3 / kg,-1.0,-,1363.039002179117,J / kgK,0.0,1.0,0.0 -liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153215,m3 / s,5.0,bar,281.9254277292515,kJ / kg,92.28684488833767,C,0.0,C,0.0011139604596594307,m3 / kg,0.0,-,880.7937574528975,J / kgK,0.3773512435050734,0.5700278468317559,0.05262090966317071 -drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262272,m3 / s,5.0,bar,184.93088408428227,kJ / kg,99.99999999999994,C,0.0,C,0.0012051217762996621,m3 / kg,0.0,-,559.4856087856979,J / kgK,0.7898560794044664,0.1,0.11014392059553348 +liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153596,m3 / s,5.0,bar,281.925427729251,kJ / kg,92.28684488833983,C,-59.544234214727965,C,0.0011139604596594405,m3 / kg,0.0,-,880.7937574528644,J / kgK,0.052620909663170706,0.5700278468317559,0.3773512435050734 +drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262276,m3 / s,5.0,bar,184.93088408428306,kJ / kg,100.00000000000051,C,-51.83107910306728,C,0.0012051217762996623,m3 / kg,0.0,-,559.4856087857008,J / kgK,0.1101439205955335,0.1,0.7898560794044664 drier:out2_vapourextract2:in1,20.719247501469713,kg / s,34.63773627778022,m3 / s,1.0141799665682765,bar,2675.569884418101,kJ / kg,99.999999999137,C,0.0,C,1.6717661331727036,m3 / kg,1.0,-,7354.1191457120685,J / kgK,0.0,1.0,0.0 diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py new file mode 100644 index 000000000..97008b871 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py @@ -0,0 +1,96 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH("Separator",num_out=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +#c1.set_attr(T0=10) # it seems guess values are SI + +c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) + +se.set_attr(SFS={ + 'val': 0.6, 'is_set': True, + 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}, + deltaP=0.0) + +se.set_attr(deltaH=50e3) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + +# Now it is possible to set the temperatures out of the separator differently +se.set_attr(deltaH=None) +c2.set_attr(T=20) +c3.set_attr(T=10) + + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +se.set_attr(deltaH=0.0) +c2.set_attr(T=None) +c3.set_attr(T=None) + + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index f07652e93..db5c1ea90 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -8,6 +8,10 @@ from tespy.components.component import Component +from tespy.tools.fluid_properties import dT_mix_dph +from tespy.tools.fluid_properties import dT_mix_pdh + + import warnings @@ -577,7 +581,7 @@ def component(): def get_parameters(self): variables = super().get_parameters() variables["deltaT"] = dc_cp( - deriv=self.energy_balance_deriv, # same as before + deriv=self.energy_balance_deltaT_deriv, # same as before func=self.energy_balance_deltaT_func, latex=self.pr_func_doc, num_eq=self.num_out @@ -594,9 +598,10 @@ def get_mandatory_constraints(self): 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, 'num_eq': num_fluid_eq} - del constraints['energy_balance_constraints'] + if constraints.get("energy_balance_constraints",False): + del constraints['energy_balance_constraints'] return constraints - + def energy_balance_deltaT_func(self): r""" Calculate deltaT residuals. @@ -616,6 +621,36 @@ def energy_balance_deltaT_func(self): for o in self.outl: residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess return residual + + def energy_balance_deltaT_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) + dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) + # dT_dfluid_in = {} + # for fluid in i.fluid.is_var: + # dT_dfluid_in[fluid] = dT_mix_ph_dfluid(i) + for o in self.outl: + if self.is_variable(i.p): + self.jacobian[k, i.p.J_col] = dT_dp_in + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = dT_dh_in + # for fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col[fluid]] = dT_dfluid_in[fluid] + args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule,i.T.val_SI,o.force_state) + if self.is_variable(o.p): + self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -dT_mix_pdh(*args) + # for fluid in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col[fluid]] = -dT_mix_ph_dfluid(o) + k += 1 + + # deriv = [d for d in self.jacobian.items()] + # [print(d) for d in deriv] + # deriv def calc_parameters(self): super().calc_parameters() @@ -629,6 +664,72 @@ def calc_parameters(self): else: self.deltaT.val = i.T.val_SI - Tmax +class SeparatorWithSpeciesSplitsDeltaH(SeparatorWithSpeciesSplits): + + @staticmethod + def component(): + return 'separator with species flow splits and dH on outlets' + + def get_parameters(self): + variables = super().get_parameters() + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=self.num_out + ) + variables["Q"] = dc_cp(is_result=True) + #variables["Qout"] = dc_cpa() + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + if constraints.get("energy_balance_constraints",False): + del constraints['energy_balance_constraints'] + return constraints + + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. + + """ + i = self.inl[0] + residual = [] + for o in self.outl: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual + + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in self.outl: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 + + def calc_parameters(self): + super().calc_parameters() + i = self.inl[0] + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + + hmin = min([o.h.val_SI for o in self.outl]) + hmax = max([o.h.val_SI for o in self.outl]) + if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): + self.deltaH.val = i.h.val_SI - hmin + else: + self.deltaH.val = i.h.val_SI - hmax + + class SeparatorWithSpeciesSplitsDeltaP(SeparatorWithSpeciesSplits): @staticmethod @@ -709,8 +810,24 @@ def get_mandatory_constraints(self): #del constraints['energy_balance_constraints'] return constraints +class SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaP): -class DrierWithAir(SeparatorWithSpeciesSplitsDeltaP): + @staticmethod + def component(): + return 'separator with species flow splits and dT, dH and dP on outlets' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + #del constraints['pressure_constraints'] + #del constraints['energy_balance_constraints'] + return constraints + + +class DrierWithAir(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaP): def __init__(self, label, **kwargs): #self.set_attr(**kwargs) @@ -742,14 +859,6 @@ def inlets(self): def get_parameters(self): variables = super().get_parameters() variables["num_in"] = dc_simple() - variables["deltaT"] = dc_cp( - deriv=self.energy_balance_deriv, # same as before - func=self.energy_balance_deltaT_func, - latex=self.pr_func_doc, - num_eq=self.num_out - ) - variables["Q"] = dc_cp(is_result=True) - #variables["Qout"] = dc_cpa() return variables def get_mandatory_constraints(self): @@ -760,24 +869,11 @@ def get_mandatory_constraints(self): 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, 'num_eq': num_fluid_eq} - del constraints['energy_balance_constraints'] return constraints def fluid_func(self): r""" Calculate the vector of residual values for fluid balance equations. - - Returns - ------- - residual : list - Vector of residual values for component's fluid balance. - - .. math:: - - 0 = \dot{m}_{in} \cdot x_{fl,in} - \dot {m}_{out,j} - \cdot x_{fl,out,j}\\ - \forall fl \in \text{network fluids,} - \; \forall j \in \text{outlets} """ #i = self.inl[0] residual = [] @@ -799,14 +895,6 @@ def fluid_func(self): def fluid_deriv(self, increment_filter, k): r""" Calculate partial derivatives of fluid balance. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of derivatives in Jacobian matrix (k-th equation). """ #i = self.inl[0] for fluid in self.variable_fluids: @@ -822,10 +910,6 @@ def fluid_deriv(self, increment_filter, k): if fluid in i.fluid.is_var: self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - # if fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI k += 1 i = self.inl[1] @@ -839,27 +923,6 @@ def fluid_deriv(self, increment_filter, k): if fluid in i.fluid.is_var: self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - def energy_balance_deltaT_func(self): - r""" - Calculate deltaT residuals based on in[0] solely. - - """ - i = self.inl[0] - if i.T.is_set: - T_in = i.T.val_SI - else: - # calculate T_in - if i.T.val0 > 0: - T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule,i.T.val0) - else: - T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule) - - residual = [] - for o in self.outl: - residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess - return residual - def calc_parameters(self): super().calc_parameters() @@ -874,7 +937,6 @@ def calc_parameters(self): self.deltaT.val = i.T.val_SI - Tmin else: self.deltaT.val = i.T.val_SI - Tmax - class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): @@ -939,6 +1001,60 @@ def bus_deriv(self, bus): bus.jacobian[o.m.J_col] -= self.numeric_deriv(f, 'm', o, bus=bus) +class SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaP): + + @staticmethod + def component(): + return 'separator with species flow splits and dT, dH and dP on outlets' + + def get_parameters(self): + variables = super().get_parameters() + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + #del constraints['pressure_constraints'] + #del constraints['energy_balance_constraints'] + return constraints + + def get_parameters(self): + variables = super().get_parameters() + variables["FS"] = dc_cp_FS( + min_val=0, + deriv=self.FS_deriv, + func=self.FS_func, + latex=self.pr_func_doc, + num_eq=1, + ) + return variables + + def FS_func(self): + r""" + Equation for flow split. + + """ + + out_i = int(self.FS.split_outlet[3:]) - 1 + res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI + return res + + def FS_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for flow split + + """ + + out_i = int(self.FS.split_outlet[3:]) - 1 + + i = self.inl[0] + o = self.outl[out_i] + if i.m.is_var: + self.jacobian[k, i.m.J_col] = self.FS.val + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + + + class SplitterDeltaP(Splitter): def __init__(self, label, **kwargs): diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 31ecb8ff4..857d2bdb3 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -161,7 +161,7 @@ def _check_imposed_state(self,p,T,**kwargs): #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) else: - self.AS.update(CP.PT_INPUTS, p, T) + self.AS.update(CP.QT_INPUTS, 0, T) else: if (kwargs['force_state'] == "l") and not (T > self.AS.T_critical()): self.AS.update(CP.QT_INPUTS, 0, T) From 12deb223139c06cb883558e2b63dc1a4c7d227a6 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 13:45:30 +0100 Subject: [PATCH 051/105] EXTREMELY IMPORTANT TO SET ENTHALPY BASED ON T0 WHEN SOLVING FOR TOUT --- ...SpeciesFlowSplitWithDeltaT-drierWithAir.py | 28 +++--- src/tespy/components/newcomponents.py | 92 ++++++++++++++++--- src/tespy/networks/network.py | 7 ++ 3 files changed, 102 insertions(+), 25 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py index 486efb6e8..5b53e7aba 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py @@ -35,28 +35,34 @@ nw.add_conns(c1, c2, c3, c4) +# for c in nw.conns['object']: +# c.set_attr(m0=1, h0=100, p0=1.2) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") -c4.set_attr(m=10, p=1.2, T=80, fluid={"INCOMP::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") +c1.set_attr(m=1, p=1.2, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") +c4.set_attr(m=10, p=1.2, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") c2.set_attr(fluid={"INCOMP::T66": 0}) -c3.set_attr(fluid={"INCOMP::Water": 0.08, "HEOS::Air": 0}) +c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) -c2.set_attr(p=1.2,T=60) +#c2.set_attr(p=1.2,T=60,force_state='g') +c2.set_attr(p=1.2,T=60,force_state='g') c3.set_attr(p=1.2,T=60) +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() +# print(nw.results['Connection']) + + +c2.set_attr(T=None,T0=60) +c3.set_attr(T=None,T0=60) +se.set_attr(Eff_T=0.5) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - - diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index db5c1ea90..c9e774f85 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -11,12 +11,29 @@ from tespy.tools.fluid_properties import dT_mix_dph from tespy.tools.fluid_properties import dT_mix_pdh - +from CoolProp.HumidAirProp import HAPropsSI import warnings import numpy as np + +def get_T(port): + if port.T.is_set: + T = port.T.val_SI + else: + if port.T.val0 > 0: + T = T_mix_ph(port.p.val_SI,port.h.val_SI,port.fluid_data,port.mixing_rule,port.T.val0,port.force_state) + else: + T = T_mix_ph(port.p.val_SI,port.h.val_SI,port.fluid_data,port.mixing_rule,300,port.force_state) + return T + +def get_Twb(port,T): + M = port.fluid.val["Water"]/(port.fluid.val["Water"]+port.fluid.val["Air"]) + W = M/(1-M) + return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) + + class DiabaticSimpleHeatExchanger(SimpleHeatExchanger): @staticmethod @@ -607,16 +624,7 @@ def energy_balance_deltaT_func(self): Calculate deltaT residuals. """ - i = self.inl[0] - if i.T.is_set: - T_in = i.T.val_SI - else: - # calculate T_in - if i.T.val0 > 0: - T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule,i.T.val0) - else: - T_in = T_mix_ph(i.p.val_SI,i.h.val_SI,i.fluid_data,i.mixing_rule) - + T_in = get_T(self.inl[0]) residual = [] for o in self.outl: residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess @@ -859,6 +867,14 @@ def inlets(self): def get_parameters(self): variables = super().get_parameters() variables["num_in"] = dc_simple() + variables["Eff_T"] = dc_cp( + min_val=0,max_val=1, + deriv=self.Eff_T_deriv, + func=self.Eff_T_func, + latex=self.pr_func_doc, + num_eq=2, + ) + return variables def get_mandatory_constraints(self): @@ -885,12 +901,12 @@ def fluid_func(self): res -= o.fluid.val[fluid] * o.m.val_SI residual += [res] - # additional equation for air conservation + # additional balance equation for calculating water vapor mass fraction i = self.inl[1] o = self.outl[0] # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - residual += [(o.m.val_SI - i.m.val_SI*i.fluid.val['Air']) - o.fluid.val['Water'] * o.m.val_SI] - return residual + residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + return residual def fluid_deriv(self, increment_filter, k): r""" @@ -923,6 +939,45 @@ def fluid_deriv(self, increment_filter, k): if fluid in i.fluid.is_var: self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + def Eff_T_residuals(self,eq_num): + # set Tout2 equal to Twb + i = self.inl[1] + T_in = get_T(i) + T_wb = get_Twb(i,T_in) + if eq_num == 1: + o = self.outl[0] + T_out = get_T(o) + return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val + elif eq_num == 2: + o = self.outl[1] + T_out = get_T(o) + return T_out - T_wb + + def Eff_T_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + res = [] + res += [self.Eff_T_residuals(eq_num=1)] + res += [self.Eff_T_residuals(eq_num=2)] + return res + + def Eff_T_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for c in [self.inl[1], self.outl[0]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'p', c, eq_num=1) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'h', c, eq_num=1) + k = k + 1 + for c in [self.inl[1], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'p', c, eq_num=2) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'h', c, eq_num=2) + def calc_parameters(self): super().calc_parameters() @@ -937,6 +992,15 @@ def calc_parameters(self): self.deltaT.val = i.T.val_SI - Tmin else: self.deltaT.val = i.T.val_SI - Tmax + + if self.outl[1].fluid.val['Air'] > 0: + raise Exception("Air cannot go into out2") + + if not self.Eff_T.is_set: + T_in = get_T(self.inl[1]) + T_out = get_T(self.outl[0]) + T_wb = get_Twb(self.inl[1],T_in) + self.Eff_T.val = (T_in-T_out)/(T_in-T_wb) class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 475055c3d..43d9a3881 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1767,6 +1767,13 @@ def init_precalc_properties(self, c): except ValueError: pass + if not np.isnan(c.T.val0): + try: + c.h.val_SI = fp.h_mix_pT(c.p.val_SI, c.T.val0 + 273.15, c.fluid_data, c.mixing_rule, force_state=c.force_state) + except ValueError: + pass + + def init_val0(self, c: con.Connection, key: str): r""" Set starting values for fluid properties. From 5f1028d753c25f261fa9400a3ab5287cba04569d Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 14:31:43 +0100 Subject: [PATCH 052/105] Possibility to set Q for SFS models --- .../SpeciesFlowSplitWithDeltaH-drier.py | 105 ++++++++++++++++++ src/tespy/components/newcomponents.py | 51 ++++++++- 2 files changed, 151 insertions(+), 5 deletions(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py new file mode 100644 index 000000000..a58b9e729 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py @@ -0,0 +1,105 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +se = SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH("Separator",num_out=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +nw.add_conns(c1, c2, c3) + +# set global guess values +m0 = 1 # transform unit at some point [this is kt/yr] +h0 = 1e2 # global guess value in kJ/kg +p0 = 5 # global guess value in bar + +# set some generic data for starting values +c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) +#c1.set_attr(T0=10) # it seems guess values are SI + +c2.set_attr(fluid={"INCOMP::Water": 1, "INCOMP::T66": 0.0}) +c3.set_attr(fluid={"INCOMP::Water": 0.08}) + +c2.set_attr(p=1.2,T=100) +c3.set_attr(p=1.2,T=100) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + + +c2.set_attr(T=None) +c3.set_attr(T=None) + +se.set_attr(Q=2e5) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() + + + + + + +import sys +sys.exit() + + + + + + + + + +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + +se.set_attr(deltaH=0.0) +c2.set_attr(T=None) +c3.set_attr(T=None) + + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +m_T66_c1 = c1.m.val * c1.fluid.val['T66'] +m_T66_c2 = c2.m.val * c2.fluid.val['T66'] +print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") +print(f"\n") + + diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index c9e774f85..495d578bd 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -686,7 +686,10 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=self.num_out ) - variables["Q"] = dc_cp(is_result=True) + variables["Q"] = dc_cp( + max_val=0, func=self.Q_func, num_eq=2, + deriv=self.Q_deriv, + latex=self.pr_func_doc) #variables["Qout"] = dc_cpa() return variables @@ -725,6 +728,46 @@ def energy_balance_deltaH_deriv(self, increment_filter, k): self.jacobian[k, o.h.J_col] = -1 k += 1 + def Q_func_Tequality(self,port1,port2): + return get_T(port1) - get_T(port2) + + def Q_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + res = [] + res += [self.outl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) \ + + self.outl[1].m.val_SI * (self.outl[1].h.val_SI - self.inl[0].h.val_SI) \ + - self.Q.val] + res += [self.Q_func_Tequality(self.outl[0],self.outl[1])] + return res + + def Q_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = i.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = i.m.val_SI + + k = k + 1 + + for c in [self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + def calc_parameters(self): super().calc_parameters() i = self.inl[0] @@ -818,7 +861,7 @@ def get_mandatory_constraints(self): #del constraints['energy_balance_constraints'] return constraints -class SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaP): +class SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaP): @staticmethod def component(): @@ -834,8 +877,7 @@ def get_mandatory_constraints(self): #del constraints['energy_balance_constraints'] return constraints - -class DrierWithAir(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaP): +class DrierWithAir(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): def __init__(self, label, **kwargs): #self.set_attr(**kwargs) @@ -874,7 +916,6 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=2, ) - return variables def get_mandatory_constraints(self): From 55599be66764c5f336c60100554e3203f2079160 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 15:06:31 +0100 Subject: [PATCH 053/105] rename --- ...drierWithAir.py => SpeciesFlowSplitWithDeltaH-drierWithAir.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename incompressiblesTests/newComponentsTests/{SpeciesFlowSplitWithDeltaT-drierWithAir.py => SpeciesFlowSplitWithDeltaH-drierWithAir.py} (100%) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py similarity index 100% rename from incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT-drierWithAir.py rename to incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py From b600d4e725fc6c88090df83b94ad61fcb14abb9a Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 17:12:04 +0100 Subject: [PATCH 054/105] workinng on Q for drier --- .../SpeciesFlowSplitWithDeltaH-drier.py | 19 ++- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 30 ++++- src/tespy/components/newcomponents.py | 124 ++++++++++++++++-- 3 files changed, 154 insertions(+), 19 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py index a58b9e729..4c930a68f 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py @@ -53,18 +53,31 @@ if not nw.converged: raise Exception("not converged") nw.print_results() +print(nw.results['Connection']) -c2.set_attr(T=None) +se.set_attr(Q=2.0e5) +# c3.set_attr(fluid={"INCOMP::Water": None}) +# c3.set_attr(fluid0={"INCOMP::Water": 0.08, "INCOMP::T66": 0.92}) +# c3.set_attr(T0=100) c3.set_attr(T=None) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + -se.set_attr(Q=2e5) + +se.set_attr(Q=None) +se.set_attr(KPI=1.5e5) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() - +print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index 5b53e7aba..ab33faca6 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -50,11 +50,31 @@ c3.set_attr(p=1.2,T=60) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() -# print(nw.results['Connection']) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c3.set_attr(fluid={"INCOMP::Water": None}) +c2.set_attr(T=100) +c3.set_attr(T=None) +se.set_attr(Q=1.0e6) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + + +import sys +sys.exit() + + c2.set_attr(T=None,T0=60) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 495d578bd..59d44f133 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -4,7 +4,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import SimpleDataContainer as dc_simple from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.tools.fluid_properties import T_mix_ph +from tespy.tools.fluid_properties import T_mix_ph, h_mix_pT from tespy.components.component import Component @@ -687,9 +687,14 @@ def get_parameters(self): num_eq=self.num_out ) variables["Q"] = dc_cp( - max_val=0, func=self.Q_func, num_eq=2, + max_val=0, func=self.Q_func, num_eq=1, deriv=self.Q_deriv, latex=self.pr_func_doc) + variables["KPI"] = dc_cp( + deriv=self.KPI_deriv, + func=self.KPI_func, + latex=self.pr_func_doc, + num_eq=2) #variables["Qout"] = dc_cpa() return variables @@ -735,20 +740,63 @@ def Q_func(self): r""" Equation for hot side heat exchanger energy balance. """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + + #res = [] + #res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val] + #res += [self.Q_func_Tequality(o1,o2)] + #return res + return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val + + def Q_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + # k = k + 1 + + # for c in [self.outl[0], self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + + def KPI_func(self): + r""" + Equation for total heat flow rate + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] res = [] - res += [self.outl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) \ - + self.outl[1].m.val_SI * (self.outl[1].h.val_SI - self.inl[0].h.val_SI) \ - - self.Q.val] - res += [self.Q_func_Tequality(self.outl[0],self.outl[1])] + res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] + res += [self.Q_func_Tequality(o1,o2)] return res - def Q_deriv(self, increment_filter, k): + def KPI_deriv(self, increment_filter, k): r""" Partial derivatives for hot side heat exchanger energy balance. """ i = self.inl[0] o1 = self.outl[0] o2 = self.outl[1] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = - self.KPI.val if self.is_variable(i.h): self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI if self.is_variable(o1.m): @@ -756,9 +804,9 @@ def Q_deriv(self, increment_filter, k): if self.is_variable(o2.m): self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = i.m.val_SI + self.jacobian[k, o1.h.J_col] = o1.m.val_SI if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = i.m.val_SI + self.jacobian[k, o2.h.J_col] = o2.m.val_SI k = k + 1 @@ -771,7 +819,11 @@ def Q_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() i = self.inl[0] - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + + if not self.Q.is_set: + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + elif not self.KPI.is_set: + self.KPI.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) / i.m.val_SI hmin = min([o.h.val_SI for o in self.outl]) hmax = max([o.h.val_SI for o in self.outl]) @@ -825,7 +877,6 @@ def deltaP_deriv(self, increment_filter, k): Calculate the partial derivatives for pressure drop """ - i = self.inl[0] for o in self.outl: if i.p.is_var: @@ -1019,6 +1070,57 @@ def Eff_T_deriv(self, increment_filter, k): if self.is_variable(c.h): #, increment_filter): self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'h', c, eq_num=2) + def Q_func_Tequality(self,port1,port2): + return get_T(port1) - get_T(port2) + + def Q_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + res = [] + res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val] + res += [self.Q_func_Tequality(o1,o2)] + return res + + def Q_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = -i1.h.val_SI + if self.is_variable(i2.m): + self.jacobian[k, i2.m.J_col] = -i2.h.val_SI + if self.is_variable(i1.h): + self.jacobian[k, i1.h.J_col] = -i1.m.val_SI + if self.is_variable(i2.h): + self.jacobian[k, i2.h.J_col] = -i2.m.val_SI + + k = k + 1 + + for c in [self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + def calc_parameters(self): super().calc_parameters() From 91daf5bba4fb9f3eb96a5540c9a4bde2f442b65d Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 09:35:21 +0100 Subject: [PATCH 055/105] EXTREMELY IMPORTANT TO UPDATE FLUIDS MASS FRACTION FROM ONE SOLUTION TO ANOTHER TOO --- src/tespy/networks/network.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 43d9a3881..e0669b33b 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1649,6 +1649,14 @@ def init_properties(self): """ if self.init_path is not None: df = self.init_read_connections(self.init_path) + # read val0 for fluids first, before build_fluid_data below + for c in self.conns['object']: + for key in ['fluid']: + if c.get_attr(key).is_var: + #print(c.get_attr(key).val) + #print(c.get_attr(key).val0) + for k,v in c.get_attr(key).val0.items(): + c.get_attr(key).val[k] = v # improved starting values for referenced connections, # specified vapour content values, temperature values as well as # subccooling/overheating and state specification From 16daf72242bedbba520dc6c7f2d8add44bebec0c Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 13:14:23 +0100 Subject: [PATCH 056/105] working on the drier --- .../SpeciesFlowSplitWithDeltaH-drier.py | 21 +- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 46 ++- src/tespy/components/newcomponents.py | 297 ++++++++++++------ 3 files changed, 246 insertions(+), 118 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py index 4c930a68f..cf6665d88 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py @@ -33,21 +33,16 @@ nw.add_conns(c1, c2, c3) -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - # set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") +c1.set_attr(m=1, p=1.0, h=1e2, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") #c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) #c1.set_attr(T0=10) # it seems guess values are SI -c2.set_attr(fluid={"INCOMP::Water": 1, "INCOMP::T66": 0.0}) -c3.set_attr(fluid={"INCOMP::Water": 0.08}) +c2.set_attr(fluid={"HEOS::Water": 1, "INCOMP::T66": 0.0},force_state='g') +c3.set_attr(fluid={"HEOS::Water": 0.08},force_state='l') -c2.set_attr(p=1.2,T=100) -c3.set_attr(p=1.2,T=100) +c2.set_attr(p=1.0,T=100) +c3.set_attr(p=1.0,T=100) nw.solve("design") if not nw.converged: @@ -56,11 +51,11 @@ print(nw.results['Connection']) -se.set_attr(Q=2.0e5) -# c3.set_attr(fluid={"INCOMP::Water": None}) +se.set_attr(Q=2.0e6) +c3.set_attr(fluid={"HEOS::Water": None}) # c3.set_attr(fluid0={"INCOMP::Water": 0.08, "INCOMP::T66": 0.92}) # c3.set_attr(T0=100) -c3.set_attr(T=None) +#c3.set_attr(T=None) nw.solve("design") if not nw.converged: raise Exception("not converged") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index ab33faca6..73cd54738 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -39,16 +39,16 @@ # c.set_attr(m0=1, h0=100, p0=1.2) # set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") -c4.set_attr(m=10, p=1.2, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") +c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") +c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") c2.set_attr(fluid={"INCOMP::T66": 0}) c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) #c2.set_attr(p=1.2,T=60,force_state='g') -c2.set_attr(p=1.2,T=60,force_state='g') -c3.set_attr(p=1.2,T=60) - +c2.set_attr(p=1.0,T=60,force_state='g') +c3.set_attr(p=1.0,force_state='l') +se.set_attr(dTwbProd=0) nw.solve("design") if not nw.converged: @@ -56,12 +56,6 @@ nw.print_results() print(nw.results['Connection']) - -c3.set_attr(fluid={"INCOMP::Water": None}) -c2.set_attr(T=100) -c3.set_attr(T=None) -se.set_attr(Q=1.0e6) - nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -70,19 +64,41 @@ +c3.set_attr(fluid={"INCOMP::Water": None}) +se.set_attr(Q=1.90e6) -import sys -sys.exit() +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +se.set_attr(Q=None) +se.set_attr(KPI=1.5e5) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) +se.set_attr(KPI=None) +c3.set_attr(fluid={"INCOMP::Water": 0.08}) c2.set_attr(T=None,T0=60) -c3.set_attr(T=None,T0=60) -se.set_attr(Eff_T=0.5) +# #c3.set_attr(T=None +c3.set_attr(T0=60) +se.set_attr(Eff_T=0.85) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) +se.set_attr(Eff_T=None) +se.set_attr(kA=10.0e4) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) \ No newline at end of file diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 59d44f133..6d9a2b75b 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -18,22 +18,11 @@ import numpy as np -def get_T(port): - if port.T.is_set: - T = port.T.val_SI - else: - if port.T.val0 > 0: - T = T_mix_ph(port.p.val_SI,port.h.val_SI,port.fluid_data,port.mixing_rule,port.T.val0,port.force_state) - else: - T = T_mix_ph(port.p.val_SI,port.h.val_SI,port.fluid_data,port.mixing_rule,300,port.force_state) - return T - def get_Twb(port,T): M = port.fluid.val["Water"]/(port.fluid.val["Water"]+port.fluid.val["Air"]) W = M/(1-M) return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) - class DiabaticSimpleHeatExchanger(SimpleHeatExchanger): @staticmethod @@ -624,10 +613,10 @@ def energy_balance_deltaT_func(self): Calculate deltaT residuals. """ - T_in = get_T(self.inl[0]) + T_in = self.inl[0].calc_T(T0=self.inl[0].T.val_SI) residual = [] for o in self.outl: - residual += [T_in - self.deltaT.val - T_mix_ph(o.p.val_SI,o.h.val_SI,o.fluid_data,o.mixing_rule, T0=T_in)] # use T_in as guess + residual += [T_in - self.deltaT.val - o.calc_T(T0=T_in)] # use T_in as guess return residual def energy_balance_deltaT_deriv(self, increment_filter, k): @@ -663,7 +652,8 @@ def energy_balance_deltaT_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() i = self.inl[0] - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + if not self.Q.is_set: + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) Tmin = min([o.T.val_SI for o in self.outl]) Tmax = max([o.T.val_SI for o in self.outl]) @@ -687,14 +677,14 @@ def get_parameters(self): num_eq=self.num_out ) variables["Q"] = dc_cp( - max_val=0, func=self.Q_func, num_eq=1, - deriv=self.Q_deriv, - latex=self.pr_func_doc) + func=self.Q_func, num_eq=1, + deriv=self.Q_deriv, + latex=self.pr_func_doc) variables["KPI"] = dc_cp( deriv=self.KPI_deriv, func=self.KPI_func, latex=self.pr_func_doc, - num_eq=2) + num_eq=1) #variables["Qout"] = dc_cpa() return variables @@ -734,7 +724,7 @@ def energy_balance_deltaH_deriv(self, increment_filter, k): k += 1 def Q_func_Tequality(self,port1,port2): - return get_T(port1) - get_T(port2) + return port1.calc_T(T0=port1.T.val_SI) - port2.calc_T(T0=port2.T.val_SI) def Q_func(self): r""" @@ -743,11 +733,10 @@ def Q_func(self): i = self.inl[0] o1 = self.outl[0] o2 = self.outl[1] - - #res = [] - #res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val] - #res += [self.Q_func_Tequality(o1,o2)] - #return res + # #res = [] + # #res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val] + # #res += [self.Q_func_Tequality(o1,o2)] + # #return res return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val def Q_deriv(self, increment_filter, k): @@ -769,7 +758,6 @@ def Q_deriv(self, increment_filter, k): self.jacobian[k, o2.h.J_col] = o2.m.val_SI # k = k + 1 - # for c in [self.outl[0], self.outl[1]]: # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) @@ -783,10 +771,11 @@ def KPI_func(self): i = self.inl[0] o1 = self.outl[0] o2 = self.outl[1] - res = [] - res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] - res += [self.Q_func_Tequality(o1,o2)] - return res + # res = [] + # res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] + # res += [self.Q_func_Tequality(o1,o2)] + # return res + return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI def KPI_deriv(self, increment_filter, k): r""" @@ -808,13 +797,12 @@ def KPI_deriv(self, increment_filter, k): if self.is_variable(o2.h): self.jacobian[k, o2.h.J_col] = o2.m.val_SI - k = k + 1 - - for c in [self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + # k = k + 1 + # for c in [self.outl[0], self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) def calc_parameters(self): super().calc_parameters() @@ -822,7 +810,7 @@ def calc_parameters(self): if not self.Q.is_set: self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - elif not self.KPI.is_set: + if not self.KPI.is_set: self.KPI.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) / i.m.val_SI hmin = min([o.h.val_SI for o in self.outl]) @@ -965,8 +953,22 @@ def get_parameters(self): deriv=self.Eff_T_deriv, func=self.Eff_T_func, latex=self.pr_func_doc, - num_eq=2, + num_eq=1, ) + variables["dTwbProd"] = dc_cp( + deriv=self.dTwbProd_deriv, + func=self.dTwbProd_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables['kA'] = dc_cp( + min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, + deriv=self.kA_deriv) + variables['td_log'] = dc_cp(min_val=0, is_result=True) + variables['ttd_u'] = dc_cp(min_val=0, is_result=True) + variables['ttd_l'] = dc_cp(min_val=0, is_result=True) + variables['Ii'] = dc_cp(min_val=0, is_result=True) + variables['Io'] = dc_cp(min_val=0, is_result=True) return variables def get_mandatory_constraints(self): @@ -1031,28 +1033,16 @@ def fluid_deriv(self, increment_filter, k): if fluid in i.fluid.is_var: self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - def Eff_T_residuals(self,eq_num): - # set Tout2 equal to Twb - i = self.inl[1] - T_in = get_T(i) - T_wb = get_Twb(i,T_in) - if eq_num == 1: - o = self.outl[0] - T_out = get_T(o) - return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val - elif eq_num == 2: - o = self.outl[1] - T_out = get_T(o) - return T_out - T_wb - def Eff_T_func(self): r""" Calculate the vector of residual values for fluid balance equations. """ - res = [] - res += [self.Eff_T_residuals(eq_num=1)] - res += [self.Eff_T_residuals(eq_num=2)] - return res + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[0] + T_out = o.calc_T(T0=o.T.val_SI) + return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val def Eff_T_deriv(self, increment_filter, k): r""" @@ -1060,35 +1050,57 @@ def Eff_T_deriv(self, increment_filter, k): """ for c in [self.inl[1], self.outl[0]]: if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'p', c, eq_num=1) + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_func, 'h', c) + + def dTwbProd_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[1] + T_out = o.calc_T(T0=o.T.val_SI) + return T_out - T_wb - self.dTwbProd.val + + def dTwbProd_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for c in [self.inl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'h', c, eq_num=1) - k = k + 1 - for c in [self.inl[1], self.outl[1]]: + self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # T_wb is nonlinear and we cannot differentiate easily + for c in [self.outl[1]]: if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'p', c, eq_num=2) + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_residuals, 'h', c, eq_num=2) + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) def Q_func_Tequality(self,port1,port2): - return get_T(port1) - get_T(port2) + return port1.calc_T(T0=port1.T.val_SI) - port2.calc_T(T0=port2.T.val_SI) def Q_func(self): r""" - Equation for hot side heat exchanger energy balance. + Need overwrite this function to take into account air inlet """ i1 = self.inl[0] i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] - res = [] - res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val] - res += [self.Q_func_Tequality(o1,o2)] - return res + # res = [] + # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val] + # res += [self.Q_func_Tequality(o1,o2)] + # return res + return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val def Q_deriv(self, increment_filter, k): r""" - Partial derivatives for hot side heat exchanger energy balance. + Need overwrite this function to take into account air inlet """ i1 = self.inl[0] i2 = self.inl[1] @@ -1113,38 +1125,143 @@ def Q_deriv(self, increment_filter, k): if self.is_variable(i2.h): self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - k = k + 1 + # k = k + 1 - for c in [self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + # for c in [self.outl[0], self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + + def KPI_func(self): + r""" + modify Q_func + """ + i1 = self.inl[0] + return self.Q_func() + self.Q.val - i1.m.val_SI*self.KPI.val + + def KPI_deriv(self, increment_filter, k): + r""" + modify Q_deriv + """ + self.Q_deriv(increment_filter, k) + i1 = self.inl[0] + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = self.jacobian[k, i1.m.J_col] - self.KPI.val + + def calculate_td_log(self): + # 1 is with air + i1 = self.inl[1] + o1 = self.outl[0] + + # temperature value manipulation for convergence stability + T_i1 = i1.calc_T(T0=i1.T.val_SI) + T_i2 = get_Twb(i1,T_i1) + T_o1 = o1.calc_T(T0=o1.T.val_SI) + T_o2 = T_i2 + + if T_i1 <= T_o2: + T_i1 = T_o2 + 0.01 + if T_i1 <= T_o2: + T_o2 = T_i1 - 0.01 + if T_i1 <= T_o2: + T_o1 = T_i2 + 0.02 + if T_o1 <= T_i2: + T_i2 = T_o1 - 0.02 + + ttd_u = T_i1 - T_o2 + ttd_l = T_o1 - T_i2 + + if ttd_u == ttd_l: + td_log = ttd_l + else: + td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) + + return td_log + + def kA_func(self): + r""" + Calculate heat transfer from heat transfer coefficient. + """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.kA.val * self.calculate_td_log() + + def kA_deriv(self, increment_filter, k): + r""" + Partial derivatives of heat transfer coefficient function. + """ + f = self.kA_func + for c in self.inl: + if self.is_variable(c.m): + self.jacobian[k, c.m.J_col] = -c.h.val_SI + for c in self.outl: + if self.is_variable(c.m): + self.jacobian[k, c.m.J_col] = c.h.val_SI + for c in self.inl + self.outl: + if self.is_variable(c.p): + self.jacobian[k, c.p.J_col] = self.numeric_deriv(f, 'p', c) + if self.is_variable(c.h): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c) def calc_parameters(self): super().calc_parameters() - self.Q.val = sum([o.m.val_SI * o.h.val_SI for o in self.outl]) \ - - sum([i.m.val_SI * i.h.val_SI for i in self.inl]) - - i = self.inl[0] - if not i.T.is_set: - Tmin = min([o.T.val_SI for o in self.outl]) - Tmax = max([o.T.val_SI for o in self.outl]) - if abs(i.T.val_SI - Tmin) >= abs(i.T.val_SI - Tmax): - self.deltaT.val = i.T.val_SI - Tmin - else: - self.deltaT.val = i.T.val_SI - Tmax - + if not self.Q.is_set: + self.Q.val = sum([o.m.val_SI * o.h.val_SI for o in self.outl]) \ + - sum([i.m.val_SI * i.h.val_SI for i in self.inl]) + if not self.KPI.is_set: + self.KPI.val = (sum([o.m.val_SI * o.h.val_SI for o in self.outl]) + - sum([i.m.val_SI * i.h.val_SI for i in self.inl])) / self.inl[0].m.val_SI + if self.outl[1].fluid.val['Air'] > 0: raise Exception("Air cannot go into out2") + T_in = self.inl[1].T.val_SI + T_out = self.outl[0].T.val_SI + T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) + if not self.Eff_T.is_set: - T_in = get_T(self.inl[1]) - T_out = get_T(self.outl[0]) - T_wb = get_Twb(self.inl[1],T_in) self.Eff_T.val = (T_in-T_out)/(T_in-T_wb) + self.ttd_u.val = T_in - T_wb + self.ttd_l.val = T_out - T_wb + + if not self.kA.is_set: + # kA and logarithmic temperature difference + if self.ttd_u.val < 0 or self.ttd_l.val < 0: + self.td_log.val = np.nan + elif self.ttd_l.val == self.ttd_u.val: + self.td_log.val = self.ttd_l.val + else: + self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / + np.log(self.ttd_l.val / self.ttd_u.val)) + self.kA.val = self.Q.val / self.td_log.val + + port_i = self.inl[1] + M_i = port_i.fluid.val["Water"]/(port_i.fluid.val["Water"]+port_i.fluid.val["Air"]) + W_i = M_i/(1-M_i) + I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) + port_o = self.outl[0] + M_o = port_o.fluid.val["Water"]/(port_o.fluid.val["Water"]+port_o.fluid.val["Air"]) + W_o = M_o/(1-M_o) + I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) + + I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) + W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) + T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) + + T_o = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o*0.5) + + print(int(I_i),int(I_o)) + + print("hey") + + + + class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): @staticmethod From d75ca80fd8a637badc7e1a2b566c5a47d44a2093 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 16:46:43 +0100 Subject: [PATCH 057/105] still not workign as wished --- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 31 ++- src/tespy/components/newcomponents.py | 217 ++++++++++-------- 2 files changed, 135 insertions(+), 113 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index 73cd54738..eb4567c2d 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -46,10 +46,11 @@ c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) #c2.set_attr(p=1.2,T=60,force_state='g') -c2.set_attr(p=1.0,T=60,force_state='g') -c3.set_attr(p=1.0,force_state='l') +c2.set_attr(p=1.0,T0=30,force_state='g') +c3.set_attr(p=1.0,T0=30,force_state='l') se.set_attr(dTwbProd=0) + nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -65,38 +66,36 @@ c3.set_attr(fluid={"INCOMP::Water": None}) -se.set_attr(Q=1.90e6) - +se.set_attr(KPI=0.85) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) -se.set_attr(Q=None) -se.set_attr(KPI=1.5e5) +se.set_attr(KPI=None) +c3.set_attr(fluid={"INCOMP::Water": 0.08}) +c4.set_attr(m=None) +#se.set_attr(Eff_T=0.85) +c2.set_attr(T=40) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) - -se.set_attr(KPI=None) -c3.set_attr(fluid={"INCOMP::Water": 0.08}) - -c2.set_attr(T=None,T0=60) -# #c3.set_attr(T=None -c3.set_attr(T0=60) -se.set_attr(Eff_T=0.85) +c2.set_attr(T0=40) +se.set_attr(Eff_T=0.75) +c2.set_attr(T=None) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) -se.set_attr(Eff_T=None) -se.set_attr(kA=10.0e4) + +se.set_attr(Eff_T=0.85) +se.set_attr(kA=6.0e4) nw.solve("design") if not nw.converged: raise Exception("not converged") diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 6d9a2b75b..09c1de4bb 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -5,6 +5,7 @@ from tespy.tools.data_containers import SimpleDataContainer as dc_simple from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.fluid_properties import T_mix_ph, h_mix_pT +from tespy.tools.helpers import TESPyComponentError from tespy.components.component import Component @@ -948,6 +949,12 @@ def inlets(self): def get_parameters(self): variables = super().get_parameters() variables["num_in"] = dc_simple() + variables["dTwbProd"] = dc_cp( + deriv=self.dTwbProd_deriv, + func=self.dTwbProd_func, + latex=self.pr_func_doc, + num_eq=1, + ) variables["Eff_T"] = dc_cp( min_val=0,max_val=1, deriv=self.Eff_T_deriv, @@ -955,20 +962,14 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=1, ) - variables["dTwbProd"] = dc_cp( - deriv=self.dTwbProd_deriv, - func=self.dTwbProd_func, - latex=self.pr_func_doc, - num_eq=1, - ) variables['kA'] = dc_cp( min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, deriv=self.kA_deriv) variables['td_log'] = dc_cp(min_val=0, is_result=True) variables['ttd_u'] = dc_cp(min_val=0, is_result=True) variables['ttd_l'] = dc_cp(min_val=0, is_result=True) - variables['Ii'] = dc_cp(min_val=0, is_result=True) - variables['Io'] = dc_cp(min_val=0, is_result=True) + variables['m_evap'] = dc_cp(min_val=0, is_result=True) + variables['Q_evap'] = dc_cp(min_val=0, is_result=True) return variables def get_mandatory_constraints(self): @@ -979,6 +980,11 @@ def get_mandatory_constraints(self): 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, 'num_eq': num_fluid_eq} + constraints['energy_balance_constraints'] = { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} return constraints def fluid_func(self): @@ -999,7 +1005,8 @@ def fluid_func(self): i = self.inl[1] o = self.outl[0] # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + #residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + residual += [o.m.val_SI*o.fluid.val['Air'] - i.m.val_SI*i.fluid.val['Air']] return residual def fluid_deriv(self, increment_filter, k): @@ -1024,35 +1031,23 @@ def fluid_deriv(self, increment_filter, k): i = self.inl[1] o = self.outl[0] + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + # if fluid in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + # if fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + self.jacobian[k, o.m.J_col] = o.fluid.val['Air'] + if 'Air' in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Air']] = o.m.val_SI if self.is_variable(i.m): self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - def Eff_T_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[0] - T_out = o.calc_T(T0=o.T.val_SI) - return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val - - def Eff_T_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for c in [self.inl[1], self.outl[0]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_func, 'h', c) + if 'Air' in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col['Air']] = -i.m.val_SI def dTwbProd_func(self): r""" @@ -1081,10 +1076,7 @@ def dTwbProd_deriv(self, increment_filter, k): if self.is_variable(c.h): #, increment_filter): self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - def Q_func_Tequality(self,port1,port2): - return port1.calc_T(T0=port1.T.val_SI) - port2.calc_T(T0=port2.T.val_SI) - - def Q_func(self): + def energy_balance_func(self): r""" Need overwrite this function to take into account air inlet """ @@ -1092,13 +1084,14 @@ def Q_func(self): i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] - # res = [] - # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val] - # res += [self.Q_func_Tequality(o1,o2)] - # return res - return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.Q.val + print(i1.m.val_SI) + print(o1.m.val_SI) + print(i2.m.val_SI) + print(o2.m.val_SI) + print(o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI) + return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - def Q_deriv(self, increment_filter, k): + def energy_balance_deriv(self, increment_filter, k): r""" Need overwrite this function to take into account air inlet """ @@ -1125,29 +1118,42 @@ def Q_deriv(self, increment_filter, k): if self.is_variable(i2.h): self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - # k = k + 1 - - # for c in [self.outl[0], self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + def Eff_T_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[0] + T_out = o.calc_T(T0=o.T.val_SI) + print ((T_in-T_out) - (T_in-T_wb)*self.Eff_T.val) + return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val + + def Eff_T_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for c in [self.inl[1], self.outl[0]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_func, 'h', c) def KPI_func(self): r""" - modify Q_func + how much water is dried """ - i1 = self.inl[0] - return self.Q_func() + self.Q.val - i1.m.val_SI*self.KPI.val + o = self.outl[0] + m_evap = o.m.val_SI*o.fluid.val['Water'] + return m_evap - self.KPI.val def KPI_deriv(self, increment_filter, k): - r""" - modify Q_deriv - """ - self.Q_deriv(increment_filter, k) - i1 = self.inl[0] - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = self.jacobian[k, i1.m.J_col] - self.KPI.val + o = self.outl[0] + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] + if 'Water' in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI def calculate_td_log(self): # 1 is with air @@ -1183,41 +1189,56 @@ def kA_func(self): r""" Calculate heat transfer from heat transfer coefficient. """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - self.kA.val * self.calculate_td_log() + i = self.inl[1] + o = self.outl[0] + m_air = i.m.val_SI*i.fluid.val['Air'] + Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + return Q_air - self.kA.val * self.calculate_td_log() def kA_deriv(self, increment_filter, k): r""" Partial derivatives of heat transfer coefficient function. """ - f = self.kA_func - for c in self.inl: - if self.is_variable(c.m): - self.jacobian[k, c.m.J_col] = -c.h.val_SI - for c in self.outl: - if self.is_variable(c.m): - self.jacobian[k, c.m.J_col] = c.h.val_SI + i = self.inl[1] + o = self.outl[0] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + if 'Air' in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) for c in self.inl + self.outl: if self.is_variable(c.p): - self.jacobian[k, c.p.J_col] = self.numeric_deriv(f, 'p', c) + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) if self.is_variable(c.h): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c) + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) def calc_parameters(self): super().calc_parameters() + + i = self.inl[0] + o = self.outl[0] + self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] + self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) + -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) + i = self.inl[1] + o = self.outl[0] + m_air = i.m.val_SI*i.fluid.val['Air'] + Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + if not self.Q.is_set: - self.Q.val = sum([o.m.val_SI * o.h.val_SI for o in self.outl]) \ - - sum([i.m.val_SI * i.h.val_SI for i in self.inl]) + self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + + self.outl[1].m.val_SI * self.outl[1].h.val_SI - + self.inl[0].m.val_SI * self.inl[0].h.val_SI - + self.inl[1].m.val_SI * self.inl[1].h.val_SI) if not self.KPI.is_set: - self.KPI.val = (sum([o.m.val_SI * o.h.val_SI for o in self.outl]) - - sum([i.m.val_SI * i.h.val_SI for i in self.inl])) / self.inl[0].m.val_SI + self.KPI.val = self.m_evap.val if self.outl[1].fluid.val['Air'] > 0: - raise Exception("Air cannot go into out2") + TESPyComponentError("Air cannot go into out2") T_in = self.inl[1].T.val_SI T_out = self.outl[0].T.val_SI @@ -1225,6 +1246,8 @@ def calc_parameters(self): if not self.Eff_T.is_set: self.Eff_T.val = (T_in-T_out)/(T_in-T_wb) + if self.Eff_T.val > 1.0: + TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") self.ttd_u.val = T_in - T_wb self.ttd_l.val = T_out - T_wb @@ -1238,26 +1261,26 @@ def calc_parameters(self): else: self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / np.log(self.ttd_l.val / self.ttd_u.val)) - self.kA.val = self.Q.val / self.td_log.val - - port_i = self.inl[1] - M_i = port_i.fluid.val["Water"]/(port_i.fluid.val["Water"]+port_i.fluid.val["Air"]) - W_i = M_i/(1-M_i) - I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) - port_o = self.outl[0] - M_o = port_o.fluid.val["Water"]/(port_o.fluid.val["Water"]+port_o.fluid.val["Air"]) - W_o = M_o/(1-M_o) - I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) + self.kA.val = -Q_air / self.td_log.val + + # port_i = self.inl[1] + # M_i = port_i.fluid.val["Water"]/(port_i.fluid.val["Water"]+port_i.fluid.val["Air"]) + # W_i = M_i/(1-M_i) + # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) + # port_o = self.outl[0] + # M_o = port_o.fluid.val["Water"]/(port_o.fluid.val["Water"]+port_o.fluid.val["Air"]) + # W_o = M_o/(1-M_o) + # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) - I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) - W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) - T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) + # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) + # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) + # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) - T_o = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o*0.5) + # T_o = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) - print(int(I_i),int(I_o)) + # print(int(I_i),int(I_o)) - print("hey") + # print("hey") From dc11134da7095f3a7ea721382226f43b63c0ce90 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 29 Nov 2023 14:37:31 +0100 Subject: [PATCH 058/105] done drier --- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 46 +- src/tespy/components/newcomponents.py | 395 +++++++++++++++--- 2 files changed, 374 insertions(+), 67 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index eb4567c2d..e45e0f786 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -45,18 +45,41 @@ c2.set_attr(fluid={"INCOMP::T66": 0}) c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) + #c2.set_attr(p=1.2,T=60,force_state='g') +c2.set_attr(p=1.0) +c3.set_attr(p=1.0) + +se.set_attr(deltaH=0) +se.set_attr(dfluid=0) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + c2.set_attr(p=1.0,T0=30,force_state='g') c3.set_attr(p=1.0,T0=30,force_state='l') -se.set_attr(dTwbProd=0) +se.set_attr(dTwbProd=0) +se.set_attr(dfluid=0) + nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) + +c2.set_attr(p=1.0,T=None,force_state='g') +c3.set_attr(p=1.0,T=None,force_state='l') +se.set_attr(dTwbProd=0) +se.set_attr(dfluid=0) +#se.set_attr(eb=0) + + nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -74,19 +97,19 @@ print(nw.results['Connection']) se.set_attr(KPI=None) -c3.set_attr(fluid={"INCOMP::Water": 0.08}) -c4.set_attr(m=None) -#se.set_attr(Eff_T=0.85) -c2.set_attr(T=40) +#c3.set_attr(fluid={"INCOMP::Water": 0.08}) +#c4.set_attr(m=None) +se.set_attr(WBeff=0.6) +#c2.set_attr(T=40) nw.solve("design") if not nw.converged: raise Exception("not converged") nw.print_results() print(nw.results['Connection']) -c2.set_attr(T0=40) -se.set_attr(Eff_T=0.75) -c2.set_attr(T=None) + +se.set_attr(WBeff=None) +se.set_attr(kA=4.6e4) nw.solve("design") if not nw.converged: raise Exception("not converged") @@ -94,10 +117,3 @@ print(nw.results['Connection']) -se.set_attr(Eff_T=0.85) -se.set_attr(kA=6.0e4) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) \ No newline at end of file diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 09c1de4bb..015c93083 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -955,10 +955,10 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=1, ) - variables["Eff_T"] = dc_cp( + variables["WBeff"] = dc_cp( min_val=0,max_val=1, - deriv=self.Eff_T_deriv, - func=self.Eff_T_func, + deriv=self.WBeff_deriv, + func=self.WBeff_func, latex=self.pr_func_doc, num_eq=1, ) @@ -969,13 +969,71 @@ def get_parameters(self): variables['ttd_u'] = dc_cp(min_val=0, is_result=True) variables['ttd_l'] = dc_cp(min_val=0, is_result=True) variables['m_evap'] = dc_cp(min_val=0, is_result=True) - variables['Q_evap'] = dc_cp(min_val=0, is_result=True) + variables['Q_evap'] = dc_cp(min_val=0, is_result=True) + variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) + variables["dWo"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dWo_deriv, + func=self.dWo_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["dWo2"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dWo2_deriv, + func=self.dWo2_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["dfluid"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dfluid_deriv, + func=self.dfluid_func, + latex=self.pr_func_doc, + num_eq=1, + ) + # variables['eb'] = dc_cp( + # min_val = 0, max_val=1, + # deriv=self.energy_balance_deriv, + # func=self.energy_balance_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=1 + ) return variables + + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. + + """ + i = self.inl[0] + residual = [] + for o in [self.outl[1]]: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual[0] + + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in [self.outl[1]]: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids)+1 + num_fluid_eq = len(self.variable_fluids) constraints['fluid_constraints'] = { 'func': self.fluid_func, 'deriv': self.fluid_deriv, 'constant_deriv': False, 'latex': self.fluid_func_doc, @@ -1001,12 +1059,18 @@ def fluid_func(self): res -= o.fluid.val[fluid] * o.m.val_SI residual += [res] - # additional balance equation for calculating water vapor mass fraction - i = self.inl[1] - o = self.outl[0] - # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - #residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] - residual += [o.m.val_SI*o.fluid.val['Air'] - i.m.val_SI*i.fluid.val['Air']] + # # additional balance equation for calculating water vapor mass fraction + # i = self.inl[1] + # o = self.outl[0] + # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] return residual def fluid_deriv(self, increment_filter, k): @@ -1029,8 +1093,8 @@ def fluid_deriv(self, increment_filter, k): k += 1 - i = self.inl[1] - o = self.outl[0] + # i = self.inl[1] + # o = self.outl[0] # if self.is_variable(o.m): # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] # if fluid in o.fluid.is_var: @@ -1040,14 +1104,75 @@ def fluid_deriv(self, increment_filter, k): # if fluid in i.fluid.is_var: # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = 1 + + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # if 'Water' in o2.fluid.is_var: + # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # if 'Water' in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = -1 + + + def dfluid_func(self): + # additional balance equation for calculating water vapor mass fraction + i = self.inl[1] + o = self.outl[0] + # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val + + def dfluid_deriv(self, increment_filter, k): + + i = self.inl[1] + o = self.outl[0] if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = o.fluid.val['Air'] - if 'Air' in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Air']] = o.m.val_SI + self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + if 'Water' in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI if self.is_variable(i.m): self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = -i.m.val_SI + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = 1 + + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # if 'Water' in o2.fluid.is_var: + # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # if 'Water' in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = -1 def dTwbProd_func(self): r""" @@ -1076,6 +1201,137 @@ def dTwbProd_deriv(self, increment_filter, k): if self.is_variable(c.h): #, increment_filter): self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) + def dWo_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i2 = self.inl[1] + o1 = self.outl[0] + T_i = i2.calc_T(T0=i2.T.val_SI) + T_o = o1.calc_T(T0=o1.T.val_SI) + + M_i = i2.fluid.val["Water"] + W_i = M_i/(1-M_i) + I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) + + T_wb = get_Twb(i2,T_i) + W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) + + M_o = o1.fluid.val["Water"] + W_o = M_o/(1-M_o) + + #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) + W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) + + #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + return W_o_calc - W_o - self.dWo.val + + + + def dWo_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + i2 = self.inl[1] + o1 = self.outl[0] + for c in [i2, o1]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) + + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) + + def dWo2_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + Ti1 = i1.calc_T(T0=i1.T.val_SI) + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) + #To2 = o2.calc_T(T0=o2.T.val_SI) + + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] + Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + return Q_evap + Q_air - self.dWo2.val + + + def dWo2_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + Ti1 = i1.calc_T(T0=i1.T.val_SI) + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) + + dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w + if 'Water' in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w + if 'Water' in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a + # if 'Air' in o1.fluid.is_var: + # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a + + if self.is_variable(i2.m): + self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a + if 'Air' in i2.fluid.is_var: + self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a + + + + + def res2(self,i2,o1): + T_i = i2.calc_T(T0=i2.T.val_SI) + T_o = o1.calc_T(T0=o1.T.val_SI) + T_wb = get_Twb(i2,T_i) + W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + + M_i = i2.fluid.val["Water"] + W_i = M_i/(1-M_i) + M_o = o1.fluid.val["Water"] + W_o = M_o/(1-M_o) + + #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + return W_o_calc - W_o + def energy_balance_func(self): r""" Need overwrite this function to take into account air inlet @@ -1084,13 +1340,13 @@ def energy_balance_func(self): i2 = self.inl[1] o1 = self.outl[0] o2 = self.outl[1] - print(i1.m.val_SI) - print(o1.m.val_SI) - print(i2.m.val_SI) - print(o2.m.val_SI) - print(o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI) - return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI + # res = [] + # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] + # res += [self.res2(i2,o1)] + # return res + return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI + def energy_balance_deriv(self, increment_filter, k): r""" Need overwrite this function to take into account air inlet @@ -1118,7 +1374,21 @@ def energy_balance_deriv(self, increment_filter, k): if self.is_variable(i2.h): self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - def Eff_T_func(self): + # k = k + 1 + + # for c in [i2, o1]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) + + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) + + def WBeff_func(self): r""" Calculate the vector of residual values for fluid balance equations. """ @@ -1127,18 +1397,22 @@ def Eff_T_func(self): T_wb = get_Twb(i,T_in) o = self.outl[0] T_out = o.calc_T(T0=o.T.val_SI) - print ((T_in-T_out) - (T_in-T_wb)*self.Eff_T.val) - return (T_in-T_out) - (T_in-T_wb)*self.Eff_T.val + #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) + return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val - def Eff_T_deriv(self, increment_filter, k): + def WBeff_deriv(self, increment_filter, k): r""" Calculate partial derivatives of fluid balance. """ for c in [self.inl[1], self.outl[0]]: if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Eff_T_func, 'p', c) + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Eff_T_func, 'h', c) + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) + + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) def KPI_func(self): r""" @@ -1155,16 +1429,16 @@ def KPI_deriv(self, increment_filter, k): if 'Water' in o.fluid.is_var: self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI - def calculate_td_log(self): + def calculate_td_log(self,T_i,T_wb,T_o): # 1 is with air i1 = self.inl[1] o1 = self.outl[0] # temperature value manipulation for convergence stability - T_i1 = i1.calc_T(T0=i1.T.val_SI) - T_i2 = get_Twb(i1,T_i1) - T_o1 = o1.calc_T(T0=o1.T.val_SI) - T_o2 = T_i2 + T_i1 = T_i + T_o1 = T_o + T_i2 = T_wb + T_o2 = T_wb if T_i1 <= T_o2: T_i1 = T_o2 + 0.01 @@ -1191,10 +1465,14 @@ def kA_func(self): """ i = self.inl[1] o = self.outl[0] + T_i = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_i) + T_o = o.calc_T(T0=o.T.val_SI) + m_air = i.m.val_SI*i.fluid.val['Air'] - Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) - return Q_air - self.kA.val * self.calculate_td_log() + Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) def kA_deriv(self, increment_filter, k): r""" @@ -1202,18 +1480,25 @@ def kA_deriv(self, increment_filter, k): """ i = self.inl[1] o = self.outl[0] + T_i = i.calc_T(T0=i.T.val_SI) + #T_wb = get_Twb(i,T_i) + T_o = o.calc_T(T0=o.T.val_SI) if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) for c in self.inl + self.outl: if self.is_variable(c.p): self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) if self.is_variable(c.h): self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) + def calc_parameters(self): super().calc_parameters() @@ -1221,7 +1506,7 @@ def calc_parameters(self): o = self.outl[0] self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) - -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) + -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) i = self.inl[1] o = self.outl[0] @@ -1244,11 +1529,12 @@ def calc_parameters(self): T_out = self.outl[0].T.val_SI T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) - if not self.Eff_T.is_set: - self.Eff_T.val = (T_in-T_out)/(T_in-T_wb) - if self.Eff_T.val > 1.0: + if not self.WBeff.is_set: + self.WBeff.val = (T_in-T_out)/(T_in-T_wb) + if self.WBeff.val > 1.0: TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") + self.ttd_u.val = T_in - T_wb self.ttd_l.val = T_out - T_wb @@ -1263,26 +1549,31 @@ def calc_parameters(self): np.log(self.ttd_l.val / self.ttd_u.val)) self.kA.val = -Q_air / self.td_log.val - # port_i = self.inl[1] - # M_i = port_i.fluid.val["Water"]/(port_i.fluid.val["Water"]+port_i.fluid.val["Air"]) + port_i = self.inl[1] + # M_i = port_i.fluid.val["Water"] # W_i = M_i/(1-M_i) # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) - # port_o = self.outl[0] - # M_o = port_o.fluid.val["Water"]/(port_o.fluid.val["Water"]+port_o.fluid.val["Air"]) - # W_o = M_o/(1-M_o) + port_o = self.outl[0] + M_o = port_o.fluid.val["Water"] + W_o = M_o/(1-M_o) # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) - # T_o = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) + # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) # print(int(I_i),int(I_o)) + # print(int(T_o),int(T_o_2)) # print("hey") - + Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) + if self.WBeff.val > 1.0 or W_o > Wmax: + self.RH.val = 100 + else: + self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): From ee83b5338597d75d76131c6a7ada7da603aa5d6b Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 29 Nov 2023 16:27:32 +0100 Subject: [PATCH 059/105] started working on the evaporator --- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 4 +- ...SplitWithDeltaTDeltaP-evaporatorWithHot.py | 76 + src/tespy/components/AirDrier.py | 1669 +++++++++++++++++ src/tespy/components/newcomponents.py | 657 ------- src/tespy/networks/network_reader.py | 3 + 5 files changed, 1751 insertions(+), 658 deletions(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py create mode 100644 src/tespy/components/AirDrier.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index e45e0f786..5508dc569 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -11,7 +11,9 @@ from tespy.components.newcomponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT,DrierWithAir + SeparatorWithSpeciesSplitsDeltaT + +from tespy.components.AirDrier import DrierWithAir logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py new file mode 100644 index 000000000..9cb92f315 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py @@ -0,0 +1,76 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newcomponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP + +from tespy.components.AirDrier import TwoStreamEvaporator + + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +fluids = ["HEOS::Water", "INCOMP::FoodFat", "INCOMP::FoodProtein"] +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so1 = Source("Source 1") +so2 = Source("Source 2") +se = TwoStreamEvaporator("Separator",num_in=2,num_out=3) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") +si3 = Sink("Sink 3") + +c1 = Connection(so1, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") + +c4 = Connection(so2, "out1", se, "in2", label="4") +c5 = Connection(se, "out3", si3, "in1", label="5") + +nw.add_conns(c1, c2, c3, c4, c5) + +# set global guess values +m0 = 74.6 # transform unit at some point [this is kt/yr] +h0 = 323.3 # global guess value in kJ/kg +p0 = 1 # global guess value in bar + +# for c in nw.conns['object']: +# n_fl = 3 # len(nw.fluids) +# c.set_attr(m0=70,h0=h0,p0=p0,fluid0={'HEOS::Water': 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) + +# set some generic data for starting values +c1.set_attr(m=m0, p=p0, T=80, fluid={'HEOS::Water': 0.942, "INCOMP::FoodFat": 0.004, "INCOMP::FoodProtein": 0.054}, mixing_rule="incompressible") +c2.set_attr(p=p0, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) +c3.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) + +# Now it is possible to set the temperatures out of the separator differently +c4.set_attr(m=25, p=p0, x=1, fluid={'HEOS::Water': 1.0,"INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}, mixing_rule="incompressible") +c5.set_attr(p=p0) + +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() +# print(nw.results['Connection']) + + +c3.set_attr(fluid={"INCOMP::FoodProtein": None}) +c5.set_attr(p=p0,x=0) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + diff --git a/src/tespy/components/AirDrier.py b/src/tespy/components/AirDrier.py new file mode 100644 index 000000000..699658342 --- /dev/null +++ b/src/tespy/components/AirDrier.py @@ -0,0 +1,1669 @@ +import logging + +from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter, HeatExchanger +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import SimpleDataContainer as dc_simple +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp +from tespy.tools.fluid_properties import T_mix_ph, h_mix_pT +from tespy.tools.helpers import TESPyComponentError + +from tespy.components.component import Component + +from tespy.tools.fluid_properties import dT_mix_dph +from tespy.tools.fluid_properties import dT_mix_pdh + +from CoolProp.HumidAirProp import HAPropsSI + +import warnings + +import numpy as np + +from .newcomponents import SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP + + +def get_Twb(port,T): + M = port.fluid.val["Water"]/(port.fluid.val["Water"]+port.fluid.val["Air"]) + W = M/(1-M) + return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) + + +class DrierWithAir(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): + + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + self.num_out = 2 # default + self.num_in = 2 # default + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + if key == 'num_in': + self.num_in=kwargs[key] + super().__init__(label, **kwargs) + + @staticmethod + def component(): + return 'separator with species flow splits and dT on outlets' + + @staticmethod + def inlets(): + return ['in1'] + + def inlets(self): + if self.num_in.is_set: + return ['in' + str(i + 1) for i in range(self.num_in.val)] + else: + self.set_attr(num_in=2) + return self.inlets() + + def get_parameters(self): + variables = super().get_parameters() + variables["num_in"] = dc_simple() + variables["dTwbProd"] = dc_cp( + deriv=self.dTwbProd_deriv, + func=self.dTwbProd_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["WBeff"] = dc_cp( + min_val=0,max_val=1, + deriv=self.WBeff_deriv, + func=self.WBeff_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables['kA'] = dc_cp( + min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, + deriv=self.kA_deriv) + variables['td_log'] = dc_cp(min_val=0, is_result=True) + variables['ttd_u'] = dc_cp(min_val=0, is_result=True) + variables['ttd_l'] = dc_cp(min_val=0, is_result=True) + variables['m_evap'] = dc_cp(min_val=0, is_result=True) + variables['Q_evap'] = dc_cp(min_val=0, is_result=True) + variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) + variables["dWo"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dWo_deriv, + func=self.dWo_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["dWo2"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dWo2_deriv, + func=self.dWo2_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["dfluid"] = dc_cp( + min_val = 0, max_val=1, + deriv=self.dfluid_deriv, + func=self.dfluid_func, + latex=self.pr_func_doc, + num_eq=1, + ) + # variables['eb'] = dc_cp( + # min_val = 0, max_val=1, + # deriv=self.energy_balance_deriv, + # func=self.energy_balance_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=1 + ) + return variables + + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. + + """ + i = self.inl[0] + residual = [] + for o in [self.outl[1]]: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual[0] + + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in [self.outl[1]]: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + constraints['energy_balance_constraints'] = { + 'func': self.energy_balance_func, + 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} + return constraints + + def fluid_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + #i = self.inl[0] + residual = [] + for fluid in self.variable_fluids: + res = 0 + for i in self.inl: + res += i.fluid.val[fluid] * i.m.val_SI + for o in self.outl: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + + # # additional balance equation for calculating water vapor mass fraction + # i = self.inl[1] + # o = self.outl[0] + # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] + return residual + + def fluid_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + #i = self.inl[0] + for fluid in self.variable_fluids: + for o in self.outl: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + + for i in self.inl: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + + k += 1 + + # i = self.inl[1] + # o = self.outl[0] + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + # if fluid in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + # if fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = 1 + + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # if 'Water' in o2.fluid.is_var: + # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # if 'Water' in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = -1 + + + def dfluid_func(self): + # additional balance equation for calculating water vapor mass fraction + i = self.inl[1] + o = self.outl[0] + # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val + + def dfluid_deriv(self, increment_filter, k): + + i = self.inl[1] + o = self.outl[0] + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + if 'Water' in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + if 'Air' in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = 1 + + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # if 'Water' in o2.fluid.is_var: + # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # if 'Water' in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = -1 + + def dTwbProd_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[1] + T_out = o.calc_T(T0=o.T.val_SI) + return T_out - T_wb - self.dTwbProd.val + + def dTwbProd_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for c in [self.inl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # T_wb is nonlinear and we cannot differentiate easily + for c in [self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) + + def dWo_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i2 = self.inl[1] + o1 = self.outl[0] + T_i = i2.calc_T(T0=i2.T.val_SI) + T_o = o1.calc_T(T0=o1.T.val_SI) + + M_i = i2.fluid.val["Water"] + W_i = M_i/(1-M_i) + I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) + + T_wb = get_Twb(i2,T_i) + W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) + + M_o = o1.fluid.val["Water"] + W_o = M_o/(1-M_o) + + #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) + W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) + + #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + return W_o_calc - W_o - self.dWo.val + + + + def dWo_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + i2 = self.inl[1] + o1 = self.outl[0] + for c in [i2, o1]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) + + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) + + def dWo2_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + Ti1 = i1.calc_T(T0=i1.T.val_SI) + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) + #To2 = o2.calc_T(T0=o2.T.val_SI) + + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] + Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + return Q_evap + Q_air - self.dWo2.val + + + def dWo2_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + Ti1 = i1.calc_T(T0=i1.T.val_SI) + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) + + dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w + if 'Water' in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w + if 'Water' in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a + # if 'Air' in o1.fluid.is_var: + # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a + + if self.is_variable(i2.m): + self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a + if 'Air' in i2.fluid.is_var: + self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a + + + + + def res2(self,i2,o1): + T_i = i2.calc_T(T0=i2.T.val_SI) + T_o = o1.calc_T(T0=o1.T.val_SI) + T_wb = get_Twb(i2,T_i) + W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + + M_i = i2.fluid.val["Water"] + W_i = M_i/(1-M_i) + M_o = o1.fluid.val["Water"] + W_o = M_o/(1-M_o) + + #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + return W_o_calc - W_o + + def energy_balance_func(self): + r""" + Need overwrite this function to take into account air inlet + """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + # res = [] + # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] + # res += [self.res2(i2,o1)] + # return res + return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI + + def energy_balance_deriv(self, increment_filter, k): + r""" + Need overwrite this function to take into account air inlet + """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] + o2 = self.outl[1] + + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = -i1.h.val_SI + if self.is_variable(i2.m): + self.jacobian[k, i2.m.J_col] = -i2.h.val_SI + if self.is_variable(i1.h): + self.jacobian[k, i1.h.J_col] = -i1.m.val_SI + if self.is_variable(i2.h): + self.jacobian[k, i2.h.J_col] = -i2.m.val_SI + + # k = k + 1 + + # for c in [i2, o1]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) + + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) + + def WBeff_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[0] + T_out = o.calc_T(T0=o.T.val_SI) + #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) + return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val + + def WBeff_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for c in [self.inl[1], self.outl[0]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) + + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) + + def KPI_func(self): + r""" + how much water is dried + """ + o = self.outl[0] + m_evap = o.m.val_SI*o.fluid.val['Water'] + return m_evap - self.KPI.val + + def KPI_deriv(self, increment_filter, k): + o = self.outl[0] + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] + if 'Water' in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI + + def calculate_td_log(self,T_i,T_wb,T_o): + # 1 is with air + i1 = self.inl[1] + o1 = self.outl[0] + + # temperature value manipulation for convergence stability + T_i1 = T_i + T_o1 = T_o + T_i2 = T_wb + T_o2 = T_wb + + if T_i1 <= T_o2: + T_i1 = T_o2 + 0.01 + if T_i1 <= T_o2: + T_o2 = T_i1 - 0.01 + if T_i1 <= T_o2: + T_o1 = T_i2 + 0.02 + if T_o1 <= T_i2: + T_i2 = T_o1 - 0.02 + + ttd_u = T_i1 - T_o2 + ttd_l = T_o1 - T_i2 + + if ttd_u == ttd_l: + td_log = ttd_l + else: + td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) + + return td_log + + def kA_func(self): + r""" + Calculate heat transfer from heat transfer coefficient. + """ + i = self.inl[1] + o = self.outl[0] + T_i = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_i) + T_o = o.calc_T(T0=o.T.val_SI) + + m_air = i.m.val_SI*i.fluid.val['Air'] + Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) + + def kA_deriv(self, increment_filter, k): + r""" + Partial derivatives of heat transfer coefficient function. + """ + i = self.inl[1] + o = self.outl[0] + T_i = i.calc_T(T0=i.T.val_SI) + #T_wb = get_Twb(i,T_i) + T_o = o.calc_T(T0=o.T.val_SI) + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + if 'Air' in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + for c in self.inl + self.outl: + if self.is_variable(c.p): + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) + if self.is_variable(c.h): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) + + def calc_parameters(self): + super().calc_parameters() + + i = self.inl[0] + o = self.outl[0] + self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] + self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) + -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) + + i = self.inl[1] + o = self.outl[0] + m_air = i.m.val_SI*i.fluid.val['Air'] + Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + + if not self.Q.is_set: + self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + + self.outl[1].m.val_SI * self.outl[1].h.val_SI - + self.inl[0].m.val_SI * self.inl[0].h.val_SI - + self.inl[1].m.val_SI * self.inl[1].h.val_SI) + if not self.KPI.is_set: + self.KPI.val = self.m_evap.val + + if self.outl[1].fluid.val['Air'] > 0: + TESPyComponentError("Air cannot go into out2") + + T_in = self.inl[1].T.val_SI + T_out = self.outl[0].T.val_SI + T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) + + if not self.WBeff.is_set: + self.WBeff.val = (T_in-T_out)/(T_in-T_wb) + if self.WBeff.val > 1.0: + TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") + + + self.ttd_u.val = T_in - T_wb + self.ttd_l.val = T_out - T_wb + + if not self.kA.is_set: + # kA and logarithmic temperature difference + if self.ttd_u.val < 0 or self.ttd_l.val < 0: + self.td_log.val = np.nan + elif self.ttd_l.val == self.ttd_u.val: + self.td_log.val = self.ttd_l.val + else: + self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / + np.log(self.ttd_l.val / self.ttd_u.val)) + self.kA.val = -Q_air / self.td_log.val + + port_i = self.inl[1] + # M_i = port_i.fluid.val["Water"] + # W_i = M_i/(1-M_i) + # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) + port_o = self.outl[0] + M_o = port_o.fluid.val["Water"] + W_o = M_o/(1-M_o) + # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) + + # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) + # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) + # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) + + # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) + + # print(int(I_i),int(I_o)) + # print(int(T_o),int(T_o_2)) + + # print("hey") + + Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) + if self.WBeff.val > 1.0 or W_o > Wmax: + self.RH.val = 100 + else: + self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) + + + + + + + + + + + + + + +class TwoStreamEvaporator(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): + + + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + self.num_out = 3 # default + self.num_in = 2 # default + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + if key == 'num_in': + self.num_in=kwargs[key] + super().__init__(label, **kwargs) + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=3) + return self.outlets() + + def inlets(self): + if self.num_in.is_set: + return ['in' + str(i + 1) for i in range(self.num_in.val)] + else: + self.set_attr(num_in=2) + return self.inlets() + + @staticmethod + def component(): + return 'separator with species flow splits and dH on outlets' + + def get_parameters(self): + variables = super().get_parameters() + variables["num_in"] = dc_simple() + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=self.num_out + ) + variables["Q"] = dc_cp( + func=self.Q_func, num_eq=1, + deriv=self.Q_deriv, + latex=self.pr_func_doc) + variables["KPI"] = dc_cp( + deriv=self.KPI_deriv, + func=self.KPI_func, + latex=self.pr_func_doc, + num_eq=1) + #variables["Qout"] = dc_cpa() + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) * 2 + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + constraints['energy_balance_constraints'] = { + 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} + constraints['mass_flow_constraints'] = { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 2} + return constraints + + def fluid_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + hi = [self.inl[1]] + ho = [self.outl[2]] + + residual = [] + for fluid in self.variable_fluids: + res = 0 + for i in ci: + res += i.fluid.val[fluid] * i.m.val_SI + for o in co: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + + for fluid in self.variable_fluids: + res = 0 + for i in hi: + res += i.fluid.val[fluid] * i.m.val_SI + for o in ho: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + + return residual + + def fluid_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + hi = [self.inl[1]] + ho = [self.outl[2]] + + for fluid in self.variable_fluids: + for o in co: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + for i in ci: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + k += 1 + + for fluid in self.variable_fluids: + for o in ho: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + for i in hi: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + k += 1 + + + def mass_flow_func(self): + r""" + Calculate the residual value for mass flow balance equation. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + hi = [self.inl[1]] + ho = [self.outl[2]] + + residuals = [] + res = 0 + for i in ci: + res += i.m.val_SI + for o in co: + res -= o.m.val_SI + residuals += [res] + res = 0 + for i in hi: + res += i.m.val_SI + for o in ho: + res -= o.m.val_SI + residuals += [res] + return residuals + + def mass_flow_deriv(self, k): + r""" + Calculate partial derivatives for mass flow equation. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + hi = [self.inl[1]] + ho = [self.outl[2]] + + for i in ci: + if i.m.is_var: + self.jacobian[k, i.m.J_col] = 1 + for o in co: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + + k = k + 1 + + for i in hi: + if i.m.is_var: + self.jacobian[k, i.m.J_col] = 1 + for o in ho: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. + + """ + i = self.inl[0] + residual = [] + for o in self.outl: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual + + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in self.outl: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 + + def energy_balance_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + + hi = self.inl[1] + ho = self.outl[2] + return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) + hi.m.val_SI * (ho.h.val_SI - hi.h.val_SI) + + def energy_balance_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + hi = self.inl[1] + ho = self.outl[2] + + if self.is_variable(hi.m): + self.jacobian[k, hi.m.J_col] = (ho.h.val_SI - hi.h.val_SI) + if self.is_variable(hi.h): + self.jacobian[k, hi.h.J_col] = -hi.m.val_SI + if self.is_variable(ho.h): + self.jacobian[k, ho.h.J_col] = ho.m.val_SI + + # k = k + 1 + # for c in [self.outl[0], self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + + def KPI_func(self): + r""" + Equation for total heat flow rate + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + # res = [] + # res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] + # res += [self.Q_func_Tequality(o1,o2)] + # return res + return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI + + def KPI_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = - self.KPI.val + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + # k = k + 1 + # for c in [self.outl[0], self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + + def calc_parameters(self): + super().calc_parameters() + i = self.inl[0] + + if not self.Q.is_set: + self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + if not self.KPI.is_set: + self.KPI.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) / i.m.val_SI + + hmin = min([o.h.val_SI for o in self.outl]) + hmax = max([o.h.val_SI for o in self.outl]) + if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): + self.deltaH.val = i.h.val_SI - hmin + else: + self.deltaH.val = i.h.val_SI - hmax + + + # def __init__(self, label, **kwargs): + # #self.set_attr(**kwargs) + # # need to assign the number of outlets before the variables are set + # self.num_out = 2 # default + # self.num_in = 2 # default + # for key in kwargs: + # if key == 'num_out': + # self.num_out=kwargs[key] + # if key == 'num_in': + # self.num_in=kwargs[key] + # super().__init__(label, **kwargs) + + # @staticmethod + # def component(): + # return 'separator with species flow splits and dT on outlets' + + # @staticmethod + # def inlets(): + # return ['in1'] + + # def inlets(self): + # if self.num_in.is_set: + # return ['in' + str(i + 1) for i in range(self.num_in.val)] + # else: + # self.set_attr(num_in=2) + # return self.inlets() + + # def get_parameters(self): + # variables = super().get_parameters() + # variables["num_in"] = dc_simple() + # variables["dTwbProd"] = dc_cp( + # deriv=self.dTwbProd_deriv, + # func=self.dTwbProd_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + # variables["WBeff"] = dc_cp( + # min_val=0,max_val=1, + # deriv=self.WBeff_deriv, + # func=self.WBeff_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + # variables['kA'] = dc_cp( + # min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, + # deriv=self.kA_deriv) + # variables['td_log'] = dc_cp(min_val=0, is_result=True) + # variables['ttd_u'] = dc_cp(min_val=0, is_result=True) + # variables['ttd_l'] = dc_cp(min_val=0, is_result=True) + # variables['m_evap'] = dc_cp(min_val=0, is_result=True) + # variables['Q_evap'] = dc_cp(min_val=0, is_result=True) + # variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) + # variables["dWo"] = dc_cp( + # min_val = 0, max_val=1, + # deriv=self.dWo_deriv, + # func=self.dWo_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + # variables["dWo2"] = dc_cp( + # min_val = 0, max_val=1, + # deriv=self.dWo2_deriv, + # func=self.dWo2_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + # variables["dfluid"] = dc_cp( + # min_val = 0, max_val=1, + # deriv=self.dfluid_deriv, + # func=self.dfluid_func, + # latex=self.pr_func_doc, + # num_eq=1, + # ) + # # variables['eb'] = dc_cp( + # # min_val = 0, max_val=1, + # # deriv=self.energy_balance_deriv, + # # func=self.energy_balance_func, + # # latex=self.pr_func_doc, + # # num_eq=1, + # # ) + # variables["deltaH"] = dc_cp( + # deriv=self.energy_balance_deltaH_deriv, # same as before + # func=self.energy_balance_deltaH_func, + # latex=self.pr_func_doc, + # num_eq=1 + # ) + # return variables + + # def energy_balance_deltaH_func(self): + # r""" + # Calculate deltaH residuals. + + # """ + # i = self.inl[0] + # residual = [] + # for o in [self.outl[1]]: + # residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + # return residual[0] + + # def energy_balance_deltaH_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of energy balance. + # """ + # i = self.inl[0] + # for o in [self.outl[1]]: + # if self.is_variable(i.h): + # self.jacobian[k, i.h.J_col] = 1 + # if self.is_variable(o.h): + # self.jacobian[k, o.h.J_col] = -1 + # k += 1 + + # def get_mandatory_constraints(self): + # constraints = super().get_mandatory_constraints() + # self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + # num_fluid_eq = len(self.variable_fluids) + # constraints['fluid_constraints'] = { + # 'func': self.fluid_func, 'deriv': self.fluid_deriv, + # 'constant_deriv': False, 'latex': self.fluid_func_doc, + # 'num_eq': num_fluid_eq} + # constraints['energy_balance_constraints'] = { + # 'func': self.energy_balance_func, + # 'deriv': self.energy_balance_deriv, + # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + # 'num_eq': 1} + # return constraints + + # def fluid_func(self): + # r""" + # Calculate the vector of residual values for fluid balance equations. + # """ + # #i = self.inl[0] + # residual = [] + # for fluid in self.variable_fluids: + # res = 0 + # for i in self.inl: + # res += i.fluid.val[fluid] * i.m.val_SI + # for o in self.outl: + # res -= o.fluid.val[fluid] * o.m.val_SI + # residual += [res] + + # # # additional balance equation for calculating water vapor mass fraction + # # i = self.inl[1] + # # o = self.outl[0] + # # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + # # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] + + # # i1 = self.inl[0] + # # i2 = self.inl[1] + # # o1 = self.outl[0] + # # o2 = self.outl[1] + # # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] + # return residual + + # def fluid_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of fluid balance. + # """ + # #i = self.inl[0] + # for fluid in self.variable_fluids: + # for o in self.outl: + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + # if fluid in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + + # for i in self.inl: + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + # if fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + + # k += 1 + + # # i = self.inl[1] + # # o = self.outl[0] + # # if self.is_variable(o.m): + # # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + # # if fluid in o.fluid.is_var: + # # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + # # if self.is_variable(i.m): + # # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + # # if fluid in i.fluid.is_var: + # # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + # # i1 = self.inl[0] + # # i2 = self.inl[1] + # # o1 = self.outl[0] + # # o2 = self.outl[1] + + # # if self.is_variable(i2.m): + # # self.jacobian[k, i2.m.J_col] = 1 + + # # if self.is_variable(o2.m): + # # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # # if 'Water' in o2.fluid.is_var: + # # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # # if self.is_variable(i1.m): + # # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # # if 'Water' in i1.fluid.is_var: + # # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # # if self.is_variable(o1.m): + # # self.jacobian[k, o1.m.J_col] = -1 + + + # def dfluid_func(self): + # # additional balance equation for calculating water vapor mass fraction + # i = self.inl[1] + # o = self.outl[0] + # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by + # return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI + + # # i1 = self.inl[0] + # # i2 = self.inl[1] + # # o1 = self.outl[0] + # # o2 = self.outl[1] + # # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val + + # def dfluid_deriv(self, increment_filter, k): + + # i = self.inl[1] + # o = self.outl[0] + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] + # if 'Water' in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] + # if 'Air' in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI + + # # i1 = self.inl[0] + # # i2 = self.inl[1] + # # o1 = self.outl[0] + # # o2 = self.outl[1] + + # # if self.is_variable(i2.m): + # # self.jacobian[k, i2.m.J_col] = 1 + + # # if self.is_variable(o2.m): + # # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] + # # if 'Water' in o2.fluid.is_var: + # # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI + + # # if self.is_variable(i1.m): + # # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] + # # if 'Water' in i1.fluid.is_var: + # # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI + + # # if self.is_variable(o1.m): + # # self.jacobian[k, o1.m.J_col] = -1 + + # def dTwbProd_func(self): + # r""" + # Calculate the vector of residual values for fluid balance equations. + # """ + # i = self.inl[1] + # T_in = i.calc_T(T0=i.T.val_SI) + # T_wb = get_Twb(i,T_in) + # o = self.outl[1] + # T_out = o.calc_T(T0=o.T.val_SI) + # return T_out - T_wb - self.dTwbProd.val + + # def dTwbProd_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of fluid balance. + # """ + # for c in [self.inl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # # T_wb is nonlinear and we cannot differentiate easily + # for c in [self.outl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) + + # def dWo_func(self): + # r""" + # Calculate the vector of residual values for fluid balance equations. + # """ + # i2 = self.inl[1] + # o1 = self.outl[0] + # T_i = i2.calc_T(T0=i2.T.val_SI) + # T_o = o1.calc_T(T0=o1.T.val_SI) + + # M_i = i2.fluid.val["Water"] + # W_i = M_i/(1-M_i) + # I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) + + # T_wb = get_Twb(i2,T_i) + # W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + # I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) + + # M_o = o1.fluid.val["Water"] + # W_o = M_o/(1-M_o) + + # #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + # I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) + # W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) + + # #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + # #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + # return W_o_calc - W_o - self.dWo.val + + + + # def dWo_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of fluid balance. + # """ + + # i2 = self.inl[1] + # o1 = self.outl[0] + # for c in [i2, o1]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) + # # if self.is_variable(c.m): #, increment_filter): + # # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) + + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) + + # def dWo2_func(self): + # r""" + # Calculate the vector of residual values for fluid balance equations. + # """ + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # Ti1 = i1.calc_T(T0=i1.T.val_SI) + # Ti2 = i2.calc_T(T0=i2.T.val_SI) + # To1 = o1.calc_T(T0=o1.T.val_SI) + # #To2 = o2.calc_T(T0=o2.T.val_SI) + + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + # Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + # m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] + # Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + # return Q_evap + Q_air - self.dWo2.val + + + # def dWo2_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of fluid balance. + # """ + + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # Ti1 = i1.calc_T(T0=i1.T.val_SI) + # Ti2 = i2.calc_T(T0=i2.T.val_SI) + # To1 = o1.calc_T(T0=o1.T.val_SI) + + # dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + # dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) + # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) + + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w + # if 'Water' in o2.fluid.is_var: + # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w + # if 'Water' in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w + + # # if self.is_variable(o1.m): + # # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a + # # if 'Air' in o1.fluid.is_var: + # # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a + # if 'Air' in i2.fluid.is_var: + # self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a + + + + + # def res2(self,i2,o1): + # T_i = i2.calc_T(T0=i2.T.val_SI) + # T_o = o1.calc_T(T0=o1.T.val_SI) + # T_wb = get_Twb(i2,T_i) + # W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + + # M_i = i2.fluid.val["Water"] + # W_i = M_i/(1-M_i) + # M_o = o1.fluid.val["Water"] + # W_o = M_o/(1-M_o) + + # #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + # W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) + # return W_o_calc - W_o + + # def energy_balance_func(self): + # r""" + # Need overwrite this function to take into account air inlet + # """ + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # # res = [] + # # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] + # # res += [self.res2(i2,o1)] + # # return res + # return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI + + # def energy_balance_deriv(self, increment_filter, k): + # r""" + # Need overwrite this function to take into account air inlet + # """ + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] + # o2 = self.outl[1] + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = o1.h.val_SI + # if self.is_variable(o2.m): + # self.jacobian[k, o2.m.J_col] = o2.h.val_SI + # if self.is_variable(o1.h): + # self.jacobian[k, o1.h.J_col] = o1.m.val_SI + # if self.is_variable(o2.h): + # self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = -i1.h.val_SI + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = -i2.h.val_SI + # if self.is_variable(i1.h): + # self.jacobian[k, i1.h.J_col] = -i1.m.val_SI + # if self.is_variable(i2.h): + # self.jacobian[k, i2.h.J_col] = -i2.m.val_SI + + # # k = k + 1 + + # # for c in [i2, o1]: + # # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) + # # if self.is_variable(c.h): #, increment_filter): + # # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) + # # if self.is_variable(c.m): #, increment_filter): + # # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) + + # # for fluid in self.variable_fluids: + # # if fluid in c.fluid.is_var: + # # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) + + # def WBeff_func(self): + # r""" + # Calculate the vector of residual values for fluid balance equations. + # """ + # i = self.inl[1] + # T_in = i.calc_T(T0=i.T.val_SI) + # T_wb = get_Twb(i,T_in) + # o = self.outl[0] + # T_out = o.calc_T(T0=o.T.val_SI) + # #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) + # return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val + + # def WBeff_deriv(self, increment_filter, k): + # r""" + # Calculate partial derivatives of fluid balance. + # """ + # for c in [self.inl[1], self.outl[0]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) + + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) + + # def KPI_func(self): + # r""" + # how much water is dried + # """ + # o = self.outl[0] + # m_evap = o.m.val_SI*o.fluid.val['Water'] + # return m_evap - self.KPI.val + + # def KPI_deriv(self, increment_filter, k): + # o = self.outl[0] + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] + # if 'Water' in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI + + # def calculate_td_log(self,T_i,T_wb,T_o): + # # 1 is with air + # i1 = self.inl[1] + # o1 = self.outl[0] + + # # temperature value manipulation for convergence stability + # T_i1 = T_i + # T_o1 = T_o + # T_i2 = T_wb + # T_o2 = T_wb + + # if T_i1 <= T_o2: + # T_i1 = T_o2 + 0.01 + # if T_i1 <= T_o2: + # T_o2 = T_i1 - 0.01 + # if T_i1 <= T_o2: + # T_o1 = T_i2 + 0.02 + # if T_o1 <= T_i2: + # T_i2 = T_o1 - 0.02 + + # ttd_u = T_i1 - T_o2 + # ttd_l = T_o1 - T_i2 + + # if ttd_u == ttd_l: + # td_log = ttd_l + # else: + # td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) + + # return td_log + + # def kA_func(self): + # r""" + # Calculate heat transfer from heat transfer coefficient. + # """ + # i = self.inl[1] + # o = self.outl[0] + # T_i = i.calc_T(T0=i.T.val_SI) + # T_wb = get_Twb(i,T_i) + # T_o = o.calc_T(T0=o.T.val_SI) + + # m_air = i.m.val_SI*i.fluid.val['Air'] + # Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + # return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) + + # def kA_deriv(self, increment_filter, k): + # r""" + # Partial derivatives of heat transfer coefficient function. + # """ + # i = self.inl[1] + # o = self.outl[0] + # T_i = i.calc_T(T0=i.T.val_SI) + # #T_wb = get_Twb(i,T_i) + # T_o = o.calc_T(T0=o.T.val_SI) + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + # if 'Air' in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') + # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) + # for c in self.inl + self.outl: + # if self.is_variable(c.p): + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) + # if self.is_variable(c.h): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) + + # def calc_parameters(self): + # super().calc_parameters() + + # i = self.inl[0] + # o = self.outl[0] + # self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] + # self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) + # -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) + + # i = self.inl[1] + # o = self.outl[0] + # m_air = i.m.val_SI*i.fluid.val['Air'] + # Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') + # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) + + # if not self.Q.is_set: + # self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + + # self.outl[1].m.val_SI * self.outl[1].h.val_SI - + # self.inl[0].m.val_SI * self.inl[0].h.val_SI - + # self.inl[1].m.val_SI * self.inl[1].h.val_SI) + # if not self.KPI.is_set: + # self.KPI.val = self.m_evap.val + + # if self.outl[1].fluid.val['Air'] > 0: + # TESPyComponentError("Air cannot go into out2") + + # T_in = self.inl[1].T.val_SI + # T_out = self.outl[0].T.val_SI + # T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) + + # if not self.WBeff.is_set: + # self.WBeff.val = (T_in-T_out)/(T_in-T_wb) + # if self.WBeff.val > 1.0: + # TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") + + + # self.ttd_u.val = T_in - T_wb + # self.ttd_l.val = T_out - T_wb + + # if not self.kA.is_set: + # # kA and logarithmic temperature difference + # if self.ttd_u.val < 0 or self.ttd_l.val < 0: + # self.td_log.val = np.nan + # elif self.ttd_l.val == self.ttd_u.val: + # self.td_log.val = self.ttd_l.val + # else: + # self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / + # np.log(self.ttd_l.val / self.ttd_u.val)) + # self.kA.val = -Q_air / self.td_log.val + + # port_i = self.inl[1] + # # M_i = port_i.fluid.val["Water"] + # # W_i = M_i/(1-M_i) + # # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) + # port_o = self.outl[0] + # M_o = port_o.fluid.val["Water"] + # W_o = M_o/(1-M_o) + # # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) + + # # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) + # # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) + # # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) + + # # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) + + # # print(int(I_i),int(I_o)) + # # print(int(T_o),int(T_o_2)) + + # # print("hey") + + # Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) + # if self.WBeff.val > 1.0 or W_o > Wmax: + # self.RH.val = 100 + # else: + # self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) \ No newline at end of file diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newcomponents.py index 015c93083..a53139816 100644 --- a/src/tespy/components/newcomponents.py +++ b/src/tespy/components/newcomponents.py @@ -917,663 +917,6 @@ def get_mandatory_constraints(self): #del constraints['energy_balance_constraints'] return constraints -class DrierWithAir(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - self.num_out = 2 # default - self.num_in = 2 # default - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - if key == 'num_in': - self.num_in=kwargs[key] - super().__init__(label, **kwargs) - - @staticmethod - def component(): - return 'separator with species flow splits and dT on outlets' - - @staticmethod - def inlets(): - return ['in1'] - - def inlets(self): - if self.num_in.is_set: - return ['in' + str(i + 1) for i in range(self.num_in.val)] - else: - self.set_attr(num_in=2) - return self.inlets() - - def get_parameters(self): - variables = super().get_parameters() - variables["num_in"] = dc_simple() - variables["dTwbProd"] = dc_cp( - deriv=self.dTwbProd_deriv, - func=self.dTwbProd_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["WBeff"] = dc_cp( - min_val=0,max_val=1, - deriv=self.WBeff_deriv, - func=self.WBeff_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables['kA'] = dc_cp( - min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, - deriv=self.kA_deriv) - variables['td_log'] = dc_cp(min_val=0, is_result=True) - variables['ttd_u'] = dc_cp(min_val=0, is_result=True) - variables['ttd_l'] = dc_cp(min_val=0, is_result=True) - variables['m_evap'] = dc_cp(min_val=0, is_result=True) - variables['Q_evap'] = dc_cp(min_val=0, is_result=True) - variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) - variables["dWo"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dWo_deriv, - func=self.dWo_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["dWo2"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dWo2_deriv, - func=self.dWo2_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["dfluid"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dfluid_deriv, - func=self.dfluid_func, - latex=self.pr_func_doc, - num_eq=1, - ) - # variables['eb'] = dc_cp( - # min_val = 0, max_val=1, - # deriv=self.energy_balance_deriv, - # func=self.energy_balance_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in [self.outl[1]]: - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual[0] - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in [self.outl[1]]: - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - constraints['energy_balance_constraints'] = { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - return constraints - - def fluid_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - #i = self.inl[0] - residual = [] - for fluid in self.variable_fluids: - res = 0 - for i in self.inl: - res += i.fluid.val[fluid] * i.m.val_SI - for o in self.outl: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - - # # additional balance equation for calculating water vapor mass fraction - # i = self.inl[1] - # o = self.outl[0] - # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] - return residual - - def fluid_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - #i = self.inl[0] - for fluid in self.variable_fluids: - for o in self.outl: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - - for i in self.inl: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - - k += 1 - - # i = self.inl[1] - # o = self.outl[0] - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - # if fluid in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - # if fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = 1 - - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # if 'Water' in o2.fluid.is_var: - # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # if 'Water' in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = -1 - - - def dfluid_func(self): - # additional balance equation for calculating water vapor mass fraction - i = self.inl[1] - o = self.outl[0] - # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val - - def dfluid_deriv(self, increment_filter, k): - - i = self.inl[1] - o = self.outl[0] - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - if 'Water' in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = 1 - - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # if 'Water' in o2.fluid.is_var: - # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # if 'Water' in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = -1 - - def dTwbProd_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[1] - T_out = o.calc_T(T0=o.T.val_SI) - return T_out - T_wb - self.dTwbProd.val - - def dTwbProd_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for c in [self.inl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # T_wb is nonlinear and we cannot differentiate easily - for c in [self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - - def dWo_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i2 = self.inl[1] - o1 = self.outl[0] - T_i = i2.calc_T(T0=i2.T.val_SI) - T_o = o1.calc_T(T0=o1.T.val_SI) - - M_i = i2.fluid.val["Water"] - W_i = M_i/(1-M_i) - I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) - - T_wb = get_Twb(i2,T_i) - W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) - I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) - - M_o = o1.fluid.val["Water"] - W_o = M_o/(1-M_o) - - #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) - W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) - - #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - return W_o_calc - W_o - self.dWo.val - - - - def dWo_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - i2 = self.inl[1] - o1 = self.outl[0] - for c in [i2, o1]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) - - def dWo2_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - Ti2 = i2.calc_T(T0=i2.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - #To2 = o2.calc_T(T0=o2.T.val_SI) - - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - return Q_evap + Q_air - self.dWo2.val - - - def dWo2_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - Ti2 = i2.calc_T(T0=i2.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - - dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w - if 'Water' in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w - if 'Water' in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a - # if 'Air' in o1.fluid.is_var: - # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a - - if self.is_variable(i2.m): - self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a - if 'Air' in i2.fluid.is_var: - self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a - - - - - def res2(self,i2,o1): - T_i = i2.calc_T(T0=i2.T.val_SI) - T_o = o1.calc_T(T0=o1.T.val_SI) - T_wb = get_Twb(i2,T_i) - W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) - - M_i = i2.fluid.val["Water"] - W_i = M_i/(1-M_i) - M_o = o1.fluid.val["Water"] - W_o = M_o/(1-M_o) - - #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - return W_o_calc - W_o - - def energy_balance_func(self): - r""" - Need overwrite this function to take into account air inlet - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - # res = [] - # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] - # res += [self.res2(i2,o1)] - # return res - return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - - def energy_balance_deriv(self, increment_filter, k): - r""" - Need overwrite this function to take into account air inlet - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = -i1.h.val_SI - if self.is_variable(i2.m): - self.jacobian[k, i2.m.J_col] = -i2.h.val_SI - if self.is_variable(i1.h): - self.jacobian[k, i1.h.J_col] = -i1.m.val_SI - if self.is_variable(i2.h): - self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - - # k = k + 1 - - # for c in [i2, o1]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) - - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) - - def WBeff_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[0] - T_out = o.calc_T(T0=o.T.val_SI) - #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) - return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val - - def WBeff_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for c in [self.inl[1], self.outl[0]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) - - def KPI_func(self): - r""" - how much water is dried - """ - o = self.outl[0] - m_evap = o.m.val_SI*o.fluid.val['Water'] - return m_evap - self.KPI.val - - def KPI_deriv(self, increment_filter, k): - o = self.outl[0] - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] - if 'Water' in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI - - def calculate_td_log(self,T_i,T_wb,T_o): - # 1 is with air - i1 = self.inl[1] - o1 = self.outl[0] - - # temperature value manipulation for convergence stability - T_i1 = T_i - T_o1 = T_o - T_i2 = T_wb - T_o2 = T_wb - - if T_i1 <= T_o2: - T_i1 = T_o2 + 0.01 - if T_i1 <= T_o2: - T_o2 = T_i1 - 0.01 - if T_i1 <= T_o2: - T_o1 = T_i2 + 0.02 - if T_o1 <= T_i2: - T_i2 = T_o1 - 0.02 - - ttd_u = T_i1 - T_o2 - ttd_l = T_o1 - T_i2 - - if ttd_u == ttd_l: - td_log = ttd_l - else: - td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) - - return td_log - - def kA_func(self): - r""" - Calculate heat transfer from heat transfer coefficient. - """ - i = self.inl[1] - o = self.outl[0] - T_i = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_i) - T_o = o.calc_T(T0=o.T.val_SI) - - m_air = i.m.val_SI*i.fluid.val['Air'] - Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) - - def kA_deriv(self, increment_filter, k): - r""" - Partial derivatives of heat transfer coefficient function. - """ - i = self.inl[1] - o = self.outl[0] - T_i = i.calc_T(T0=i.T.val_SI) - #T_wb = get_Twb(i,T_i) - T_o = o.calc_T(T0=o.T.val_SI) - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - for c in self.inl + self.outl: - if self.is_variable(c.p): - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - if self.is_variable(c.h): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) - - def calc_parameters(self): - super().calc_parameters() - - i = self.inl[0] - o = self.outl[0] - self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] - self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) - -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) - - i = self.inl[1] - o = self.outl[0] - m_air = i.m.val_SI*i.fluid.val['Air'] - Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) - - if not self.Q.is_set: - self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + - self.outl[1].m.val_SI * self.outl[1].h.val_SI - - self.inl[0].m.val_SI * self.inl[0].h.val_SI - - self.inl[1].m.val_SI * self.inl[1].h.val_SI) - if not self.KPI.is_set: - self.KPI.val = self.m_evap.val - - if self.outl[1].fluid.val['Air'] > 0: - TESPyComponentError("Air cannot go into out2") - - T_in = self.inl[1].T.val_SI - T_out = self.outl[0].T.val_SI - T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) - - if not self.WBeff.is_set: - self.WBeff.val = (T_in-T_out)/(T_in-T_wb) - if self.WBeff.val > 1.0: - TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") - - - self.ttd_u.val = T_in - T_wb - self.ttd_l.val = T_out - T_wb - - if not self.kA.is_set: - # kA and logarithmic temperature difference - if self.ttd_u.val < 0 or self.ttd_l.val < 0: - self.td_log.val = np.nan - elif self.ttd_l.val == self.ttd_u.val: - self.td_log.val = self.ttd_l.val - else: - self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / - np.log(self.ttd_l.val / self.ttd_u.val)) - self.kA.val = -Q_air / self.td_log.val - - port_i = self.inl[1] - # M_i = port_i.fluid.val["Water"] - # W_i = M_i/(1-M_i) - # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) - port_o = self.outl[0] - M_o = port_o.fluid.val["Water"] - W_o = M_o/(1-M_o) - # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) - - # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) - # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) - # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) - - # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) - - # print(int(I_i),int(I_o)) - # print(int(T_o),int(T_o_2)) - - # print("hey") - - Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) - if self.WBeff.val > 1.0 or W_o > Wmax: - self.RH.val = 100 - else: - self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index c74843a1d..502740eed 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -41,7 +41,10 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer + from tespy.components.newcomponents import * +from tespy.components.AirDrier import * + from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref From 7516340f69e2f94689c3ece68819bbef16fa7cd3 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 09:25:02 +0100 Subject: [PATCH 060/105] missing setting fluid0 right --- src/tespy/connections/connection.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 218466f9d..6e9eda767 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -500,7 +500,12 @@ def _fluid_specification(self, key, value): self.fluid.back_end[fluid] = back_end elif key == "fluid0": - self.fluid.val0.update(value) + for fluid, fraction in value.items(): + if "::" in fluid: + back_end, fluid = fluid.split("::") + else: + back_end = None + self.fluid.val0.update({fluid:fraction}) elif key == "fluid_engines": self.fluid.engine = value From 0760e60d51d8296d404dc8eaa679f1baf3800c3c Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:33:46 +0100 Subject: [PATCH 061/105] print the branches for debug --- src/tespy/connections/connection.py | 3 ++- src/tespy/networks/network.py | 10 ++++++++++ src/tespy/networks/network_reader.py | 2 -- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 6e9eda767..cd70d15b8 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -902,7 +902,8 @@ def solve(self, increment_filter): data.deriv(k, **data.func_params) def calc_results(self): - self.T.val_SI = self.calc_T() + if not self.T.is_set: + self.T.val_SI = self.calc_T() number_fluids = get_number_of_fluids(self.fluid_data) _converged = True if number_fluids > 1 and not "HEOS" in [self.fluid_data[f]["wrapper"].back_end for f in self.fluid_data] and not "Water" in [self.fluid_data[f]["wrapper"].fluid for f in self.fluid_data]: diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index e0669b33b..2da771dbc 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -715,6 +715,16 @@ def create_massflow_and_fluid_branches(self): for start in start_components: self.branches.update(start.start_branch()) + self.branchesNames = {} + msg = ("Branched the following components and connections:") + logger.debug(msg) + for k,v in self.branches.items(): + self.branchesNames[k] = v['components'][0].label + for conn,comp in zip(v['connections'],v['components'][1:]): + self.branchesNames[k] += " -> " + conn.label + " -> " + comp.label + msg = (self.branchesNames[k]) + logger.debug(msg) + self.massflow_branches = hlp.get_all_subdictionaries(self.branches) self.fluid_branches = {} diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 502740eed..e5e83e939 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -41,10 +41,8 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer - from tespy.components.newcomponents import * from tespy.components.AirDrier import * - from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref From eb99e6a2a4e6908e802c7d17fd4e6c07a59b2bb7 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:38:39 +0100 Subject: [PATCH 062/105] two stream evaporator thickener --- .../newComponentsTests/2streamHX.py | 4 +- ...sFlowSplitWithDeltaTDeltaP-decanterTest.py | 10 +- ...SplitWithDeltaTDeltaP-evaporatorWithHot.py | 84 +- src/tespy/components/AirDrier.py | 1063 +++++++---------- 4 files changed, 478 insertions(+), 683 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py index dcc243bb5..6248a353d 100644 --- a/incompressiblesTests/newComponentsTests/2streamHX.py +++ b/incompressiblesTests/newComponentsTests/2streamHX.py @@ -32,13 +32,13 @@ for c in nw.conns['object']: n_fl=3 c.set_attr(m0=0.5,h0=1e2,p0=3, mixing_rule="incompressible") - c.set_attr(fluid0={"HEOS::Water": 1/n_fl, 'INCOMP::PHE': 1/n_fl, 'INCOMP::S800': 1/n_fl}) + #c.set_attr(fluid0={"HEOS::Water": 1/n_fl, 'INCOMP::PHE': 1/n_fl, 'INCOMP::S800': 1/n_fl}) #c.set_attr(fluid0={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}) c.set_attr(force_state='l') c.set_attr(good_starting_values=True) he.set_attr(pr1=1, pr2=1) -cold_in_he.set_attr(fluid={'HEOS::Water': 1,'INCOMP::PHE': 0,'INCOMP::S800': 0}, T=1, m=1, p=3,mixing_rule="incompressible") +cold_in_he.set_attr(fluid={'HEOS::Water': 1}, T=1, m=1, p=3,mixing_rule="incompressible") hot_in_he.set_attr(fluid={'HEOS::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, T=35, m=0.5, p=3) hot_he_out.set_attr(T=30) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py index d1190a737..6077ca3c9 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py @@ -37,16 +37,16 @@ h0 = 119 # global guess value in kJ/kg p0 = 1 # global guess value in bar -#water = 'INCOMP::FoodWater' -water = 'Water' # wrapper gets HEOS backend +water = 'INCOMP::FoodWater' +#water = 'Water' # wrapper gets HEOS backend for c in nw.conns['object']: n_fl = 3 # len(nw.fluids) - c.set_attr(m0=80,h0=h0,p0=p0,fluid0={water: 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) + c.set_attr(m0=80,h0=h0,p0=p0,fluid0={'INCOMP::FoodWater': 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) # set some generic data for starting values -c1.set_attr(m=1, p=p0, T=95, fluid={water: 0.902, "INCOMP::FoodFat": 0.023, "INCOMP::FoodProtein": 0.075}, mixing_rule="incompressible") -c2.set_attr(fluid={water: 0.648, "INCOMP::FoodFat": 0.022, "INCOMP::FoodProtein": 0.33}) +c1.set_attr(m=1, p=p0, T=95, fluid={'INCOMP::FoodWater': 0.902, "INCOMP::FoodFat": 0.023, "INCOMP::FoodProtein": 0.075}, mixing_rule="incompressible") +c2.set_attr(fluid={'INCOMP::FoodWater': 0.648, "INCOMP::FoodFat": 0.022, "INCOMP::FoodProtein": 0.33}) c3.set_attr(force_state='l') diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py index 9cb92f315..4b02b265a 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py @@ -13,7 +13,7 @@ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP -from tespy.components.AirDrier import TwoStreamEvaporator +from tespy.components.AirDrier import TwoStreamEvaporatorNEW logging.basicConfig(level=logging.DEBUG) @@ -26,7 +26,7 @@ so1 = Source("Source 1") so2 = Source("Source 2") -se = TwoStreamEvaporator("Separator",num_in=2,num_out=3) +se = TwoStreamEvaporatorNEW("Separator",num_in=2,num_out=3) si1 = Sink("Sink 1") si2 = Sink("Sink 2") si3 = Sink("Sink 3") @@ -51,21 +51,20 @@ # set some generic data for starting values c1.set_attr(m=m0, p=p0, T=80, fluid={'HEOS::Water': 0.942, "INCOMP::FoodFat": 0.004, "INCOMP::FoodProtein": 0.054}, mixing_rule="incompressible") -c2.set_attr(p=p0, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) -c3.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) +c2.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) +c3.set_attr(x=1, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) # Now it is possible to set the temperatures out of the separator differently -c4.set_attr(m=25, p=p0, x=1, fluid={'HEOS::Water': 1.0,"INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}, mixing_rule="incompressible") +c4.set_attr(m=25, p=p0, x=1, fluid={'HEOS::Water': 1.0}, mixing_rule="incompressible") c5.set_attr(p=p0) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() -# print(nw.results['Connection']) - +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) -c3.set_attr(fluid={"INCOMP::FoodProtein": None}) +c2.set_attr(fluid={"INCOMP::FoodProtein": None}) c5.set_attr(p=p0,x=0) nw.solve("design") if not nw.converged: @@ -74,3 +73,64 @@ print(nw.results['Connection']) +c5.set_attr(x=None) +se.set_attr(Q=5e7) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c5.set_attr(x=None) +se.set_attr(Q=None) +se.set_attr(kA=8e5) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +c5.set_attr(x=None) +se.set_attr(Q=None) +se.set_attr(kA=None) +se.set_attr(KPI=6e5) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +se.set_attr(KPI=None) +se.set_attr(kA=7e5) +se.set_attr(dTo=0) +c2.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) +c2.set_attr(T=None) +c3.set_attr(T=None) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + +# mass balance mode + +c2.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) +c2.set_attr(p=p0, x=None, T=None, force_state=None) +c3.set_attr(p=p0, x=None, T=None, force_state=None) + +c5.set_attr(x=None, force_state=None) +se.set_attr(Q=None) +se.set_attr(kA=None) +se.set_attr(dTo=None) +se.set_attr(KPI=None) +se.set_attr(deltaH=0) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) diff --git a/src/tespy/components/AirDrier.py b/src/tespy/components/AirDrier.py index 699658342..9170c21c5 100644 --- a/src/tespy/components/AirDrier.py +++ b/src/tespy/components/AirDrier.py @@ -700,32 +700,14 @@ def calc_parameters(self): class TwoStreamEvaporator(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - self.num_out = 3 # default - self.num_in = 2 # default - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - if key == 'num_in': - self.num_in=kwargs[key] + def __init__(self, label, **kwargs): super().__init__(label, **kwargs) def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=3) - return self.outlets() + return ['out1', 'out2', 'out3'] def inlets(self): - if self.num_in.is_set: - return ['in' + str(i + 1) for i in range(self.num_in.val)] - else: - self.set_attr(num_in=2) - return self.inlets() + return ['in1', 'in2'] @staticmethod def component(): @@ -1012,658 +994,411 @@ def calc_parameters(self): self.deltaH.val = i.h.val_SI - hmax - # def __init__(self, label, **kwargs): - # #self.set_attr(**kwargs) - # # need to assign the number of outlets before the variables are set - # self.num_out = 2 # default - # self.num_in = 2 # default - # for key in kwargs: - # if key == 'num_out': - # self.num_out=kwargs[key] - # if key == 'num_in': - # self.num_in=kwargs[key] - # super().__init__(label, **kwargs) - - # @staticmethod - # def component(): - # return 'separator with species flow splits and dT on outlets' - - # @staticmethod - # def inlets(): - # return ['in1'] - - # def inlets(self): - # if self.num_in.is_set: - # return ['in' + str(i + 1) for i in range(self.num_in.val)] - # else: - # self.set_attr(num_in=2) - # return self.inlets() - - # def get_parameters(self): - # variables = super().get_parameters() - # variables["num_in"] = dc_simple() - # variables["dTwbProd"] = dc_cp( - # deriv=self.dTwbProd_deriv, - # func=self.dTwbProd_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - # variables["WBeff"] = dc_cp( - # min_val=0,max_val=1, - # deriv=self.WBeff_deriv, - # func=self.WBeff_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - # variables['kA'] = dc_cp( - # min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, - # deriv=self.kA_deriv) - # variables['td_log'] = dc_cp(min_val=0, is_result=True) - # variables['ttd_u'] = dc_cp(min_val=0, is_result=True) - # variables['ttd_l'] = dc_cp(min_val=0, is_result=True) - # variables['m_evap'] = dc_cp(min_val=0, is_result=True) - # variables['Q_evap'] = dc_cp(min_val=0, is_result=True) - # variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) - # variables["dWo"] = dc_cp( - # min_val = 0, max_val=1, - # deriv=self.dWo_deriv, - # func=self.dWo_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - # variables["dWo2"] = dc_cp( - # min_val = 0, max_val=1, - # deriv=self.dWo2_deriv, - # func=self.dWo2_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - # variables["dfluid"] = dc_cp( - # min_val = 0, max_val=1, - # deriv=self.dfluid_deriv, - # func=self.dfluid_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - # # variables['eb'] = dc_cp( - # # min_val = 0, max_val=1, - # # deriv=self.energy_balance_deriv, - # # func=self.energy_balance_func, - # # latex=self.pr_func_doc, - # # num_eq=1, - # # ) - # variables["deltaH"] = dc_cp( - # deriv=self.energy_balance_deltaH_deriv, # same as before - # func=self.energy_balance_deltaH_func, - # latex=self.pr_func_doc, - # num_eq=1 - # ) - # return variables - - # def energy_balance_deltaH_func(self): - # r""" - # Calculate deltaH residuals. - - # """ - # i = self.inl[0] - # residual = [] - # for o in [self.outl[1]]: - # residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - # return residual[0] - - # def energy_balance_deltaH_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of energy balance. - # """ - # i = self.inl[0] - # for o in [self.outl[1]]: - # if self.is_variable(i.h): - # self.jacobian[k, i.h.J_col] = 1 - # if self.is_variable(o.h): - # self.jacobian[k, o.h.J_col] = -1 - # k += 1 - - # def get_mandatory_constraints(self): - # constraints = super().get_mandatory_constraints() - # self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - # num_fluid_eq = len(self.variable_fluids) - # constraints['fluid_constraints'] = { - # 'func': self.fluid_func, 'deriv': self.fluid_deriv, - # 'constant_deriv': False, 'latex': self.fluid_func_doc, - # 'num_eq': num_fluid_eq} - # constraints['energy_balance_constraints'] = { - # 'func': self.energy_balance_func, - # 'deriv': self.energy_balance_deriv, - # 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - # 'num_eq': 1} - # return constraints - - # def fluid_func(self): - # r""" - # Calculate the vector of residual values for fluid balance equations. - # """ - # #i = self.inl[0] - # residual = [] - # for fluid in self.variable_fluids: - # res = 0 - # for i in self.inl: - # res += i.fluid.val[fluid] * i.m.val_SI - # for o in self.outl: - # res -= o.fluid.val[fluid] * o.m.val_SI - # residual += [res] - - # # # additional balance equation for calculating water vapor mass fraction - # # i = self.inl[1] - # # o = self.outl[0] - # # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - # # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] - - # # i1 = self.inl[0] - # # i2 = self.inl[1] - # # o1 = self.outl[0] - # # o2 = self.outl[1] - # # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] - # return residual - - # def fluid_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of fluid balance. - # """ - # #i = self.inl[0] - # for fluid in self.variable_fluids: - # for o in self.outl: - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - # if fluid in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - - # for i in self.inl: - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - # if fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - - # k += 1 - - # # i = self.inl[1] - # # o = self.outl[0] - # # if self.is_variable(o.m): - # # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - # # if fluid in o.fluid.is_var: - # # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - # # if self.is_variable(i.m): - # # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - # # if fluid in i.fluid.is_var: - # # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # # i1 = self.inl[0] - # # i2 = self.inl[1] - # # o1 = self.outl[0] - # # o2 = self.outl[1] - - # # if self.is_variable(i2.m): - # # self.jacobian[k, i2.m.J_col] = 1 - - # # if self.is_variable(o2.m): - # # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # # if 'Water' in o2.fluid.is_var: - # # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # # if self.is_variable(i1.m): - # # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # # if 'Water' in i1.fluid.is_var: - # # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # # if self.is_variable(o1.m): - # # self.jacobian[k, o1.m.J_col] = -1 - - # def dfluid_func(self): - # # additional balance equation for calculating water vapor mass fraction - # i = self.inl[1] - # o = self.outl[0] - # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - # return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI - - # # i1 = self.inl[0] - # # i2 = self.inl[1] - # # o1 = self.outl[0] - # # o2 = self.outl[1] - # # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val - - # def dfluid_deriv(self, increment_filter, k): - - # i = self.inl[1] - # o = self.outl[0] - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - # if 'Water' in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - # if 'Air' in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # # i1 = self.inl[0] - # # i2 = self.inl[1] - # # o1 = self.outl[0] - # # o2 = self.outl[1] - - # # if self.is_variable(i2.m): - # # self.jacobian[k, i2.m.J_col] = 1 - - # # if self.is_variable(o2.m): - # # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # # if 'Water' in o2.fluid.is_var: - # # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # # if self.is_variable(i1.m): - # # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # # if 'Water' in i1.fluid.is_var: - # # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # # if self.is_variable(o1.m): - # # self.jacobian[k, o1.m.J_col] = -1 - - # def dTwbProd_func(self): - # r""" - # Calculate the vector of residual values for fluid balance equations. - # """ - # i = self.inl[1] - # T_in = i.calc_T(T0=i.T.val_SI) - # T_wb = get_Twb(i,T_in) - # o = self.outl[1] - # T_out = o.calc_T(T0=o.T.val_SI) - # return T_out - T_wb - self.dTwbProd.val - - # def dTwbProd_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of fluid balance. - # """ - # for c in [self.inl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # # T_wb is nonlinear and we cannot differentiate easily - # for c in [self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - - # def dWo_func(self): - # r""" - # Calculate the vector of residual values for fluid balance equations. - # """ - # i2 = self.inl[1] - # o1 = self.outl[0] - # T_i = i2.calc_T(T0=i2.T.val_SI) - # T_o = o1.calc_T(T0=o1.T.val_SI) - - # M_i = i2.fluid.val["Water"] - # W_i = M_i/(1-M_i) - # I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) - - # T_wb = get_Twb(i2,T_i) - # W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) - # I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) - - # M_o = o1.fluid.val["Water"] - # W_o = M_o/(1-M_o) - - # #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - # I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) - # W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) - - # #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - # #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - # return W_o_calc - W_o - self.dWo.val - + + +class TwoStreamEvaporatorNEW(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): + + def __init__(self, label, **kwargs): + super().__init__(label, **kwargs) + + def outlets(self): + return ['out1', 'out2', 'out3'] + + def inlets(self): + return ['in1', 'in2'] + + @staticmethod + def component(): + return 'separator with species flow splits and dH on outlets' + + def get_parameters(self): + variables = super().get_parameters() + variables["num_in"] = dc_simple() + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=2 + ) + variables["Q"] = dc_cp( + max_val=0, func=self.energy_balance_hot_func, num_eq=1, + deriv=self.energy_balance_hot_deriv, + latex=self.pr_func_doc) + variables["KPI"] = dc_cp( + deriv=self.KPI_deriv, + func=self.KPI_func, + latex=self.pr_func_doc, + num_eq=1) + #variables["Qout"] = dc_cpa() + variables['kA'] = dc_cp( + min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, + deriv=self.kA_deriv) + variables['td'] = dc_cp(min_val=0, is_result=True) + variables['dTo'] = dc_cp( + min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, + deriv=self.dTo_deriv) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + constraints['energy_balance_constraints'] = { + 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} + constraints['mass_flow_constraints'] = { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 1} + return constraints - # def dWo_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of fluid balance. - # """ - - # i2 = self.inl[1] - # o1 = self.outl[0] - # for c in [i2, o1]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) - # # if self.is_variable(c.m): #, increment_filter): - # # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) - - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) - - # def dWo2_func(self): - # r""" - # Calculate the vector of residual values for fluid balance equations. - # """ - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # Ti1 = i1.calc_T(T0=i1.T.val_SI) - # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To1 = o1.calc_T(T0=o1.T.val_SI) - # #To2 = o2.calc_T(T0=o2.T.val_SI) - - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - # m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - # Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - # return Q_evap + Q_air - self.dWo2.val - + + @staticmethod + def is_branch_source(): + # trigger start_branch + return True + + def start_branch(self): + branches = {} + for outconn in [self.outl[0],self.outl[1]]: + branch = { + "connections": [outconn], + "components": [self, outconn.target], + "subbranches": {} + } + outconn.target.propagate_to_target(branch) + + branches[outconn.label] = branch + return branches + + def propagate_to_target(self, branch): + inconn = branch["connections"][-1] + conn_idx = self.inl.index(inconn) + if conn_idx == 1: + # connect in2 with with out3 - othervice stop the connections + outconn = self.outl[2] + branch["connections"] += [outconn] + branch["components"] += [outconn.target] + outconn.target.propagate_to_target(branch) + + def propagate_wrapper_to_target(self, branch): + inconn = branch["connections"][-1] + conn_idx = self.inl.index(inconn) + if conn_idx == 1: + # connect in2 with with out3 + outconn = self.outl[2] + branch["connections"] += [outconn] + branch["components"] += [self] + outconn.target.propagate_wrapper_to_target(branch) + elif conn_idx == 0: + # propagate wrapper to new start branches + branch["components"] += [self] + for outconn in [self.outl[0],self.outl[1]]: + branch["connections"] += [outconn] + outconn.target.propagate_wrapper_to_target(branch) + + def fluid_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + # hi = [self.inl[1]] + # ho = [self.outl[2]] + residual = [] + for fluid in self.variable_fluids: + res = 0 + for i in ci: + res += i.fluid.val[fluid] * i.m.val_SI + for o in co: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + # for fluid in self.variable_fluids: + # res = 0 + # for i in hi: + # res += i.fluid.val[fluid] * i.m.val_SI + # for o in ho: + # res -= o.fluid.val[fluid] * o.m.val_SI + # residual += [res] + return residual - # def dWo2_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of fluid balance. - # """ - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # Ti1 = i1.calc_T(T0=i1.T.val_SI) - # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To1 = o1.calc_T(T0=o1.T.val_SI) - - # dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - # dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w - # if 'Water' in o2.fluid.is_var: - # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w - # if 'Water' in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w - - # # if self.is_variable(o1.m): - # # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a - # # if 'Air' in o1.fluid.is_var: - # # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a - # if 'Air' in i2.fluid.is_var: - # self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a + def fluid_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + # hi = [self.inl[1]] + # ho = [self.outl[2]] + for fluid in self.variable_fluids: + for o in co: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + for i in ci: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + k += 1 + # for fluid in self.variable_fluids: + # for o in ho: + # if self.is_variable(o.m): + # self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + # if fluid in o.fluid.is_var: + # self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + # for i in hi: + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + # if fluid in i.fluid.is_var: + # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + # k += 1 - + def mass_flow_func(self): + r""" + Calculate the residual value for mass flow balance equation. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + # hi = [self.inl[1]] + # ho = [self.outl[2]] + residuals = [] + res = 0 + for i in ci: + res += i.m.val_SI + for o in co: + res -= o.m.val_SI + residuals += [res] + # res = 0 + # for i in hi: + # res += i.m.val_SI + # for o in ho: + # res -= o.m.val_SI + # residuals += [res] + return residuals + def mass_flow_deriv(self, k): + r""" + Calculate partial derivatives for mass flow equation. + """ + ci = [self.inl[0]] + co = [self.outl[0],self.outl[1]] + # hi = [self.inl[1]] + # ho = [self.outl[2]] + for i in ci: + if i.m.is_var: + self.jacobian[k, i.m.J_col] = 1 + for o in co: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + # k = k + 1 + # for i in hi: + # if i.m.is_var: + # self.jacobian[k, i.m.J_col] = 1 + # for o in ho: + # if o.m.is_var: + # self.jacobian[k, o.m.J_col] = -1 - # def res2(self,i2,o1): - # T_i = i2.calc_T(T0=i2.T.val_SI) - # T_o = o1.calc_T(T0=o1.T.val_SI) - # T_wb = get_Twb(i2,T_i) - # W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. - # M_i = i2.fluid.val["Water"] - # W_i = M_i/(1-M_i) - # M_o = o1.fluid.val["Water"] - # W_o = M_o/(1-M_o) - - # #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - # W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - # return W_o_calc - W_o - - # def energy_balance_func(self): - # r""" - # Need overwrite this function to take into account air inlet - # """ - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # # res = [] - # # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] - # # res += [self.res2(i2,o1)] - # # return res - # return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - - # def energy_balance_deriv(self, increment_filter, k): - # r""" - # Need overwrite this function to take into account air inlet - # """ - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = o1.h.val_SI - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = o2.h.val_SI - # if self.is_variable(o1.h): - # self.jacobian[k, o1.h.J_col] = o1.m.val_SI - # if self.is_variable(o2.h): - # self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = -i1.h.val_SI - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = -i2.h.val_SI - # if self.is_variable(i1.h): - # self.jacobian[k, i1.h.J_col] = -i1.m.val_SI - # if self.is_variable(i2.h): - # self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - - # # k = k + 1 - - # # for c in [i2, o1]: - # # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) - # # if self.is_variable(c.h): #, increment_filter): - # # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) - # # if self.is_variable(c.m): #, increment_filter): - # # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) - - # # for fluid in self.variable_fluids: - # # if fluid in c.fluid.is_var: - # # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) - - # def WBeff_func(self): - # r""" - # Calculate the vector of residual values for fluid balance equations. - # """ - # i = self.inl[1] - # T_in = i.calc_T(T0=i.T.val_SI) - # T_wb = get_Twb(i,T_in) - # o = self.outl[0] - # T_out = o.calc_T(T0=o.T.val_SI) - # #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) - # return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val + """ + i = self.inl[0] + residual = [] + for o in [self.outl[0],self.outl[1]]: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual - # def WBeff_deriv(self, increment_filter, k): - # r""" - # Calculate partial derivatives of fluid balance. - # """ - # for c in [self.inl[1], self.outl[0]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) - - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) - - # def KPI_func(self): - # r""" - # how much water is dried - # """ - # o = self.outl[0] - # m_evap = o.m.val_SI*o.fluid.val['Water'] - # return m_evap - self.KPI.val - - # def KPI_deriv(self, increment_filter, k): - # o = self.outl[0] - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] - # if 'Water' in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI - - # def calculate_td_log(self,T_i,T_wb,T_o): - # # 1 is with air - # i1 = self.inl[1] - # o1 = self.outl[0] - - # # temperature value manipulation for convergence stability - # T_i1 = T_i - # T_o1 = T_o - # T_i2 = T_wb - # T_o2 = T_wb - - # if T_i1 <= T_o2: - # T_i1 = T_o2 + 0.01 - # if T_i1 <= T_o2: - # T_o2 = T_i1 - 0.01 - # if T_i1 <= T_o2: - # T_o1 = T_i2 + 0.02 - # if T_o1 <= T_i2: - # T_i2 = T_o1 - 0.02 - - # ttd_u = T_i1 - T_o2 - # ttd_l = T_o1 - T_i2 - - # if ttd_u == ttd_l: - # td_log = ttd_l - # else: - # td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) - - # return td_log - - # def kA_func(self): - # r""" - # Calculate heat transfer from heat transfer coefficient. - # """ - # i = self.inl[1] - # o = self.outl[0] - # T_i = i.calc_T(T0=i.T.val_SI) - # T_wb = get_Twb(i,T_i) - # T_o = o.calc_T(T0=o.T.val_SI) - - # m_air = i.m.val_SI*i.fluid.val['Air'] - # Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - # return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) - - # def kA_deriv(self, increment_filter, k): - # r""" - # Partial derivatives of heat transfer coefficient function. - # """ - # i = self.inl[1] - # o = self.outl[0] - # T_i = i.calc_T(T0=i.T.val_SI) - # #T_wb = get_Twb(i,T_i) - # T_o = o.calc_T(T0=o.T.val_SI) - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - # if 'Air' in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - # for c in self.inl + self.outl: - # if self.is_variable(c.p): - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - # if self.is_variable(c.h): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) - - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) - - # def calc_parameters(self): - # super().calc_parameters() - - # i = self.inl[0] - # o = self.outl[0] - # self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] - # self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) - # -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) - - # i = self.inl[1] - # o = self.outl[0] - # m_air = i.m.val_SI*i.fluid.val['Air'] - # Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - # -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) - - # if not self.Q.is_set: - # self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + - # self.outl[1].m.val_SI * self.outl[1].h.val_SI - - # self.inl[0].m.val_SI * self.inl[0].h.val_SI - - # self.inl[1].m.val_SI * self.inl[1].h.val_SI) - # if not self.KPI.is_set: - # self.KPI.val = self.m_evap.val - - # if self.outl[1].fluid.val['Air'] > 0: - # TESPyComponentError("Air cannot go into out2") - - # T_in = self.inl[1].T.val_SI - # T_out = self.outl[0].T.val_SI - # T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) - - # if not self.WBeff.is_set: - # self.WBeff.val = (T_in-T_out)/(T_in-T_wb) - # if self.WBeff.val > 1.0: - # TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") - - - # self.ttd_u.val = T_in - T_wb - # self.ttd_l.val = T_out - T_wb - - # if not self.kA.is_set: - # # kA and logarithmic temperature difference - # if self.ttd_u.val < 0 or self.ttd_l.val < 0: - # self.td_log.val = np.nan - # elif self.ttd_l.val == self.ttd_u.val: - # self.td_log.val = self.ttd_l.val - # else: - # self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / - # np.log(self.ttd_l.val / self.ttd_u.val)) - # self.kA.val = -Q_air / self.td_log.val - - # port_i = self.inl[1] - # # M_i = port_i.fluid.val["Water"] - # # W_i = M_i/(1-M_i) - # # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) - # port_o = self.outl[0] - # M_o = port_o.fluid.val["Water"] - # W_o = M_o/(1-M_o) - # # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) - - # # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) - # # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) - # # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in [self.outl[0],self.outl[1]]: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 - # # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) - - # # print(int(I_i),int(I_o)) - # # print(int(T_o),int(T_o_2)) + def energy_balance_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + + hi = self.inl[1] + ho = self.outl[2] + return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) + hi.m.val_SI * (ho.h.val_SI - hi.h.val_SI) + + def energy_balance_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[0] + o1 = self.outl[0] + o2 = self.outl[1] + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI + if self.is_variable(o1.h): + self.jacobian[k, o1.h.J_col] = o1.m.val_SI + if self.is_variable(o2.h): + self.jacobian[k, o2.h.J_col] = o2.m.val_SI + + hi = self.inl[1] + ho = self.outl[2] + + if self.is_variable(hi.m): + self.jacobian[k, hi.m.J_col] = (ho.h.val_SI - hi.h.val_SI) + if self.is_variable(hi.h): + self.jacobian[k, hi.h.J_col] = -hi.m.val_SI + if self.is_variable(ho.h): + self.jacobian[k, ho.h.J_col] = ho.m.val_SI - # # print("hey") - # Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) - # if self.WBeff.val > 1.0 or W_o > Wmax: - # self.RH.val = 100 - # else: - # self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) \ No newline at end of file + def dTo_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + return T0 - T1 - self.dTo.val + + def dTo_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + for c in [self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) + + def energy_balance_hot_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + return self.inl[1].m.val_SI * ( + self.outl[2].h.val_SI - self.inl[1].h.val_SI + ) + self.Q.val + + def energy_balance_hot_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[1] + o = self.outl[2] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = -i.m.val_SI + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = i.m.val_SI + + def KPI_func(self): + r""" + Equation for total heat flow rate + """ + return self.inl[1].m.val_SI * ( + self.outl[2].h.val_SI - self.inl[1].h.val_SI + ) + self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']*self.KPI.val + + + def KPI_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[1] + o = self.outl[2] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = -i.m.val_SI + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = i.m.val_SI + ci = self.inl[0] + if self.is_variable(ci.m): + self.jacobian[k, ci.m.J_col] = ci.fluid.val['Water']*self.KPI.val + if 'Water' in ci.fluid.is_var: + self.jacobian[k, ci.fluid.J_col['Water']] = ci.m.val_SI*self.KPI.val + + def kA_func(self): + r""" + Calculate heat transfer from heat transfer coefficient. + """ + + Tcold = self.outl[1].calc_T(T0=self.outl[0].T.val_SI) # vapor out + #Thot = self.outl[2].calc_T(T0=self.outl[2].T.val_SI) + Thot = self.inl[1].calc_T_sat() # liquid out + self.td.val = (Thot-Tcold) + + return self.inl[1].m.val_SI * ( + self.outl[2].h.val_SI - self.inl[1].h.val_SI + ) + self.kA.val * self.td.val + + def kA_deriv(self, increment_filter, k): + r""" + Partial derivatives of heat transfer coefficient function. + """ + + i = self.inl[1] + o = self.outl[2] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) + if self.is_variable(i.p): + self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = i.m.val_SI + c = self.outl[1] + if self.is_variable(c.p): + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) + if self.is_variable(c.h): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + + def calc_parameters(self): + super().calc_parameters() + i = self.inl[0] + + if not self.Q.is_set: + self.Q.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) # np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + if not self.KPI.is_set: + self.KPI.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) / (self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']) + + hmin = min([o.h.val_SI for o in self.outl]) + hmax = max([o.h.val_SI for o in self.outl]) + if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): + self.deltaH.val = i.h.val_SI - hmin + else: + self.deltaH.val = i.h.val_SI - hmax + + if not self.kA.is_set: + Tcold = self.outl[0].T.val_SI # vapor out + #Thot = self.outl[2].T.val_SI + Thot = self.inl[1].calc_T_sat() # liquid out + self.td.val = (Thot-Tcold) + if Thot == Tcold: + self.kA.val = np.NaN + else: + self.kA.val = -self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI)/self.td.val From 22ef2dd438c622edb71ac2423c5e28783a443ea4 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:51:21 +0100 Subject: [PATCH 063/105] Changed some filenames --- incompressiblesTests/Ex1.py | 2 +- incompressiblesTests/Ex4.py | 2 +- incompressiblesTests/Ex8.py | 2 +- incompressiblesTests/Ex9.py | 2 +- .../newComponentsTests/2streamHX.py | 2 +- .../newComponentsTests/SpeciesFlowSplit.py | 2 +- .../SpeciesFlowSplitDeltaP.py | 2 +- .../SpeciesFlowSplitWithDeltaH-drier.py | 2 +- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 4 +- .../SpeciesFlowSplitWithDeltaH.py | 2 +- .../SpeciesFlowSplitWithDeltaT.py | 2 +- ...sFlowSplitWithDeltaTDeltaP-decanterTest.py | 2 +- ...SplitWithDeltaTDeltaP-evaporatorWithHot.py | 6 +- .../SpeciesFlowSplitWithDeltaTDeltaP.py | 2 +- .../SpeciesFlowSplitWithDeltaTDeltaPBus.py | 2 +- .../newComponentsTests/SplitterWithDeltaP.py | 2 +- .../SplitterWithFlowSplitter.py | 2 +- .../SplitterWithFlowSplitterDeltaP.py | 2 +- .../newComponentsTests/heatex+merge.py | 2 +- .../newComponentsTests/heatex_alone.py | 2 +- .../heatex_alone_DeltaPLfKpi.py | 2 +- .../newComponentsTests/heatex_alone_deltaP.py | 2 +- .../heatex_alone_lossFactor.py | 2 +- .../newComponentsTests/merge_mrk.py | 2 +- src/tespy/components/__init__.py | 6 +- .../{AirDrier.py => newAdvancedComponents.py} | 303 +----------------- src/tespy/networks/network_reader.py | 4 +- 27 files changed, 34 insertions(+), 333 deletions(-) rename src/tespy/components/{AirDrier.py => newAdvancedComponents.py} (79%) diff --git a/incompressiblesTests/Ex1.py b/incompressiblesTests/Ex1.py index 1e7bc20b1..ac0010563 100644 --- a/incompressiblesTests/Ex1.py +++ b/incompressiblesTests/Ex1.py @@ -18,7 +18,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SimpleHeatExchanger +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SimpleHeatExchanger import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/Ex4.py b/incompressiblesTests/Ex4.py index 2735fdea6..a65aae026 100644 --- a/incompressiblesTests/Ex4.py +++ b/incompressiblesTests/Ex4.py @@ -17,7 +17,7 @@ from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/Ex8.py b/incompressiblesTests/Ex8.py index 403431daf..42b48fb8a 100644 --- a/incompressiblesTests/Ex8.py +++ b/incompressiblesTests/Ex8.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/Ex9.py b/incompressiblesTests/Ex9.py index dea719ab6..4d3327714 100644 --- a/incompressiblesTests/Ex9.py +++ b/incompressiblesTests/Ex9.py @@ -7,7 +7,7 @@ import matplotlib.pyplot as plt from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaTDeltaP +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaTDeltaP import logging #logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py index 6248a353d..bc2c044f3 100644 --- a/incompressiblesTests/newComponentsTests/2streamHX.py +++ b/incompressiblesTests/newComponentsTests/2streamHX.py @@ -1,5 +1,5 @@ from tespy.components import Sink, Source, HeatExchanger -from tespy.components.newcomponents import TwoStreamHeatExchanger +from tespy.components.newComponents import TwoStreamHeatExchanger from tespy.connections import Connection from tespy.networks import Network diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py index dd0761214..cef5dd53a 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py index d97520770..d4c595d20 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaP diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py index cf6665d88..b10ec6640 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py index 5508dc569..82710410a 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py @@ -9,11 +9,11 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT -from tespy.components.AirDrier import DrierWithAir +from tespy.components.newAdvancedComponents import DrierWithAir logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py index 97008b871..427cc4738 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py index 2c30a614a..32c1e1f53 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py index 6077ca3c9..33ad4d9c1 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py index 4b02b265a..eb10e3685 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py @@ -9,11 +9,11 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP -from tespy.components.AirDrier import TwoStreamEvaporatorNEW +from tespy.components.newAdvancedComponents import TwoStreamEvaporator logging.basicConfig(level=logging.DEBUG) @@ -26,7 +26,7 @@ so1 = Source("Source 1") so2 = Source("Source 2") -se = TwoStreamEvaporatorNEW("Separator",num_in=2,num_out=3) +se = TwoStreamEvaporator("Separator",num_in=2,num_out=3) si1 = Sink("Sink 1") si2 = Sink("Sink 2") si3 = Sink("Sink 3") diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py index 3dc3815e8..f26896be9 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py index 3a0a91f40..be3e97e91 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import \ +from tespy.components.newComponents import \ DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaTDeltaPBus,SimpleHeatExchangerDeltaP diff --git a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py index 4c121aea2..9b6da6c85 100644 --- a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterDeltaP +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterDeltaP logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py index 666db85bf..f0a5ae5a3 100644 --- a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py index aa1894037..95748209f 100644 --- a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py +++ b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SplitterWithFlowSplitterDeltaP +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SplitterWithFlowSplitterDeltaP logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py index 67c24ef3a..3f007f155 100644 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ b/incompressiblesTests/newComponentsTests/heatex+merge.py @@ -8,7 +8,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone.py b/incompressiblesTests/newComponentsTests/heatex_alone.py index c8516c6fe..2cba2abab 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone.py @@ -12,7 +12,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py b/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py index e99f216a0..e9ca3381f 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py @@ -12,7 +12,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLfKpi,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import SimpleHeatExchangerDeltaPLfKpi,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py index 3e3f348fd..7ca48eb97 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py @@ -11,7 +11,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py index e2bce867c..a526093c0 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py @@ -12,7 +12,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/incompressiblesTests/newComponentsTests/merge_mrk.py b/incompressiblesTests/newComponentsTests/merge_mrk.py index 632154ae5..623fcd9ea 100644 --- a/incompressiblesTests/newComponentsTests/merge_mrk.py +++ b/incompressiblesTests/newComponentsTests/merge_mrk.py @@ -9,7 +9,7 @@ from tespy.tools.data_containers import ComponentProperties as dc_cp from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.components.newcomponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits +from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits logging.basicConfig(level=logging.DEBUG) diff --git a/src/tespy/components/__init__.py b/src/tespy/components/__init__.py index d7f99362d..dca0441da 100644 --- a/src/tespy/components/__init__.py +++ b/src/tespy/components/__init__.py @@ -29,5 +29,7 @@ from .turbomachinery.turbine import Turbine # noqa: F401 # New components -from .newcomponents import * -from .energySupplyComponents import * \ No newline at end of file +from .newComponents import * +from .newAdvancedComponents import * +from .energySupplyComponents import * + diff --git a/src/tespy/components/AirDrier.py b/src/tespy/components/newAdvancedComponents.py similarity index 79% rename from src/tespy/components/AirDrier.py rename to src/tespy/components/newAdvancedComponents.py index 9170c21c5..e71fc4088 100644 --- a/src/tespy/components/AirDrier.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -18,7 +18,7 @@ import numpy as np -from .newcomponents import SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP +from .newComponents import SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP def get_Twb(port,T): @@ -697,309 +697,8 @@ def calc_parameters(self): - class TwoStreamEvaporator(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - def __init__(self, label, **kwargs): - super().__init__(label, **kwargs) - - def outlets(self): - return ['out1', 'out2', 'out3'] - - def inlets(self): - return ['in1', 'in2'] - - @staticmethod - def component(): - return 'separator with species flow splits and dH on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["num_in"] = dc_simple() - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=self.num_out - ) - variables["Q"] = dc_cp( - func=self.Q_func, num_eq=1, - deriv=self.Q_deriv, - latex=self.pr_func_doc) - variables["KPI"] = dc_cp( - deriv=self.KPI_deriv, - func=self.KPI_func, - latex=self.pr_func_doc, - num_eq=1) - #variables["Qout"] = dc_cpa() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) * 2 - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - constraints['energy_balance_constraints'] = { - 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - constraints['mass_flow_constraints'] = { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 2} - return constraints - - def fluid_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - hi = [self.inl[1]] - ho = [self.outl[2]] - - residual = [] - for fluid in self.variable_fluids: - res = 0 - for i in ci: - res += i.fluid.val[fluid] * i.m.val_SI - for o in co: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - - for fluid in self.variable_fluids: - res = 0 - for i in hi: - res += i.fluid.val[fluid] * i.m.val_SI - for o in ho: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - - return residual - - def fluid_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - hi = [self.inl[1]] - ho = [self.outl[2]] - - for fluid in self.variable_fluids: - for o in co: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - for i in ci: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - k += 1 - - for fluid in self.variable_fluids: - for o in ho: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - for i in hi: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - k += 1 - - - def mass_flow_func(self): - r""" - Calculate the residual value for mass flow balance equation. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - hi = [self.inl[1]] - ho = [self.outl[2]] - - residuals = [] - res = 0 - for i in ci: - res += i.m.val_SI - for o in co: - res -= o.m.val_SI - residuals += [res] - res = 0 - for i in hi: - res += i.m.val_SI - for o in ho: - res -= o.m.val_SI - residuals += [res] - return residuals - - def mass_flow_deriv(self, k): - r""" - Calculate partial derivatives for mass flow equation. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - hi = [self.inl[1]] - ho = [self.outl[2]] - - for i in ci: - if i.m.is_var: - self.jacobian[k, i.m.J_col] = 1 - for o in co: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - k = k + 1 - - for i in hi: - if i.m.is_var: - self.jacobian[k, i.m.J_col] = 1 - for o in ho: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in self.outl: - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in self.outl: - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def energy_balance_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - - hi = self.inl[1] - ho = self.outl[2] - return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) + hi.m.val_SI * (ho.h.val_SI - hi.h.val_SI) - - def energy_balance_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - hi = self.inl[1] - ho = self.outl[2] - - if self.is_variable(hi.m): - self.jacobian[k, hi.m.J_col] = (ho.h.val_SI - hi.h.val_SI) - if self.is_variable(hi.h): - self.jacobian[k, hi.h.J_col] = -hi.m.val_SI - if self.is_variable(ho.h): - self.jacobian[k, ho.h.J_col] = ho.m.val_SI - - # k = k + 1 - # for c in [self.outl[0], self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) - - def KPI_func(self): - r""" - Equation for total heat flow rate - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - # res = [] - # res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] - # res += [self.Q_func_Tequality(o1,o2)] - # return res - return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI - - def KPI_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = - self.KPI.val - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - # k = k + 1 - # for c in [self.outl[0], self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) - - def calc_parameters(self): - super().calc_parameters() - i = self.inl[0] - - if not self.Q.is_set: - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - if not self.KPI.is_set: - self.KPI.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) / i.m.val_SI - - hmin = min([o.h.val_SI for o in self.outl]) - hmax = max([o.h.val_SI for o in self.outl]) - if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): - self.deltaH.val = i.h.val_SI - hmin - else: - self.deltaH.val = i.h.val_SI - hmax - - - - - - -class TwoStreamEvaporatorNEW(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - def __init__(self, label, **kwargs): super().__init__(label, **kwargs) diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index e5e83e939..9fbe3b599 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -41,8 +41,8 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer -from tespy.components.newcomponents import * -from tespy.components.AirDrier import * +from tespy.components.newComponents import * +from tespy.components.newAdvancedComponents import * from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref From 7e6e38cfd306137a8115c881635d24ef9b54c15a Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 1 Dec 2023 09:24:50 +0100 Subject: [PATCH 064/105] write branch info --- src/tespy/networks/network.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 2da771dbc..913dfd684 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -721,7 +721,8 @@ def create_massflow_and_fluid_branches(self): for k,v in self.branches.items(): self.branchesNames[k] = v['components'][0].label for conn,comp in zip(v['connections'],v['components'][1:]): - self.branchesNames[k] += " -> " + conn.label + " -> " + comp.label + #self.branchesNames[k] += " -> " + conn.label + " -> " + comp.label + self.branchesNames[k] += " -> " + comp.label msg = (self.branchesNames[k]) logger.debug(msg) @@ -744,6 +745,17 @@ def create_fluid_wrapper_branches(self): for start in start_components: self.fluid_wrapper_branches.update(start.start_fluid_wrapper_branch()) + self.branchesNames = {} + msg = ("Wrapped the following components and connections:") + logger.debug(msg) + for k,v in self.fluid_wrapper_branches.items(): + self.branchesNames[k] = v['components'][0].label + for conn,comp in zip(v['connections'],v['components'][1:]): + #self.branchesNames[k] += " -> " + conn.label + " -> " + comp.label + self.branchesNames[k] += " -> " + comp.label + msg = (self.branchesNames[k]) + logger.debug(msg) + merged = self.fluid_wrapper_branches.copy() for branch_name, branch_data in self.fluid_wrapper_branches.items(): if branch_name not in merged: From 699093eceecd4a99e876eca43c776caa21c54633 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 08:34:19 +0100 Subject: [PATCH 065/105] deltaP on hot side advanced evaporator --- src/tespy/components/newAdvancedComponents.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index e71fc4088..9c0fc5751 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -738,6 +738,9 @@ def get_parameters(self): variables['dTo'] = dc_cp( min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, deriv=self.dTo_deriv) + variables['deltaPhot'] = dc_cp( + min_val=0, num_eq=1, func=self.deltaPhot_func, latex=self.pr_func_doc, + deriv=self.deltaPhot_deriv) return variables def get_mandatory_constraints(self): @@ -803,6 +806,15 @@ def propagate_wrapper_to_target(self, branch): branch["connections"] += [outconn] outconn.target.propagate_wrapper_to_target(branch) + def deltaPhot_func(self): + return self.inl[1].p.val_SI - self.deltaPhot.val*1e5 - self.outl[2].p.val_SI + + def deltaPhot_deriv(self, increment_filter, k): + if self.inl[1].p.is_var: + self.jacobian[k, self.inl[1].p.J_col] = 1 + if self.outl[2].p.is_var: + self.jacobian[k, self.outl[2].p.J_col] = -1 + def fluid_func(self): r""" Calculate the vector of residual values for fluid balance equations. From 875464f3cce4bab66d435f49a0255271e6828feb Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 15:42:08 +0100 Subject: [PATCH 066/105] new drier --- src/tespy/components/newAdvancedComponents.py | 555 +++++++++++++++++- 1 file changed, 553 insertions(+), 2 deletions(-) diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index 9c0fc5751..64b07d525 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -994,8 +994,8 @@ def dTo_deriv(self, increment_filter, k): r""" Partial derivatives for hot side heat exchanger energy balance. """ - T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) for c in [self.outl[0], self.outl[1]]: if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) @@ -1113,3 +1113,554 @@ def calc_parameters(self): self.kA.val = np.NaN else: self.kA.val = -self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI)/self.td.val + + + + +class TwoStreamDrier(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): + + def __init__(self, label, **kwargs): + super().__init__(label, **kwargs) + + def outlets(self): + return ['out1', 'out2'] + + def inlets(self): + return ['in1', 'in2'] + + @staticmethod + def component(): + return 'separator with species flow splits and dH on outlets' + + def get_parameters(self): + variables = super().get_parameters() + variables["num_in"] = dc_simple() + variables["deltaH"] = dc_cp( + deriv=self.energy_balance_deltaH_deriv, # same as before + func=self.energy_balance_deltaH_func, + latex=self.pr_func_doc, + num_eq=2 + ) + variables["dTwbProd"] = dc_cp( + deriv=self.dTwbProd_deriv, + func=self.dTwbProd_func, + latex=self.pr_func_doc, + num_eq=1, + ) + variables["Q"] = dc_cp( + max_val=0, func=self.energy_balance_hot_func, num_eq=1, + deriv=self.energy_balance_hot_deriv, + latex=self.pr_func_doc) + variables["KPI"] = dc_cp( + deriv=self.KPI_deriv, + func=self.KPI_func, + latex=self.pr_func_doc, + num_eq=1) + #variables["Qout"] = dc_cpa() + variables['kA'] = dc_cp( + min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, + deriv=self.kA_deriv) + variables['td'] = dc_cp(min_val=0, is_result=True) + variables['dTo'] = dc_cp( + min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, + deriv=self.dTo_deriv) + variables['deltaPhot'] = dc_cp( + min_val=0, num_eq=1, func=self.deltaPhot_func, latex=self.pr_func_doc, + deriv=self.deltaPhot_deriv) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) + #self.variable_product_fluids = [fluid for fluid in self.variable_fluids if not fluid in ['Water','Air']] + num_fluid_eq = len(self.variable_fluids) + constraints['fluid_constraints'] = { + 'func': self.fluid_func, 'deriv': self.fluid_deriv, + 'constant_deriv': False, 'latex': self.fluid_func_doc, + 'num_eq': num_fluid_eq} + constraints['energy_balance_constraints'] = { + 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, + 'constant_deriv': False, 'latex': self.energy_balance_func_doc, + 'num_eq': 1} + constraints['mass_flow_constraints'] = { + 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, + 'constant_deriv': True, 'latex': self.mass_flow_func_doc, + 'num_eq': 2} + return constraints + + + # @staticmethod + # def is_branch_source(): + # # trigger start_branch + # return True + + # def start_branch(self): + # branches = {} + # for outconn in [self.outl[0],self.outl[1]]: + # branch = { + # "connections": [outconn], + # "components": [self, outconn.target], + # "subbranches": {} + # } + # outconn.target.propagate_to_target(branch) + + # branches[outconn.label] = branch + # return branches + + # def propagate_to_target(self, branch): + # inconn = branch["connections"][-1] + # conn_idx = self.inl.index(inconn) + # if conn_idx == 1: + # # connect in2 with with out3 - othervice stop the connections + # outconn = self.outl[2] + # branch["connections"] += [outconn] + # branch["components"] += [outconn.target] + # outconn.target.propagate_to_target(branch) + + # def propagate_wrapper_to_target(self, branch): + # inconn = branch["connections"][-1] + # conn_idx = self.inl.index(inconn) + # if conn_idx == 1: + # # connect in2 with with out3 + # outconn = self.outl[2] + # branch["connections"] += [outconn] + # branch["components"] += [self] + # outconn.target.propagate_wrapper_to_target(branch) + # elif conn_idx == 0: + # # propagate wrapper to new start branches + # branch["components"] += [self] + # for outconn in [self.outl[0],self.outl[1]]: + # branch["connections"] += [outconn] + # outconn.target.propagate_wrapper_to_target(branch) + + def deltaPhot_func(self): + return self.inl[1].p.val_SI - self.deltaPhot.val*1e5 - self.outl[2].p.val_SI + + def deltaPhot_deriv(self, increment_filter, k): + if self.inl[1].p.is_var: + self.jacobian[k, self.inl[1].p.J_col] = 1 + if self.outl[2].p.is_var: + self.jacobian[k, self.outl[2].p.J_col] = -1 + + def fluid_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + residual = [] + for fluid in self.variable_fluids: + res = 0 + for i in self.inl: + res += i.fluid.val[fluid] * i.m.val_SI + for o in self.outl: + res -= o.fluid.val[fluid] * o.m.val_SI + residual += [res] + return residual + + def fluid_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + for fluid in self.variable_fluids: + for o in self.outl: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] + if fluid in o.fluid.is_var: + self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI + for i in self.inl: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] + if fluid in i.fluid.is_var: + self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI + k += 1 + + def mass_flow_func(self): + r""" + Calculate the residual value for mass flow balance equation. + """ + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + residuals = [] + residuals += [i1.m.val_SI - o1.m.val_SI - m_evap] + residuals += [i2.m.val_SI - o2.m.val_SI + m_evap] + + return residuals + + def mass_flow_deriv(self, k): + r""" + Calculate partial derivatives for mass flow equation. + """ + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + fluid = 'Water' + + if i1.m.is_var: + self.jacobian[k, i1.m.J_col] = 1 - i1.fluid.val[fluid] + if o1.m.is_var: + self.jacobian[k, o1.m.J_col] = -1 + o1.fluid.val[fluid] + if fluid in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col[fluid]] = - i1.m.val_SI + if fluid in o1.fluid.is_var: + self.jacobian[k, o1.fluid.J_col[fluid]] = + o1.m.val_SI + + k = k + 1 + + if i2.m.is_var: + self.jacobian[k, i2.m.J_col] = 1 + if o2.m.is_var: + self.jacobian[k, o2.m.J_col] = -1 + if i1.m.is_var: + self.jacobian[k, i1.m.J_col] = + i1.fluid.val[fluid] + if o1.m.is_var: + self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] + if fluid in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col[fluid]] = + i1.m.val_SI + if fluid in o1.fluid.is_var: + self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI + + def energy_balance_deltaH_func(self): + r""" + Calculate deltaH residuals. + + """ + i = self.inl[0] + residual = [] + for o in [self.outl[0],self.outl[1]]: + residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] + return residual + + def energy_balance_deltaH_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of energy balance. + """ + i = self.inl[0] + for o in [self.outl[0],self.outl[1]]: + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = 1 + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -1 + k += 1 + + def energy_balance_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + return i1.m.val_SI * i1.h.val_SI + i2.m.val_SI * i2.h.val_SI \ + - o1.m.val_SI * o1.h.val_SI - o2.m.val_SI * o2.h.val_SI + + def energy_balance_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + for i in [i1,i2]: + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = i.m.val_SI + for o in [o1,o2]: + if self.is_variable(o.m): + self.jacobian[k, o.m.J_col] = -o.h.val_SI + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = -o.m.val_SI + + + def dTwbProd_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i = self.inl[1] + T_in = i.calc_T(T0=i.T.val_SI) + T_wb = get_Twb(i,T_in) + o = self.outl[0] + T_out = o.calc_T(T0=o.T.val_SI) + return T_out - T_wb - self.dTwbProd.val + + def dTwbProd_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + # for c in [self.inl[1]]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) + # T_wb is nonlinear and we cannot differentiate easily + for c in [self.inl[1],self.outl[0]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) + + def dTo_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + return T0 - T1 - self.dTo.val + + def dTo_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + for c in [self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) + + def energy_balance_hot_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + + # i1 = self.inl[0] + # o1 = self.outl[0] # liquid + # o2 = self.outl[1] # vapor + + # Ti1 = i1.calc_T(T0=i1.T.val_SI) + # To2 = o2.calc_T(T0=o2.T.val_SI) + + # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + # Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + # return (Q_evap - self.Q.val)/self.Q.val + + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + + m_air = i2.m.val_SI*i2.fluid.val['Air'] + Q_air = m_air * (i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) + -o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state)) + + return (Q_air - self.Q.val)/self.Q.val + + def energy_balance_hot_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + + # i1 = self.inl[0] + # i2 = self.inl[1] # air + # o1 = self.outl[0] # liquid + # o2 = self.outl[1] # vapor + + # fluid = 'Air' + # Ti2 = i2.calc_T(T0=i2.T.val_SI) + # To2 = o2.calc_T(T0=o2.T.val_SI) + # hi2 = i2.fluid_data[fluid]['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) + # ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + + # # Q_air = i2.m.val_SI*i2.fluid.val['Air'] * (hi2 - ho2) + + # if self.is_variable(i2.m): + # self.jacobian[k, i2.m.J_col] = i2.fluid.val[fluid] * (hi2 - ho2) + # if fluid in i2.fluid.is_var: + # self.jacobian[k, i2.fluid.J_col[fluid]] = i2.m.val_SI * (hi2 - ho2) + + # for c in [i2,o2]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) + + # for c in [i2,o2]: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) + + + + + + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + fluid = 'Water' + Ti1 = i1.calc_T(T0=i1.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) + + #Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + + # if self.is_variable(i1.m): + # self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/self.Q.val + # if fluid in i1.fluid.is_var: + # self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/self.Q.val + + # if self.is_variable(o1.m): + # self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/self.Q.val + # if fluid in o1.fluid.is_var: + # self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/self.Q.val + + for c in [i1,i2,o1,o2]: + if self.is_variable(c.m): #, increment_filter): + self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) + + + # for c in [i1,i2,o1,o2]: + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) + + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) + + # #for c in [i1,o1,o2]: + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) + + + + def KPI_func(self): + r""" + Equation for total heat flow rate + """ + return self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) + self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']*self.KPI.val + + + def KPI_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + i = self.inl[1] + o = self.outl[2] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = -i.m.val_SI + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = i.m.val_SI + ci = self.inl[0] + if self.is_variable(ci.m): + self.jacobian[k, ci.m.J_col] = ci.fluid.val['Water']*self.KPI.val + if 'Water' in ci.fluid.is_var: + self.jacobian[k, ci.fluid.J_col['Water']] = ci.m.val_SI*self.KPI.val + + def kA_func(self): + r""" + Calculate heat transfer from heat transfer coefficient. + """ + + Tcold = self.outl[1].calc_T(T0=self.outl[0].T.val_SI) # vapor out + #Thot = self.outl[2].calc_T(T0=self.outl[2].T.val_SI) + Thot = self.inl[1].calc_T_sat() # liquid out + self.td.val = (Thot-Tcold) + + return self.inl[1].m.val_SI * ( + self.outl[2].h.val_SI - self.inl[1].h.val_SI + ) + self.kA.val * self.td.val + + def kA_deriv(self, increment_filter, k): + r""" + Partial derivatives of heat transfer coefficient function. + """ + + i = self.inl[1] + o = self.outl[2] + if self.is_variable(i.m): + self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + if self.is_variable(i.h): + self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) + if self.is_variable(i.p): + self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) + if self.is_variable(o.h): + self.jacobian[k, o.h.J_col] = i.m.val_SI + c = self.outl[1] + if self.is_variable(c.p): + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) + if self.is_variable(c.h): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + + def calc_parameters(self): + super().calc_parameters() + i = self.inl[0] + + i1 = self.inl[0] + i2 = self.inl[1] # air + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + Q_prod = o1.m.val_SI * (o2.h.val_SI - i1.h.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + Q_prod_w = m_evap * (o2.h.val_SI - i1.h.val_SI) + Q_e = m_evap * (o2.h.val_SI - i1.h.val_SI) + Q_air = i1.m.val_SI * i1.h.val_SI - i2.m.val_SI - i2.h.val_SI + + + Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state)) + + m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] + Q_air = + m_air * (o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,i2.T.val_SI,force_state=i2.force_state)) + + fluid = 'Water' + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) + + self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + + + print(Q_air) + + # if not self.Q.is_set: + # self.Q.val = - self.inl[1].m.val_SI * (self.outl[1].h.val_SI - self.inl[1].h.val_SI) # np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) + # if not self.KPI.is_set: + # self.KPI.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) / (self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']) + + # hmin = min([o.h.val_SI for o in self.outl]) + # hmax = max([o.h.val_SI for o in self.outl]) + # if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): + # self.deltaH.val = i.h.val_SI - hmin + # else: + # self.deltaH.val = i.h.val_SI - hmax + + # if not self.kA.is_set: + # Tcold = self.outl[0].T.val_SI # vapor out + # #Thot = self.outl[2].T.val_SI + # Thot = self.inl[1].calc_T_sat() # liquid out + # self.td.val = (Thot-Tcold) + # if Thot == Tcold: + # self.kA.val = np.NaN + # else: + # self.kA.val = -self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI)/self.td.val From dd734940786ffaa34641b0ce95d9b21c7a9a18d3 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 17:00:22 +0100 Subject: [PATCH 067/105] New improved drier model --- ...plitWithDeltaH-drierWithAir_newApproach.py | 194 ++++++++ src/tespy/components/newAdvancedComponents.py | 414 +++++++++++------- 2 files changed, 445 insertions(+), 163 deletions(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py new file mode 100644 index 000000000..29163b34d --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py @@ -0,0 +1,194 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newComponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT + +from tespy.components.newAdvancedComponents import TwoStreamDrier + +logging.basicConfig(level=logging.DEBUG) + +# %% + +# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? +#fluids = ["INCOMP::Water", "INCOMP::T66"] +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +soAir = Source("SourceAir") +se = TwoStreamDrier("Separator",num_out=2,num_in=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") +c3 = Connection(se, "out2", si2, "in1", label="3") +c4 = Connection(soAir, "out1", se, "in2", label="4") + +nw.add_conns(c1, c2, c3, c4) + +# for c in nw.conns['object']: +# c.set_attr(m0=1, h0=100, p0=1.2) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") +c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") + +c2.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) +c3.set_attr(fluid={"INCOMP::T66": 0}) + + +#c2.set_attr(p=1.2,T=60,force_state='g') +c2.set_attr(p=1.0) +c3.set_attr(p=1.0) + +se.set_attr(deltaH=0) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +se.set_attr(deltaH=None) +c3.set_attr(p=1.0,T=None,force_state='g') +c2.set_attr(p=1.0,T=None,force_state='l') +se.set_attr(dTwbProd=0) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c2.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=se.Q.val) +se.set_attr(Q=1e6) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c2.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=2.250e6) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c2.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=None) +se.set_attr(kA=6.0e+04) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +c2.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=None) +se.set_attr(kA=None) +se.set_attr(WBeff=0.4) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + + + +import sys +sys.exit() + + +#se.set_attr(deltaH=0) +#se.set_attr(dfluid=0) + +# nw.solve("design") +# if not nw.converged: +# raise Exception("not converged") +# nw.print_results() +# print(nw.results['Connection']) + +c2.set_attr(p=1.0,T=30,force_state='g') +c3.set_attr(p=1.0,T=30,force_state='l') + + +se.set_attr(dTwbProd=0) +se.set_attr(dfluid=0) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c2.set_attr(p=1.0,T=None,force_state='g') +c3.set_attr(p=1.0,T=None,force_state='l') +se.set_attr(dTwbProd=0) +se.set_attr(dfluid=0) +#se.set_attr(eb=0) + + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + +c3.set_attr(fluid={"INCOMP::Water": None}) +se.set_attr(KPI=0.85) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +se.set_attr(KPI=None) +#c3.set_attr(fluid={"INCOMP::Water": 0.08}) +#c4.set_attr(m=None) +se.set_attr(WBeff=0.6) +#c2.set_attr(T=40) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +se.set_attr(WBeff=None) +se.set_attr(kA=4.6e4) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index 64b07d525..6af7986fd 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -1139,7 +1139,7 @@ def get_parameters(self): deriv=self.energy_balance_deltaH_deriv, # same as before func=self.energy_balance_deltaH_func, latex=self.pr_func_doc, - num_eq=2 + num_eq=1 ) variables["dTwbProd"] = dc_cp( deriv=self.dTwbProd_deriv, @@ -1160,13 +1160,14 @@ def get_parameters(self): variables['kA'] = dc_cp( min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, deriv=self.kA_deriv) - variables['td'] = dc_cp(min_val=0, is_result=True) - variables['dTo'] = dc_cp( - min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, - deriv=self.dTo_deriv) - variables['deltaPhot'] = dc_cp( - min_val=0, num_eq=1, func=self.deltaPhot_func, latex=self.pr_func_doc, - deriv=self.deltaPhot_deriv) + variables['td_log'] = dc_cp(min_val=0, is_result=True) + variables["WBeff"] = dc_cp( + min_val=0,max_val=1, + deriv=self.WBeff_deriv, + func=self.WBeff_func, + latex=self.pr_func_doc, + num_eq=1, + ) return variables def get_mandatory_constraints(self): @@ -1233,14 +1234,6 @@ def get_mandatory_constraints(self): # branch["connections"] += [outconn] # outconn.target.propagate_wrapper_to_target(branch) - def deltaPhot_func(self): - return self.inl[1].p.val_SI - self.deltaPhot.val*1e5 - self.outl[2].p.val_SI - - def deltaPhot_deriv(self, increment_filter, k): - if self.inl[1].p.is_var: - self.jacobian[k, self.inl[1].p.J_col] = 1 - if self.outl[2].p.is_var: - self.jacobian[k, self.outl[2].p.J_col] = -1 def fluid_func(self): r""" @@ -1331,7 +1324,7 @@ def energy_balance_deltaH_func(self): """ i = self.inl[0] residual = [] - for o in [self.outl[0],self.outl[1]]: + for o in [self.outl[0]]: # ,self.outl[1]]: # let energy balance solve the other residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] return residual @@ -1340,7 +1333,7 @@ def energy_balance_deltaH_deriv(self, increment_filter, k): Calculate partial derivatives of energy balance. """ i = self.inl[0] - for o in [self.outl[0],self.outl[1]]: + for o in [self.outl[0]]: # ,self.outl[1]]: # let energy balance solve the other if self.is_variable(i.h): self.jacobian[k, i.h.J_col] = 1 if self.is_variable(o.h): @@ -1407,60 +1400,37 @@ def dTwbProd_deriv(self, increment_filter, k): if self.is_variable(c.h): #, increment_filter): self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - def dTo_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - return T0 - T1 - self.dTo.val - - def dTo_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - for c in [self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) def energy_balance_hot_func(self): r""" Equation for hot side heat exchanger energy balance. """ - # i1 = self.inl[0] - # o1 = self.outl[0] # liquid - # o2 = self.outl[1] # vapor - - # Ti1 = i1.calc_T(T0=i1.T.val_SI) - # To2 = o2.calc_T(T0=o2.T.val_SI) - - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] - # Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) - # -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - # return (Q_evap - self.Q.val)/self.Q.val - i1 = self.inl[0] - i2 = self.inl[1] # air o1 = self.outl[0] # liquid o2 = self.outl[1] # vapor - Ti2 = i2.calc_T(T0=i2.T.val_SI) + Ti1 = i1.calc_T(T0=i1.T.val_SI) To2 = o2.calc_T(T0=o2.T.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + return (Q_evap - self.Q.val)/(self.Q.val+1e-6) + + # i1 = self.inl[0] + # i2 = self.inl[1] # air + # o1 = self.outl[0] # liquid + # o2 = self.outl[1] # vapor + + # Ti2 = i2.calc_T(T0=i2.T.val_SI) + # To2 = o2.calc_T(T0=o2.T.val_SI) - m_air = i2.m.val_SI*i2.fluid.val['Air'] - Q_air = m_air * (i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) - -o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state)) + # m_air = i2.m.val_SI*i2.fluid.val['Air'] + # Q_air = m_air * (i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) + # -o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state)) - return (Q_air - self.Q.val)/self.Q.val + # return (Q_air - self.Q.val)/self.Q.val def energy_balance_hot_deriv(self, increment_filter, k): r""" @@ -1490,19 +1460,31 @@ def energy_balance_hot_deriv(self, increment_filter, k): # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # for c in [i2,o2]: # if fluid in c.fluid.is_var: # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) + # # let's just do numerical derivative of them all + # i1 = self.inl[0] + # i2 = self.inl[1] + # o1 = self.outl[0] # liquid + # o2 = self.outl[1] # vapor - - + # for c in [i1,i2,o1,o2]: + # if self.is_variable(c.m): #, increment_filter): + # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) + # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) + # if self.is_variable(c.h): #, increment_filter): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) + # for fluid in self.variable_fluids: + # if fluid in c.fluid.is_var: + # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) i1 = self.inl[0] i2 = self.inl[1] o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o2 = self.outl[1] # vapor fluid = 'Water' Ti1 = i1.calc_T(T0=i1.T.val_SI) @@ -1511,105 +1493,215 @@ def energy_balance_hot_deriv(self, increment_filter, k): ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - #Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/self.Q.val - # if fluid in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/self.Q.val + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/(self.Q.val+1e-6) + if fluid in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/(self.Q.val+1e-6) - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/self.Q.val - # if fluid in o1.fluid.is_var: - # self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/self.Q.val - - for c in [i1,i2,o1,o2]: - if self.is_variable(c.m): #, increment_filter): - self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) - + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(self.Q.val+1e-6) + if fluid in o1.fluid.is_var: + self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(self.Q.val+1e-6) # for c in [i1,i2,o1,o2]: # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # if self.is_variable(c.m): #, increment_filter): # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) - # #for c in [i1,o1,o2]: # for fluid in self.variable_fluids: # if fluid in c.fluid.is_var: # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) - def KPI_func(self): r""" Equation for total heat flow rate """ - return self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) + self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']*self.KPI.val + i1 = self.inl[0] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + Ti1 = i1.calc_T(T0=i1.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val + return (Q_evap - Q)/(Q+1e-6) def KPI_deriv(self, increment_filter, k): r""" Partial derivatives for hot side heat exchanger energy balance. """ - i = self.inl[1] - o = self.outl[2] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = -i.m.val_SI - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = i.m.val_SI - ci = self.inl[0] - if self.is_variable(ci.m): - self.jacobian[k, ci.m.J_col] = ci.fluid.val['Water']*self.KPI.val - if 'Water' in ci.fluid.is_var: - self.jacobian[k, ci.fluid.J_col['Water']] = ci.m.val_SI*self.KPI.val + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + fluid = 'Water' + Ti1 = i1.calc_T(T0=i1.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) + + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val + + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = (i1.fluid.val[fluid] - i1.m.val_SI*self.KPI.val) * (ho2 - hi1)/(Q+1e-6) + if fluid in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col[fluid]] = (i1.m.val_SI - i1.fluid.val['Water']*self.KPI.val) * (ho2 - hi1)/(Q+1e-6) + + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) + if fluid in o1.fluid.is_var: + self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + + def calculate_td_log(self,T_i,T_wb,T_o): + # 1 is with air + i1 = self.inl[1] + o1 = self.outl[0] + + # temperature value manipulation for convergence stability + T_i1 = T_i + T_o1 = T_o + T_i2 = T_wb + T_o2 = T_wb + + if T_i1 <= T_o2: + T_i1 = T_o2 + 0.01 + if T_i1 <= T_o2: + T_o2 = T_i1 - 0.01 + if T_i1 <= T_o2: + T_o1 = T_i2 + 0.02 + if T_o1 <= T_i2: + T_i2 = T_o1 - 0.02 + + ttd_u = T_i1 - T_o2 + ttd_l = T_o1 - T_i2 + + if ttd_u == ttd_l: + td_log = ttd_l + else: + td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) + + return td_log + def kA_func(self): r""" Calculate heat transfer from heat transfer coefficient. """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor - Tcold = self.outl[1].calc_T(T0=self.outl[0].T.val_SI) # vapor out - #Thot = self.outl[2].calc_T(T0=self.outl[2].T.val_SI) - Thot = self.inl[1].calc_T_sat() # liquid out - self.td.val = (Thot-Tcold) + Ti2 = i2.calc_T(T0=i2.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + Twb = get_Twb(i2,Ti2) + self.td_log.val = self.calculate_td_log(Ti2,Twb,To2) - return self.inl[1].m.val_SI * ( - self.outl[2].h.val_SI - self.inl[1].h.val_SI - ) + self.kA.val * self.td.val + Ti1 = i1.calc_T(T0=i1.T.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) + + Q = self.kA.val * self.td_log.val + return (Q_evap - Q)/(Q+1e-6) def kA_deriv(self, increment_filter, k): r""" Partial derivatives of heat transfer coefficient function. """ + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor - i = self.inl[1] - o = self.outl[2] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) - if self.is_variable(i.p): - self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = i.m.val_SI - c = self.outl[1] - if self.is_variable(c.p): - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - if self.is_variable(c.h): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + fluid = 'Water' + Ti1 = i1.calc_T(T0=i1.T.val_SI) + To2 = o2.calc_T(T0=o2.T.val_SI) + + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) + + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + Q = self.kA.val * self.td_log.val + + if self.is_variable(i1.m): + self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) + if fluid in i1.fluid.is_var: + self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + + if self.is_variable(o1.m): + self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) + if fluid in o1.fluid.is_var: + self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + + # i = self.inl[1] + # o = self.outl[2] + # if self.is_variable(i.m): + # self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI + # if self.is_variable(i.h): + # self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) + # if self.is_variable(i.p): + # self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) + # if self.is_variable(o.h): + # self.jacobian[k, o.h.J_col] = i.m.val_SI + # c = self.outl[1] + # if self.is_variable(c.p): + # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) + # if self.is_variable(c.h): + # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) + + + def WBeff_func(self): + r""" + Calculate the vector of residual values for fluid balance equations. + """ + i1 = self.inl[1] + Ti1 = i1.calc_T(T0=i1.T.val_SI) + o1 = self.inl[1] + To1 = o1.calc_T(T0=o1.T.val_SI) + + i2 = self.inl[1] + Ti2 = i2.calc_T(T0=i2.T.val_SI) + T_wb = get_Twb(i2,Ti2) + o2 = self.outl[1] + To2 = o2.calc_T(T0=o2.T.val_SI) + + return (Ti2-To2) - (Ti2-T_wb)*self.WBeff.val + + def WBeff_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives of fluid balance. + """ + + # let's just do numerical derivative of them all + i1 = self.inl[0] + i2 = self.inl[1] + o1 = self.outl[0] # liquid + o2 = self.outl[1] # vapor + + for c in [i1,i2,o1,o2]: + if self.is_variable(c.m): #, increment_filter): + self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.WBeff_func, 'm', c) + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) def calc_parameters(self): super().calc_parameters() @@ -1620,47 +1712,43 @@ def calc_parameters(self): o1 = self.outl[0] # liquid o2 = self.outl[1] # vapor - Q_prod = o1.m.val_SI * (o2.h.val_SI - i1.h.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] - Q_prod_w = m_evap * (o2.h.val_SI - i1.h.val_SI) - Q_e = m_evap * (o2.h.val_SI - i1.h.val_SI) - Q_air = i1.m.val_SI * i1.h.val_SI - i2.m.val_SI - i2.h.val_SI - - - Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state)) - - m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - Q_air = + m_air * (o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) - -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,i2.T.val_SI,force_state=i2.force_state)) - - fluid = 'Water' - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) - - self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + # m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] + # Q_air = + m_air * (o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,i2.T.val_SI,force_state=i2.force_state)) + if not self.Q.is_set: + fluid = 'Water' + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) + self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + if not self.KPI.is_set: + fluid = 'Water' + ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) + self.KPI.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) / (i1.m.val_SI*i1.fluid.val['Water']) - print(Q_air) + hmin = min([o.h.val_SI for o in self.outl]) + hmax = max([o.h.val_SI for o in self.outl]) + if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): + self.deltaH.val = i.h.val_SI - hmin + else: + self.deltaH.val = i.h.val_SI - hmax - # if not self.Q.is_set: - # self.Q.val = - self.inl[1].m.val_SI * (self.outl[1].h.val_SI - self.inl[1].h.val_SI) # np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - # if not self.KPI.is_set: - # self.KPI.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) / (self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']) + Thot_in = i2.T.val_SI + Thot_out = o2.T.val_SI + Tcold = get_Twb(i2,Thot_in) + if not self.kA.is_set: + ttd_u = Thot_in - Tcold + ttd_l = Thot_out - Tcold + if ttd_u < 0 or ttd_l < 0: + self.td_log.val = np.nan + elif ttd_l == ttd_u: + self.td_log.val = ttd_l + else: + self.td_log.val = ((ttd_l - ttd_u) / np.log(ttd_l / ttd_u)) + self.kA.val = self.Q.val / self.td_log.val - # hmin = min([o.h.val_SI for o in self.outl]) - # hmax = max([o.h.val_SI for o in self.outl]) - # if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): - # self.deltaH.val = i.h.val_SI - hmin - # else: - # self.deltaH.val = i.h.val_SI - hmax - - # if not self.kA.is_set: - # Tcold = self.outl[0].T.val_SI # vapor out - # #Thot = self.outl[2].T.val_SI - # Thot = self.inl[1].calc_T_sat() # liquid out - # self.td.val = (Thot-Tcold) - # if Thot == Tcold: - # self.kA.val = np.NaN - # else: - # self.kA.val = -self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI)/self.td.val + if not self.WBeff.is_set: + self.WBeff.val = (Thot_in-Thot_out)/(Thot_in-Tcold) + if self.WBeff.val > 1.0: + TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") \ No newline at end of file From c9aee1aa65ca4019c038e25bbbf22f75a7dbaf05 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 5 Dec 2023 12:58:17 +0100 Subject: [PATCH 068/105] switched vapor and liquid to be consistent --- ...plitWithDeltaH-drierWithAir_newApproach.py | 97 +------ ...SplitWithDeltaTDeltaP-evaporatorWithHot.py | 20 +- src/tespy/components/newAdvancedComponents.py | 244 +++++++++--------- 3 files changed, 146 insertions(+), 215 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py index 29163b34d..5ea6cecc8 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py @@ -31,8 +31,8 @@ si2 = Sink("Sink 2") c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") +c2 = Connection(se, "out1", si1, "in1", label="2") # vapor +c3 = Connection(se, "out2", si2, "in1", label="3") # liquid c4 = Connection(soAir, "out1", se, "in2", label="4") nw.add_conns(c1, c2, c3, c4) @@ -44,13 +44,13 @@ c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") -c2.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) -c3.set_attr(fluid={"INCOMP::T66": 0}) +c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) +c2.set_attr(fluid={"INCOMP::T66": 0}) -#c2.set_attr(p=1.2,T=60,force_state='g') -c2.set_attr(p=1.0) +#c3.set_attr(p=1.2,T=60,force_state='g') c3.set_attr(p=1.0) +c2.set_attr(p=1.0) se.set_attr(deltaH=0) @@ -62,8 +62,8 @@ se.set_attr(deltaH=None) -c3.set_attr(p=1.0,T=None,force_state='g') -c2.set_attr(p=1.0,T=None,force_state='l') +c2.set_attr(p=1.0,T=None,force_state='g') +c3.set_attr(p=1.0,T=None,force_state='l') se.set_attr(dTwbProd=0) nw.solve("design") if not nw.converged: @@ -72,7 +72,7 @@ print(nw.results['Connection']) -c2.set_attr(fluid={"HEOS::Water": None}) +c3.set_attr(fluid={"HEOS::Water": None}) se.set_attr(Q=se.Q.val) se.set_attr(Q=1e6) @@ -83,7 +83,7 @@ print(nw.results['Connection']) -c2.set_attr(fluid={"HEOS::Water": None}) +c3.set_attr(fluid={"HEOS::Water": None}) se.set_attr(Q=None) se.set_attr(KPI=2.250e6) @@ -94,7 +94,7 @@ print(nw.results['Connection']) -c2.set_attr(fluid={"HEOS::Water": None}) +c3.set_attr(fluid={"HEOS::Water": None}) se.set_attr(Q=None) se.set_attr(KPI=None) se.set_attr(kA=6.0e+04) @@ -105,7 +105,7 @@ nw.print_results() print(nw.results['Connection']) -c2.set_attr(fluid={"HEOS::Water": None}) +c3.set_attr(fluid={"HEOS::Water": None}) se.set_attr(Q=None) se.set_attr(KPI=None) se.set_attr(kA=None) @@ -119,76 +119,3 @@ - - -import sys -sys.exit() - - -#se.set_attr(deltaH=0) -#se.set_attr(dfluid=0) - -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() -# print(nw.results['Connection']) - -c2.set_attr(p=1.0,T=30,force_state='g') -c3.set_attr(p=1.0,T=30,force_state='l') - - -se.set_attr(dTwbProd=0) -se.set_attr(dfluid=0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c2.set_attr(p=1.0,T=None,force_state='g') -c3.set_attr(p=1.0,T=None,force_state='l') -se.set_attr(dTwbProd=0) -se.set_attr(dfluid=0) -#se.set_attr(eb=0) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - -c3.set_attr(fluid={"INCOMP::Water": None}) -se.set_attr(KPI=0.85) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -se.set_attr(KPI=None) -#c3.set_attr(fluid={"INCOMP::Water": 0.08}) -#c4.set_attr(m=None) -se.set_attr(WBeff=0.6) -#c2.set_attr(T=40) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(WBeff=None) -se.set_attr(kA=4.6e4) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py index eb10e3685..90014891a 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py @@ -32,11 +32,11 @@ si3 = Sink("Sink 3") c1 = Connection(so1, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") +c2 = Connection(se, "out1", si1, "in1", label="2") # vapor +c3 = Connection(se, "out2", si2, "in1", label="3") # liquid c4 = Connection(so2, "out1", se, "in2", label="4") -c5 = Connection(se, "out3", si3, "in1", label="5") +c5 = Connection(se, "out3", si3, "in1", label="5") # condensate nw.add_conns(c1, c2, c3, c4, c5) @@ -51,8 +51,8 @@ # set some generic data for starting values c1.set_attr(m=m0, p=p0, T=80, fluid={'HEOS::Water': 0.942, "INCOMP::FoodFat": 0.004, "INCOMP::FoodProtein": 0.054}, mixing_rule="incompressible") -c2.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) -c3.set_attr(x=1, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) +c2.set_attr(x=1, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) +c3.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) # Now it is possible to set the temperatures out of the separator differently c4.set_attr(m=25, p=p0, x=1, fluid={'HEOS::Water': 1.0}, mixing_rule="incompressible") @@ -64,7 +64,7 @@ nw.print_results() print(nw.results['Connection']) -c2.set_attr(fluid={"INCOMP::FoodProtein": None}) +c3.set_attr(fluid={"INCOMP::FoodProtein": None}) c5.set_attr(p=p0,x=0) nw.solve("design") if not nw.converged: @@ -105,9 +105,9 @@ se.set_attr(KPI=None) se.set_attr(kA=7e5) se.set_attr(dTo=0) -c2.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) -c2.set_attr(T=None) +c3.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) c3.set_attr(T=None) +c2.set_attr(T=None) nw.solve("design") if not nw.converged: @@ -119,9 +119,9 @@ # mass balance mode -c2.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) -c2.set_attr(p=p0, x=None, T=None, force_state=None) +c3.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) c3.set_attr(p=p0, x=None, T=None, force_state=None) +c2.set_attr(p=p0, x=None, T=None, force_state=None) c5.set_attr(x=None, force_state=None) se.set_attr(Q=None) diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index 6af7986fd..8aa98d50b 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -703,8 +703,10 @@ def __init__(self, label, **kwargs): super().__init__(label, **kwargs) def outlets(self): - return ['out1', 'out2', 'out3'] - + return ['out1', # vapor + 'out2', # liquid + 'out3'] # steam condensate + def inlets(self): return ['in1', 'in2'] @@ -1058,7 +1060,7 @@ def kA_func(self): Calculate heat transfer from heat transfer coefficient. """ - Tcold = self.outl[1].calc_T(T0=self.outl[0].T.val_SI) # vapor out + Tcold = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) # vapor out #Thot = self.outl[2].calc_T(T0=self.outl[2].T.val_SI) Thot = self.inl[1].calc_T_sat() # liquid out self.td.val = (Thot-Tcold) @@ -1082,7 +1084,7 @@ def kA_deriv(self, increment_filter, k): self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) if self.is_variable(o.h): self.jacobian[k, o.h.J_col] = i.m.val_SI - c = self.outl[1] + c = self.outl[0] if self.is_variable(c.p): self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) if self.is_variable(c.h): @@ -1123,7 +1125,8 @@ def __init__(self, label, **kwargs): super().__init__(label, **kwargs) def outlets(self): - return ['out1', 'out2'] + return ['out1', # vapor + 'out2'] # liquid def inlets(self): return ['in1', 'in2'] @@ -1168,6 +1171,7 @@ def get_parameters(self): latex=self.pr_func_doc, num_eq=1, ) + variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) return variables def get_mandatory_constraints(self): @@ -1272,13 +1276,13 @@ def mass_flow_func(self): """ i1 = self.inl[0] i2 = self.inl[1] # air - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] residuals = [] - residuals += [i1.m.val_SI - o1.m.val_SI - m_evap] - residuals += [i2.m.val_SI - o2.m.val_SI + m_evap] + residuals += [i1.m.val_SI - o2.m.val_SI - m_evap] + residuals += [i2.m.val_SI - o1.m.val_SI + m_evap] return residuals @@ -1288,34 +1292,34 @@ def mass_flow_deriv(self, k): """ i1 = self.inl[0] i2 = self.inl[1] # air - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid fluid = 'Water' if i1.m.is_var: self.jacobian[k, i1.m.J_col] = 1 - i1.fluid.val[fluid] - if o1.m.is_var: - self.jacobian[k, o1.m.J_col] = -1 + o1.fluid.val[fluid] + if o2.m.is_var: + self.jacobian[k, o2.m.J_col] = -1 + o2.fluid.val[fluid] if fluid in i1.fluid.is_var: self.jacobian[k, i1.fluid.J_col[fluid]] = - i1.m.val_SI - if fluid in o1.fluid.is_var: - self.jacobian[k, o1.fluid.J_col[fluid]] = + o1.m.val_SI + if fluid in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col[fluid]] = + o2.m.val_SI k = k + 1 if i2.m.is_var: self.jacobian[k, i2.m.J_col] = 1 - if o2.m.is_var: - self.jacobian[k, o2.m.J_col] = -1 + if o1.m.is_var: + self.jacobian[k, o1.m.J_col] = -1 if i1.m.is_var: self.jacobian[k, i1.m.J_col] = + i1.fluid.val[fluid] - if o1.m.is_var: - self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] + if o2.m.is_var: + self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] if fluid in i1.fluid.is_var: self.jacobian[k, i1.fluid.J_col[fluid]] = + i1.m.val_SI - if fluid in o1.fluid.is_var: - self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI + if fluid in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI def energy_balance_deltaH_func(self): r""" @@ -1324,7 +1328,7 @@ def energy_balance_deltaH_func(self): """ i = self.inl[0] residual = [] - for o in [self.outl[0]]: # ,self.outl[1]]: # let energy balance solve the other + for o in [self.outl[1]]: # liquid -- let energy balance solve the other residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] return residual @@ -1333,7 +1337,7 @@ def energy_balance_deltaH_deriv(self, increment_filter, k): Calculate partial derivatives of energy balance. """ i = self.inl[0] - for o in [self.outl[0]]: # ,self.outl[1]]: # let energy balance solve the other + for o in [self.outl[1]]: # liquid -- let energy balance solve the other if self.is_variable(i.h): self.jacobian[k, i.h.J_col] = 1 if self.is_variable(o.h): @@ -1346,11 +1350,11 @@ def energy_balance_func(self): """ i1 = self.inl[0] i2 = self.inl[1] # air - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid return i1.m.val_SI * i1.h.val_SI + i2.m.val_SI * i2.h.val_SI \ - - o1.m.val_SI * o1.h.val_SI - o2.m.val_SI * o2.h.val_SI + - o2.m.val_SI * o2.h.val_SI - o1.m.val_SI * o1.h.val_SI def energy_balance_deriv(self, increment_filter, k): r""" @@ -1358,15 +1362,15 @@ def energy_balance_deriv(self, increment_filter, k): """ i1 = self.inl[0] i2 = self.inl[1] # air - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid for i in [i1,i2]: if self.is_variable(i.m): self.jacobian[k, i.m.J_col] = i.h.val_SI if self.is_variable(i.h): self.jacobian[k, i.h.J_col] = i.m.val_SI - for o in [o1,o2]: + for o in [o2,o1]: if self.is_variable(o.m): self.jacobian[k, o.m.J_col] = -o.h.val_SI if self.is_variable(o.h): @@ -1380,7 +1384,7 @@ def dTwbProd_func(self): i = self.inl[1] T_in = i.calc_T(T0=i.T.val_SI) T_wb = get_Twb(i,T_in) - o = self.outl[0] + o = self.outl[1] # liquid T_out = o.calc_T(T0=o.T.val_SI) return T_out - T_wb - self.dTwbProd.val @@ -1394,7 +1398,7 @@ def dTwbProd_deriv(self, increment_filter, k): # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) # T_wb is nonlinear and we cannot differentiate easily - for c in [self.inl[1],self.outl[0]]: + for c in [self.inl[1],self.outl[1]]: # in and liquid if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) if self.is_variable(c.h): #, increment_filter): @@ -1407,28 +1411,28 @@ def energy_balance_hot_func(self): """ i1 = self.inl[0] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid Ti1 = i1.calc_T(T0=i1.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] - Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + To1 = o1.calc_T(T0=o1.T.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) return (Q_evap - self.Q.val)/(self.Q.val+1e-6) # i1 = self.inl[0] # i2 = self.inl[1] # air - # o1 = self.outl[0] # liquid - # o2 = self.outl[1] # vapor + # o1 = self.outl[0] # vapor + # o2 = self.outl[1] # liquid # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To2 = o2.calc_T(T0=o2.T.val_SI) + # To1 = o1.calc_T(T0=o1.T.val_SI) # m_air = i2.m.val_SI*i2.fluid.val['Air'] # Q_air = m_air * (i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) - # -o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state)) + # -o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state)) # return (Q_air - self.Q.val)/self.Q.val @@ -1439,38 +1443,38 @@ def energy_balance_hot_deriv(self, increment_filter, k): # i1 = self.inl[0] # i2 = self.inl[1] # air - # o1 = self.outl[0] # liquid - # o2 = self.outl[1] # vapor + # o1 = self.outl[0] # vapor + # o2 = self.outl[1] # liquid # fluid = 'Air' # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To2 = o2.calc_T(T0=o2.T.val_SI) + # To1 = o1.calc_T(T0=o1.T.val_SI) # hi2 = i2.fluid_data[fluid]['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) - # ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + # ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - # # Q_air = i2.m.val_SI*i2.fluid.val['Air'] * (hi2 - ho2) + # # Q_air = i2.m.val_SI*i2.fluid.val['Air'] * (hi2 - ho1) # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = i2.fluid.val[fluid] * (hi2 - ho2) + # self.jacobian[k, i2.m.J_col] = i2.fluid.val[fluid] * (hi2 - ho1) # if fluid in i2.fluid.is_var: - # self.jacobian[k, i2.fluid.J_col[fluid]] = i2.m.val_SI * (hi2 - ho2) + # self.jacobian[k, i2.fluid.J_col[fluid]] = i2.m.val_SI * (hi2 - ho1) - # for c in [i2,o2]: + # for c in [i2,o1]: # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # for c in [i2,o2]: + # for c in [i2,o1]: # if fluid in c.fluid.is_var: # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) # # let's just do numerical derivative of them all # i1 = self.inl[0] # i2 = self.inl[1] - # o1 = self.outl[0] # liquid - # o2 = self.outl[1] # vapor + # o1 = self.outl[0] # vapor + # o2 = self.outl[1] # liquid - # for c in [i1,i2,o1,o2]: + # for c in [i1,i2,o2,o1]: # if self.is_variable(c.m): #, increment_filter): # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end @@ -1483,36 +1487,36 @@ def energy_balance_hot_deriv(self, increment_filter, k): i1 = self.inl[0] i2 = self.inl[1] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid fluid = 'Water' Ti1 = i1.calc_T(T0=i1.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/(self.Q.val+1e-6) + self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho1 - hi1)/(self.Q.val+1e-6) if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/(self.Q.val+1e-6) + self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho1 - hi1)/(self.Q.val+1e-6) - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(self.Q.val+1e-6) - if fluid in o1.fluid.is_var: - self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(self.Q.val+1e-6) + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(self.Q.val+1e-6) + if fluid in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(self.Q.val+1e-6) - # for c in [i1,i2,o1,o2]: + # for c in [i1,i2,o2,o1]: # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) # if self.is_variable(c.m): #, increment_filter): # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) - # #for c in [i1,o1,o2]: + # #for c in [i1,o2,o1]: # for fluid in self.variable_fluids: # if fluid in c.fluid.is_var: # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) @@ -1524,13 +1528,13 @@ def KPI_func(self): """ i1 = self.inl[0] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid Ti1 = i1.calc_T(T0=i1.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] - Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + To1 = o1.calc_T(T0=o1.T.val_SI) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val @@ -1543,34 +1547,30 @@ def KPI_deriv(self, increment_filter, k): i1 = self.inl[0] i2 = self.inl[1] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid fluid = 'Water' Ti1 = i1.calc_T(T0=i1.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = (i1.fluid.val[fluid] - i1.m.val_SI*self.KPI.val) * (ho2 - hi1)/(Q+1e-6) + self.jacobian[k, i1.m.J_col] = (i1.fluid.val[fluid] - i1.m.val_SI*self.KPI.val) * (ho1 - hi1)/(Q+1e-6) if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = (i1.m.val_SI - i1.fluid.val['Water']*self.KPI.val) * (ho2 - hi1)/(Q+1e-6) + self.jacobian[k, i1.fluid.J_col[fluid]] = (i1.m.val_SI - i1.fluid.val['Water']*self.KPI.val) * (ho1 - hi1)/(Q+1e-6) - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) - if fluid in o1.fluid.is_var: - self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) + if fluid in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(Q+1e-6) def calculate_td_log(self,T_i,T_wb,T_o): - # 1 is with air - i1 = self.inl[1] - o1 = self.outl[0] - # temperature value manipulation for convergence stability T_i1 = T_i T_o1 = T_o @@ -1602,17 +1602,17 @@ def kA_func(self): """ i1 = self.inl[0] i2 = self.inl[1] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid Ti2 = i2.calc_T(T0=i2.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) Twb = get_Twb(i2,Ti2) - self.td_log.val = self.calculate_td_log(Ti2,Twb,To2) + self.td_log.val = self.calculate_td_log(Ti2,Twb,To1) Ti1 = i1.calc_T(T0=i1.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o1.m.val_SI*o1.fluid.val['Water'] - Q_evap = m_evap * (o2.fluid_data['Water']['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] + Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) Q = self.kA.val * self.td_log.val @@ -1624,28 +1624,28 @@ def kA_deriv(self, increment_filter, k): """ i1 = self.inl[0] i2 = self.inl[1] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid fluid = 'Water' Ti1 = i1.calc_T(T0=i1.T.val_SI) - To2 = o2.calc_T(T0=o2.T.val_SI) + To1 = o1.calc_T(T0=o1.T.val_SI) - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,To2,force_state=o2.force_state) + ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) Q = self.kA.val * self.td_log.val if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) + self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho1 - hi1)/(Q+1e-6) - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = - o1.fluid.val[fluid] * (ho2 - hi1)/(Q+1e-6) - if fluid in o1.fluid.is_var: - self.jacobian[k, o1.fluid.J_col[fluid]] = - o1.m.val_SI * (ho2 - hi1)/(Q+1e-6) + if self.is_variable(o2.m): + self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) + if fluid in o2.fluid.is_var: + self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(Q+1e-6) # i = self.inl[1] # o = self.outl[2] @@ -1668,15 +1668,10 @@ def WBeff_func(self): r""" Calculate the vector of residual values for fluid balance equations. """ - i1 = self.inl[1] - Ti1 = i1.calc_T(T0=i1.T.val_SI) - o1 = self.inl[1] - To1 = o1.calc_T(T0=o1.T.val_SI) - i2 = self.inl[1] Ti2 = i2.calc_T(T0=i2.T.val_SI) T_wb = get_Twb(i2,Ti2) - o2 = self.outl[1] + o2 = self.outl[0] # vapor To2 = o2.calc_T(T0=o2.T.val_SI) return (Ti2-To2) - (Ti2-T_wb)*self.WBeff.val @@ -1689,8 +1684,8 @@ def WBeff_deriv(self, increment_filter, k): # let's just do numerical derivative of them all i1 = self.inl[0] i2 = self.inl[1] - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid for c in [i1,i2,o1,o2]: if self.is_variable(c.m): #, increment_filter): @@ -1709,23 +1704,23 @@ def calc_parameters(self): i1 = self.inl[0] i2 = self.inl[1] # air - o1 = self.outl[0] # liquid - o2 = self.outl[1] # vapor + o1 = self.outl[0] # vapor + o2 = self.outl[1] # liquid # m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - # Q_air = + m_air * (o2.fluid_data['Air']['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + # Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,i2.T.val_SI,force_state=i2.force_state)) if not self.Q.is_set: fluid = 'Water' - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) - self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) + self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) if not self.KPI.is_set: fluid = 'Water' - ho2 = o2.fluid_data[fluid]['wrapper'].h_pT(o2.p.val_SI,o2.T.val_SI,force_state=o2.force_state) + ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) - self.KPI.val = (i1.m.val_SI*i1.fluid.val[fluid] - o1.m.val_SI*o1.fluid.val[fluid]) * (ho2 - hi1) / (i1.m.val_SI*i1.fluid.val['Water']) + self.KPI.val = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) / (i1.m.val_SI*i1.fluid.val['Water']) hmin = min([o.h.val_SI for o in self.outl]) hmax = max([o.h.val_SI for o in self.outl]) @@ -1735,7 +1730,7 @@ def calc_parameters(self): self.deltaH.val = i.h.val_SI - hmax Thot_in = i2.T.val_SI - Thot_out = o2.T.val_SI + Thot_out = o1.T.val_SI Tcold = get_Twb(i2,Thot_in) if not self.kA.is_set: ttd_u = Thot_in - Tcold @@ -1751,4 +1746,13 @@ def calc_parameters(self): if not self.WBeff.is_set: self.WBeff.val = (Thot_in-Thot_out)/(Thot_in-Tcold) if self.WBeff.val > 1.0: - TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") \ No newline at end of file + TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") + + M_o = o1.fluid.val["Water"] + W_o = M_o/(1-M_o) + Wmax = HAPropsSI('W','P',o1.p.val_SI,'T',o1.T.val_SI,'R',1) + if self.WBeff.val > 1.0 or W_o > Wmax: + self.RH.val = W_o/Wmax*100 + TESPyComponentError("Relative humidity cannot be greater than 100 %, try increase air mass flow") + else: + self.RH.val = 100 * HAPropsSI('R','P',o1.p.val_SI,'T',o1.T.val_SI,'W',W_o) \ No newline at end of file From 1000b48fb38a95e928106cb3ecf176a48a90844b Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 5 Dec 2023 14:30:13 +0100 Subject: [PATCH 069/105] Let's save guesses from one calculation to another --- src/tespy/components/newAdvancedComponents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index 8aa98d50b..0a83a9c9c 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -1751,7 +1751,7 @@ def calc_parameters(self): M_o = o1.fluid.val["Water"] W_o = M_o/(1-M_o) Wmax = HAPropsSI('W','P',o1.p.val_SI,'T',o1.T.val_SI,'R',1) - if self.WBeff.val > 1.0 or W_o > Wmax: + if W_o > Wmax: self.RH.val = W_o/Wmax*100 TESPyComponentError("Relative humidity cannot be greater than 100 %, try increase air mass flow") else: From 94ecca7150d620474c82c23485f07181df292744 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 11:04:35 +0100 Subject: [PATCH 070/105] removing coolprop submodule --- .gitmodules | 3 - externals/CoolProp | 1 - poetry.lock | 1774 ++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 1 + 4 files changed, 1775 insertions(+), 4 deletions(-) delete mode 160000 externals/CoolProp create mode 100644 poetry.lock diff --git a/.gitmodules b/.gitmodules index e10b5a8ba..e69de29bb 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "externals/CoolProp"] - path = externals/CoolProp - url = git@github.com:IPUdk/CoolProp.git diff --git a/externals/CoolProp b/externals/CoolProp deleted file mode 160000 index cc87fa1da..000000000 --- a/externals/CoolProp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit cc87fa1dabd85cd571c949360634bde63ce04ac3 diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 000000000..1c7136e08 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,1774 @@ +# This file is automatically @generated by Poetry and should not be changed by hand. + +[[package]] +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, +] + +[[package]] +name = "asttokens" +version = "2.4.1" +description = "Annotate AST trees with source code positions" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + +[[package]] +name = "certifi" +version = "2023.11.17" +description = "Python package for providing Mozilla's CA Bundle." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, +] + +[[package]] +name = "cffi" +version = "1.16.0" +description = "Foreign Function Interface for Python calling C code." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, + {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, + {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, + {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, + {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, + {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, + {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, + {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, + {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, + {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, + {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, + {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, + {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, + {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, + {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, + {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, + {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, + {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, + {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, + {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, + {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, + {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, + {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, + {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, + {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, + {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +category = "dev" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +category = "dev" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "comm" +version = "0.2.0" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"}, + {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "contourpy" +version = "1.2.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "coolprop" +version = "6.6.0" +description = "Open-source thermodynamic and transport properties database" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "CoolProp-6.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e628b334548f5eaf7d7508b673d3a1bcf61c8691c0d020057eb0c9f842e8b702"}, + {file = "CoolProp-6.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8245dd194a8f0946d03f6d0bd62e143c7cb3dbf0c10c49879a888cb275e8038f"}, + {file = "CoolProp-6.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f79733ae173f095670d94d7faf2ecbbea21da76775c803fc3332e0ed22e2ef66"}, + {file = "CoolProp-6.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e401b2e7fa3fd03dcfdd3e2d8c782656d359031a51add7ebe4c5545a0b098a"}, + {file = "CoolProp-6.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d23642e904377984b6d6bacb428890bb89bd8a78a0496b8559b698ca2e001f23"}, + {file = "CoolProp-6.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d32580510054c4ba5c14d9dc0eeda77b5c0dc263b0cc153de7dff9b9de77e28b"}, + {file = "CoolProp-6.6.0-cp310-cp310-win32.whl", hash = "sha256:1febe6ebdb340635bf6c1bb58678fe7edb93c9698e605c3975e1c4749646ee34"}, + {file = "CoolProp-6.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:0bb213ea8d9f509ae0d4c0009dffbda2f52f370eac3b4576c974188f1cd3ced1"}, + {file = "CoolProp-6.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cfe23e785e27ac4d12e0b13708a8bdc087caee8133fa0840509efaaf1ad311ba"}, + {file = "CoolProp-6.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f374a948bc42babdf644f912958c79effa8ccc4f3f461a0f822715dcdf819c6b"}, + {file = "CoolProp-6.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b43e70dfd9825a4de138ce76365978e24532711fb2f4781dacf2b92b96985ed"}, + {file = "CoolProp-6.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c46edd2dad3b99402ad2bff227a53182e0aba954847cac12686e78abd37ae1d"}, + {file = "CoolProp-6.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b83370f50f85cf80ad6c010175b99d6ed7485e647ab70ca85772fecebdcfce86"}, + {file = "CoolProp-6.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9bf37b539640e787250075e9042590f89bf83a1859c62d1695d2269d95fe7cff"}, + {file = "CoolProp-6.6.0-cp311-cp311-win32.whl", hash = "sha256:7b72406779cb17b4197d8bfbb90601f60a5ebb44b8c0c5882e8353021163783a"}, + {file = "CoolProp-6.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:b22c30a23603ce3df88a18a445fad14f93fd9757720f43d3b8041549e93c4b93"}, + {file = "CoolProp-6.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2f738c22f4c81d7bc91567fe101502c5106cefc98a9afe884be72cf6908b3b7f"}, + {file = "CoolProp-6.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e2ef2de94f51ec8f095fe772cdb22593245feeb7df76d3616eb19c5da1d4ac7f"}, + {file = "CoolProp-6.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f3de22cfbdb31e9a2f19aefb8074c25c57abba7ba6302eb331694e7bcc4b11"}, + {file = "CoolProp-6.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f3339c3d590d2c86f9f2c055b9423001653344958000b8dcf7655710a5adee"}, + {file = "CoolProp-6.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c556df424dcf93ce2e4b41f1f52537b94050ddf595df67eb7a76a1dd0d92263e"}, + {file = "CoolProp-6.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:75dd59ea068a6385977815b0572dd824f8cb932a97432737392e3aba11782210"}, + {file = "CoolProp-6.6.0-cp312-cp312-win32.whl", hash = "sha256:bfc5729c00376c00b33538d4685f4243ea43e69d618f2edd31729003a0fb1440"}, + {file = "CoolProp-6.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:809a8572515009a42386ce7381f7d11fd5c785657637cb402f722edf266a6fb3"}, + {file = "CoolProp-6.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c11811e6730dda4c69fc3765e57697ee9390d9266fc7d0e3a40bfc841783b6c"}, + {file = "CoolProp-6.6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:addd2a7ae804e5bce85bdd3747fbea6c654fdb10b88212845b894c936a5162c9"}, + {file = "CoolProp-6.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c573ea9ebaffd85613322e8d8e1574268a4e12eca685742afbf5487cf3e37"}, + {file = "CoolProp-6.6.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:483babcc2cf2b3ce7761b3e8639e49700ff73828270956937b4e99451ad04476"}, + {file = "CoolProp-6.6.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:936bc62c1b33d6322b1b589f824284552e5654abc2c86d91313a952fca378fc9"}, + {file = "CoolProp-6.6.0-cp36-cp36m-win32.whl", hash = "sha256:efd4ec19f566aee8b119b2f9c6c91969e131baef0e2315fb1d66bd4b56edc1d5"}, + {file = "CoolProp-6.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:19cf50201ec36037ef402749bf67bd47eb6f68809c61ce4259d6703898876355"}, + {file = "CoolProp-6.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:60ff433382c801a8d473be57903adbd9957549adff189598ad65e8040626218b"}, + {file = "CoolProp-6.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57b7e46d3d60962afe2deec068b042e4257e579b2a0d710202d2c2b2186eb2b3"}, + {file = "CoolProp-6.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1f4fe22c62fbc269d1aeee705a7dec23066a683b5615789020974504b76a520"}, + {file = "CoolProp-6.6.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c80fec6127bf9e18174609a4f117ec591e47a04e87e31f271e7d6e2daa4a81b7"}, + {file = "CoolProp-6.6.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e40acd6124d217881717fdd3218ef57d832cd010b22f40637d0f2330fdd0c330"}, + {file = "CoolProp-6.6.0-cp37-cp37m-win32.whl", hash = "sha256:8ba5530b8ca15d0715f86b397e0dc5b1dcc993bcc59175c5e54e27a9bbf4842e"}, + {file = "CoolProp-6.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:60ff22a0969dd6a163ef29fd62f62c72e00bfc80731f4c10b2c89e409a294de9"}, + {file = "CoolProp-6.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7b79982edf62364a4c710ef6804a6b2946696bd95a789e2616dcee741a80f7b1"}, + {file = "CoolProp-6.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9c081df57cda0e156e78c40fde9d83fd3f1aa262ed74dc70a2ea8fdb816ac70"}, + {file = "CoolProp-6.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15f781be1e761002e95d3de3ac7a02a8ed81adbaa9915ec9942a0575c2cde15d"}, + {file = "CoolProp-6.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a1117d8229a8d612a3a9ca18a3d994bc2e134de52bf9efb05530219ae19339"}, + {file = "CoolProp-6.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fbe7d8ec427e30a0e95716a77406da4fd7d1299e84f00cca228fa2f7a5ae4ec6"}, + {file = "CoolProp-6.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96065c6c3f17b9b9eeec9620369ffab3047de747c2967db9598f20b56d0cdf2c"}, + {file = "CoolProp-6.6.0-cp38-cp38-win32.whl", hash = "sha256:d02d8ddf1e7af355a334323cc649a391b8c457993631665242d700875b6f7887"}, + {file = "CoolProp-6.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:10b4fd508dc85e2045cf02f5a8ba55c6c5ac9d4ebefbe7940dbc33fe4b392127"}, + {file = "CoolProp-6.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:647102f943d449294e67a89c6f23cf8e59c3763880cc2c7642de21dca2c53631"}, + {file = "CoolProp-6.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b0df572addaf43679f986d76a3cdbe4d4cbd6f4ffe89f1d63be3bd8be38c9212"}, + {file = "CoolProp-6.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c41db6c9172d0ae79e2b3b74aab0e63edeabab999c9dd6a3ca8a0df63f8bfc0"}, + {file = "CoolProp-6.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a994a909a8950170e55a5dce831e2b7b5b6f7cb66a3b49f1afdb04e43b35f42"}, + {file = "CoolProp-6.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:09437ff654af822caf8c904bb2882844a1d7ddffa19c9c9c4c3ef9e9a0f50be1"}, + {file = "CoolProp-6.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9aa70af252e973f8e1e87cd6ab41b94aa4d563906c57b41c170a9d3cae854797"}, + {file = "CoolProp-6.6.0-cp39-cp39-win32.whl", hash = "sha256:dff965f4e44d3af623a02c8bd55f9887daf21990a3f3f1f4bfc46e462106b9fd"}, + {file = "CoolProp-6.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb0ace860286cf2f9346e98a07bc8fc4ca55cf17ee0b1972a5b72a8bfb2716ac"}, + {file = "CoolProp-6.6.0.tar.gz", hash = "sha256:cf6fad704b3ae00f4df309cfd1e2ee48d155886b569a73f2cc38a57eda463082"}, +] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "cython" +version = "0.29.36" +description = "The Cython compiler for writing C extensions for the Python language." +category = "dev" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "Cython-0.29.36-py2.py3-none-any.whl", hash = "sha256:95bb13d8be507425d03ebe051f90d4b2a9fdccc64e4f30b35645fdb7542742eb"}, + {file = "Cython-0.29.36.tar.gz", hash = "sha256:41c0cfd2d754e383c9eeb95effc9aa4ab847d0c9747077ddd7c0dcb68c3bc01f"}, +] + +[[package]] +name = "debugpy" +version = "1.8.0" +description = "An implementation of the Debug Adapter Protocol for Python" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, + {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, + {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, + {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, + {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, + {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, + {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, + {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, + {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, + {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, + {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, + {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, + {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, + {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, + {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, + {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, + {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, + {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "executing" +version = "2.0.1" +description = "Get the currently executing AST node of a frame, and other information" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, + {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "fonttools" +version = "4.46.0" +description = "Tools to manipulate font files" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276"}, + {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd"}, + {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af"}, + {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e"}, + {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517"}, + {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844"}, + {file = "fonttools-4.46.0-cp310-cp310-win32.whl", hash = "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205"}, + {file = "fonttools-4.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4"}, + {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6"}, + {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c"}, + {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34"}, + {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5"}, + {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204"}, + {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be"}, + {file = "fonttools-4.46.0-cp311-cp311-win32.whl", hash = "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2"}, + {file = "fonttools-4.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646"}, + {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62"}, + {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b"}, + {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da"}, + {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11"}, + {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b"}, + {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752"}, + {file = "fonttools-4.46.0-cp312-cp312-win32.whl", hash = "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720"}, + {file = "fonttools-4.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114"}, + {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b"}, + {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63"}, + {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122"}, + {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041"}, + {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570"}, + {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3"}, + {file = "fonttools-4.46.0-cp38-cp38-win32.whl", hash = "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5"}, + {file = "fonttools-4.46.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42"}, + {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8"}, + {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd"}, + {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6"}, + {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933"}, + {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c"}, + {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228"}, + {file = "fonttools-4.46.0-cp39-cp39-win32.whl", hash = "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254"}, + {file = "fonttools-4.46.0-cp39-cp39-win_amd64.whl", hash = "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214"}, + {file = "fonttools-4.46.0-py3-none-any.whl", hash = "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4"}, + {file = "fonttools-4.46.0.tar.gz", hash = "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "importlib-metadata" +version = "7.0.0" +description = "Read metadata from Python packages" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, + {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.1.1" +description = "Read resources from Python packages" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] + +[[package]] +name = "ipykernel" +version = "6.27.1" +description = "IPython Kernel for Jupyter" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.27.1-py3-none-any.whl", hash = "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686"}, + {file = "ipykernel-6.27.1.tar.gz", hash = "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=20" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "8.18.1" +description = "IPython: Productive Interactive Computing" +category = "dev" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] + +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "jupyter-client" +version = "8.6.0" +description = "Jupyter protocol implementation and client libraries" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.6.0-py3-none-any.whl", hash = "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99"}, + {file = "jupyter_client-8.6.0.tar.gz", hash = "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.5.0" +description = "Jupyter core package. A base package on which Jupyter projects rely." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"}, + {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "matplotlib" +version = "3.8.2" +description = "Python plotting package" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, + {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, + {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, + {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, + {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, + {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, + {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, + {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, + {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, + {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, + {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, + {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, + {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, + {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, + {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, + {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, + {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, + {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, + {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[[package]] +name = "matplotlib-inline" +version = "0.1.6" +description = "Inline Matplotlib backend for Jupyter" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, + {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "nest-asyncio" +version = "1.5.8" +description = "Patch asyncio to allow nested event loops" +category = "dev" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"}, + {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, +] + +[[package]] +name = "numpy" +version = "1.26.2" +description = "Fundamental package for array computing in Python" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"}, + {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"}, + {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"}, + {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"}, + {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"}, + {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"}, + {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"}, + {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"}, + {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"}, + {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"}, + {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"}, + {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"}, + {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"}, + {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"}, + {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"}, + {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"}, + {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"}, + {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"}, + {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"}, + {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"}, + {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"}, + {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"}, + {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"}, + {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"}, + {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"}, + {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"}, + {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"}, + {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"}, + {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"}, + {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"}, + {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"}, + {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"}, + {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"}, + {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pandas" +version = "2.1.3" +description = "Powerful data structures for data analysis, time series, and statistics" +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f"}, + {file = "pandas-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb"}, + {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb"}, + {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4"}, + {file = "pandas-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03"}, + {file = "pandas-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e"}, + {file = "pandas-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82"}, + {file = "pandas-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042"}, + {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef"}, + {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58"}, + {file = "pandas-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2"}, + {file = "pandas-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f"}, + {file = "pandas-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140"}, + {file = "pandas-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d"}, + {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e"}, + {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683"}, + {file = "pandas-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00"}, + {file = "pandas-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549"}, + {file = "pandas-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8"}, + {file = "pandas-2.1.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d"}, + {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a"}, + {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2"}, + {file = "pandas-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a"}, + {file = "pandas-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71"}, + {file = "pandas-2.1.3.tar.gz", hash = "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] +aws = ["s3fs (>=2022.05.0)"] +clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"] +compression = ["zstandard (>=0.17.0)"] +computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2022.05.0)"] +gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"] +hdf5 = ["tables (>=3.7.0)"] +html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"] +mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"] +spss = ["pyreadstat (>=1.1.5)"] +sql-other = ["SQLAlchemy (>=1.4.36)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.8.0)"] + +[[package]] +name = "parso" +version = "0.8.3" +description = "A Python Parser" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, + {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, +] + +[package.extras] +qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] +testing = ["docopt", "pytest (<6.0.0)"] + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pillow" +version = "10.1.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"}, + {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"}, + {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"}, + {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"}, + {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"}, + {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"}, + {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"}, + {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "platformdirs" +version = "4.1.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.41" +description = "Library for building powerful interactive command lines in Python" +category = "dev" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, + {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "5.9.6" +description = "Cross-platform lib for process and system monitoring in Python." +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, + {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, + {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, + {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, + {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, + {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, + {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, + {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, + {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, + {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.2" +description = "Safely evaluate AST nodes without side effects" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, + {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pycparser" +version = "2.21" +description = "C parser in Python" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, +] + +[[package]] +name = "pygments" +version = "2.17.2" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, +] + +[package.extras] +plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyparsing" +version = "3.1.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +category = "main" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pytz" +version = "2023.3.post1" +description = "World timezone definitions, modern and historical" +category = "main" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "pyzmq" +version = "25.1.2" +description = "Python bindings for 0MQ" +category = "dev" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4"}, + {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d"}, + {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979"}, + {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08"}, + {file = "pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886"}, + {file = "pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c"}, + {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840"}, + {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b"}, + {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3"}, + {file = "pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097"}, + {file = "pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a"}, + {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee"}, + {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe"}, + {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737"}, + {file = "pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d"}, + {file = "pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0"}, + {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a"}, + {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win32.whl", hash = "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc"}, + {file = "pyzmq-25.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68"}, + {file = "pyzmq-25.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003"}, + {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec"}, + {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win32.whl", hash = "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7"}, + {file = "pyzmq-25.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41"}, + {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7"}, + {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f"}, + {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755"}, + {file = "pyzmq-25.1.2-cp38-cp38-win32.whl", hash = "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07"}, + {file = "pyzmq-25.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6"}, + {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add"}, + {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6"}, + {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2"}, + {file = "pyzmq-25.1.2-cp39-cp39-win32.whl", hash = "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289"}, + {file = "pyzmq-25.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4"}, + {file = "pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96"}, + {file = "pyzmq-25.1.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611"}, + {file = "pyzmq-25.1.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc"}, + {file = "pyzmq-25.1.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314"}, + {file = "pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "setuptools" +version = "67.8.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, + {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "tabulate" +version = "0.9.0" +description = "Pretty-print tabular data" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, + {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, +] + +[package.extras] +widechars = ["wcwidth"] + +[[package]] +name = "tornado" +version = "6.4" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +category = "dev" +optional = false +python-versions = ">= 3.8" +files = [ + {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, + {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, + {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, + {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, + {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, + {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, + {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, +] + +[[package]] +name = "traitlets" +version = "5.14.0" +description = "Traitlets Python configuration system" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"}, + {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +category = "main" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "urllib3" +version = "2.1.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.12" +description = "Measures the displayed width of unicode strings in a terminal" +category = "dev" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, + {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, +] + +[[package]] +name = "wheel" +version = "0.40.0" +description = "A built-package format for Python" +category = "dev" +optional = false +python-versions = ">=3.7" +files = [ + {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"}, + {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)"] + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9" +content-hash = "dd70d1f72e5bb26d5bc836e3ebc8adb1001dcc907d1e8f89a307cf7dd3ca176c" diff --git a/pyproject.toml b/pyproject.toml index 558aa0138..81a92eca0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,6 +11,7 @@ numpy = "^1.25.1" matplotlib = "^3.7.2" pandas = "^2.0.3" tabulate = "^0.9.0" +coolprop = "^6.6.0" [tool.poetry.group.coolprop.dependencies] cython = "^0.29.35" From 8bbb1894d2b8a6d901f8509f926b9ed2b0321856 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 11:14:47 +0100 Subject: [PATCH 071/105] adding plotly and fluprodia --- src/tespy/tools/fluid_properties/wrappers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 857d2bdb3..56c98846f 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -163,7 +163,7 @@ def _check_imposed_state(self,p,T,**kwargs): else: self.AS.update(CP.QT_INPUTS, 0, T) else: - if (kwargs['force_state'] == "l") and not (T > self.AS.T_critical()): + if (kwargs.get('force_state',False) == "l") and not (T > self.AS.T_critical()): self.AS.update(CP.QT_INPUTS, 0, T) if p > self.AS.p(): try: @@ -171,7 +171,7 @@ def _check_imposed_state(self,p,T,**kwargs): except: #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) - elif kwargs['force_state'] == "g" and not (T > self.AS.T_critical()): + elif kwargs.get('force_state',False) == "g" and not (T > self.AS.T_critical()): self.AS.update(CP.QT_INPUTS, 1, T) if p < self.AS.p(): try: From 23e56e7c62ff11310682be09a579be4efee061c9 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 20:07:08 +0100 Subject: [PATCH 072/105] sankey diagram sk --- incompressiblesTests/Ex9.py | 229 ++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) diff --git a/incompressiblesTests/Ex9.py b/incompressiblesTests/Ex9.py index 4d3327714..d74b1ba1c 100644 --- a/incompressiblesTests/Ex9.py +++ b/incompressiblesTests/Ex9.py @@ -140,3 +140,232 @@ print(f"Total heat for boiler is {boiler.Q.val/(3.6*1e6):.1f}") print(f"Total heat for presswater heater is {presswaterheater.Q.val/(3.6*1e6):.1f}") + + +def get_paths(self): + def generate_paths(start, current_comp_path, current_conn_path): + # If the component is not in the connections, append the current path, we are finished + if start not in comp_connections: + comps_paths.append(current_comp_path) + conns_paths.append(current_conn_path) + return + # Iterate through the connected lists + for comp_list,conn_list in zip(comp_connections[start],conn_connections[start]): + # Recursively generate paths + generate_paths(comp_list[-1], current_comp_path + comp_list[1:], current_conn_path + conn_list) + + # make lists of component and connection branches + comp_branches = [b['components'] for b in self.nw.massflow_branches] + conn_branches = [b['connections'] for b in self.nw.massflow_branches] + + # make connections dict to iterate over + comp_connections = {} + conn_connections = {} + for comps,conns in zip(comp_branches,conn_branches): + if comps[0] not in comp_connections: + comp_connections[comps[0]] = [] + conn_connections[comps[0]] = [] + comp_connections[comps[0]].append(comps) + conn_connections[comps[0]].append(conns) + + # get sources to start from and iterate for each uniquie path + sources = [k for k in comp_connections.keys() if type(k).__name__ == "Source"] + comps_paths = [] + conns_paths = [] + for start in sources: + generate_paths(start, [start], []) + + paths = {} + paths['connections'] = sorted(conns_paths, key=len, reverse=True) + paths['components'] = sorted(comps_paths, key=len, reverse=True) + + return paths + +class SELF(): + pass + +self = SELF() +self.nw = network + +paths = get_paths(self) + +print(paths['components']) + +longest_path_components = max(paths['components'], key=len) +longest_path_components_label = [l.label for l in longest_path_components] + +path = {} +path["T"] = [] +path["source"] = [] +path["source_id"] = [] +path["target"] = [] +for conns in paths['connections']: + T = [] + source = [] + source_id = [] + target = [] + for c in conns: + T += [c.T.val] + source += [c.source.label] + source_id += [longest_path_components_label.index(c.source.label)] + target += [c.target.label] + path["T"].append(T) + path["source"].append(source) + path["source_id"].append(source_id) + + path["target"].append(target) + +longest_path_components_label + + +import matplotlib.pyplot as plt + +plt.figure() +for s,T in zip(path["source_id"],path["T"]): + #x = np.array([i for i,_ in enumerate(T)]) + #y = np.array(T) + x = [longest_path_components_label[i] for i in s] + plt.plot(x, T) + +plt.xlabel('X-axis') +plt.ylabel('Y-axis') +plt.legend() +plt.show() + + +print(x) + +print(x) +print(x) +print(x) + +import sys +sys.exit() + + + + +sankey_nodes = [] +for name,comp in self.nw.comps.iterrows(): + sankey_nodes += [name] + +#missing = [value for value in sankey_nodes if not value in longest_path_components_label] +#sankey_nodes = longest_path_components_label + missing + + +links = { + 'source': [], + 'target': [], + 'value': [], + #'color': [] +} + + +for i,c in self.nw.conns.iterrows(): + links["source"] += [sankey_nodes.index(c.source.label)] + links["target"] += [sankey_nodes.index(c.target.label)] + links["value"] += [c['object'].m.val_SI] + #links["color"] + #print(c) + +from plotly.offline import plot +import plotly.graph_objects as go +import plotly as px + + + +fig = go.Figure(go.Sankey( + #arrangement="snap", + node = dict( + pad = 100, + thickness = 20, + line = dict(color = "grey", width = 0.5), + label = sankey_nodes, + color = "blue" + ), + # node={ + # "label": sankey_nodes, + # 'pad': 10, + # 'thickness': 10, + # 'color': 'orange'}, + link=links)) +plot(fig, filename='R410A_sankey.html') + + +print("hey") + + +# "----------------------------------------------------------------------------------" +# "----------------------------------------------------------------------------------" +# "----------------------------------------------------------------------------------" +# "----------------------------------------------------------------------------------" + + + + +sankey_nodes = [] +for name,comp in self.nw.comps.iterrows(): + sankey_nodes += [name] + +#missing = [value for value in sankey_nodes if not value in longest_path_components_label] +#sankey_nodes = longest_path_components_label + missing + +links = { + 'source': [], + 'target': [], + 'value': [], + 'color': [] +} + +#colors = px.colors.DEFAULT_PLOTLY_COLORS +colors = ["rgba(242, 142, 43, 0.75)", + "rgba(118, 183, 178, 0.75)", + "rgba(176, 122, 161, 0.75)", + "rgba(156, 117, 95, 0.75)", + "rgba(237, 201, 72, 0.75)", + "rgba(186, 176, 172, 0.75)", + "rgba(89, 161, 79, 0.75)", + "rgba(255, 157, 167, 0.75)", + "rgba(78, 121, 167, 0.75)", + "rgba(225, 87, 89, 0.75)", + "rgba(100, 100, 100, 1.00)"] + +for fluid in self.nw.all_fluids: + + for i,c in self.nw.conns.iterrows(): + links["source"] += [sankey_nodes.index(c.source.label)] + links["target"] += [sankey_nodes.index(c.target.label)] + links["value"] += [c['object'].m.val_SI * c['object'].fluid.val[fluid]] + links["color"] += [colors[list(self.nw.all_fluids).index(fluid)]] + #links["color"] + #print(c) + +from plotly.offline import plot +import plotly.graph_objects as go + +fig = go.Figure(go.Sankey( + #arrangement="snap", + node = dict( + pad = 200, + thickness = 10, + #line = dict(color = "grey", width = 0.5), + label = sankey_nodes, + color = "grey" + ), + # node={ + # "label": sankey_nodes, + # 'pad': 10, + # 'thickness': 10, + # 'color': 'orange'}, + link=links)) +plot(fig, filename='R410A_sankey.html') + + +print("hey") + + + + + + + From 08d5349e32fb59d060ac80d1bac02733c3fa4a03 Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Fri, 8 Dec 2023 15:04:12 +0100 Subject: [PATCH 073/105] fix newComponents file name --- src/tespy/components/{newcomponents.py => newComponents.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/tespy/components/{newcomponents.py => newComponents.py} (100%) diff --git a/src/tespy/components/newcomponents.py b/src/tespy/components/newComponents.py similarity index 100% rename from src/tespy/components/newcomponents.py rename to src/tespy/components/newComponents.py From 04bc1b59218dcc836a46f1838ae764025a4b73b9 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 8 Dec 2023 22:29:47 +0100 Subject: [PATCH 074/105] 3 different results tables --- incompressiblesTests/Ex9.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/incompressiblesTests/Ex9.py b/incompressiblesTests/Ex9.py index d74b1ba1c..e09896fd8 100644 --- a/incompressiblesTests/Ex9.py +++ b/incompressiblesTests/Ex9.py @@ -233,14 +233,7 @@ class SELF(): plt.show() -print(x) -print(x) -print(x) -print(x) - -import sys -sys.exit() From 640a77b7ffd147b19638fe027dc79019ebac0410 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 13:11:54 +0100 Subject: [PATCH 075/105] handling units in components - the quick way .. --- .../newComponentsTests/heatex_alone_deltaP.py | 7 +++ src/tespy/networks/network.py | 44 +++++++++++++++++++ src/tespy/tools/data_containers.py | 11 ++++- src/tespy/tools/global_vars.py | 12 +++++ src/tespy/tools/helpers.py | 13 +++++- 5 files changed, 84 insertions(+), 3 deletions(-) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py index 7ca48eb97..e16b1a5ec 100644 --- a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py +++ b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py @@ -20,6 +20,8 @@ # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) +nw.set_attr(Q_unit='kW') + so = Source("Source") # Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system # boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta @@ -58,6 +60,11 @@ raise Exception("not converged") nw.print_results() + +c2.set_attr(T=None) #,p=1) +he.set_attr(Q=2e2) + + nw.solve("design") if not nw.converged: raise Exception("not converged") diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 913dfd684..5ffad2278 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -37,6 +37,8 @@ from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.global_vars import ERR from tespy.tools.global_vars import fluid_property_data as fpd +from tespy.tools.global_vars import component_property_data as cpd + # Only require cupy if Cuda shall be used try: @@ -215,6 +217,10 @@ def set_defaults(self): # standard unit set self.__dict__.update({prop + '_unit': data['SI_unit']}) msg += data['text'] + ': ' + data['SI_unit'] + '\n' + for prop, data in cpd.items(): + # standard unit set + self.__dict__.update({prop + '_unit': data['SI_unit']}) + msg += data['text'] + ': ' + data['SI_unit'] + '\n' # don't need the last newline logger.debug(msg[:-1]) @@ -273,6 +279,10 @@ def set_attr(self, **kwargs): vol_unit : str Specify the unit for specific volume: 'm3 / kg', 'l / kg'. + + Q_unit : str + Specify the unit for heat flow rate: 'W', 'kW', 'MW'. + """ # unit sets for prop in fpd.keys(): @@ -291,6 +301,24 @@ def set_attr(self, **kwargs): fpd[prop]['text'] + ' are: ' + keys) logger.error(msg) raise ValueError(msg) + + for prop in cpd.keys(): + unit = prop + '_unit' + if unit in kwargs: + if kwargs[unit] in cpd[prop]['units']: + self.__dict__.update({unit: kwargs[unit]}) + msg = ( + 'Setting ' + cpd[prop]['text'] + + ' unit: ' + kwargs[unit] + '.') + logger.debug(msg) + else: + keys = ', '.join(cpd[prop]['units'].keys()) + msg = ( + 'Allowed units for ' + + cpd[prop]['text'] + ' are: ' + keys) + logger.error(msg) + raise ValueError(msg) + for prop in ['m', 'p', 'h']: if prop + '_range' in kwargs: @@ -1229,6 +1257,16 @@ def init_design(self): respective :code:`design_path`. In this case, the design values are unset, the offdesign values set. """ + for c in self.comps['object']: + print(c) + for prop in cpd.keys(): + if c.parameters.get(prop,False): + c.parameters[prop].unit = self.get_attr(prop + '_unit') + if c.parameters[prop].is_set: + # we simply overwrite to begin with.. because all model do not use val_SI + c.parameters[prop].val = hlp.convert_comp_to_SI(prop, c.parameters[prop].val, c.parameters[prop].unit) + # we then convert back again upon solution + # connections self._conn_variables = [] _local_designs = {} @@ -2574,6 +2612,12 @@ def process_components(self): cp.calc_parameters() cp.check_parameter_bounds() + for prop in cpd.keys(): + if cp.parameters.get(prop,False): + # we simply overwrite to begin with.. because all model do not use val_SI + cp.parameters[prop].val_SI = cp.parameters[prop].val # delete this when proper use of val_SI is done + cp.parameters[prop].val = hlp.convert_comp_from_SI(prop, cp.parameters[prop].val, cp.parameters[prop].unit) + key = cp.__class__.__name__ for param in self.results[key].columns: p = cp.get_attr(param) diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index 0a7a70e11..fc878d5f0 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -293,6 +293,13 @@ class ComponentProperties(DataContainer): max_val : float Maximum value for this attribute, used if attribute is part of the system variables, default: max_val=1e12. + + unit : str + Unit for this property, default: ref=None. + + unit : boolean + Has the unit for this property been specified manually by the user? + default: unit_set=False. """ @staticmethod @@ -307,7 +314,7 @@ def attr(): values. """ return { - 'val': 1, 'val_SI': 0, 'is_set': False, 'd': 1e-4, + 'val': 1, 'val_SI': 0, 'is_set': False, 'd': 1e-4, 'unit': None, 'min_val': -1e12, 'max_val': 1e12, 'is_var': False, 'design': np.nan, 'is_result': False, 'num_eq': 0, 'func_params': {}, 'func': None, 'deriv': None, @@ -321,7 +328,7 @@ def serialize(self): @staticmethod def _serializable_keys(): return [ - "val", "val_SI", "is_set", "d", "min_val", "max_val", "is_var", + "val", "val_SI", "is_set", "d", "min_val", "max_val", "is_var", "unit" ] diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index 37a9273e5..c55991351 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -15,6 +15,18 @@ gas_constants = {} gas_constants['uni'] = 8.314462618 +component_property_data = OrderedDict({ + 'Q': { + 'text': 'heat flow', + 'SI_unit': 'W', + 'units': { + 'W': 1, 'kW': 1000, 'MW': 1e6 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + } + }) + fluid_property_data = OrderedDict({ 'm': { 'text': 'mass flow', diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index 102d94ae4..3a170b8a5 100644 --- a/src/tespy/tools/helpers.py +++ b/src/tespy/tools/helpers.py @@ -21,7 +21,7 @@ from tespy import __datapath__ from tespy.tools import logger from tespy.tools.global_vars import ERR -from tespy.tools.global_vars import fluid_property_data +from tespy.tools.global_vars import fluid_property_data, component_property_data from tespy.tools.global_vars import molar_masses @@ -145,6 +145,17 @@ def convert_to_SI(property, value, unit): else: return value * fluid_property_data[property]['units'][unit] +def convert_comp_to_SI(property, value, unit): + r""" + Convert a value to its SI value. + """ + return value * component_property_data[property]['units'][unit] + +def convert_comp_from_SI(property, value, unit): + r""" + Convert a value to its SI value. + """ + return value / component_property_data[property]['units'][unit] def convert_from_SI(property, SI_value, unit): r""" From 09b2f7f9223b24f5c7df20b121b374a049abe180 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 14:05:19 +0100 Subject: [PATCH 076/105] deleting deprecated model --- src/tespy/components/newAdvancedComponents.py | 669 ------------------ 1 file changed, 669 deletions(-) diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py index 0a83a9c9c..a0bdb1622 100644 --- a/src/tespy/components/newAdvancedComponents.py +++ b/src/tespy/components/newAdvancedComponents.py @@ -27,675 +27,6 @@ def get_Twb(port,T): return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) -class DrierWithAir(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - self.num_out = 2 # default - self.num_in = 2 # default - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - if key == 'num_in': - self.num_in=kwargs[key] - super().__init__(label, **kwargs) - - @staticmethod - def component(): - return 'separator with species flow splits and dT on outlets' - - @staticmethod - def inlets(): - return ['in1'] - - def inlets(self): - if self.num_in.is_set: - return ['in' + str(i + 1) for i in range(self.num_in.val)] - else: - self.set_attr(num_in=2) - return self.inlets() - - def get_parameters(self): - variables = super().get_parameters() - variables["num_in"] = dc_simple() - variables["dTwbProd"] = dc_cp( - deriv=self.dTwbProd_deriv, - func=self.dTwbProd_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["WBeff"] = dc_cp( - min_val=0,max_val=1, - deriv=self.WBeff_deriv, - func=self.WBeff_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables['kA'] = dc_cp( - min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, - deriv=self.kA_deriv) - variables['td_log'] = dc_cp(min_val=0, is_result=True) - variables['ttd_u'] = dc_cp(min_val=0, is_result=True) - variables['ttd_l'] = dc_cp(min_val=0, is_result=True) - variables['m_evap'] = dc_cp(min_val=0, is_result=True) - variables['Q_evap'] = dc_cp(min_val=0, is_result=True) - variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) - variables["dWo"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dWo_deriv, - func=self.dWo_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["dWo2"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dWo2_deriv, - func=self.dWo2_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["dfluid"] = dc_cp( - min_val = 0, max_val=1, - deriv=self.dfluid_deriv, - func=self.dfluid_func, - latex=self.pr_func_doc, - num_eq=1, - ) - # variables['eb'] = dc_cp( - # min_val = 0, max_val=1, - # deriv=self.energy_balance_deriv, - # func=self.energy_balance_func, - # latex=self.pr_func_doc, - # num_eq=1, - # ) - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=1 - ) - return variables - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in [self.outl[1]]: - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual[0] - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in [self.outl[1]]: - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - constraints['energy_balance_constraints'] = { - 'func': self.energy_balance_func, - 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - return constraints - - def fluid_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - #i = self.inl[0] - residual = [] - for fluid in self.variable_fluids: - res = 0 - for i in self.inl: - res += i.fluid.val[fluid] * i.m.val_SI - for o in self.outl: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - - # # additional balance equation for calculating water vapor mass fraction - # i = self.inl[1] - # o = self.outl[0] - # # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - # residual += [o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI] - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # residual += [i2.m.val_SI + m_evap - o1.m.val_SI] - return residual - - def fluid_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - #i = self.inl[0] - for fluid in self.variable_fluids: - for o in self.outl: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - - for i in self.inl: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - - k += 1 - - # i = self.inl[1] - # o = self.outl[0] - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - # if fluid in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - # if fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = 1 - - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # if 'Water' in o2.fluid.is_var: - # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # if 'Water' in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = -1 - - - def dfluid_func(self): - # additional balance equation for calculating water vapor mass fraction - i = self.inl[1] - o = self.outl[0] - # known imposition of water and air flows, mean we calculate o.fluid.val['Water'] by - return o.m.val_SI - i.m.val_SI*i.fluid.val['Air'] - o.fluid.val['Water'] * o.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - # m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - # return i2.m.val_SI + m_evap - o1.m.val_SI - self.dfluid.val - - def dfluid_deriv(self, increment_filter, k): - - i = self.inl[1] - o = self.outl[0] - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = 1 - o.fluid.val['Water'] - if 'Water' in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Water']] = - o.m.val_SI - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = -i.fluid.val['Air'] - if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI - - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] - # o2 = self.outl[1] - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = 1 - - # if self.is_variable(o2.m): - # self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] - # if 'Water' in o2.fluid.is_var: - # self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI - - # if self.is_variable(i1.m): - # self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] - # if 'Water' in i1.fluid.is_var: - # self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = -1 - - def dTwbProd_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[1] - T_out = o.calc_T(T0=o.T.val_SI) - return T_out - T_wb - self.dTwbProd.val - - def dTwbProd_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for c in [self.inl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # T_wb is nonlinear and we cannot differentiate easily - for c in [self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - - def dWo_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i2 = self.inl[1] - o1 = self.outl[0] - T_i = i2.calc_T(T0=i2.T.val_SI) - T_o = o1.calc_T(T0=o1.T.val_SI) - - M_i = i2.fluid.val["Water"] - W_i = M_i/(1-M_i) - I_i = HAPropsSI('H','P',i2.p.val_SI,'T',T_i,'W',W_i) - - T_wb = get_Twb(i2,T_i) - W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) - I_wb = HAPropsSI('H','P',i2.p.val_SI,'T',T_wb,'R',1) - - M_o = o1.fluid.val["Water"] - W_o = M_o/(1-M_o) - - #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - I_o = I_i - (T_i-T_o)/(T_i-T_wb)*(I_i-I_wb) - W_o_calc = HAPropsSI('W','P',i2.p.val_SI,'H',I_o,'T',T_o) - - #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - #W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - return W_o_calc - W_o - self.dWo.val - - - - def dWo_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - i2 = self.inl[1] - o1 = self.outl[0] - for c in [i2, o1]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dWo_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dWo_func, 'h', c) - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.dWo_func, 'm', c, i2=i2, o1=o1) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dWo_func, fluid, c) - - def dWo2_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - Ti2 = i2.calc_T(T0=i2.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - #To2 = o2.calc_T(T0=o2.T.val_SI) - - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - return Q_evap + Q_air - self.dWo2.val - - - def dWo2_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - Ti2 = i2.calc_T(T0=i2.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - - dh_w = (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - dh_a = (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state)) - - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = - o2.fluid.val['Water'] * dh_w - if 'Water' in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col['Water']] = - o2.m.val_SI * dh_w - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val['Water'] * dh_w - if 'Water' in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col['Water']] = i1.m.val_SI * dh_w - - # if self.is_variable(o1.m): - # self.jacobian[k, o1.m.J_col] = o1.fluid.val['Air'] * dh_a - # if 'Air' in o1.fluid.is_var: - # self.jacobian[k, o1.fluid.J_col['Air']] = o1.m.val_SI * dh_a - - if self.is_variable(i2.m): - self.jacobian[k, i2.m.J_col] = i2.fluid.val['Air'] * dh_a - if 'Air' in i2.fluid.is_var: - self.jacobian[k, i2.fluid.J_col['Air']] = i2.m.val_SI * dh_a - - - - - def res2(self,i2,o1): - T_i = i2.calc_T(T0=i2.T.val_SI) - T_o = o1.calc_T(T0=o1.T.val_SI) - T_wb = get_Twb(i2,T_i) - W_wb = HAPropsSI('W','P',i2.p.val_SI,'T',T_wb,'R',1) - - M_i = i2.fluid.val["Water"] - W_i = M_i/(1-M_i) - M_o = o1.fluid.val["Water"] - W_o = M_o/(1-M_o) - - #T_o_linear = T_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - W_o_calc = W_i - (T_i-T_o)/(T_i-T_wb)*(W_i-W_wb) - return W_o_calc - W_o - - def energy_balance_func(self): - r""" - Need overwrite this function to take into account air inlet - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - # res = [] - # res += [o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI] - # res += [self.res2(i2,o1)] - # return res - return o1.m.val_SI * o1.h.val_SI + o2.m.val_SI * o2.h.val_SI - i1.m.val_SI * i1.h.val_SI - i2.m.val_SI * i2.h.val_SI - - def energy_balance_deriv(self, increment_filter, k): - r""" - Need overwrite this function to take into account air inlet - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] - o2 = self.outl[1] - - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = -i1.h.val_SI - if self.is_variable(i2.m): - self.jacobian[k, i2.m.J_col] = -i2.h.val_SI - if self.is_variable(i1.h): - self.jacobian[k, i1.h.J_col] = -i1.m.val_SI - if self.is_variable(i2.h): - self.jacobian[k, i2.h.J_col] = -i2.m.val_SI - - # k = k + 1 - - # for c in [i2, o1]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.res2, 'p', c, i2=i2, o1=o1) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.res2, 'h', c, i2=i2, o1=o1) - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.res2, 'm', c, i2=i2, o1=o1) - - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.res2, fluid, c, i2=i2, o1=o1) - - def WBeff_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[0] - T_out = o.calc_T(T0=o.T.val_SI) - #print ((T_in-T_out) - (T_in-T_wb)*self.WBeff.val) - return (T_in-T_out) - (T_in-T_wb)*self.WBeff.val - - def WBeff_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for c in [self.inl[1], self.outl[0]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) - - def KPI_func(self): - r""" - how much water is dried - """ - o = self.outl[0] - m_evap = o.m.val_SI*o.fluid.val['Water'] - return m_evap - self.KPI.val - - def KPI_deriv(self, increment_filter, k): - o = self.outl[0] - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = o.fluid.val['Water'] - if 'Water' in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col['Water']] = o.m.val_SI - - def calculate_td_log(self,T_i,T_wb,T_o): - # 1 is with air - i1 = self.inl[1] - o1 = self.outl[0] - - # temperature value manipulation for convergence stability - T_i1 = T_i - T_o1 = T_o - T_i2 = T_wb - T_o2 = T_wb - - if T_i1 <= T_o2: - T_i1 = T_o2 + 0.01 - if T_i1 <= T_o2: - T_o2 = T_i1 - 0.01 - if T_i1 <= T_o2: - T_o1 = T_i2 + 0.02 - if T_o1 <= T_i2: - T_i2 = T_o1 - 0.02 - - ttd_u = T_i1 - T_o2 - ttd_l = T_o1 - T_i2 - - if ttd_u == ttd_l: - td_log = ttd_l - else: - td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) - - return td_log - - def kA_func(self): - r""" - Calculate heat transfer from heat transfer coefficient. - """ - i = self.inl[1] - o = self.outl[0] - T_i = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_i) - T_o = o.calc_T(T0=o.T.val_SI) - - m_air = i.m.val_SI*i.fluid.val['Air'] - Q_air = - m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - return Q_air - self.kA.val * self.calculate_td_log(T_i,T_wb,T_o) - - def kA_deriv(self, increment_filter, k): - r""" - Partial derivatives of heat transfer coefficient function. - """ - i = self.inl[1] - o = self.outl[0] - T_i = i.calc_T(T0=i.T.val_SI) - #T_wb = get_Twb(i,T_i) - T_o = o.calc_T(T0=o.T.val_SI) - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = - i.fluid.val['Air']*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - if 'Air' in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col['Air']] = - i.m.val_SI*(o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,T_o,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,T_i,force_state='g')) - for c in self.inl + self.outl: - if self.is_variable(c.p): - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - if self.is_variable(c.h): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) - - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.kA_func, fluid, c) - - def calc_parameters(self): - super().calc_parameters() - - i = self.inl[0] - o = self.outl[0] - self.m_evap.val = o.m.val_SI*o.fluid.val['Water'] - self.Q_evap.val = self.m_evap.val * (o.fluid_data['Water']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state=o.force_state) - -i.fluid_data['Water']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state=i.force_state)) - - i = self.inl[1] - o = self.outl[0] - m_air = i.m.val_SI*i.fluid.val['Air'] - Q_air = m_air * (o.fluid_data['Air']['wrapper'].h_pT(o.p.val_SI,o.T.val_SI,force_state='g') - -i.fluid_data['Air']['wrapper'].h_pT(i.p.val_SI,i.T.val_SI,force_state='g')) - - if not self.Q.is_set: - self.Q.val = (self.outl[0].m.val_SI * self.outl[0].h.val_SI + - self.outl[1].m.val_SI * self.outl[1].h.val_SI - - self.inl[0].m.val_SI * self.inl[0].h.val_SI - - self.inl[1].m.val_SI * self.inl[1].h.val_SI) - if not self.KPI.is_set: - self.KPI.val = self.m_evap.val - - if self.outl[1].fluid.val['Air'] > 0: - TESPyComponentError("Air cannot go into out2") - - T_in = self.inl[1].T.val_SI - T_out = self.outl[0].T.val_SI - T_wb = self.outl[1].T.val_SI # get_Twb(self.inl[1],T_in) - - if not self.WBeff.is_set: - self.WBeff.val = (T_in-T_out)/(T_in-T_wb) - if self.WBeff.val > 1.0: - TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") - - - self.ttd_u.val = T_in - T_wb - self.ttd_l.val = T_out - T_wb - - if not self.kA.is_set: - # kA and logarithmic temperature difference - if self.ttd_u.val < 0 or self.ttd_l.val < 0: - self.td_log.val = np.nan - elif self.ttd_l.val == self.ttd_u.val: - self.td_log.val = self.ttd_l.val - else: - self.td_log.val = ((self.ttd_l.val - self.ttd_u.val) / - np.log(self.ttd_l.val / self.ttd_u.val)) - self.kA.val = -Q_air / self.td_log.val - - port_i = self.inl[1] - # M_i = port_i.fluid.val["Water"] - # W_i = M_i/(1-M_i) - # I_i = HAPropsSI('H','P',port_i.p.val_SI,'T',port_i.T.val_SI,'W',W_i) - port_o = self.outl[0] - M_o = port_o.fluid.val["Water"] - W_o = M_o/(1-M_o) - # I_o = HAPropsSI('H','P',port_o.p.val_SI,'T',port_o.T.val_SI,'W',W_o) - - # I_wb = HAPropsSI('H','P',port_o.p.val_SI,'T',T_wb,'R',1) - # W_wb = HAPropsSI('W','P',port_o.p.val_SI,'T',T_wb,'R',1) - # T_o = T_in - (T_in-T_wb)/(W_i-W_wb)*(W_i-W_o) - - # T_o_2 = HAPropsSI('T','P',port_o.p.val_SI,'H',I_i,'W',W_o) - - # print(int(I_i),int(I_o)) - # print(int(T_o),int(T_o_2)) - - # print("hey") - - Wmax = HAPropsSI('W','P',port_i.p.val_SI,'T',port_o.T.val_SI,'R',1) - if self.WBeff.val > 1.0 or W_o > Wmax: - self.RH.val = 100 - else: - self.RH.val = 100 * HAPropsSI('R','P',port_i.p.val_SI,'T',port_o.T.val_SI,'W',W_o) - - - - - - - - - - - - class TwoStreamEvaporator(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): From 19afc7571939dadb1c1f014f56f944d4fa9c73e1 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 14:05:36 +0100 Subject: [PATCH 077/105] adding more variables for component units --- src/tespy/tools/global_vars.py | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index c55991351..cc25f30e2 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -20,13 +20,42 @@ 'text': 'heat flow', 'SI_unit': 'W', 'units': { - 'W': 1, 'kW': 1000, 'MW': 1e6 + 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} - } + }, + 'Q_loss': { + 'text': 'heat flow', + 'SI_unit': 'W', + 'units': { + 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + }, + 'Q_total': { + 'text': 'heat flow', + 'SI_unit': 'W', + 'units': { + 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + }, + 'kA': { + 'text': 'heat flow', + 'SI_unit': 'W / K', + 'units': { + 'W / K': 1, 'kW / K': 1000, 'MW / K': 1e6, 'GW / K': 1e9, 'TW / K': 1e12 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + } + }) + fluid_property_data = OrderedDict({ 'm': { 'text': 'mass flow', From 6d6cb8979e920b06ea040f6ce1c16dd610cf127e Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 09:43:44 +0100 Subject: [PATCH 078/105] more units for components --- src/tespy/networks/network_reader.py | 1 - src/tespy/tools/global_vars.py | 25 ++++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 9fbe3b599..6bcbf75ab 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -92,7 +92,6 @@ 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, 'SimpleHeatExchangerDeltaPLfKpi' : SimpleHeatExchangerDeltaPLfKpi, - 'DrierWithAir' : DrierWithAir, } ENGINE_TARGET_CLASSES = { diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index cc25f30e2..d5b0eb99a 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -44,14 +44,33 @@ #'documentation': {'float_fmt': '{:,.3f}'} }, 'kA': { - 'text': 'heat flow', + 'text': 'heat transfer conductance', 'SI_unit': 'W / K', 'units': { 'W / K': 1, 'kW / K': 1000, 'MW / K': 1e6, 'GW / K': 1e9, 'TW / K': 1e12 }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} - } + }, + 'KPI': { + 'text': 'KPI scaling with Q', + 'SI_unit': 'Wx', + 'units': { + 'Wx': 1, 'kWx': 1000, 'MWx': 1e6, 'GWx': 1e9, 'TWx': 1e12 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + }, + 'SF': { + 'text': 'species split is a mass flow', + 'SI_unit': 'kg / s', + 'units': { + 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / 3600*24*365 + }, + #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', + #'documentation': {'float_fmt': '{:,.3f}'} + } }) @@ -62,7 +81,7 @@ 'SI_unit': 'kg / s', 'units': { 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, - 't / h': 1 / 3.6, 'g / s': 1 / 1e3 + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / 3600*24*365 }, 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', 'documentation': {'float_fmt': '{:,.3f}'} From 41fea622420c79803e7a39909fa6c1d6b7e75fd8 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 17:29:56 +0100 Subject: [PATCH 079/105] goofy unit --- src/tespy/tools/global_vars.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index d5b0eb99a..ed677daf9 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -66,7 +66,7 @@ 'SI_unit': 'kg / s', 'units': { 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, - 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / 3600*24*365 + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365) }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} @@ -81,7 +81,7 @@ 'SI_unit': 'kg / s', 'units': { 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, - 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / 3600*24*365 + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365) }, 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', 'documentation': {'float_fmt': '{:,.3f}'} From 2c29210813c858a81e2cecaa4917f161b438daa1 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 22:50:13 +0100 Subject: [PATCH 080/105] units --- src/tespy/tools/global_vars.py | 50 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index ed677daf9..52606d914 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -20,25 +20,17 @@ 'text': 'heat flow', 'SI_unit': 'W', 'units': { - 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 - }, - #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', - #'documentation': {'float_fmt': '{:,.3f}'} - }, - 'Q_loss': { - 'text': 'heat flow', - 'SI_unit': 'W', - 'units': { - 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 - }, - #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', - #'documentation': {'float_fmt': '{:,.3f}'} - }, - 'Q_total': { - 'text': 'heat flow', - 'SI_unit': 'W', - 'units': { - 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12 + 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12, + 'J / s': 1 , 'J / h': 1 / 3.6e3, 'J / y': 1 / (3.6e3*24*365), + 'kJ / s': 1e3, 'kJ / h': 1e3 / 3.6e3, 'kJ / y': 1e3 / (3.6e3*24*365), + 'MJ / s': 1e6, 'MJ / h': 1e6 / 3.6e3, 'GJ / y': 1e6 / (3.6e3*24*365), + 'GJ / s': 1e9, 'GJ / h': 1e9 / 3.6e3, 'MJ / y': 1e9 / (3.6e3*24*365), + 'TJ / s': 1e12, 'TJ / h': 1e12 / 3.6e3, 'TJ / y': 1e12 / (3.6e3*24*365), + 'Wh / s': 3.6e3 , 'Wh / h': 3.6e3 / 3.6e3, 'Wh / y': 3.6e3 / (3.6e3*24*365), + 'kWh / s': 3.6e6, 'kWh / h': 3.6e6 / 3.6e3, 'kWh / y': 3.6e6 / (3.6e3*24*365), + 'MWh / s': 3.6e9, 'MWh / h': 3.6e9 / 3.6e3, 'GWh / y': 3.6e9 / (3.6e3*24*365), + 'GWh / s': 3.6e12, 'GWh / h': 3.6e12 / 3.6e3, 'MWh / y': 3.6e12 / (3.6e3*24*365), + 'TWh / s': 3.6e15, 'TWh / h': 3.6e15 / 3.6e3, 'TWh / y': 3.6e15 / (3.6e3*24*365), }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} @@ -56,7 +48,17 @@ 'text': 'KPI scaling with Q', 'SI_unit': 'Wx', 'units': { - 'Wx': 1, 'kWx': 1000, 'MWx': 1e6, 'GWx': 1e9, 'TWx': 1e12 + 'J / kg': 1 , 'J / t': 1 / 1e3, + 'kJ / kg': 1e3 , 'kJ / t': 1e3 / 1e3, + 'MJ / kg': 1e6 , 'MJ / t': 1e6 / 1e3, + 'GJ / kg': 1e9 , 'GJ / t': 1e9 / 1e3, + 'TJ / kg': 1e12 , 'TJ / t': 1e12 / 1e3, + + 'Wh / kg': 3.6e3 , 'Wh / t': 3.6e3 / 1e3, + 'kWh / kg': 3.6e6 , 'kWh / t': 3.6e6 / 1e3, + 'MWh / kg': 3.6e9 , 'MWh / t': 3.6e9 / 1e3, + 'GWh / kg': 3.6e12 , 'GWh / t': 3.6e12 / 1e3, + 'TWh / kg': 3.6e15 , 'TWh / t': 3.6e15 / 1e3, }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} @@ -66,7 +68,7 @@ 'SI_unit': 'kg / s', 'units': { 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, - 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365) + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365), 't / s': 1e3 / 1 }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', #'documentation': {'float_fmt': '{:,.3f}'} @@ -74,6 +76,10 @@ }) +component_property_data['Q_loss'] = component_property_data['Q'] +component_property_data['Q_total'] = component_property_data['Q'] + + fluid_property_data = OrderedDict({ 'm': { @@ -81,7 +87,7 @@ 'SI_unit': 'kg / s', 'units': { 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, - 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365) + 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365), 't / s': 1e3 / 1 }, 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', 'documentation': {'float_fmt': '{:,.3f}'} From 448c0e57fe12ef361888ddff7ccae236beeaef4e Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:01:56 +0100 Subject: [PATCH 081/105] equal To of SFS model --- src/tespy/components/newComponents.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tespy/components/newComponents.py b/src/tespy/components/newComponents.py index a53139816..cb01f61e9 100644 --- a/src/tespy/components/newComponents.py +++ b/src/tespy/components/newComponents.py @@ -686,6 +686,9 @@ def get_parameters(self): func=self.KPI_func, latex=self.pr_func_doc, num_eq=1) + variables['dTo'] = dc_cp( + min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, + deriv=self.dTo_deriv) #variables["Qout"] = dc_cpa() return variables @@ -805,6 +808,29 @@ def KPI_deriv(self, increment_filter, k): # if self.is_variable(c.h): #, increment_filter): # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) + def dTo_func(self): + r""" + Equation for hot side heat exchanger energy balance. + """ + T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + return T0 - T1 - self.dTo.val + + def dTo_deriv(self, increment_filter, k): + r""" + Partial derivatives for hot side heat exchanger energy balance. + """ + #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) + #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) + for c in [self.outl[0], self.outl[1]]: + if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end + self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) + if self.is_variable(c.h): #, increment_filter): + self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) + for fluid in self.variable_fluids: + if fluid in c.fluid.is_var: + self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) + def calc_parameters(self): super().calc_parameters() i = self.inl[0] From a36009def2648779982c34a7f0eba773f6261242 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:02:49 +0100 Subject: [PATCH 082/105] add to export debugging class list --- src/tespy/networks/network_reader.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 6bcbf75ab..748d91ca5 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -92,6 +92,7 @@ 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, 'SimpleHeatExchangerDeltaPLfKpi' : SimpleHeatExchangerDeltaPLfKpi, + 'SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH' : SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH, } ENGINE_TARGET_CLASSES = { From 89be247bbac67919baa143d062702f253c7875db Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:05:15 +0100 Subject: [PATCH 083/105] Huge issue on scaling residuals and jacobians, which is missing in tespy. (the solver obs out on systems with very small mass flow...). Quick and dirty handleling by adding normalized increments to the residual norm --- src/tespy/networks/network.py | 49 +++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 5ffad2278..9f44b791f 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1835,11 +1835,12 @@ def init_precalc_properties(self, c): except ValueError: pass - if not np.isnan(c.T.val0): - try: - c.h.val_SI = fp.h_mix_pT(c.p.val_SI, c.T.val0 + 273.15, c.fluid_data, c.mixing_rule, force_state=c.force_state) - except ValueError: - pass + if c.T.val0: + if not np.isnan(c.T.val0): + try: + c.h.val_SI = fp.h_mix_pT(c.p.val_SI, c.T.val0 + 273.15, c.fluid_data, c.mixing_rule, force_state=c.force_state) + except ValueError: + pass def init_val0(self, c: con.Connection, key: str): @@ -2080,12 +2081,20 @@ def solve_loop(self, print_results=True): for self.iter in range(self.max_iter): self.increment_filter = np.absolute(self.increment) < ERR ** 2 self.solve_control() + # self.residual_history = np.append( + # self.residual_history, norm(self.residual) + # ) + + # if self.iterinfo: + # self.iterinfo_body(print_results) + + # must always call this one to add increments residual to the solver + residual_norm = self.iterinfo_body(print_results) + self.residual_history = np.append( - self.residual_history, norm(self.residual) + self.residual_history, residual_norm ) - if self.iterinfo: - self.iterinfo_body(print_results) if ( (self.iter >= self.min_iter - 1 @@ -2219,16 +2228,24 @@ def iterinfo_body(self, print_results=True): fluid = 'NaN' component = 'NaN' + if not self.lin_dep and not np.isnan(residual_norm): + norm_massflow = norm(self.increment[m]) / fpd['m']['units'][self.m_unit] # scale with mass unit + norm_pressure = norm(self.increment[p]) / 1e5 # scale with 1 bar + norm_enthalpy = norm(self.increment[h]) / 1e5 # scale with enthalpy + norm_fluid = norm(self.increment[fl]) / fpd['m']['units'][self.m_unit] # scale with mass unit + norm_component = norm(self.increment[cp]) + + massflow = '{:.2e}'.format(norm_massflow) + pressure = '{:.2e}'.format(norm_pressure) + enthalpy = '{:.2e}'.format(norm_enthalpy) + fluid = '{:.2e}'.format(norm_fluid) + component = '{:.2e}'.format(norm_component) + + residual_norm = norm(np.append(residual_norm,np.array([norm_massflow, norm_pressure, norm_enthalpy, norm_fluid, norm_component]))) + if not np.isnan(residual_norm): residual = '{:.2e}'.format(residual_norm) - if not self.lin_dep and not np.isnan(residual_norm): - massflow = '{:.2e}'.format(norm(self.increment[m])) - pressure = '{:.2e}'.format(norm(self.increment[p])) - enthalpy = '{:.2e}'.format(norm(self.increment[h])) - fluid = '{:.2e}'.format(norm(self.increment[fl])) - component = '{:.2e}'.format(norm(self.increment[cp])) - progress_val = -1 if not np.isnan(residual_norm): # This should not be hardcoded here. @@ -2262,7 +2279,7 @@ def iterinfo_body(self, print_results=True): logger.progress(progress_val, msg) if print_results: print(msg) - return + return residual_norm def iterinfo_tail(self, print_results=True): """Print tail of convergence progress.""" From e4c26e7a9c61dc58e61e3f14dfd4b03f40859a1a Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 19 Dec 2023 16:33:10 +0100 Subject: [PATCH 084/105] safe delete object --- src/tespy/networks/network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 9f44b791f..f83639d80 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -801,7 +801,8 @@ def create_fluid_wrapper_branches(self): merged[branch_name]["components"] = list( set(branch_data["components"] + ob_data["components"]) ) - del merged[ob_name] + if merged.get(ob_name,False): + del merged[ob_name] break self.fluid_wrapper_branches = merged From beae8fedce2524c57100a8d8f97453ded34219e5 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 30 Jan 2024 08:25:21 +0100 Subject: [PATCH 085/105] unit --- src/tespy/tools/global_vars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index 52606d914..0614b9136 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -86,7 +86,7 @@ 'text': 'mass flow', 'SI_unit': 'kg / s', 'units': { - 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, + 'kg / s': 1, 'kg / min': 1 / 60, 'kg / h': 1 / 3.6e3, 'kg / y': 1 / (3600*24*365), 't / h': 1 / 3.6, 'g / s': 1 / 1e3, 't / y': 1e3 / (3600*24*365), 't / s': 1e3 / 1 }, 'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', From b7be6f676edb4099c09f5a57389bfc31d77099fd Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 31 Jan 2024 12:13:03 +0100 Subject: [PATCH 086/105] adding new features for energy supply, e.g. mass flow specification inside sourcea nad sink --- .../components/energySupplyComponents.py | 261 +++++++++++++++++- src/tespy/networks/network.py | 2 +- 2 files changed, 252 insertions(+), 11 deletions(-) diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index 32b88e1a5..1d48b9935 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -1,8 +1,13 @@ import logging from tespy.components import Merge, Splitter +from tespy.components import Sink + from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.components.nodes.base import NodeBase +from tespy.tools.data_containers import SimpleDataContainer as dc_simple + # Fictious Energy Supply models (energy flows modelled as mass flows) # No real use for tespy I guess @@ -22,6 +27,8 @@ def get_parameters(self): latex=self.mass_flow_func_doc, num_eq=1 ) + variables['Heating'] = dc_cp(min_val=0, is_result=True) + variables['Cooling'] = dc_cp(min_val=0, is_result=True) return variables def get_mandatory_constraints(self): @@ -67,8 +74,10 @@ def COP_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() - self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) - + if not self.COP.is_set: + self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) + self.Heating.val = self.outl[0].m.val_SI + self.Cooling.val = self.outl[1].m.val_SI class MassLossEnergySupply(Splitter): @@ -78,35 +87,102 @@ def component(): def get_parameters(self): variables = super().get_parameters() - variables["Loss"] = dc_cp( + variables["LossRatio"] = dc_cp( min_val=0, deriv=self.Loss_deriv, func=self.Loss_func, latex=self.mass_flow_func_doc, num_eq=1 ) + variables['Energy'] = dc_cp(min_val=0, is_result=True) + variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) return variables + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=1) + return self.outlets() def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() + del constraints['mass_flow_constraints'] del constraints['pressure_constraints'] del constraints['energy_balance_constraints'] return constraints def Loss_func(self): - return self.inl[0].m.val_SI * (1-self.Loss.val) - self.outl[0].m.val_SI + return self.inl[0].m.val_SI * (1-self.LossRatio.val) - sum([o.m.val_SI for o in self.outl]) def Loss_deriv(self, increment_filter, k): inl = self.inl[0] - outl = self.outl[0] if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = (1-self.Loss.val) - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 + self.jacobian[k, inl.m.J_col] = (1-self.LossRatio.val) + for o in self.outl: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + mout = sum([o.m.val_SI for o in self.outl]) + if not self.LossRatio.is_set: + self.LossRatio.val = (self.inl[0].m.val_SI - mout)/self.inl[0].m.val_SI + self.EnergyLoss.val = self.inl[0].m.val_SI - mout + self.Energy.val = mout + +class BoilerEffEnergySupply(Splitter): + + @staticmethod + def component(): + return 'mass efficiency model for splitting energy flows (modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["BoilerEff"] = dc_cp( + min_val=0, + deriv=self.Eff_deriv, + func=self.Eff_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables['Energy'] = dc_cp(min_val=0, is_result=True) + variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) + return variables + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=1) + return self.outlets() + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['mass_flow_constraints'] + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints + + def Eff_func(self): + return self.inl[0].m.val_SI * self.BoilerEff.val - sum([o.m.val_SI for o in self.outl]) + + def Eff_deriv(self, increment_filter, k): + inl = self.inl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.BoilerEff.val + for o in self.outl: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 def calc_parameters(self): super().calc_parameters() - self.Loss.val = (self.inl[0].m.val_SI - self.outl[0].m.val_SI)/self.inl[0].m.val_SI + mout = sum([o.m.val_SI for o in self.outl]) + if not self.BoilerEff.is_set: + self.BoilerEff.val = mout/self.inl[0].m.val_SI + self.EnergyLoss.val = self.inl[0].m.val_SI - mout + self.Energy.val = mout + class MergeEnergySupply(Merge): @@ -138,4 +214,169 @@ def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() del constraints['pressure_constraints'] del constraints['energy_balance_constraints'] - return constraints \ No newline at end of file + return constraints + + + +class SourceEnergy(NodeBase): + + def __init__(self, label, **kwargs): + #self.set_attr(**kwargs) + # need to assign the number of outlets before the variables are set + for key in kwargs: + if key == 'num_out': + self.num_out=kwargs[key] + super().__init__(label, **kwargs) + + @staticmethod + def component(): + return 'Source' + + def get_parameters(self): + variables = super().get_parameters() + variables['num_out'] = dc_simple() + variables["Energy"] = dc_cp( + min_val=0, + deriv=self.mass_flow_deriv, + func=self.mass_flow_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + return {} + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=2) + return self.outlets() + + @staticmethod + def is_branch_source(): + return True + + def start_branch(self): + branches = {} + for outconn in self.outl: + branch = { + "connections": [outconn], + "components": [self, outconn.target], + "subbranches": {} + } + outconn.target.propagate_to_target(branch) + branches[outconn.label] = branch + return branches + + def start_fluid_wrapper_branch(self): + branches = {} + for outconn in self.outl: + branch = { + "connections": [outconn], + "components": [self] + } + outconn.target.propagate_wrapper_to_target(branch) + branches[outconn.label] = branch + return branches + + def mass_flow_func(self): + r""" + Calculate the residual value for mass flow balance equation. + + Returns + ------- + res : float + Residual value of equation. + + .. math:: + + 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; + \forall i \in inlets, \forall j \in outlets + """ + res = self.Energy.val + for o in self.outl: + res -= o.m.val_SI + return res + + def mass_flow_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives for mass flow equation. + + Returns + ------- + deriv : list + Matrix with partial derivatives for the fluid equations. + """ + for o in self.outl: + if o.m.is_var: + self.jacobian[k, o.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + if not self.Energy.is_set: + self.Energy.val = sum([o.m.val_SI for o in self.outl]) + + +class SinkEnergy(Sink): + + @staticmethod + def component(): + return 'sink with energy ' + + def get_parameters(self): + variables = super().get_parameters() + variables["Energy"] = dc_cp( + min_val=0, + deriv=self.mass_flow_deriv, + func=self.mass_flow_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + return constraints + + + def mass_flow_func(self): + r""" + Calculate the residual value for mass flow balance equation. + + Returns + ------- + res : float + Residual value of equation. + + .. math:: + + 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; + \forall i \in inlets, \forall j \in outlets + """ + res = self.Energy.val + for i in self.inl: + res -= i.m.val_SI + return res + + def mass_flow_func_doc(self, label): + pass + + def mass_flow_deriv(self, increment_filter, k): + r""" + Calculate partial derivatives for mass flow equation. + + Returns + ------- + deriv : list + Matrix with partial derivatives for the fluid equations. + """ + for i in self.inl: + if i.m.is_var: + self.jacobian[k, i.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + if not self.Energy.is_set: + self.Energy.val = self.inl[0].m.val_SI \ No newline at end of file diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index f83639d80..6f0d3e5f6 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -766,7 +766,7 @@ def create_fluid_wrapper_branches(self): self.fluid_wrapper_branches = {} mask = self.comps["comp_type"].isin( - ["Source", "CycleCloser", "WaterElectrolyzer", "FuelCell"] + ["Source", "SourceEnergy", "CycleCloser", "WaterElectrolyzer", "FuelCell"] ) start_components = self.comps["object"].loc[mask] From e5a9e51fbc2a3fea051533fe5b075aa86023eb25 Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Wed, 31 Jan 2024 14:19:13 -0300 Subject: [PATCH 087/105] Fix unit conversion (switched MWh and GWh) --- src/tespy/tools/global_vars.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index 0614b9136..a37f75960 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -23,13 +23,13 @@ 'W': 1, 'kW': 1000, 'MW': 1e6, 'GW': 1e9, 'TW': 1e12, 'J / s': 1 , 'J / h': 1 / 3.6e3, 'J / y': 1 / (3.6e3*24*365), 'kJ / s': 1e3, 'kJ / h': 1e3 / 3.6e3, 'kJ / y': 1e3 / (3.6e3*24*365), - 'MJ / s': 1e6, 'MJ / h': 1e6 / 3.6e3, 'GJ / y': 1e6 / (3.6e3*24*365), - 'GJ / s': 1e9, 'GJ / h': 1e9 / 3.6e3, 'MJ / y': 1e9 / (3.6e3*24*365), + 'MJ / s': 1e6, 'MJ / h': 1e6 / 3.6e3, 'MJ / y': 1e6 / (3.6e3*24*365), + 'GJ / s': 1e9, 'GJ / h': 1e9 / 3.6e3, 'GJ / y': 1e9 / (3.6e3*24*365), 'TJ / s': 1e12, 'TJ / h': 1e12 / 3.6e3, 'TJ / y': 1e12 / (3.6e3*24*365), 'Wh / s': 3.6e3 , 'Wh / h': 3.6e3 / 3.6e3, 'Wh / y': 3.6e3 / (3.6e3*24*365), 'kWh / s': 3.6e6, 'kWh / h': 3.6e6 / 3.6e3, 'kWh / y': 3.6e6 / (3.6e3*24*365), - 'MWh / s': 3.6e9, 'MWh / h': 3.6e9 / 3.6e3, 'GWh / y': 3.6e9 / (3.6e3*24*365), - 'GWh / s': 3.6e12, 'GWh / h': 3.6e12 / 3.6e3, 'MWh / y': 3.6e12 / (3.6e3*24*365), + 'MWh / s': 3.6e9, 'MWh / h': 3.6e9 / 3.6e3, 'MWh / y': 3.6e9 / (3.6e3*24*365), + 'GWh / s': 3.6e12, 'GWh / h': 3.6e12 / 3.6e3, 'GWh / y': 3.6e12 / (3.6e3*24*365), 'TWh / s': 3.6e15, 'TWh / h': 3.6e15 / 3.6e3, 'TWh / y': 3.6e15 / (3.6e3*24*365), }, #'latex_eq': r'0 = \dot{m} - \dot{m}_\mathrm{spec}', From 57b96038e627c32cfc2a52238e612e067d89fbe6 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 6 Feb 2024 13:19:20 +0100 Subject: [PATCH 088/105] boiler, compressor, ref unit and heat pump with usefull ratios --- .../components/energySupplyComponents.py | 229 +++++++++++++++++- 1 file changed, 227 insertions(+), 2 deletions(-) diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index 1d48b9935..da46afc9d 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -12,7 +12,8 @@ # Fictious Energy Supply models (energy flows modelled as mass flows) # No real use for tespy I guess -class MassFactorEnergySupply(Splitter): + +class VaporCompressionSystemEnergySupply(Splitter): @staticmethod def component(): @@ -79,6 +80,150 @@ def calc_parameters(self): self.Heating.val = self.outl[0].m.val_SI self.Cooling.val = self.outl[1].m.val_SI + + +class HeatPumpEnergySupply(Splitter): + + """ + COP sets self.outl[0].m.val_SI + UsefullCoolingRatio sets self.outl[1].m.val_SI + """ + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["COP"] = dc_cp( + min_val=0, + deriv=self.COP_deriv, + func=self.COP_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables["UsefullCoolingRatio"] = dc_cp( + min_val=0, + deriv=self.usefull_deriv, + func=self.usefull_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables["NonUseFullCooling"] = dc_cp(min_val=0, is_result=True) + variables['Heating'] = dc_cp(min_val=0, is_result=True) + variables['Cooling'] = dc_cp(min_val=0, is_result=True) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + del constraints['mass_flow_constraints'] + return constraints + + def COP_func(self): + return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI + + def COP_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.COP.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + + def usefull_func(self): + return self.inl[0].m.val_SI * (self.COP.val-1) * self.UsefullCoolingRatio.val + self.outl[1].m.val_SI # cooling negative + + def usefull_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[1] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = (self.COP.val-1) * self.UsefullCoolingRatio.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = 1 + + def calc_parameters(self): + super().calc_parameters() + # if not self.COP.is_set: + # self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) + self.Heating.val = self.outl[0].m.val_SI + self.Cooling.val = self.outl[1].m.val_SI + self.NonUseFullCooling.val = self.inl[0].m.val_SI * (self.COP.val - 1) * (1 - self.UsefullCoolingRatio.val) + + +class RefUnitEnergySupply(Splitter): + + """ + COP sets self.outl[1].m.val_SI + UsefullHeatingRatio sets self.outl[0].m.val_SI + """ + + + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["COP"] = dc_cp( + min_val=0, + deriv=self.COP_deriv, + func=self.COP_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables["UsefullHeatingRatio"] = dc_cp( + min_val=0, + deriv=self.usefull_deriv, + func=self.usefull_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables["NonUseFullHeating"] = dc_cp(min_val=0, is_result=True) + variables['Heating'] = dc_cp(min_val=0, is_result=True) + variables['Cooling'] = dc_cp(min_val=0, is_result=True) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + del constraints['mass_flow_constraints'] + return constraints + + def COP_func(self): + return self.inl[0].m.val_SI * self.COP.val + self.outl[1].m.val_SI # cooling negative + + def COP_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[1] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.COP.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = 1 + + def usefull_func(self): + return self.inl[0].m.val_SI * (self.COP.val + 1) * self.UsefullHeatingRatio.val - self.outl[0].m.val_SI + + def usefull_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = (self.COP.val + 1) * self.UsefullHeatingRatio.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + # if not self.COP.is_set: + # self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) + self.Heating.val = self.outl[0].m.val_SI + self.Cooling.val = self.outl[1].m.val_SI + self.NonUseFullHeating.val = self.inl[0].m.val_SI * (self.COP.val + 1) * (1 - self.UsefullHeatingRatio.val) + + + class MassLossEnergySupply(Splitter): @staticmethod @@ -121,7 +266,7 @@ def Loss_deriv(self, increment_filter, k): self.jacobian[k, inl.m.J_col] = (1-self.LossRatio.val) for o in self.outl: if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 + self.jacobian[k, o.m.J_col] = -1 def calc_parameters(self): super().calc_parameters() @@ -184,6 +329,86 @@ def calc_parameters(self): self.Energy.val = mout + +class BoilerEffUsefullLossEnergySupply(Splitter): + + """ + BoilerEff defines self.outl[0].m.val_SI + UsefullLossRatio defines self.outl[1].m.val_SI + """ + + @staticmethod + def component(): + return 'mass efficiency model for splitting energy flows (modelled using tespy mass balances)' + + def get_parameters(self): + variables = super().get_parameters() + variables["BoilerEff"] = dc_cp( + min_val=0, + deriv=self.Eff_deriv, + func=self.Eff_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables["UsefullLossRatio"] = dc_cp( + min_val=0, + deriv=self.usefull_deriv, + func=self.usefull_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables['Energy'] = dc_cp(min_val=0, is_result=True) + variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) + variables['EnergyLossUsefull'] = dc_cp(min_val=0, is_result=True) + return variables + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=2) + return self.outlets() + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['mass_flow_constraints'] + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints + + def Eff_func(self): + return self.inl[0].m.val_SI * self.BoilerEff.val - self.outl[0].m.val_SI + + def Eff_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.BoilerEff.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + + def usefull_func(self): + return self.inl[0].m.val_SI * (1-self.BoilerEff.val) * self.UsefullLossRatio.val - self.outl[1].m.val_SI + + def usefull_deriv(self, increment_filter, k): + inl = self.inl[0] + outl = self.outl[1] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = (1-self.BoilerEff.val) * self.UsefullLossRatio.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = -1 + + def calc_parameters(self): + super().calc_parameters() + # mout = sum([o.m.val_SI for o in self.outl]) + # if not self.BoilerEff.is_set: + # self.BoilerEff.val = mout/self.inl[0].m.val_SI + self.EnergyLossUsefull.val = self.outl[1].m.val_SI + self.EnergyLoss.val = self.inl[0].m.val_SI - sum([o.m.val_SI for o in self.outl]) + self.Energy.val = self.outl[0].m.val_SI + + + class MergeEnergySupply(Merge): @staticmethod From 9bb892c71a28ade7fbed94390c98b7451f043a1f Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 7 Feb 2024 14:55:57 +0100 Subject: [PATCH 089/105] adding functionality for energy supply --- src/tespy/components/component.py | 41 ++--- .../components/energySupplyComponents.py | 149 +++++++++++++++--- 2 files changed, 137 insertions(+), 53 deletions(-) diff --git a/src/tespy/components/component.py b/src/tespy/components/component.py index 0eaac894f..11b03f5d7 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -212,42 +212,19 @@ def set_attr(self, **kwargs): raise TypeError(msg) elif isinstance(data, dc_cpa): - try: - for f in kwargs[key]: - float(f) - is_numeric = True - except (TypeError, ValueError): - is_numeric = False - - for f in kwargs[key]: - if (f == 'var'): - is_var = True - else: - is_var = False - break - - if is_numeric: - if np.isnan(kwargs[key]).any(): - data.set_attr(is_set=False) - if isinstance(data, dc_cpa): - data.set_attr(is_var=False) - else: - data.set_attr(val=kwargs[key], is_set=True) - if isinstance(data, dc_cpa): - data.set_attr(is_var=False) - data.set_attr(num_eq=len(kwargs[key])) - - elif is_var: - if isinstance(data, dc_cpa): - data.set_attr(is_set=True, is_var=True) - data.set_attr(num_eq=len(kwargs[key])) - - # invalid datatype for keyword + floats = [isinstance(f, float) for f in kwargs[key]] + vars = [f == 'var' for f in kwargs[key]] + is_numeric = any(floats) + is_var = any(vars) + num_eq = floats.count(True) + + if is_numeric or is_var: + data.set_attr(val=kwargs[key], is_set=floats, is_var=vars, num_eq = num_eq) else: msg = ( 'Bad datatype for keyword argument ' + key + ' at ' + self.label + '.') - logging.error(msg) + logger.error(msg) raise TypeError(msg) elif key in ['design', 'offdesign']: diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index da46afc9d..1a95ebba8 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -4,6 +4,7 @@ from tespy.components import Sink from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa from tespy.components.nodes.base import NodeBase from tespy.tools.data_containers import SimpleDataContainer as dc_simple @@ -443,6 +444,107 @@ def get_mandatory_constraints(self): +# class SourceEnergy(NodeBase): + +# def __init__(self, label, **kwargs): +# #self.set_attr(**kwargs) +# # need to assign the number of outlets before the variables are set +# for key in kwargs: +# if key == 'num_out': +# self.num_out=kwargs[key] +# super().__init__(label, **kwargs) + +# @staticmethod +# def component(): +# return 'Source' + +# def get_parameters(self): +# variables = super().get_parameters() +# variables['num_out'] = dc_simple() +# variables["Energy"] = dc_cp( +# min_val=0, +# deriv=self.mass_flow_deriv, +# func=self.mass_flow_func, +# latex=self.mass_flow_func_doc, +# num_eq=1 +# ) +# return variables + +# def get_mandatory_constraints(self): +# return {} + +# def outlets(self): +# if self.num_out.is_set: +# return ['out' + str(i + 1) for i in range(self.num_out.val)] +# else: +# self.set_attr(num_out=2) +# return self.outlets() + +# @staticmethod +# def is_branch_source(): +# return True + +# def start_branch(self): +# branches = {} +# for outconn in self.outl: +# branch = { +# "connections": [outconn], +# "components": [self, outconn.target], +# "subbranches": {} +# } +# outconn.target.propagate_to_target(branch) +# branches[outconn.label] = branch +# return branches + +# def start_fluid_wrapper_branch(self): +# branches = {} +# for outconn in self.outl: +# branch = { +# "connections": [outconn], +# "components": [self] +# } +# outconn.target.propagate_wrapper_to_target(branch) +# branches[outconn.label] = branch +# return branches + +# def mass_flow_func(self): +# r""" +# Calculate the residual value for mass flow balance equation. + +# Returns +# ------- +# res : float +# Residual value of equation. + +# .. math:: + +# 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; +# \forall i \in inlets, \forall j \in outlets +# """ +# res = self.Energy.val +# for o in self.outl: +# res -= o.m.val_SI +# return res + +# def mass_flow_deriv(self, increment_filter, k): +# r""" +# Calculate partial derivatives for mass flow equation. + +# Returns +# ------- +# deriv : list +# Matrix with partial derivatives for the fluid equations. +# """ +# for o in self.outl: +# if o.m.is_var: +# self.jacobian[k, o.m.J_col] = -1 + +# def calc_parameters(self): +# super().calc_parameters() +# if not self.Energy.is_set: +# self.Energy.val = sum([o.m.val_SI for o in self.outl]) + + class SourceEnergy(NodeBase): def __init__(self, label, **kwargs): @@ -467,6 +569,14 @@ def get_parameters(self): latex=self.mass_flow_func_doc, num_eq=1 ) + variables["EnergyArray"] = dc_cpa( + min_val=0, + deriv=self.mass_flow_array_deriv, + func=self.mass_flow_array_func, + latex=self.mass_flow_func_doc, + #num_eq=self.num_out + ) + return variables def get_mandatory_constraints(self): @@ -507,41 +617,38 @@ def start_fluid_wrapper_branch(self): return branches def mass_flow_func(self): - r""" - Calculate the residual value for mass flow balance equation. - - Returns - ------- - res : float - Residual value of equation. - - .. math:: - - 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; - \forall i \in inlets, \forall j \in outlets - """ res = self.Energy.val for o in self.outl: res -= o.m.val_SI return res def mass_flow_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives for mass flow equation. - - Returns - ------- - deriv : list - Matrix with partial derivatives for the fluid equations. - """ for o in self.outl: if o.m.is_var: self.jacobian[k, o.m.J_col] = -1 + def mass_flow_array_func(self): + residual = [] + for i,is_set in enumerate(self.EnergyArray.is_set): + if is_set: + o = self.outl[i] + residual += [self.EnergyArray.val[i] - o.m.val_SI] + return residual + + def mass_flow_array_deriv(self, increment_filter, k): + m=0 + for i,is_set in enumerate(self.EnergyArray.is_set): + if is_set: + o = self.outl[i] + self.jacobian[k + m, o.m.J_col] = -1 + m=m+1 + def calc_parameters(self): super().calc_parameters() if not self.Energy.is_set: self.Energy.val = sum([o.m.val_SI for o in self.outl]) + for i,o in enumerate(self.outl): + self.EnergyArray.val[i] = o.m.val_SI class SinkEnergy(Sink): From d7f42259031ab261430a9ebfb60f52c38b49c6aa Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 7 Feb 2024 15:46:22 +0100 Subject: [PATCH 090/105] flow energy node --- .../components/energySupplyComponents.py | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index 1a95ebba8..45b37789e 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -711,4 +711,52 @@ def mass_flow_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() if not self.Energy.is_set: - self.Energy.val = self.inl[0].m.val_SI \ No newline at end of file + self.Energy.val = self.inl[0].m.val_SI + + +class FlowEnergy(Splitter): + + @staticmethod + def component(): + return 'flow with energy ' + + def get_parameters(self): + variables = super().get_parameters() + variables["Energy"] = dc_cp( + min_val=0, + deriv=self.Energy_mass_flow_deriv, + func=self.Energy_mass_flow_func, + latex=self.Energy_mass_flow_func_doc, + num_eq=1 + ) + return variables + + def outlets(self): + self.set_attr(num_out=1) + return ['out1'] + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + #del constraints['mass_flow_constraints'] + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + return constraints + + def Energy_mass_flow_func(self): + res = self.Energy.val + for i in self.inl: + res -= i.m.val_SI + return res + + def Energy_mass_flow_deriv(self, increment_filter, k): + for i in self.inl: + if i.m.is_var: + self.jacobian[k, i.m.J_col] = -1 + + def Energy_mass_flow_func_doc(self, label): + pass + + def calc_parameters(self): + super().calc_parameters() + if not self.Energy.is_set: + self.Energy.val = self.inl[0].m.val_SI \ No newline at end of file From ab5a9f655cd4e3b0a55df4e7f1b899a844dddfc5 Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Wed, 21 Feb 2024 13:56:06 +0100 Subject: [PATCH 091/105] Changing SI unit of KPI --- src/tespy/tools/global_vars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index a37f75960..9b9316896 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -46,7 +46,7 @@ }, 'KPI': { 'text': 'KPI scaling with Q', - 'SI_unit': 'Wx', + 'SI_unit': 'J / kg', 'units': { 'J / kg': 1 , 'J / t': 1 / 1e3, 'kJ / kg': 1e3 , 'kJ / t': 1e3 / 1e3, From 118e21017d2889ce92296aee22d220641da215f0 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 2 Apr 2024 15:01:43 +0200 Subject: [PATCH 092/105] fixing basic heatpump and refunit in energy supply --- .../components/energySupplyComponents.py | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py index 45b37789e..971e262a3 100644 --- a/src/tespy/components/energySupplyComponents.py +++ b/src/tespy/components/energySupplyComponents.py @@ -13,13 +13,19 @@ # Fictious Energy Supply models (energy flows modelled as mass flows) # No real use for tespy I guess - -class VaporCompressionSystemEnergySupply(Splitter): +class HeatPumpEnergySupply(Splitter): @staticmethod def component(): return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=1) + return self.outlets() + def get_parameters(self): variables = super().get_parameters() variables["COP"] = dc_cp( @@ -30,14 +36,14 @@ def get_parameters(self): num_eq=1 ) variables['Heating'] = dc_cp(min_val=0, is_result=True) - variables['Cooling'] = dc_cp(min_val=0, is_result=True) + variables['Cooling'] = dc_cp(min_val=0, is_result=True) return variables def get_mandatory_constraints(self): constraints = super().get_mandatory_constraints() del constraints['pressure_constraints'] del constraints['energy_balance_constraints'] - #del constraints['mass_flow_constraints'] + del constraints['mass_flow_constraints'] return constraints def COP_func(self): @@ -76,14 +82,12 @@ def COP_deriv(self, increment_filter, k): def calc_parameters(self): super().calc_parameters() - if not self.COP.is_set: - self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) self.Heating.val = self.outl[0].m.val_SI - self.Cooling.val = self.outl[1].m.val_SI + self.Cooling.val = -(self.outl[0].m.val_SI-self.inl[0].m.val_SI) -class HeatPumpEnergySupply(Splitter): +class HeatPumpUsefullLossEnergySupply(Splitter): """ COP sets self.outl[0].m.val_SI @@ -155,6 +159,79 @@ def calc_parameters(self): class RefUnitEnergySupply(Splitter): + @staticmethod + def component(): + return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' + + def outlets(self): + if self.num_out.is_set: + return ['out' + str(i + 1) for i in range(self.num_out.val)] + else: + self.set_attr(num_out=1) + return self.outlets() + + def get_parameters(self): + variables = super().get_parameters() + variables["COP"] = dc_cp( + min_val=0, + deriv=self.COP_deriv, + func=self.COP_func, + latex=self.mass_flow_func_doc, + num_eq=1 + ) + variables['Heating'] = dc_cp(min_val=0, is_result=True) + variables['Cooling'] = dc_cp(min_val=0, is_result=True) + return variables + + def get_mandatory_constraints(self): + constraints = super().get_mandatory_constraints() + del constraints['pressure_constraints'] + del constraints['energy_balance_constraints'] + del constraints['mass_flow_constraints'] + return constraints + + def COP_func(self): + r""" + Equation for COP. + + Returns + ------- + residual : float + Residual value of equation. + + .. math:: + + 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} + """ + return self.inl[0].m.val_SI * self.COP.val + self.outl[0].m.val_SI + + def COP_deriv(self, increment_filter, k): + r""" + Calculate the partial derivatives for combustion pressure ratio. + + Parameters + ---------- + increment_filter : ndarray + Matrix for filtering non-changing variables. + + k : int + Position of equation in Jacobian matrix. + """ + inl = self.inl[0] + outl = self.outl[0] + if inl.m.is_var: + self.jacobian[k, inl.m.J_col] = self.COP.val + if outl.m.is_var: + self.jacobian[k, outl.m.J_col] = 1 + + def calc_parameters(self): + super().calc_parameters() + self.Cooling.val = self.outl[0].m.val_SI + self.Heating.val = -self.outl[0].m.val_SI + self.inl[0].m.val_SI + + +class RefUnitUsefullLossEnergySupply(Splitter): + """ COP sets self.outl[1].m.val_SI UsefullHeatingRatio sets self.outl[0].m.val_SI From c70decabb6fa64b7e584747fd5f2f2d9944dda04 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 14:35:49 +0200 Subject: [PATCH 093/105] working on custom fluid wrapper --- incompressiblesTests/mywrapper/MyWrapper.py | 201 ++++++++++++++++++ .../mywrapper/MyWrapper_test.py | 59 +++++ src/tespy/connections/connection.py | 9 +- src/tespy/networks/network.py | 33 +-- src/tespy/tools/data_containers.py | 1 + 5 files changed, 288 insertions(+), 15 deletions(-) create mode 100644 incompressiblesTests/mywrapper/MyWrapper.py create mode 100644 incompressiblesTests/mywrapper/MyWrapper_test.py diff --git a/incompressiblesTests/mywrapper/MyWrapper.py b/incompressiblesTests/mywrapper/MyWrapper.py new file mode 100644 index 000000000..6bb63068a --- /dev/null +++ b/incompressiblesTests/mywrapper/MyWrapper.py @@ -0,0 +1,201 @@ +import CoolProp.CoolProp as CP +from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper +import numpy as np +import matplotlib.pyplot as plt + +# # coefficients a b c d +# COEF = { +# "protein": { +# "unit" : "C", +# "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], +# "d" : [1329.9, -0.5184, 0.0, 0.0], +# } +# } + +class MyWrapper(FluidPropertyWrapper): + def __init__(self, fluid, back_end=None, Tref = 293.15, coefs=[]) -> None: + super().__init__(fluid, back_end) + if self.fluid not in coefs: + msg = "Fluid not available in database" + raise KeyError(msg) + + # get coefs (converted to kelvin) and calculate reference + self.T0 = Tref + self.get_coefs(coefs) + + #self._molar_mass = 1 + self._T_min = 100 + self._T_max = 2000 + self._p_min = 1000 + self._p_max = 10000000 + + def get_coefs(self, coefs): + if coefs[self.fluid]["unit"] == "C": + self.C_c = coefs[self.fluid]["cp"] + self.C_d = coefs[self.fluid]["d"] + # convert coefficients + T_C = np.linspace(1,50) + cp = self.cp_pT(None,T_C) + d = self.d_pT(None,T_C) + T_K = np.linspace(1+273.15,50+273.15) + self.C_c = list(np.polyfit(T_K, cp, len(coefs[self.fluid]["cp"])-1)) + self.C_c = self.C_c[::-1] + self.C_d = list(np.polyfit(T_K, d, len(coefs[self.fluid]["d"])-1)) + self.C_d = self.C_d[::-1] + elif coefs[self.fluid]["unit"] == "K": + self.C_c = coefs[self.fluid]["cp"] + self.C_d = coefs[self.fluid]["d"] + else: + ValueError("unit is not C or K") + + def cp_pT(self, p, T): + return np.sum([self.C_c[i] * T**i for i in range(len(self.C_c))], axis=0) + + def d_pT(self, p, T): + return np.sum([self.C_d[i] * T**i for i in range(len(self.C_d))], axis=0) + + def u_pT(self, p, T): + integral = 0 + for i in range(len(self.C_c)): + integral += (1 / (i + 1)) * self.C_c[i] * (T**(i + 1) - self.T0**(i + 1)) + return integral + + def h_pT(self, p, T, force_state=None): + u = self.u_pT(p, T) + d = self.d_pT(p, T) + return u - p/d + + def s_pT(self, p, T): + integral = self.C_c[0] * np.log(T / self.T0) + for i in range(len(self.C_c) - 1): + integral += (1 / (i + 1)) * self.C_c[i + 1] * (T**(i + 1) - self.T0**(i + 1)) + return integral + + def T_ph(self, p, h): + return self.newton(self.h_pT, self.cp_pT, h, p) + + def T_ps(self, p, s): + return self.newton(self.s_pT, self.dsdT, s, p) + def dsdT(self, p, T): + return self.cp_pT(p, T)/T + def h_ps(self, p, s): + T = self.T_ps(p, s) + return self.h_pT(p, T) + + def s_ph(self, p, h): + T = self.T_ph(p, h) + return self.s_pT(p, T) + + def isentropic(self, p_1, h_1, p_2): + return self.h_ps(p_2, self.s_ph(p_1, h_1)) + + def newton(self, func, deriv, val, p): + # default valaues + T = 300 + valmin = -1000 + valmax = 3000 + max_iter = 10 + tol_rel = 1e-6 + # start newton loop + expr = True + i = 0 + while expr: + # calculate function residual and new value + res = val - func(p, T) + T += res / deriv(p, T) + # check for value ranges + if T < valmin: + T = valmin + if T > valmax: + T = valmax + i += 1 + if i > max_iter: + break + expr = abs(res / val) >= tol_rel + return T + + + +if __name__ == "__main__": + + fluidwrap = MyWrapper("protein") + + T = 300 + p = 1e5 + u = fluidwrap.u_pT(p, T) + d = fluidwrap.d_pT(p, T) + h = fluidwrap.h_pT(p, T) + s = fluidwrap.s_pT(p, T) + print(f"u = {u} d = {d} h = {h} s = {s}") + + T = 273.15 + u = fluidwrap.u_pT(p, T) + d = fluidwrap.d_pT(p, T) + h = fluidwrap.h_pT(p, T) + s = fluidwrap.s_pT(p, T) + print(f"u = {u} d = {d} h = {h} s = {s}") + + T = 373.15 + u = fluidwrap.u_pT(p, T) + d = fluidwrap.d_pT(p, T) + h = fluidwrap.h_pT(p, T) + s = fluidwrap.s_pT(p, T) + print(f"u = {u} d = {d} h = {h} s = {s}") + T = fluidwrap.T_ph(p,h) + s = fluidwrap.s_ph(p,h) + print(f"recalc: T = {T} s = {s}") + T = fluidwrap.T_ps(p,s) + h = fluidwrap.h_ps(p,s) + print(f"recalc: T = {T} h = {h}") + + CP_cp = [] + CP_k = [] + CP_d = [] + CP_h = [] + CP_s = [] + + wrap_cp = [] + wrap_d = [] + wrap_h = [] + wrap_s = [] + + p = 101325 * 5 + + #Specific heat, kJ/(kg·K) + Tplt = np.linspace(273.15,373.15) + for T in Tplt: + CP_cp += [CP.PropsSI('C','T',T,'P',p,'INCOMP::FoodProtein')] + CP_k += [CP.PropsSI('L','T',T,'P',p,'INCOMP::FoodProtein')] + CP_d += [CP.PropsSI('D','T',T,'P',p,'INCOMP::FoodProtein')] + CP_h += [CP.PropsSI('H','T',T,'P',p,'INCOMP::FoodProtein')] + CP_s += [CP.PropsSI('S','T',T,'P',p,'INCOMP::FoodProtein')] + wrap_cp += [fluidwrap.cp_pT(p, T)] + wrap_d += [fluidwrap.d_pT(p, T)] + wrap_h += [fluidwrap.h_pT(p, T)] + wrap_s += [fluidwrap.s_pT(p, T)] + + + + fig, ax = plt.subplots(2, 2, figsize=(16, 8)) + ax = ax.flatten() + [a.grid() for a in ax] + [a.set_xlabel('temperature, K') for a in ax] + + ax[0].plot(Tplt, wrap_cp) + ax[1].plot(Tplt, wrap_d) + ax[2].plot(Tplt, wrap_h) + ax[3].plot(Tplt, wrap_s) + + ax[0].scatter(Tplt, CP_cp) + ax[1].scatter(Tplt, CP_d) + ax[2].scatter(Tplt, CP_h) + ax[3].scatter(Tplt, CP_s) + + ax[0].set_ylabel('cp') + ax[1].set_ylabel('d') + ax[2].set_ylabel('h') + ax[3].set_ylabel('s') + + plt.show() + + print("hey") \ No newline at end of file diff --git a/incompressiblesTests/mywrapper/MyWrapper_test.py b/incompressiblesTests/mywrapper/MyWrapper_test.py new file mode 100644 index 000000000..95a007134 --- /dev/null +++ b/incompressiblesTests/mywrapper/MyWrapper_test.py @@ -0,0 +1,59 @@ +import numpy as np +from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper +from tespy.tools.global_vars import gas_constants +from MyWrapper import MyWrapper +import logging +logging.basicConfig(level=logging.DEBUG) + + +# coefficients a b c d +COEF = { + "protein": { + "unit" : "C", + "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], + "d" : [1329.9, -0.5184, 0.0, 0.0], + } +} + +myWrapper = MyWrapper("protein", Tref=298.15, coefs=COEF) # same as in CoolProp +h = myWrapper.h_pT(1e5, 400) +T = myWrapper.T_ph(1e5, h) + +# from tespy.tools.fluid_properties import CoolPropWrapper +# coolprop_water = CoolPropWrapper("H2O") +# h_cp = coolprop_water.h_pT(1e5, 400) +# T_cp = coolprop_water.T_ph(1e5, h_cp) + + +from tespy.components import Sink +from tespy.components import Source +from tespy.components import SimpleHeatExchanger +from tespy.connections import Connection +from tespy.networks import Network + +nwk = Network(T_unit="C", p_unit="bar", iterinfo=True) + +so = Source("Source") +hx = SimpleHeatExchanger("Heatex") +si = Sink("Sink") + +c1 = Connection(so, "out1", hx, "in1", label="1") +c2 = Connection(hx, "out1", si, "in1", label="2") + +nwk.add_conns(c1, c2) + +c1.set_attr( + m=1, p=1, T=20, + fluid={"protein": 1}, fluid_engines={"protein": MyWrapper}, fluid_coefs = COEF +) +c2.set_attr(p=1, T=80) + +nwk.solve("design") + +hx.set_attr(Q=1.5e5) +c2.set_attr(T=None) +nwk.solve("design") + +nwk.print_results() + +print("hey") diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index cd70d15b8..645c3f457 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -513,6 +513,9 @@ def _fluid_specification(self, key, value): elif key == "fluid_balance": self.fluid.set_attr(balance=value) + elif key == "fluid_coefs": + self.fluid.fluid_coefs = value + else: msg = f"Connections do not have an attribute named {key}" logger.error(msg) @@ -626,7 +629,11 @@ def _create_fluid_wrapper(self): else: self.fluid.back_end[fluid] = None - self.fluid.wrapper[fluid] = self.fluid.engine[fluid](fluid, back_end) + if self.fluid.engine[fluid].__name__ == 'MyWrapper': + self.fluid.wrapper[fluid] = self.fluid.engine[fluid](fluid, back_end, coefs=self.fluid.fluid_coefs) + else: + self.fluid.fluid_coefs[fluid] = None + self.fluid.wrapper[fluid] = self.fluid.engine[fluid](fluid, back_end) def preprocess(self): self.num_eq = 0 diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 6f0d3e5f6..3d2f051c2 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -938,6 +938,7 @@ def propagate_fluid_wrappers(self): any_fluids_set = [] engines = {} back_ends = {} + fluid_coefss = {} for c in all_connections: for f in c.fluid.is_set: any_fluids_set += [f] @@ -945,6 +946,8 @@ def propagate_fluid_wrappers(self): engines[f] = c.fluid.engine[f] if f in c.fluid.back_end: back_ends[f] = c.fluid.back_end[f] + if f in c.fluid.fluid_coefs: + fluid_coefss[f] = c.fluid.fluid_coefs[f] mixing_rules = [ c.mixing_rule for c in all_connections @@ -990,7 +993,8 @@ def propagate_fluid_wrappers(self): c.fluid.engine[f] = engine for f, back_end in back_ends.items(): c.fluid.back_end[f] = back_end - + for f, fluid_coefs in fluid_coefss.items(): + c.fluid.fluid_coefs[f] = fluid_coefs c._create_fluid_wrapper() def presolve_massflow_topology(self): @@ -2267,19 +2271,20 @@ def iterinfo_body(self, print_results=True): progress = '{:d} %'.format(progress_val) - msg = self.iterinfo_fmt.format( - iter=iter_str, - residual=residual, - progress=progress, - massflow=massflow, - pressure=pressure, - enthalpy=enthalpy, - fluid=fluid, - component=component - ) - logger.progress(progress_val, msg) - if print_results: - print(msg) + if self.iterinfo: + msg = self.iterinfo_fmt.format( + iter=iter_str, + residual=residual, + progress=progress, + massflow=massflow, + pressure=pressure, + enthalpy=enthalpy, + fluid=fluid, + component=component + ) + logger.progress(progress_val, msg) + if print_results: + print(msg) return residual_norm def iterinfo_tail(self, print_results=True): diff --git a/src/tespy/tools/data_containers.py b/src/tespy/tools/data_containers.py index fc878d5f0..5d14afc0f 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -375,6 +375,7 @@ def attr(): 'wrapper': collections.OrderedDict(), 'back_end': collections.OrderedDict(), 'engine': collections.OrderedDict(), + 'fluid_coefs': collections.OrderedDict(), "is_var": set(), "J_col": collections.OrderedDict(), 'balance': False From 28a2a4a2c7319ecd55838d7cb129063ce9d946cd Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:14:14 +0200 Subject: [PATCH 094/105] working mix of custom fluid wrapper and coolprop --- incompressiblesTests/mywrapper/MyWrapper.py | 10 ++++----- .../mywrapper/MyWrapper_test.py | 21 ++++++++++++++++--- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/incompressiblesTests/mywrapper/MyWrapper.py b/incompressiblesTests/mywrapper/MyWrapper.py index 6bb63068a..e2668571c 100644 --- a/incompressiblesTests/mywrapper/MyWrapper.py +++ b/incompressiblesTests/mywrapper/MyWrapper.py @@ -1,5 +1,5 @@ import CoolProp.CoolProp as CP -from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper +from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper, CoolPropWrapper import numpy as np import matplotlib.pyplot as plt @@ -23,7 +23,7 @@ def __init__(self, fluid, back_end=None, Tref = 293.15, coefs=[]) -> None: self.T0 = Tref self.get_coefs(coefs) - #self._molar_mass = 1 + self._molar_mass = 1 self._T_min = 100 self._T_max = 2000 self._p_min = 1000 @@ -51,7 +51,7 @@ def get_coefs(self, coefs): def cp_pT(self, p, T): return np.sum([self.C_c[i] * T**i for i in range(len(self.C_c))], axis=0) - def d_pT(self, p, T): + def d_pT(self, p, T, **kwargs): return np.sum([self.C_d[i] * T**i for i in range(len(self.C_d))], axis=0) def u_pT(self, p, T): @@ -60,12 +60,12 @@ def u_pT(self, p, T): integral += (1 / (i + 1)) * self.C_c[i] * (T**(i + 1) - self.T0**(i + 1)) return integral - def h_pT(self, p, T, force_state=None): + def h_pT(self, p, T, **kwargs): u = self.u_pT(p, T) d = self.d_pT(p, T) return u - p/d - def s_pT(self, p, T): + def s_pT(self, p, T, **kwargs): integral = self.C_c[0] * np.log(T / self.T0) for i in range(len(self.C_c) - 1): integral += (1 / (i + 1)) * self.C_c[i + 1] * (T**(i + 1) - self.T0**(i + 1)) diff --git a/incompressiblesTests/mywrapper/MyWrapper_test.py b/incompressiblesTests/mywrapper/MyWrapper_test.py index 95a007134..015cb9aef 100644 --- a/incompressiblesTests/mywrapper/MyWrapper_test.py +++ b/incompressiblesTests/mywrapper/MyWrapper_test.py @@ -1,5 +1,6 @@ import numpy as np -from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper +from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper, CoolPropWrapper +#from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper from tespy.tools.global_vars import gas_constants from MyWrapper import MyWrapper import logging @@ -43,13 +44,27 @@ nwk.add_conns(c1, c2) c1.set_attr( - m=1, p=1, T=20, - fluid={"protein": 1}, fluid_engines={"protein": MyWrapper}, fluid_coefs = COEF + m=1, + p=1, + T=20, + fluid = { + "protein": 0.5, + "water": 0.5 + }, + fluid_engines = { + "protein" : MyWrapper, + "water" : CoolPropWrapper + }, + fluid_coefs = COEF, + mixing_rule = "incompressible", ) c2.set_attr(p=1, T=80) nwk.solve("design") +nwk.print_results() + +# iterate Q hx.set_attr(Q=1.5e5) c2.set_attr(T=None) nwk.solve("design") From b4aa8be639f9a06e8e99f3268dd2033133e69e18 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:51:33 +0200 Subject: [PATCH 095/105] change folder --- .../{ => newComponentsTests}/mywrapper/MyWrapper.py | 0 .../{ => newComponentsTests}/mywrapper/MyWrapper_test.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename incompressiblesTests/{ => newComponentsTests}/mywrapper/MyWrapper.py (100%) rename incompressiblesTests/{ => newComponentsTests}/mywrapper/MyWrapper_test.py (100%) diff --git a/incompressiblesTests/mywrapper/MyWrapper.py b/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py similarity index 100% rename from incompressiblesTests/mywrapper/MyWrapper.py rename to incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py diff --git a/incompressiblesTests/mywrapper/MyWrapper_test.py b/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py similarity index 100% rename from incompressiblesTests/mywrapper/MyWrapper_test.py rename to incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py From dd0857cecac0a530d3bdb8e0527ab48ab2c64c2b Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:52:07 +0200 Subject: [PATCH 096/105] mixtures with custem wrapper and coolprop working --- ...plitWithDeltaH-drierWithAir_newApproach.py | 8 +- ...ltaH-drierWithAir_newApproach_MyWrapper.py | 132 ++++++++++++++++++ 2 files changed, 136 insertions(+), 4 deletions(-) create mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py index 5ea6cecc8..f2b760a5f 100644 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py @@ -20,7 +20,7 @@ # %% # caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -#fluids = ["INCOMP::Water", "INCOMP::T66"] +#fluids = ["INCOMP::Water", "INCOMP::FoodProtein"] nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) so = Source("Source") @@ -41,11 +41,11 @@ # c.set_attr(m0=1, h0=100, p0=1.2) # set some generic data for starting values -c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") -c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") +c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::FoodProtein": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") +c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::FoodProtein": 0, "HEOS::Air": 1}, mixing_rule="incompressible") c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) -c2.set_attr(fluid={"INCOMP::T66": 0}) +c2.set_attr(fluid={"INCOMP::FoodProtein": 0}) #c3.set_attr(p=1.2,T=60,force_state='g') diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py new file mode 100644 index 000000000..3c02e8075 --- /dev/null +++ b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py @@ -0,0 +1,132 @@ +import logging + +from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator +from tespy.tools import ComponentProperties +from tespy.connections import Connection +from tespy.networks import Network +import numpy as np + +from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp + +from tespy.components.newComponents import \ + DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ + SeparatorWithSpeciesSplitsDeltaT + +from tespy.components.newAdvancedComponents import TwoStreamDrier + +logging.basicConfig(level=logging.DEBUG) + +from mywrapper.MyWrapper import MyWrapper +from tespy.tools.fluid_properties.wrappers import CoolPropWrapper + +# %% + +nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) + +so = Source("Source") +soAir = Source("SourceAir") +se = TwoStreamDrier("Separator",num_out=2,num_in=2) +#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) +si1 = Sink("Sink 1") +si2 = Sink("Sink 2") + +c1 = Connection(so, "out1", se, "in1", label="1") +c2 = Connection(se, "out1", si1, "in1", label="2") # vapor +c3 = Connection(se, "out2", si2, "in1", label="3") # liquid +c4 = Connection(soAir, "out1", se, "in2", label="4") + +nw.add_conns(c1, c2, c3, c4) + +# for c in nw.conns['object']: +# c.set_attr(m0=1, h0=100, p0=1.2) + +# set some generic data for starting values +c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "protein": 0.1, "HEOS::Air": 0}, + fluid_engines = {"HEOS::Water": CoolPropWrapper, "protein" : MyWrapper, "HEOS::Air": CoolPropWrapper}, + fluid_coefs = { + "protein": { + "unit" : "C", + "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], + "d" : [1329.9, -0.5184, 0.0, 0.0], + } + }, + mixing_rule="incompressible") + +c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "protein": 0, "HEOS::Air": 1}, mixing_rule="incompressible") + +c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) +c2.set_attr(fluid={"protein": 0}) + + +#c3.set_attr(p=1.2,T=60,force_state='g') +c3.set_attr(p=1.0) +c2.set_attr(p=1.0) + +se.set_attr(deltaH=0) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +se.set_attr(deltaH=None) +c2.set_attr(p=1.0,T=None,force_state='g') +c3.set_attr(p=1.0,T=None,force_state='l') +se.set_attr(dTwbProd=0) +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c3.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=se.Q.val) +se.set_attr(Q=1e6) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c3.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=2.250e6) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + +c3.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=None) +se.set_attr(kA=6.0e+04) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + +c3.set_attr(fluid={"HEOS::Water": None}) +se.set_attr(Q=None) +se.set_attr(KPI=None) +se.set_attr(kA=None) +se.set_attr(WBeff=0.4) + +nw.solve("design") +if not nw.converged: + raise Exception("not converged") +nw.print_results() +print(nw.results['Connection']) + + + From 54ee55a656d882c1f7158670895eefa0709538e7 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 17:13:48 +0200 Subject: [PATCH 097/105] Make some quick fixes to integrate state and force_state keywords and remove prints --- src/tespy/connections/connection.py | 63 +++++----- src/tespy/networks/network.py | 110 +++++++----------- src/tespy/tools/fluid_properties/functions.py | 44 +++---- src/tespy/tools/fluid_properties/wrappers.py | 18 ++- tests/test_errors.py | 2 +- .../test_solar_energy_generating_system.py | 12 +- tests/test_networks/test_network.py | 14 +-- 7 files changed, 114 insertions(+), 149 deletions(-) diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index 7062eb01d..b630e651b 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -215,18 +215,15 @@ class Connection: Specify the state keyword: The fluid will be forced to liquid or gaseous state in this case. - >>> so_si2.set_attr(state='l') - >>> so_si2.state.is_set - True - >>> so_si2.set_attr(state=None) - >>> so_si2.state.is_set - False - >>> so_si2.set_attr(state='g') - >>> so_si2.state.is_set - True - >>> so_si2.set_attr(state=None) - >>> so_si2.state.is_set - False + >>> so_si2.set_attr(force_state='l') + >>> so_si2.force_state + 'l' + >>> so_si2.set_attr(force_state='g') + >>> so_si2.force_state + 'g' + >>> so_si2.set_attr(force_state=None) + >>> so_si2.force_state + """ def __init__(self, source, outlet_id, target, inlet_id, @@ -269,7 +266,6 @@ def __init__(self, source, outlet_id, target, inlet_id, k: v for k, v in self.get_parameters().items() if hasattr(v, "func") and v.func is not None } - self.state = dc_simple() self.property_data0 = [x + '0' for x in self.property_data.keys()] self.__dict__.update(self.property_data) self.mixing_rule = None @@ -410,14 +406,12 @@ def set_attr(self, **kwargs): elif key in self.property_data or key in self.property_data0: self._parameter_specification(key, kwargs[key]) - elif key == 'state': - if kwargs[key] in ['l', 'g']: - self.state.set_attr(val=kwargs[key], is_set=True) - elif kwargs[key] is None: - self.state.set_attr(is_set=False) + elif key == 'force_state': + if kwargs[key] in ['l', 'g', None]: + self.force_state = kwargs[key] else: msg = ( - 'Keyword argument "state" must either be ' + 'Keyword argument "force_state" must either be ' '"l" or "g" or be None.' ) logger.error(msg) @@ -462,9 +456,6 @@ def set_attr(self, **kwargs): elif key == "mixing_rule": self.mixing_rule = kwargs[key] - elif key == "force_state": - self.force_state = kwargs[key] - elif key == "good_starting_values": self.good_starting_values = kwargs[key] @@ -602,8 +593,6 @@ def _serialize(self): data = self.get_attr(k) export.update({k: data._serialize()}) - export.update({"state": self.state._serialize()}) - return {self.label: export} @staticmethod @@ -611,7 +600,7 @@ def _serializable(): return [ "source_id", "target_id", "design_path", "design", "offdesign", "local_design", "local_design", - "printout", "mixing_rule","good_starting_values","force_state" + "printout", "mixing_rule", "good_starting_values", "force_state" ] def _create_fluid_wrapper(self): @@ -674,25 +663,25 @@ def simplify_specifications(self): if not self.h.is_set and self.p.is_set: if self.T.is_set: self.h.val_SI = h_mix_pT(self.p.val_SI, self.T.val_SI, self.fluid_data, self.mixing_rule, self.force_state) - self.h.solved = True - self.T.solved = True + self.h._solved = True + self.T._solved = True elif self.Td_bp.is_set: T_sat = T_sat_p(self.p.val_SI, self.fluid_data, self.mixing_rule) self.h.val_SI = h_mix_pT(self.p.val_SI, T_sat + self.Td_bp.val, self.fluid_data, self.force_state) - self.h.solved = True - self.Td_bp.solved = True + self.h._solved = True + self.Td_bp._solved = True elif self.x.is_set: self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) - self.h.solved = True - self.x.solved = True + self.h._solved = True + self.x._solved = True elif not self.h.is_set and not self.p.is_set: if self.T.is_set and self.x.is_set: self.p.val_SI = p_sat_T(self.T.val_SI, self.fluid_data, self.mixing_rule) self.h.val_SI = h_mix_pQ(self.p.val_SI, self.x.val_SI, self.fluid_data, self.mixing_rule) - self.T.solved = True - self.x.solved = True - self.p.solved = True - self.h.solved = True + self.T._solved = True + self.x._solved = True + self.p._solved = True + self.h._solved = True def get_parameters(self): return { @@ -1027,12 +1016,12 @@ def check_enthalpy_bounds(self, fluid): def check_two_phase_bounds(self, fluid): - if (self.Td_bp.val_SI > 0 or (self.state.val == 'g' and self.state.is_set)): + if (self.Td_bp.val_SI > 0 or self.force_state == 'g'): h = self.fluid.wrapper[fluid].h_pQ(self.p.val_SI, 1) if self.h.val_SI < h: self.h.val_SI = h * 1.01 logger.debug(self._property_range_message('h')) - elif (self.Td_bp.val_SI < 0 or (self.state.val == 'l' and self.state.is_set)): + elif (self.Td_bp.val_SI < 0 or self.force_state == 'l'): h = self.fluid.wrapper[fluid].h_pQ(self.p.val_SI, 0) if self.h.val_SI > h: self.h.val_SI = h * 0.99 diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 633400177..9efe79f60 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -922,10 +922,10 @@ def initialise(self): if self.conns.loc[first_conn.label, "object"] != first_conn: self.create_massflow_and_fluid_branches() self.create_fluid_wrapper_branches() + self.propagate_fluid_wrappers() self.presolve_massflow_topology() self.presolve_fluid_topology() - self.init_set_properties() if self.mode == 'offdesign': @@ -1285,7 +1285,6 @@ def init_design(self): unset, the offdesign values set. """ for c in self.comps['object']: - print(c) for prop in cpd.keys(): if c.parameters.get(prop,False): c.parameters[prop].unit = self.get_attr(prop + '_unit') @@ -1740,8 +1739,6 @@ def init_properties(self): for c in self.conns['object']: for key in ['fluid']: if c.get_attr(key).is_var: - #print(c.get_attr(key).val) - #print(c.get_attr(key).val0) for k,v in c.get_attr(key).val0.items(): c.get_attr(key).val[k] = v # improved starting values for referenced connections, @@ -1790,14 +1787,12 @@ def init_properties(self): # and state specification. These should be recalculated even with # good starting values, for example, when one exchanges enthalpy # with boiling point temperature difference. - if (c.Td_bp.is_set or c.state.is_set) and c.h.is_var: - if ((c.Td_bp.val_SI > 0 and c.Td_bp.is_set) or - (c.state.val == 'g' and c.state.is_set)): + if (c.Td_bp.is_set or c.force_state) and c.h.is_var: + if ((c.Td_bp.val_SI > 0 and c.Td_bp.is_set) or c.force_state == 'g'): h = fp.h_mix_pQ(c.p.val_SI, 1, c.fluid_data) if c.h.val_SI < h: c.h.val_SI = h * 1.001 - elif ((c.Td_bp.val_SI < 0 and c.Td_bp.is_set) or - (c.state.val == 'l' and c.state.is_set)): + elif ((c.Td_bp.val_SI < 0 and c.Td_bp.is_set) or c.force_state == 'l'): h = fp.h_mix_pQ(c.p.val_SI, 0, c.fluid_data) if c.h.val_SI > h: c.h.val_SI = h * 0.999 @@ -1928,7 +1923,8 @@ def init_read_connections(base_path): def solve(self, mode, init_path=None, design_path=None, max_iter=50, min_iter=4, init_only=False, init_previous=True, - use_cuda=False, print_results=True, prepare_fast_lane=False): + use_cuda=False, print_results=True, prepare_fast_lane=False, + robust_relaxation=False): r""" Solve the network. @@ -1979,6 +1975,7 @@ def solve(self, mode, init_path=None, design_path=None, """ ## to own function self.new_design = False + self.robust_relaxation = robust_relaxation if self.design_path == design_path and design_path is not None: for c in self.conns['object']: if c.new_design: @@ -2262,13 +2259,17 @@ def iterinfo_body(self, print_results=True): fluid = '{:.2e}'.format(norm_fluid) component = '{:.2e}'.format(norm_component) - residual_norm = norm(np.append(residual_norm,np.array([norm_massflow, norm_pressure, norm_enthalpy, norm_fluid, norm_component]))) + residual_norm = norm( + np.append( + residual_norm, + np.array([norm_massflow, norm_pressure, norm_enthalpy, norm_fluid, norm_component]) + ) + ) + progress_val = -1 if not np.isnan(residual_norm): residual = '{:.2e}'.format(residual_norm) - progress_val = -1 - if not np.isnan(residual_norm): # This should not be hardcoded here. if residual_norm > np.finfo(float).eps * 100: progress_min = np.log(ERR) @@ -2336,24 +2337,24 @@ def matrix_inversion(self): except np.linalg.linalg.LinAlgError: self.increment = self.residual * 0 - def _limit_increments(self,valmin,valmax,val,increment): - inc_min = valmin-val - inc_max = valmax-val + def _limit_increments(self, valmin, valmax, val, increment): + inc_min = valmin - val + inc_max = valmax - val if increment < inc_min: # need to limit the increment - if inc_min < -0.01*(valmax-valmin): + if inc_min < -0.01 * (valmax - valmin): # if we are not close the the bound we limit it half way to the bound - increment = inc_min/2 + increment = inc_min / 2 else: # othervice we set the increment to the bound increment = inc_min - if increment > inc_max: + elif increment > inc_max: # need to limit the increment - if inc_max > 0.01*(valmax-valmin): + if inc_max > 0.01 * (valmax - valmin): # if we are not close the the bound we limit it half way to the bound - increment = inc_max/2 + increment = inc_max / 2 else: # othervice we set the increment to the bound increment = inc_max @@ -2361,70 +2362,47 @@ def _limit_increments(self,valmin,valmax,val,increment): def update_variables(self): - if self.iter < 2: - RobustRelax = 0.1 - elif self.iter < 4: - RobustRelax = 0.25 - elif self.iter < 6: - RobustRelax = 0.5 - else: - RobustRelax = 1 - - #RobustRelax = 1 + robust_relax = 1 + if self.robust_relaxation: + if self.iter < 2: + robust_relax = 0.1 + elif self.iter < 4: + robust_relax = 0.25 + elif self.iter < 6: + robust_relax = 0.5 # add the increment for data in self.variables_dict.values(): if data["variable"] == "m": container = data["obj"].get_attr(data["variable"]) increment = self.increment[container.J_col] - container.val_SI += RobustRelax * self._limit_increments(self.m_range_SI[0],self.m_range_SI[1],container.val_SI,increment) - #print(container.val_SI) + container.val_SI += robust_relax * self._limit_increments( + self.m_range_SI[0], self.m_range_SI[1], container.val_SI, increment + ) elif data["variable"] == "h": container = data["obj"].get_attr(data["variable"]) increment = self.increment[container.J_col] - container.val_SI += RobustRelax * self._limit_increments(self.h_range_SI[0],self.h_range_SI[1],container.val_SI,increment) - #print(container.val_SI) + container.val_SI += robust_relax * increment elif data["variable"] == "p": container = data["obj"].p increment = self.increment[container.J_col] + # prevents negative values relax = max(1, -2 * increment / container.val_SI) - container.val_SI += RobustRelax * increment / relax - # increment = self.increment[container.J_col] - # container.val_SI += self._limit_increments(self.p_range_SI[0],self.p_range_SI[1],container.val_SI,increment) - #print(container.val_SI) + container.val_SI += robust_relax * increment / relax elif data["variable"] == "fluid": container = data["obj"].fluid - increment = self.increment[container.J_col[data["fluid"]]] val = container.val[data["fluid"]] - container.val[data["fluid"]] += RobustRelax * self._limit_increments(0,1,val,increment) - - #print(container.val[data["fluid"]]) - - # if container.val[data["fluid"]] < ERR : - # container.val[data["fluid"]] = 0 - # elif container.val[data["fluid"]] > 1 - ERR : - # container.val[data["fluid"]] = 1 + container.val[data["fluid"]] += robust_relax * self._limit_increments( + 0, 1, val, increment + ) else: - # add increment - + # component variables increment = self.increment[data["obj"].J_col] val = data["obj"].val - data["obj"].val += RobustRelax * self._limit_increments(data["obj"].min_val,data["obj"].max_val,val,increment) - - #data["obj"].val += RobustRelax * self.increment[data["obj"].J_col] - - - #print(data["obj"].val) - - - - - # # keep value within specified value range - # if data["obj"].val < data["obj"].min_val: - # data["obj"].val = data["obj"].min_val - # elif data["obj"].val > data["obj"].max_val: - # data["obj"].val = data["obj"].max_val + data["obj"].val += robust_relax * self._limit_increments( + data["obj"].min_val, data["obj"].max_val, val, increment + ) def check_variable_bounds(self): @@ -2491,7 +2469,7 @@ def check_connection_properties(self, c): c.check_enthalpy_bounds(fl) # two-phase related - if (c.Td_bp.is_set or c.state.is_set) and self.iter < 3: + if (c.Td_bp.is_set or c.force_state) and self.iter < 3: c.check_two_phase_bounds(fl) # mixture diff --git a/src/tespy/tools/fluid_properties/functions.py b/src/tespy/tools/fluid_properties/functions.py index 49bda7377..93cf728e5 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -94,8 +94,8 @@ def T_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if fluid_data["Water"]["wrapper"].back_end == "HEOS": Tsat = fluid_data["Water"]["wrapper"].T_sat(p) T = min([fluid_data[f]["wrapper"]._T_max for f in fluid_data]+[Tsat]) - hL = h_mix_pT(p, T, fluid_data, mixing_rule, force_state = 'l') - hV = h_mix_pT(p, T, fluid_data, mixing_rule, force_state = 'g') + hL = h_mix_pT(p, T, fluid_data, mixing_rule, force_state='l') + hV = h_mix_pT(p, T, fluid_data, mixing_rule, force_state='g') if h>hL and h=hV: return 1.0 else: - return (h-hL)/(hV-hL) + return (h-hL) / (hV-hL) if force_state == 'l': return 0.0 elif force_state == 'g': return 1.0 msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" - raise ValueError(msg) + raise ValueError(msg) def p_sat_T(T, fluid_data, mixing_rule=None): if get_number_of_fluids(fluid_data) == 1: @@ -192,7 +192,7 @@ def p_sat_T(T, fluid_data, mixing_rule=None): if fluid_data["Water"]["wrapper"].back_end == "HEOS": return fluid_data["Water"]["wrapper"].p_sat(T) msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" - raise ValueError(msg) + raise ValueError(msg) def T_sat_p(p, fluid_data, mixing_rule=None): @@ -204,7 +204,7 @@ def T_sat_p(p, fluid_data, mixing_rule=None): if fluid_data["Water"]["wrapper"].back_end == "HEOS": return fluid_data["Water"]["wrapper"].T_sat(p) msg = "Saturation function cannot be called on mixtures, unless there is HEOS::Water" - raise ValueError(msg) + raise ValueError(msg) def dT_sat_dp(p, fluid_data, mixing_rule=None): @@ -222,12 +222,12 @@ def s_mix_ph(p, h, fluid_data, mixing_rule=None, T0=None, force_state=None): if "Water" in fluid_data and not force_state: if fluid_data["Water"]["wrapper"].back_end == "HEOS": Tsat = fluid_data["Water"]["wrapper"].T_sat(p) - hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'l') - hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state = 'g') + hL = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state='l') + hV = h_mix_pT(p, Tsat, fluid_data, mixing_rule, force_state='g') if h>hL and hhL and h self.AS.p(): try: self.AS.update(CP.PT_INPUTS, p, T) except: - #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) else: self.AS.update(CP.QT_INPUTS, 0, T) else: - if (kwargs.get('force_state',False) == "l") and not (T > self.AS.T_critical()): + if (kwargs.get('force_state', False) == "l") and not (T > self.AS.T_critical()): self.AS.update(CP.QT_INPUTS, 0, T) if p > self.AS.p(): try: self.AS.update(CP.PT_INPUTS, p, T) except: - #print("allowing state to move up on the liquid saturation curve") self.AS.update(CP.QT_INPUTS, 0, T) elif kwargs.get('force_state',False) == "g" and not (T > self.AS.T_critical()): self.AS.update(CP.QT_INPUTS, 1, T) @@ -220,13 +219,12 @@ def _check_imposed_state(self,p,T,**kwargs): try: self.AS.update(CP.PT_INPUTS, p, T) except: - #print("allowing state to move further down on the gas curve") self.AS.update(CP.QT_INPUTS, 1, T) else: self.AS.update(CP.PT_INPUTS, p, T) def h_pT(self, p, T, **kwargs): - self._check_imposed_state(p,T,**kwargs) + self._check_imposed_state(p, T, **kwargs) return self.AS.hmass() def h_QT(self, Q, T): @@ -259,7 +257,7 @@ def d_ph(self, p, h): return self.AS.rhomass() def d_pT(self, p, T, **kwargs): - self._check_imposed_state(p,T, **kwargs) + self._check_imposed_state(p, T, **kwargs) return self.AS.rhomass() def d_QT(self, Q, T): @@ -271,7 +269,7 @@ def viscosity_ph(self, p, h): return self.AS.viscosity() def viscosity_pT(self, p, T, **kwargs): - self._check_imposed_state(p,T, **kwargs) + self._check_imposed_state(p, T, **kwargs) return self.AS.viscosity() def s_ph(self, p, h): @@ -279,7 +277,7 @@ def s_ph(self, p, h): return self.AS.smass() def s_pT(self, p, T, **kwargs): - self._check_imposed_state(p,T, **kwargs) + self._check_imposed_state(p, T, **kwargs) return self.AS.smass() diff --git a/tests/test_errors.py b/tests/test_errors.py index b71d53fb2..9199f3bba 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -110,7 +110,7 @@ def test_set_attr_errors(): set_attr_TypeError(conn, local_design=5) set_attr_TypeError(conn, local_offdesign=5) set_attr_TypeError(conn, printout=5) - set_attr_TypeError(conn, state=5) + set_attr_TypeError(conn, force_state=5) set_attr_TypeError(nw, m_range=5) set_attr_TypeError(nw, p_range=5) diff --git a/tests/test_models/test_solar_energy_generating_system.py b/tests/test_models/test_solar_energy_generating_system.py index 5dcfcacbf..3db9b4ba0 100644 --- a/tests/test_models/test_solar_energy_generating_system.py +++ b/tests/test_models/test_solar_energy_generating_system.py @@ -316,10 +316,10 @@ def setup_method(self): c14.set_attr(p=0.29) # preheater pressure values - c19.set_attr(p=14.755, state='l') - c21.set_attr(p=9.9975, state='l') - c23.set_attr(p=8.7012, state='l') - c25.set_attr(state='l') + c19.set_attr(p=14.755, force_state='l') + c21.set_attr(p=9.9975, force_state='l') + c23.set_attr(p=8.7012, force_state='l') + c25.set_attr(force_state='l') c27.set_attr(p=125) c29.set_attr(p=112) @@ -365,8 +365,8 @@ def setup_method(self): # specification of missing parameters c19.set_attr(p=14.755) - c21.set_attr(p=9.9975, state='l') - c23.set_attr(p=8.7012, state='l') + c21.set_attr(p=9.9975, force_state='l') + c23.set_attr(p=8.7012, force_state='l') c27.set_attr(p=125) c29.set_attr(p=112) diff --git a/tests/test_networks/test_network.py b/tests/test_networks/test_network.py index e9c92e52a..f8b3d01db 100644 --- a/tests/test_networks/test_network.py +++ b/tests/test_networks/test_network.py @@ -327,7 +327,7 @@ def test_individual_design_path_on_connections_and_components(self): v1_design = self.sc1_v1.v.val_SI zeta_sc1_design = self.sc1.zeta.val - self.sc2_v2.set_attr(T=95, state='l', m=None) + self.sc2_v2.set_attr(T=95, force_state='l', m=None) self.sc1_v1.set_attr(m=0.001, T=None) self.nw.solve('design') self.nw._convergence_check() @@ -336,8 +336,8 @@ def test_individual_design_path_on_connections_and_components(self): zeta_sc2_design = self.sc2.zeta.val self.sc1_v1.set_attr(m=None) - self.sc1_v1.set_attr(design=['T'], offdesign=['v'], state='l') - self.sc2_v2.set_attr(design=['T'], offdesign=['v'], state='l') + self.sc1_v1.set_attr(design=['T'], offdesign=['v'], force_state='l') + self.sc2_v2.set_attr(design=['T'], offdesign=['v'], force_state='l') self.sc2.set_attr(design_path='design2') self.pump2.set_attr(design_path='design2') @@ -395,8 +395,8 @@ def test_local_offdesign_on_connections_and_components(self): self.nw._convergence_check() self.nw.save('design1') - self.sc1_v1.set_attr(design=['T'], offdesign=['v'], state='l') - self.sc2_v2.set_attr(design=['T'], offdesign=['v'], state='l') + self.sc1_v1.set_attr(design=['T'], offdesign=['v'], force_state='l') + self.sc2_v2.set_attr(design=['T'], offdesign=['v'], force_state='l') self.sc1.set_attr(local_offdesign=True, design_path='design1') self.pump1.set_attr(local_offdesign=True, design_path='design1') @@ -439,8 +439,8 @@ def test_missing_design_path_local_offdesign_on_connections(self): self.nw._convergence_check() self.nw.save('design1') - self.sc1_v1.set_attr(design=['T'], offdesign=['v'], state='l') - self.sc2_v2.set_attr(design=['T'], offdesign=['v'], state='l') + self.sc1_v1.set_attr(design=['T'], offdesign=['v'], force_state='l') + self.sc2_v2.set_attr(design=['T'], offdesign=['v'], force_state='l') self.sc1.set_attr(local_offdesign=True, design_path='design1') self.pump1.set_attr(local_offdesign=True, design_path='design1') From d0cb31bba7060aed875408fb35bbd69a1ccddbbf Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:38:58 +0200 Subject: [PATCH 098/105] Fix errors related to (temporary) kwargs in h_pT functions --- docs/modules/fluid_properties.rst | 2 +- src/tespy/connections/connection.py | 5 ++++- src/tespy/tools/fluid_properties/wrappers.py | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/modules/fluid_properties.rst b/docs/modules/fluid_properties.rst index eb1366578..8fa02f8ba 100644 --- a/docs/modules/fluid_properties.rst +++ b/docs/modules/fluid_properties.rst @@ -184,7 +184,7 @@ isentropic change of pressure for an ideal gas. ... + self.coefficients[5] * y ** 2 ... ) / self.coefficients[6] ... - ... def h_pT(self, p, T): + ... def h_pT(self, p, T, **kwargs): ... return self._h_pT(p, T) - self.h_ref ... ... def _h_pT(self, p, T): diff --git a/src/tespy/connections/connection.py b/src/tespy/connections/connection.py index b630e651b..79b08f314 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -897,7 +897,10 @@ def fluid_balance_deriv(self, k, **kwargs): self.jacobian[k, self.fluid.J_col[f]] = -self.fluid.val[f] def calc_s(self): - return s_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=self.T.val_SI, force_state=self.force_state) + try: + return s_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=self.T.val_SI, force_state=self.force_state) + except NotImplementedError: + return np.nan def calc_Q(self): return Q_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index e52715f16..f2d916c1e 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -66,7 +66,7 @@ def T_ph(self, p, h): def T_ps(self, p, s): self._not_implemented() - def h_pT(self, p, T): + def h_pT(self, p, T, **kwargs): self._not_implemented() def h_QT(self, Q, T): @@ -354,7 +354,7 @@ def h_pQ(self, p, Q): def h_ps(self, p, s): return self.AS(P=p / 1e6, s=s / 1e3).h * 1e3 - def h_pT(self, p, T): + def h_pT(self, p, T, **kwargs): return self.AS(P=p / 1e6, T=T).h * 1e3 def h_QT(self, Q, T): @@ -454,7 +454,7 @@ def T_ph(self, p, h): def T_ps(self, p, s): return self.AS.T(p=p, s=s)[0] - def h_pT(self, p, T): + def h_pT(self, p, T, **kwargs): return self.AS.h(p=p, T=T)[0] def h_ps(self, p, s): From eb8fd8b3474fa80d61835787667125712225e323 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:39:30 +0200 Subject: [PATCH 099/105] Align some styling and run isort --- src/tespy/components/component.py | 2 +- src/tespy/networks/network.py | 3 +- src/tespy/networks/network_reader.py | 2 +- src/tespy/tools/helpers.py | 3 +- tests/test_networks/test_network.py | 54 +++++++++++++++++----------- 5 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/tespy/components/component.py b/src/tespy/components/component.py index 96ceb0822..f179f99a5 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -21,10 +21,10 @@ from tespy.tools.data_containers import ComponentCharacteristicMaps as dc_cm from tespy.tools.data_containers import ComponentCharacteristics as dc_cc from tespy.tools.data_containers import ComponentProperties as dc_cp +from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa from tespy.tools.data_containers import GroupedComponentCharacteristics as dc_gcc from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.data_containers import SimpleDataContainer as dc_simple -from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa from tespy.tools.document_models import generate_latex_eq from tespy.tools.fluid_properties import v_mix_ph from tespy.tools.global_vars import ERR diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 9efe79f60..7dee94869 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -33,9 +33,8 @@ from tespy.tools.data_containers import GroupedComponentCharacteristics as dc_gcc from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp from tespy.tools.global_vars import ERR -from tespy.tools.global_vars import fluid_property_data as fpd from tespy.tools.global_vars import component_property_data as cpd - +from tespy.tools.global_vars import fluid_property_data as fpd # Only require cupy if Cuda shall be used try: diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 748d91ca5..0e4cd8fe4 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -41,8 +41,8 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer -from tespy.components.newComponents import * from tespy.components.newAdvancedComponents import * +from tespy.components.newComponents import * from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index ab7678ee4..8b4eabe78 100644 --- a/src/tespy/tools/helpers.py +++ b/src/tespy/tools/helpers.py @@ -19,7 +19,8 @@ from tespy import __datapath__ from tespy.tools import logger from tespy.tools.global_vars import ERR -from tespy.tools.global_vars import fluid_property_data, component_property_data +from tespy.tools.global_vars import component_property_data +from tespy.tools.global_vars import fluid_property_data def get_all_subdictionaries(data): diff --git a/tests/test_networks/test_network.py b/tests/test_networks/test_network.py index f8b3d01db..4595c8bdd 100644 --- a/tests/test_networks/test_network.py +++ b/tests/test_networks/test_network.py @@ -13,7 +13,6 @@ import os import shutil -import numpy as np from pytest import mark from pytest import raises @@ -199,8 +198,10 @@ def test_Network_missing_data_in_design_case_files(self): def test_Network_missing_data_in_individual_design_case_file(self): """Test for missing data in individual design case files.""" pi = Pipe('pipe', Q=0, pr=0.95, design=['pr'], offdesign=['zeta']) - a = Connection(self.source, 'out1', pi, 'in1', m=1, p=1, T=293.15, - fluid={'water': 1}) + a = Connection( + self.source, 'out1', pi, 'in1', m=1, p=1, T=293.15, + fluid={'water': 1} + ) b = Connection(pi, 'out1', self.sink, 'in1', design_path='tmp2') self.nw.add_conns(a, b) self.nw.solve('design') @@ -224,8 +225,10 @@ def test_Network_missing_data_in_individual_design_case_file(self): def test_Network_missing_connection_in_design_path(self): """Test for missing connection data in design case files.""" pi = Pipe('pipe', Q=0, pr=0.95, design=['pr'], offdesign=['zeta']) - a = Connection(self.source, 'out1', pi, 'in1', m=1, p=1, T=293.15, - fluid={'water': 1}) + a = Connection( + self.source, 'out1', pi, 'in1', m=1, p=1, T=293.15, + fluid={'water': 1} + ) b = Connection(pi, 'out1', self.sink, 'in1') self.nw.add_conns(a, b) self.nw.solve('design') @@ -287,16 +290,20 @@ def setup_Network_individual_offdesign(self): me = Merge('merge', num_in=2) si = Sink('sink') - self.pump1.set_attr(eta_s=0.8, design=['eta_s'], - offdesign=['eta_s_char']) - self.pump2.set_attr(eta_s=0.8, design=['eta_s'], + self.pump1.set_attr( + eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char'] + ) + self.pump2.set_attr( + eta_s=0.8, design=['eta_s'], offdesign=['eta_s_char']) - self.sc1.set_attr(pr=0.95, lkf_lin=3.33, lkf_quad=0.011, A=1252, E=700, - Tamb=20, eta_opt=0.92, design=['pr'], - offdesign=['zeta']) - self.sc2.set_attr(pr=0.95, lkf_lin=3.5, lkf_quad=0.011, A=700, E=800, - Tamb=20, eta_opt=0.92, design=['pr'], - offdesign=['zeta']) + self.sc1.set_attr( + pr=0.95, lkf_lin=3.33, lkf_quad=0.011, A=1252, E=700, Tamb=20, + eta_opt=0.92, design=['pr'], offdesign=['zeta'] + ) + self.sc2.set_attr( + pr=0.95, lkf_lin=3.5, lkf_quad=0.011, A=700, E=800, Tamb=20, + eta_opt=0.92, design=['pr'], offdesign=['zeta'] + ) fl = {'H2O': 1} inlet = Connection(so, 'out1', sp, 'in1', T=50, p=3, fluid=fl) @@ -312,8 +319,10 @@ def setup_Network_individual_offdesign(self): self.sc2_v2 = Connection(self.sc2, 'out1', v2, 'in1', p=3.1, m=0.1) v2_me = Connection(v2, 'out1', me, 'in2') - self.nw.add_conns(inlet, outlet, self.sp_p1, self.p1_sc1, self.sc1_v1, - v1_me, self.sp_p2, self.p2_sc2, self.sc2_v2, v2_me) + self.nw.add_conns( + inlet, outlet, self.sp_p1, self.p1_sc1, self.sc1_v1, + v1_me, self.sp_p2, self.p2_sc2, self.sc2_v2, v2_me + ) def test_individual_design_path_on_connections_and_components(self): """Test individual design path specification.""" @@ -412,9 +421,11 @@ def test_local_offdesign_on_connections_and_components(self): # connections and components on side 1 must have switched to offdesign - msg = ('Solar collector outlet temperature must be different from ' + - 'design value ' + str(round(self.sc1_v1.T.design - 273.15, 1)) + - ', is ' + str(round(self.sc1_v1.T.val, 1)) + '.') + msg = ( + 'Solar collector outlet temperature must be different from ' + f'design value {round(self.sc1_v1.T.design - 273.15, 1)}, is ' + f'{round(self.sc1_v1.T.val, 1)}.' + ) assert self.sc1_v1.T.design > self.sc1_v1.T.val, msg msg = "Parameter eta_s_char must be set for pump one." @@ -520,7 +531,10 @@ def test_linear_branch_massflow_presolve(self): b.set_attr(pr=1) self.nwk.solve("design") self.nwk._convergence_check() - variables = [data["obj"].get_attr(data["variable"]) for data in self.nwk.variables_dict.values()] + variables = [ + data["obj"].get_attr(data["variable"]) + for data in self.nwk.variables_dict.values() + ] # no mass flow is variable assert c1.m not in variables assert c2.m not in variables From 05fc9bc8a5ece6b33434527c851bd3cbd8553fe2 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:39:52 +0200 Subject: [PATCH 100/105] Fix examples related to removal of automatic fluid balance constraint --- src/tespy/components/nodes/merge.py | 2 +- src/tespy/components/nodes/separator.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tespy/components/nodes/merge.py b/src/tespy/components/nodes/merge.py index b3b286cb2..217ef1018 100644 --- a/src/tespy/components/nodes/merge.py +++ b/src/tespy/components/nodes/merge.py @@ -112,7 +112,7 @@ class Merge(NodeBase): >>> inc1.set_attr(fluid={'O2': 0.23, 'N2': 0.77}, p=1, T=T, m=5) >>> inc2.set_attr(fluid={'O2': 1}, T=T, m=5) >>> inc3.set_attr(fluid={'N2': 1}, T=T) - >>> outg.set_attr(fluid={'N2': 0.4}) + >>> outg.set_attr(fluid={'N2': 0.4, 'O2': 0.6}) >>> nw.solve('design') >>> round(inc3.m.val_SI, 2) 0.25 diff --git a/src/tespy/components/nodes/separator.py b/src/tespy/components/nodes/separator.py index 1b4811ff0..b2000249b 100644 --- a/src/tespy/components/nodes/separator.py +++ b/src/tespy/components/nodes/separator.py @@ -127,7 +127,7 @@ class Separator(NodeBase): mass fraction for this outlet. >>> outg1.set_attr(m=None) - >>> outg2.set_attr(fluid={'O2': 0.3}) + >>> outg2.set_attr(fluid={'O2': 0.3, 'N2': 0.7}) >>> nw.solve('design') >>> outg2.fluid.val['O2'] 0.3 From 51f5e3ca840567ab06c8074b06d654238c4a5684 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:40:07 +0200 Subject: [PATCH 101/105] Allow for higher temperatures in mixtures of gases --- src/tespy/tools/fluid_properties/helpers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tespy/tools/fluid_properties/helpers.py b/src/tespy/tools/fluid_properties/helpers.py index 8b6eeb2ad..ff05661e4 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -69,7 +69,9 @@ def inverse_temperature_mixture(p=None, target_value=None, fluid_data=None, T0=N valmin, valmax = get_mixture_temperature_range(fluid_data) if T0 is None or T0 == 0 or np.isnan(T0): T0 = (valmin + valmax) / 2.0 - T0 = max(valmin,min(valmax,T0)) + T0 = max(valmin, min(valmax, T0)) + + valmax *= 2 function_kwargs.update({ "p": p, "fluid_data": fluid_data, "T": T0, From 3766c2ec9f34ba79a23932d835ea4590d2b59619 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:46:36 +0200 Subject: [PATCH 102/105] Temporarily remove the additions of new component classes and their tests The additions are very specific, therefore I will remove them for now. However, they showcase the flexibility of tespy. I would like to see them in an own repository or move some to a tutorial/example section of the docs in order to showcase the possibilities through customization. --- .gitmodules | 0 incompressiblesTests/Ex1.py | 63 - incompressiblesTests/Ex1EEMAP_ref.csv | 3 - incompressiblesTests/Ex1tespy070.csv | 3 - incompressiblesTests/Ex4.py | 90 - incompressiblesTests/Ex4EEMAP_ref.csv | 9 - incompressiblesTests/Ex4tespy070.csv | 9 - incompressiblesTests/Ex8.py | 155 -- incompressiblesTests/Ex8EEMAP_ref_1.csv | 14 - incompressiblesTests/Ex8EEMAP_ref_2.csv | 14 - incompressiblesTests/Ex8tespy070_1.csv | 14 - incompressiblesTests/Ex8tespy070_2.csv | 14 - incompressiblesTests/Ex9.py | 364 ---- incompressiblesTests/Ex9EEMAP_ref.csv | 15 - incompressiblesTests/Ex9tespy070.csv | 15 - incompressiblesTests/diff.ipynb | 215 -- .../energy-supply_energy-merge.py | 67 - .../energy-supply_energy-split.py | 67 - .../energySupply/energy-supply_heat-pump.py | 64 - .../energySupply/energy-supply_loss.py | 65 - .../initialFoodTests/food-properties.py | 228 --- .../newComponentsTests/2streamHX.py | 130 -- .../newComponentsTests/SpeciesFlowSplit.py | 55 - .../SpeciesFlowSplitDeltaP.py | 80 - .../SpeciesFlowSplitWithDeltaH-drier.py | 113 -- ...SpeciesFlowSplitWithDeltaH-drierWithAir.py | 121 -- ...plitWithDeltaH-drierWithAir_newApproach.py | 121 -- ...ltaH-drierWithAir_newApproach_MyWrapper.py | 132 -- .../SpeciesFlowSplitWithDeltaH.py | 96 - .../SpeciesFlowSplitWithDeltaT.py | 81 - ...sFlowSplitWithDeltaTDeltaP-decanterTest.py | 120 -- ...SplitWithDeltaTDeltaP-evaporatorWithHot.py | 136 -- .../SpeciesFlowSplitWithDeltaTDeltaP.py | 114 -- .../SpeciesFlowSplitWithDeltaTDeltaPBus.py | 78 - .../newComponentsTests/SplitterWithDeltaP.py | 59 - .../SplitterWithFlowSplitter.py | 71 - .../SplitterWithFlowSplitterDeltaP.py | 71 - .../newComponentsTests/heatex+merge.py | 136 -- .../newComponentsTests/heatex_alone.py | 55 - .../heatex_alone_DeltaPLfKpi.py | 122 -- .../newComponentsTests/heatex_alone_deltaP.py | 82 - .../heatex_alone_lossFactor.py | 85 - .../newComponentsTests/merge_mrk.py | 57 - .../newComponentsTests/mywrapper/MyWrapper.py | 201 -- .../mywrapper/MyWrapper_test.py | 74 - .../simple_heatex_for_jorrit.py | 64 - poetry.lock | 1774 ----------------- pyproject_.toml | 6 - .../components/energySupplyComponents.py | 839 -------- src/tespy/components/newAdvancedComponents.py | 1089 ---------- src/tespy/components/newComponents.py | 1307 ------------ 51 files changed, 8957 deletions(-) delete mode 100644 .gitmodules delete mode 100644 incompressiblesTests/Ex1.py delete mode 100644 incompressiblesTests/Ex1EEMAP_ref.csv delete mode 100644 incompressiblesTests/Ex1tespy070.csv delete mode 100644 incompressiblesTests/Ex4.py delete mode 100644 incompressiblesTests/Ex4EEMAP_ref.csv delete mode 100644 incompressiblesTests/Ex4tespy070.csv delete mode 100644 incompressiblesTests/Ex8.py delete mode 100644 incompressiblesTests/Ex8EEMAP_ref_1.csv delete mode 100644 incompressiblesTests/Ex8EEMAP_ref_2.csv delete mode 100644 incompressiblesTests/Ex8tespy070_1.csv delete mode 100644 incompressiblesTests/Ex8tespy070_2.csv delete mode 100644 incompressiblesTests/Ex9.py delete mode 100644 incompressiblesTests/Ex9EEMAP_ref.csv delete mode 100644 incompressiblesTests/Ex9tespy070.csv delete mode 100644 incompressiblesTests/diff.ipynb delete mode 100644 incompressiblesTests/energySupply/energy-supply_energy-merge.py delete mode 100644 incompressiblesTests/energySupply/energy-supply_energy-split.py delete mode 100644 incompressiblesTests/energySupply/energy-supply_heat-pump.py delete mode 100644 incompressiblesTests/energySupply/energy-supply_loss.py delete mode 100644 incompressiblesTests/initialFoodTests/food-properties.py delete mode 100644 incompressiblesTests/newComponentsTests/2streamHX.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py delete mode 100644 incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py delete mode 100644 incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py delete mode 100644 incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py delete mode 100644 incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py delete mode 100644 incompressiblesTests/newComponentsTests/heatex+merge.py delete mode 100644 incompressiblesTests/newComponentsTests/heatex_alone.py delete mode 100644 incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py delete mode 100644 incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py delete mode 100644 incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py delete mode 100644 incompressiblesTests/newComponentsTests/merge_mrk.py delete mode 100644 incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py delete mode 100644 incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py delete mode 100644 incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py delete mode 100644 poetry.lock delete mode 100644 pyproject_.toml delete mode 100644 src/tespy/components/energySupplyComponents.py delete mode 100644 src/tespy/components/newAdvancedComponents.py delete mode 100644 src/tespy/components/newComponents.py diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e69de29bb..000000000 diff --git a/incompressiblesTests/Ex1.py b/incompressiblesTests/Ex1.py deleted file mode 100644 index ac0010563..000000000 --- a/incompressiblesTests/Ex1.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Thu Dec 22 12:00:18 2022 - -@author: mrk - -This model includes -- Boiler - - -""" - -from tespy.components import Sink, Source, HeatExchangerSimple -from tespy.connections import Connection -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SimpleHeatExchanger - -import logging -#logging.basicConfig(level=logging.DEBUG) - - -network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -# Objects -source = Source('source') -boiler = HeatExchangerSimple('boiler') -sink = Sink('sink') - -# Connections -c1 = Connection(source, 'out1', boiler, 'in1') -c2 = Connection(boiler, 'out1', sink, 'in1') - -network.add_conns(c1,c2) - -# set global guess values -m0 = 100 # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar - -# set conditions around boiler -# fluid_back_ends={'Water': "INCOMP", "PHE": "INCOMP", "S800": "INCOMP"} -c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=100, h=h0, p=p0, mixing_rule="incompressible") -#c2.set_attr(h=h0,p=p0) -c2.set_attr(h=h0) -boiler.set_attr(pr=1) - -# solve and print results -network.solve('design') -# c1.set_attr(T=40, h=None) -# c2.set_attr(T=60, h=None) -# network.solve('design') - -network.print_results() - - -print(network.results['Connection']) - -network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") \ No newline at end of file diff --git a/incompressiblesTests/Ex1EEMAP_ref.csv b/incompressiblesTests/Ex1EEMAP_ref.csv deleted file mode 100644 index 2c1c3b713..000000000 --- a/incompressiblesTests/Ex1EEMAP_ref.csv +++ /dev/null @@ -1,3 +0,0 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_sink:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 diff --git a/incompressiblesTests/Ex1tespy070.csv b/incompressiblesTests/Ex1tespy070.csv deleted file mode 100644 index 91593cccb..000000000 --- a/incompressiblesTests/Ex1tespy070.csv +++ /dev/null @@ -1,3 +0,0 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,Water,S800,PHE -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.05,0.15 -boiler:out1_sink:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.8,0.05,0.15 diff --git a/incompressiblesTests/Ex4.py b/incompressiblesTests/Ex4.py deleted file mode 100644 index a65aae026..000000000 --- a/incompressiblesTests/Ex4.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Thu Dec 22 12:00:18 2022 - -@author: mrk - -This model includes -- Boiler -- Press -- Decanter (no steam is mixed into product in the pressWater) -- Centrifuge - -""" -from tespy.components import Sink, Source, SimpleHeatExchanger -from tespy.connections import Connection -from tespy.networks import Network - - -from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits - -import logging -#logging.basicConfig(level=logging.DEBUG) - -network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=False) - -# Objects -source = Source('source') -boiler = SimpleHeatExchanger('boiler') -press = SeparatorWithSpeciesSplits('press', num_out=2) -#pressWater = Sink('pressWater') -presscake = Sink('presscake') -decanter = SeparatorWithSpeciesSplits('decanter', num_out=2) -grax = Sink('grax') -oil = Sink('oil') -centrifuge = SeparatorWithSpeciesSplits('centrifuge',num_out=2) -stickWater = Sink('stickWater') - -# Connections -c1 = Connection(source, 'out1', boiler, 'in1') -c2 = Connection(boiler, 'out1', press, 'in1') -c3 = Connection(press, 'out1', presscake, 'in1') -c4 = Connection(press, 'out2', decanter, 'in1') -c5 = Connection(decanter, 'out1', grax, 'in1') -c6 = Connection(decanter, 'out2', centrifuge, 'in1') -c7 = Connection(centrifuge, 'out1', stickWater, 'in1') -c8 = Connection(centrifuge, 'out2', oil, 'in1') - -network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8) - -# set global guess values -m0 = 100 # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar - -for c in network.conns['object']: -# n_fl = len(network.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/3, 'INCOMP::PHE': 1/3, 'INCOMP::S800': 1/3}) - -# set conditions around boiler -c1.set_attr(fluid={'INCOMP::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, h=h0, p=p0, mixing_rule="incompressible") -c2.set_attr(h=h0,p=p0) - -# set conditions around press -press.set_attr(SFS={ - 'val': 0.7, 'is_set': True, - 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'INCOMP::Water': 0.50, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.45}) - -# set conditions around decanter -decanter.set_attr(SFS={ - 'val': 0.3, 'is_set': True, - 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'INCOMP::Water': 0.6, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.35}) - -# set conditions around centrifuge -centrifuge.set_attr(SFS={ - 'val': 0.8, 'is_set': True, - 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'INCOMP::PHE': 0.99, 'INCOMP::S800': 0.01}) - -# solve and print results -network.solve('design') - -# network.print_results() -print(network.results['Connection'].loc[:, [c for c in network.results["Connection"] if "unit" not in c]]) - -print(0.7 * c1.m.val_SI * c1.fluid.val["S800"] / c3.fluid.val["S800"] == network.results['Connection'].loc["press:out1_presscake:in1", "m"]) - -network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") \ No newline at end of file diff --git a/incompressiblesTests/Ex4EEMAP_ref.csv b/incompressiblesTests/Ex4EEMAP_ref.csv deleted file mode 100644 index 2e610c0f8..000000000 --- a/incompressiblesTests/Ex4EEMAP_ref.csv +++ /dev/null @@ -1,9 +0,0 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_presscake:in1,7.777777777777778,2.0,78.66612649956119,46.945715802337304,0.008221058787004482,0.001056993272614862,256.3696338669351,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341097,46.94571580233952,0.09570564307860968,0.0010377720333825146,331.87502899705527,0.0,0.0,0.158433734939759,0.016265060240963854,0.8253012048192772 -decanter:out1_grax:in1,1.2857142857142856,2.0,85.51182358236238,46.94571580233941,0.0013476962897216462,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.02952353029265,46.94571580233952,0.09435794678888804,0.0010376244803106905,332.6266240381677,0.0,0.0,0.15996683539884796,0.011546517716879038,0.8284866468842731 -centrifuge:out1_stickWater:in1,79.18149751483085,2.0,109.46751182641472,46.945715802339464,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.03674299136386185,0.011776108371890536,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.9273942545358,46.945715802339464,0.013894775614785894,0.0011820300549596216,169.02088145066307,0.0,0.0,0.99,0.01,0.0 diff --git a/incompressiblesTests/Ex4tespy070.csv b/incompressiblesTests/Ex4tespy070.csv deleted file mode 100644 index 5c9d84019..000000000 --- a/incompressiblesTests/Ex4tespy070.csv +++ /dev/null @@ -1,9 +0,0 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,PHE,S800,Water -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.15,0.05,0.8 -press:out1_presscake:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.6661264995547,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.05,0.45,0.5 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.158433734939759,0.016265060240963854,0.8253012048192772 -decanter:out1_grax:in1,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236194,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888801,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106903,m3 / kg,0.0,-,332.6266240381676,J / kgK,0.15996683539884796,0.011546517716879038,0.828486646884273 -centrifuge:out1_stickWater:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.91496499562584,J / kgK,0.036742991363861846,0.011776108371890534,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.99,0.01,0.0 diff --git a/incompressiblesTests/Ex8.py b/incompressiblesTests/Ex8.py deleted file mode 100644 index 42b48fb8a..000000000 --- a/incompressiblesTests/Ex8.py +++ /dev/null @@ -1,155 +0,0 @@ - -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter - -import logging -#logging.basicConfig(level=logging.DEBUG) - -network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -# Objects -source = Source('source') -boiler = HeatExchangerSimple('boiler') -press = SeparatorWithSpeciesSplits('press', num_out=2) -#presswater = Sink('presswater') -#presscake = Sink('presscake') -decanter = SeparatorWithSpeciesSplits('decanter', num_out=2) -#grax = Sink('grax') -oil = Sink('oil') -centrifuge = SeparatorWithSpeciesSplits('centrifuge',num_out=2) -thickener = SeparatorWithSpeciesSplits('thickener',num_out=2) -vapourextract1 = Sink('vapourextract1') -#solubles = Sink('solubles') -liquidmerge = MergeDeltaP('liquidmerge', num_in = 3) -wetproduct = Sink('wetproduct') -drier = SeparatorWithSpeciesSplits('drier',num_out=2) -meal = Sink('meal') -vapourextract2 = Sink('vapourextract2') - -# Connections -c1 = Connection(source, 'out1', boiler, 'in1') -c2 = Connection(boiler, 'out1', press, 'in1') -c3 = Connection(press, 'out1', liquidmerge, 'in1') -c4 = Connection(press, 'out2', decanter, 'in1') -c5 = Connection(decanter, 'out1', liquidmerge, 'in2') -c6 = Connection(decanter, 'out2', centrifuge, 'in1') -c7 = Connection(centrifuge, 'out1', thickener, 'in1') -c8 = Connection(centrifuge, 'out2', oil, 'in1') -c9 = Connection(thickener, 'out1', liquidmerge, 'in3') -c10 = Connection(thickener, 'out2', vapourextract1, 'in1') -c11 = Connection(liquidmerge, 'out1', drier, 'in1') -c12 = Connection(drier, 'out1', meal, 'in1') -c13 = Connection(drier, 'out2', vapourextract2, 'in1') - -network.add_conns(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13) - -# set global guess values -m0 = 100 # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar - -for c in network.conns['object']: -# n_fl = len(network.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/3, 'INCOMP::PHE': 1/3, 'INCOMP::S800': 1/3}) - -# set conditions around boiler -c1.set_attr(fluid={'INCOMP::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, h=h0, p=p0, mixing_rule="incompressible") -c2.set_attr(h=h0,p=p0) - -# set conditions around press -press.set_attr(SFS={ - 'val': 0.7, 'is_set': True, - 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'INCOMP::Water': 0.50, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.45}) - -# set conditions around decanter -decanter.set_attr(SFS={ - 'val': 0.3, 'is_set': True, - 'split_fluid' : 'S800', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'INCOMP::Water': 0.6, 'INCOMP::PHE': 0.05, 'INCOMP::S800': 0.35}) - -# set conditions around centrifuge -centrifuge.set_attr(SFS={ - 'val': 0.8, 'is_set': True, - 'split_fluid' : 'PHE', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'INCOMP::PHE': 0.99, 'INCOMP::S800': 0.01}) - -# set conditions around thickener -c10.set_attr(fluid={'INCOMP::Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) -c9.set_attr(fluid={'INCOMP::PHE': 0.25}) - -# set conditions around liquidMerge -c11.set_attr(p=p0) - -# set conditions around drier -c12.set_attr(fluid={'INCOMP::Water': 0.1}) -c13.set_attr(fluid={'INCOMP::Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) - - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) - -oilmassflow = c8.m.val -print(f"oil mass flow is {oilmassflow}") -network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070_1.csv") - -# import sys -# sys.exit() - -# %% oil cleansing - -network2 = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -# Objects -sourceFat = Source('Fat') -sourceCitricAcid = Source('CitricAcid') -centimerge = MergeDeltaP('centimerge', num_in=2) -T2 = SplitterWithFlowSplitter('T2', num_out=2) -Oil1 = Sink('Oil1') -stripper = SplitterWithFlowSplitter('stripper', num_out=2) -Oil2 = Sink('Oil2') -scrubOil = Sink('scrubOil') - -# Connections -c1 = Connection(sourceFat, 'out1', centimerge, 'in1') -c2 = Connection(sourceCitricAcid, 'out1', centimerge, 'in2') -c3 = Connection(centimerge, 'out1', T2, 'in1') -c4 = Connection(T2, 'out1', stripper, 'in1') -c5 = Connection(T2, 'out2', Oil1, 'in1') -c6 = Connection(stripper, 'out1', scrubOil, 'in1') -c7 = Connection(stripper, 'out2', Oil2, 'in1') - -network2.add_conns(c1,c2,c3,c4,c5,c6,c7) - -# set global guess values -m0 = oilmassflow # transform unit at some point -h0 = 1e2 # global guess value in kJ/kg -p0 = 2 # global guess value in bar - -for c in network2.conns['object']: - c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::S800': 1/n_fl}) - -# set conditions around merge -c1.set_attr(fluid={'INCOMP::S800': 1}, m=m0, h=h0, p=p0, mixing_rule="incompressible") -c2.set_attr(fluid={'INCOMP::Water': 1}, m=0.7*m0/1000, h=h0, p=p0) -c3.set_attr(p=p0) - -T2.set_attr(FS={'val': 0.75, 'is_set': True, 'split_outlet' : "out1"}) -stripper.set_attr(FS={'val': 0.05, 'is_set': True, 'split_outlet' : "out1"}) - -# solve and print results -network2.solve('design') -network2.print_results() -print(network2.results['Connection']) - -network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070_2.csv") diff --git a/incompressiblesTests/Ex8EEMAP_ref_1.csv b/incompressiblesTests/Ex8EEMAP_ref_1.csv deleted file mode 100644 index 9d437a9d8..000000000 --- a/incompressiblesTests/Ex8EEMAP_ref_1.csv +++ /dev/null @@ -1,14 +0,0 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 -decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 -centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 -thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 -thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 -drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 -drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/incompressiblesTests/Ex8EEMAP_ref_2.csv b/incompressiblesTests/Ex8EEMAP_ref_2.csv deleted file mode 100644 index 9d437a9d8..000000000 --- a/incompressiblesTests/Ex8EEMAP_ref_2.csv +++ /dev/null @@ -1,14 +0,0 @@ -,m,p,h,T,v,vol,s,x,Td_bp,PHE,S800,Water -source:out1_boiler:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -boiler:out1_press:in1,100.0,2.0,100.0,46.94571580233952,0.10392670186561417,0.0010392670186561417,326.0023871536029,0.0,0.0,0.15,0.05,0.8 -press:out1_liquidmerge:in1,7.777777777777778,2.0,78.66612649956694,46.94571580233742,0.008221058787004482,0.001056993272614862,256.36963386693697,0.0,0.0,0.05,0.45,0.49999999999999994 -press:out2_decanter:in1,92.22222222222223,2.0,101.79924234341111,46.94571580233952,0.09570564307860967,0.0010377720333825144,331.8750289970552,0.0,0.0,0.158433734939759,0.016265060240963854,0.825301204819277 -decanter:out1_liquidmerge:in2,1.2857142857142858,2.0,85.51182358236268,46.94571580233941,0.0013476962897216464,0.0010482082253390583,278.7159180028229,0.0,0.0,0.05,0.35,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,2.0,102.0295235302927,46.94571580233952,0.09435794678888801,0.0010376244803106903,332.6266240381676,0.0,0.0,0.15996683539884796,0.011546517716879036,0.828486646884273 -centrifuge:out1_thickener:in1,79.18149751483085,2.0,109.4675118264149,46.94571580233952,0.08046317117410214,0.0010161865296754613,356.9149649956258,0.0,0.0,0.036742991363861846,0.011776108371890533,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,2.0,51.92739425453558,46.94571580233958,0.013894775614785896,0.0011820300549596219,169.0208814506649,0.0,0.0,0.99,0.01,0.0 -thickener:out1_liquidmerge:in3,11.637460317460313,2.0,91.88882840645805,46.94571580221913,0.012327881012708413,0.0010593274371223612,299.51821675618004,0.0,0.0,0.25,0.08012486146863365,0.6698751385313658 -thickener:out2_vapourextract1:in1,67.54403719737054,2.0,112.49622078757943,46.94571580233952,0.0681352901613929,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.700952380952376,2.0,86.52471562495244,46.94571580226835,0.021896636089434426,0.0010577598405367202,282.0143891470431,0.0,0.0,0.16243405717089926,0.23585629327256125,0.6017096495565392 -drier:out1_meal:in1,9.161099531469906,2.0,53.809499855619954,46.945715802341,0.010255768072889384,0.0011194909560428973,175.20834142223455,0.0,0.0,0.3670454262601117,0.5329545737398877,0.1 -drier:out2_vapourextract2:in1,11.53985284948247,2.0,112.4962207874663,46.94571580233952,0.01164086801654601,0.0010087535923014885,366.8041041067663,-inf,,0.0,0.0,1.0 diff --git a/incompressiblesTests/Ex8tespy070_1.csv b/incompressiblesTests/Ex8tespy070_1.csv deleted file mode 100644 index e92e0c1ba..000000000 --- a/incompressiblesTests/Ex8tespy070_1.csv +++ /dev/null @@ -1,14 +0,0 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,PHE,Water -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 -press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955471,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.05,0.5 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.158433734939759,0.8253012048192772 -decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236197,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.05,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888804,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106905,m3 / kg,0.0,-,332.6266240381677,J / kgK,0.011546517716879038,0.15996683539884796,0.8284866468842731 -centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890534,0.03674299136386185,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.99,0.0 -thickener:out1_liquidmerge:in3,11.637460317460315,kg / s,0.012327881012709246,m3 / s,2.0,bar,91.88882840645775,kJ / kg,46.94571580233952,C,0.0,C,0.0010593274371224325,m3 / kg,0.0,-,299.5182167574658,J / kgK,0.08012486146863364,0.25,0.6698751385313665 -thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757946,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.5247156249476,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.01438914775736,J / kgK,0.23585629327256122,0.16243405717089926,0.6017096495565396 -drier:out1_meal:in1,9.1610995314699,kg / s,0.010255768072889368,m3 / s,2.0,bar,53.809499855616984,kJ / kg,46.94571580233952,C,0.0,C,0.0011194909560428964,m3 / kg,0.0,-,175.20834142222498,J / kgK,0.5329545737398881,0.367045426260112,0.1 -drier:out2_vapourextract2:in1,11.53985284948248,kg / s,0.01164086801654602,m3 / s,2.0,bar,112.49622078757945,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 diff --git a/incompressiblesTests/Ex8tespy070_2.csv b/incompressiblesTests/Ex8tespy070_2.csv deleted file mode 100644 index e92e0c1ba..000000000 --- a/incompressiblesTests/Ex8tespy070_2.csv +++ /dev/null @@ -1,14 +0,0 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,PHE,Water -source:out1_boiler:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 -boiler:out1_press:in1,100.0,kg / s,0.10392670186561417,m3 / s,2.0,bar,100.0,kJ / kg,46.94571580233958,C,0.0,C,0.0010392670186561417,m3 / kg,0.0,-,326.0023871536029,J / kgK,0.05,0.15,0.8 -press:out1_liquidmerge:in1,7.777777777777778,kg / s,0.008221058787004496,m3 / s,2.0,bar,78.66612649955471,kJ / kg,46.94571580233952,C,0.0,C,0.0010569932726148638,m3 / kg,0.0,-,256.3696338669534,J / kgK,0.45,0.05,0.5 -press:out2_decanter:in1,92.22222222222223,kg / s,0.09570564307860968,m3 / s,2.0,bar,101.79924234341104,kJ / kg,46.94571580233952,C,0.0,C,0.0010377720333825146,m3 / kg,0.0,-,331.87502899705527,J / kgK,0.016265060240963854,0.158433734939759,0.8253012048192772 -decanter:out1_liquidmerge:in2,1.2857142857142858,kg / s,0.0013476962897216464,m3 / s,2.0,bar,85.51182358236197,kJ / kg,46.94571580233952,C,0.0,C,0.0010482082253390583,m3 / kg,0.0,-,278.7159180028207,J / kgK,0.35,0.05,0.6 -decanter:out2_centrifuge:in1,90.93650793650794,kg / s,0.09435794678888804,m3 / s,2.0,bar,102.02952353029268,kJ / kg,46.94571580233952,C,0.0,C,0.0010376244803106905,m3 / kg,0.0,-,332.6266240381677,J / kgK,0.011546517716879038,0.15996683539884796,0.8284866468842731 -centrifuge:out1_thickener:in1,79.18149751483085,kg / s,0.08046317117410214,m3 / s,2.0,bar,109.46751182641475,kJ / kg,46.94571580233952,C,0.0,C,0.0010161865296754613,m3 / kg,0.0,-,356.9149649956258,J / kgK,0.011776108371890534,0.03674299136386185,0.9514809002642476 -centrifuge:out2_oil:in1,11.755010421677088,kg / s,0.013894775614785896,m3 / s,2.0,bar,51.92739425453574,kJ / kg,46.94571580233958,C,0.0,C,0.0011820300549596219,m3 / kg,0.0,-,169.02088145066307,J / kgK,0.01,0.99,0.0 -thickener:out1_liquidmerge:in3,11.637460317460315,kg / s,0.012327881012709246,m3 / s,2.0,bar,91.88882840645775,kJ / kg,46.94571580233952,C,0.0,C,0.0010593274371224325,m3 / kg,0.0,-,299.5182167574658,J / kgK,0.08012486146863364,0.25,0.6698751385313665 -thickener:out2_vapourextract1:in1,67.54403719737054,kg / s,0.0681352901613929,m3 / s,2.0,bar,112.49622078757946,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 -liquidmerge:out1_drier:in1,20.70095238095238,kg / s,0.02189663608943539,m3 / s,2.0,bar,86.5247156249476,kJ / kg,46.94571580233952,C,0.0,C,0.0010577598405367666,m3 / kg,0.0,-,282.01438914775736,J / kgK,0.23585629327256122,0.16243405717089926,0.6017096495565396 -drier:out1_meal:in1,9.1610995314699,kg / s,0.010255768072889368,m3 / s,2.0,bar,53.809499855616984,kJ / kg,46.94571580233952,C,0.0,C,0.0011194909560428964,m3 / kg,0.0,-,175.20834142222498,J / kgK,0.5329545737398881,0.367045426260112,0.1 -drier:out2_vapourextract2:in1,11.53985284948248,kg / s,0.01164086801654602,m3 / s,2.0,bar,112.49622078757945,kJ / kg,46.94571580233952,C,0.0,C,0.0010087535923014885,m3 / kg,,-,366.8041041067663,J / kgK,0.0,0.0,1.0 diff --git a/incompressiblesTests/Ex9.py b/incompressiblesTests/Ex9.py deleted file mode 100644 index e09896fd8..000000000 --- a/incompressiblesTests/Ex9.py +++ /dev/null @@ -1,364 +0,0 @@ - -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaTDeltaP - -import logging -#logging.basicConfig(level=logging.DEBUG) - -network = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -# Objects -source = Source('source') -boiler = HeatExchangerSimple('boiler') -press = SeparatorWithSpeciesSplitsDeltaTDeltaP('press', num_out=2) -#presswater = Sink('presswater') -#presscake = Sink('presscake') -decanter = SeparatorWithSpeciesSplitsDeltaTDeltaP('decanter', num_out=2) -#grax = Sink('grax') -oil = Sink('oil') -centrifuge = SeparatorWithSpeciesSplitsDeltaTDeltaP('centrifuge',num_out=2) -thickener = SeparatorWithSpeciesSplitsDeltaTDeltaP('thickener',num_out=2) -vapourextract1 = Sink('vapourextract1') -#solubles = Sink('solubles') -liquidmerge = MergeDeltaP('liquidmerge', num_in = 3) -wetproduct = Sink('wetproduct') -drier = SeparatorWithSpeciesSplitsDeltaTDeltaP('drier',num_out=2) -meal = Sink('meal') -vapourextract2 = Sink('vapourextract2') - -presswaterheater = HeatExchangerSimple('presswaterheater') - -# Connections -c1 = Connection(source, 'out1', boiler, 'in1') -c2 = Connection(boiler, 'out1', press, 'in1') -c3 = Connection(press, 'out1', liquidmerge, 'in1') -#c4 = Connection(press, 'out2', decanter, 'in1') -c4a = Connection(press, 'out2', presswaterheater, 'in1') -c4b= Connection(presswaterheater, 'out1', decanter, 'in1') -c5 = Connection(decanter, 'out1', liquidmerge, 'in2') -c6 = Connection(decanter, 'out2', centrifuge, 'in1') -c7 = Connection(centrifuge, 'out1', thickener, 'in1') -c8 = Connection(centrifuge, 'out2', oil, 'in1') -c9 = Connection(thickener, 'out1', liquidmerge, 'in3') -c10 = Connection(thickener, 'out2', vapourextract1, 'in1') -c11 = Connection(liquidmerge, 'out1', drier, 'in1') -c12 = Connection(drier, 'out1', meal, 'in1') -c13 = Connection(drier, 'out2', vapourextract2, 'in1') - -network.add_conns(c1,c2,c3,c4a,c4b,c5,c6,c7,c8,c9,c10,c11,c12,c13) - -# set global guess values -m0 = 100 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -for c in network.conns['object']: - # n_fl = len(network.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0)#,fluid0={'Water': 1/n_fl, 'INCOMP::S800': 1/n_fl, 'INCOMP::PHE': 1/n_fl}) - c.set_attr(p=p0) - -# set conditions around boiler -c1.set_attr(fluid={'Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=m0, T=5, mixing_rule="incompressible") -c2.set_attr(T=95) - -# set conditions around press -press.set_attr(SFS={ - 'val': 0.7, 'is_set': True, - 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) -c3.set_attr(fluid={'Water': 0.50, 'INCOMP::S800': 0.05, 'INCOMP::PHE': 0.45}) -c3.set_attr(T=85) -c4a.set_attr(T=85) -c4b.set_attr(T=95) -#c4b.set_attr(p0=1) - -# set conditions around decanter -decanter.set_attr(SFS={ - 'val': 0.3, 'is_set': True, - 'split_fluid' : 'PHE', 'split_outlet' : "out1"}) -c5.set_attr(fluid={'Water': 0.60, 'INCOMP::S800': 0.05, 'INCOMP::PHE': 0.35}) -c5.set_attr(T=90) -c6.set_attr(T=90) - -# set conditions around centrifuge -centrifuge.set_attr(SFS={ - 'val': 0.8, 'is_set': True, - 'split_fluid' : 'S800', 'split_outlet' : "out2"}) -c8.set_attr(fluid={'Water': 0, 'INCOMP::S800': 0.99, 'INCOMP::PHE': 0.01}) -c7.set_attr(T=45) -c8.set_attr(T=80) - -# set conditions around thickener -c10.set_attr(fluid={'Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) -c9.set_attr(fluid={'INCOMP::PHE': 0.25}) -c10.set_attr(T=105) -c9.set_attr(T=105) - -c10.set_attr(p=p0) - -# set conditions around liquidMerge -#c11.set_attr(p=p0) - -# set conditions around drier -c12.set_attr(fluid={'Water': 0.1}) -c13.set_attr(fluid={'Water': 1, 'INCOMP::S800': 0, 'INCOMP::PHE': 0}) -c12.set_attr(T=100) -c13.set_attr(T=100) - -c13.set_attr(p=None,x=1) - - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) - -oilmassflow = c8.m.val -print(f"oil mass flow is {oilmassflow}") -print(f"\n") -network.results["Connection"].to_csv(f"{__file__.replace('.py', '')}tespy070.csv") - -# MJ to kwh -# -for o in network.comps['object']: - if isinstance(o,SeparatorWithSpeciesSplitsDeltaTDeltaP): - print(f"heat exchange for {o.label} = {o.Q.val}") -print(f"\n") - -for o in network.comps['object']: - if isinstance(o,SeparatorWithSpeciesSplitsDeltaTDeltaP): - print(f"Total heat for {o.label} = {o.Q.val / (3.6*1e6)}") -print(f"\n") - -print(f"Total heat for boiler is {boiler.Q.val/(3.6*1e6):.1f}") -print(f"Total heat for presswater heater is {presswaterheater.Q.val/(3.6*1e6):.1f}") - - - -def get_paths(self): - def generate_paths(start, current_comp_path, current_conn_path): - # If the component is not in the connections, append the current path, we are finished - if start not in comp_connections: - comps_paths.append(current_comp_path) - conns_paths.append(current_conn_path) - return - # Iterate through the connected lists - for comp_list,conn_list in zip(comp_connections[start],conn_connections[start]): - # Recursively generate paths - generate_paths(comp_list[-1], current_comp_path + comp_list[1:], current_conn_path + conn_list) - - # make lists of component and connection branches - comp_branches = [b['components'] for b in self.nw.massflow_branches] - conn_branches = [b['connections'] for b in self.nw.massflow_branches] - - # make connections dict to iterate over - comp_connections = {} - conn_connections = {} - for comps,conns in zip(comp_branches,conn_branches): - if comps[0] not in comp_connections: - comp_connections[comps[0]] = [] - conn_connections[comps[0]] = [] - comp_connections[comps[0]].append(comps) - conn_connections[comps[0]].append(conns) - - # get sources to start from and iterate for each uniquie path - sources = [k for k in comp_connections.keys() if type(k).__name__ == "Source"] - comps_paths = [] - conns_paths = [] - for start in sources: - generate_paths(start, [start], []) - - paths = {} - paths['connections'] = sorted(conns_paths, key=len, reverse=True) - paths['components'] = sorted(comps_paths, key=len, reverse=True) - - return paths - -class SELF(): - pass - -self = SELF() -self.nw = network - -paths = get_paths(self) - -print(paths['components']) - -longest_path_components = max(paths['components'], key=len) -longest_path_components_label = [l.label for l in longest_path_components] - -path = {} -path["T"] = [] -path["source"] = [] -path["source_id"] = [] -path["target"] = [] -for conns in paths['connections']: - T = [] - source = [] - source_id = [] - target = [] - for c in conns: - T += [c.T.val] - source += [c.source.label] - source_id += [longest_path_components_label.index(c.source.label)] - target += [c.target.label] - path["T"].append(T) - path["source"].append(source) - path["source_id"].append(source_id) - - path["target"].append(target) - -longest_path_components_label - - -import matplotlib.pyplot as plt - -plt.figure() -for s,T in zip(path["source_id"],path["T"]): - #x = np.array([i for i,_ in enumerate(T)]) - #y = np.array(T) - x = [longest_path_components_label[i] for i in s] - plt.plot(x, T) - -plt.xlabel('X-axis') -plt.ylabel('Y-axis') -plt.legend() -plt.show() - - - - - - - -sankey_nodes = [] -for name,comp in self.nw.comps.iterrows(): - sankey_nodes += [name] - -#missing = [value for value in sankey_nodes if not value in longest_path_components_label] -#sankey_nodes = longest_path_components_label + missing - - -links = { - 'source': [], - 'target': [], - 'value': [], - #'color': [] -} - - -for i,c in self.nw.conns.iterrows(): - links["source"] += [sankey_nodes.index(c.source.label)] - links["target"] += [sankey_nodes.index(c.target.label)] - links["value"] += [c['object'].m.val_SI] - #links["color"] - #print(c) - -from plotly.offline import plot -import plotly.graph_objects as go -import plotly as px - - - -fig = go.Figure(go.Sankey( - #arrangement="snap", - node = dict( - pad = 100, - thickness = 20, - line = dict(color = "grey", width = 0.5), - label = sankey_nodes, - color = "blue" - ), - # node={ - # "label": sankey_nodes, - # 'pad': 10, - # 'thickness': 10, - # 'color': 'orange'}, - link=links)) -plot(fig, filename='R410A_sankey.html') - - -print("hey") - - -# "----------------------------------------------------------------------------------" -# "----------------------------------------------------------------------------------" -# "----------------------------------------------------------------------------------" -# "----------------------------------------------------------------------------------" - - - - -sankey_nodes = [] -for name,comp in self.nw.comps.iterrows(): - sankey_nodes += [name] - -#missing = [value for value in sankey_nodes if not value in longest_path_components_label] -#sankey_nodes = longest_path_components_label + missing - -links = { - 'source': [], - 'target': [], - 'value': [], - 'color': [] -} - -#colors = px.colors.DEFAULT_PLOTLY_COLORS -colors = ["rgba(242, 142, 43, 0.75)", - "rgba(118, 183, 178, 0.75)", - "rgba(176, 122, 161, 0.75)", - "rgba(156, 117, 95, 0.75)", - "rgba(237, 201, 72, 0.75)", - "rgba(186, 176, 172, 0.75)", - "rgba(89, 161, 79, 0.75)", - "rgba(255, 157, 167, 0.75)", - "rgba(78, 121, 167, 0.75)", - "rgba(225, 87, 89, 0.75)", - "rgba(100, 100, 100, 1.00)"] - -for fluid in self.nw.all_fluids: - - for i,c in self.nw.conns.iterrows(): - links["source"] += [sankey_nodes.index(c.source.label)] - links["target"] += [sankey_nodes.index(c.target.label)] - links["value"] += [c['object'].m.val_SI * c['object'].fluid.val[fluid]] - links["color"] += [colors[list(self.nw.all_fluids).index(fluid)]] - #links["color"] - #print(c) - -from plotly.offline import plot -import plotly.graph_objects as go - -fig = go.Figure(go.Sankey( - #arrangement="snap", - node = dict( - pad = 200, - thickness = 10, - #line = dict(color = "grey", width = 0.5), - label = sankey_nodes, - color = "grey" - ), - # node={ - # "label": sankey_nodes, - # 'pad': 10, - # 'thickness': 10, - # 'color': 'orange'}, - link=links)) -plot(fig, filename='R410A_sankey.html') - - -print("hey") - - - - - - - diff --git a/incompressiblesTests/Ex9EEMAP_ref.csv b/incompressiblesTests/Ex9EEMAP_ref.csv deleted file mode 100644 index 1de6f2543..000000000 --- a/incompressiblesTests/Ex9EEMAP_ref.csv +++ /dev/null @@ -1,15 +0,0 @@ -,m,p,h,T,v,vol,s,x,Td_bp,Water,PHE,S800 -source:out1_boiler:in1,100.0,5.0,11.927817356454685,5.0,0.10244903431560166,0.0010244903431560167,42.17534307955257,0.0,0.0,0.8,0.15,0.05 -boiler:out1_press:in1,100.0,5.0,347.73276629402903,95.0,0.10731885384290359,0.0010731885384290358,1087.6845264098968,0.0,0.0,0.8,0.15,0.05 -press:out1_liquidmerge:in1,23.333333333333332,5.0,242.16768988793567,85.0,0.026160149686381976,0.0011211492722735133,763.1933790048553,0.0,0.0,0.49999999999999994,0.45,0.05 -press:out2_presswaterheater:in1,76.66666666666667,5.0,330.6883654544387,84.99999999999449,0.08038044079569369,0.0010484405321177436,1051.0286927193201,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 -presswaterheater:out1_decanter:in1,76.66666666666667,5.0,370.2784672443261,94.99999999999687,0.08096049019323474,0.0010560063938248009,1160.053457653331,0.0,0.0,0.8913043478260869,0.05869565217391304,0.049999999999999996 -decanter:out1_liquidmerge:in2,3.857142857142857,5.0,281.54439230506006,90.0,0.0042684792118244125,0.001106642758621144,883.2089826934414,0.0,0.0,0.6,0.35,0.05 -decanter:out2_centrifuge:in1,72.80952380952381,5.0,354.12058245226905,89.99999999999864,0.07639654564835188,0.0010492658329727858,1117.6733425160928,0.0,0.0,0.9067364290385874,0.043263570961412694,0.04999999999999999 -centrifuge:out1_thickener:in1,69.86772486772487,5.0,181.05101285530006,44.99999999997766,0.07114264015923703,0.0010182475569932448,611.6350715142114,0.0,0.0,0.944914804998107,0.044664142370314276,0.010421052631578944 -centrifuge:out2_oil:in1,2.9417989417989414,5.0,100.0781863246528,80.0,0.003335242690945141,0.0011337425694040138,308.9315041090459,0.0,0.0,0.0,0.01,0.99 -thickener:out1_liquidmerge:in3,12.482328042328044,5.0,356.36268450896694,105.00000000000028,0.013748836912735783,0.0011014641552531674,1096.5687083290452,0.0,0.0,0.6916699164109263,0.25,0.058330083589074044 -thickener:out2_vapourextract1:in1,57.385396825396825,5.0,440.55426498775586,104.99999999999773,0.060096661478605574,0.0010472465958797524,1363.0390021793273,-1.0,,1.0,0.0,0.0 -liquidmerge:out1_drier:in1,39.67280423280423,5.0,281.9254277292509,92.28684488833795,0.044193935239153596,0.0011139604596594405,880.7937574528526,0.0,0.0,0.5700278468317561,0.37735124350507326,0.05262090966317069 -drier:out1_meal:in1,18.953556731334505,5.0,184.93088408428466,99.99999999999937,0.022841343955262234,0.001205121776299661,559.4856087856919,0.0,0.0,0.1,0.7898560794044667,0.11014392059553352 -drier:out2_vapourextract2:in1,20.719247501469727,1.0141799666808606,2675.5698844230105,100.00000000224776,34.637736274183936,1.6717661329991302,7354.119145674784,1.0,,1.0,0.0,0.0 diff --git a/incompressiblesTests/Ex9tespy070.csv b/incompressiblesTests/Ex9tespy070.csv deleted file mode 100644 index 73eee03f7..000000000 --- a/incompressiblesTests/Ex9tespy070.csv +++ /dev/null @@ -1,15 +0,0 @@ -,m,m_unit,v,v_unit,p,p_unit,h,h_unit,T,T_unit,Td_bp,Td_bp_unit,vol,vol_unit,x,x_unit,s,s_unit,S800,Water,PHE -source:out1_boiler:in1,100.0,kg / s,0.10244903431560048,m3 / s,5.0,bar,11.927817356454685,kJ / kg,4.999999999986585,C,-146.8310791030812,C,0.0010244903431560048,m3 / kg,0.0,-,42.1753430798432,J / kgK,0.05,0.8,0.15 -boiler:out1_press:in1,100.0,kg / s,0.10731885384290363,m3 / s,5.0,bar,347.73276629402903,kJ / kg,95.00000000000261,C,-56.83107910306518,C,0.0010731885384290363,m3 / kg,0.0,-,1087.6845264099145,J / kgK,0.05,0.8,0.15 -press:out1_liquidmerge:in1,23.333333333333332,kg / s,0.026160149686381987,m3 / s,5.0,bar,242.16768988793567,kJ / kg,85.00000000000057,C,-66.83107910306722,C,0.0011211492722735137,m3 / kg,0.0,-,763.1933790048797,J / kgK,0.05,0.5,0.45 -press:out2_presswaterheater:in1,76.66666666666667,kg / s,0.0803804407956943,m3 / s,5.0,bar,330.68836545439535,kJ / kg,85.00000000000426,C,-66.83107910306353,C,0.0010484405321177516,m3 / kg,0.0,-,1051.0286927194445,J / kgK,0.04999999999999999,0.8913043478260869,0.05869565217391304 -presswaterheater:out1_decanter:in1,76.66666666666667,kg / s,0.08096049019323556,m3 / s,5.0,bar,370.27846724430117,kJ / kg,95.00000000000495,C,-56.83107910306285,C,0.0010560063938248117,m3 / kg,0.0,-,1160.053457653377,J / kgK,0.04999999999999999,0.8913043478260869,0.05869565217391304 -decanter:out1_liquidmerge:in2,3.8571428571428577,kg / s,0.004268479211824418,m3 / s,5.0,bar,281.54439230506006,kJ / kg,89.99999999999983,C,-61.831079103067964,C,0.0011066427586211452,m3 / kg,0.0,-,883.2089826934339,J / kgK,0.05,0.6,0.35 -decanter:out2_centrifuge:in1,72.80952380952381,kg / s,0.07639654564835216,m3 / s,5.0,bar,354.12058245225813,kJ / kg,90.00000000000034,C,-61.83107910306745,C,0.0010492658329727897,m3 / kg,0.0,-,1117.6733425160814,J / kgK,0.05,0.9067364290385873,0.0432635709614127 -centrifuge:out1_thickener:in1,69.86772486772487,kg / s,0.07114264015923918,m3 / s,5.0,bar,181.05101285511884,kJ / kg,45.000000000011994,C,-106.8310791030558,C,0.0010182475569932756,m3 / kg,0.0,-,611.6350715146631,J / kgK,0.010421052631578945,0.9449148049981068,0.04466414237031428 -centrifuge:out2_oil:in1,2.941798941798942,kg / s,0.0033352426909451405,m3 / s,5.0,bar,100.0781863246528,kJ / kg,79.99999999999994,C,-71.83107910306785,C,0.0011337425694040136,m3 / kg,0.0,-,308.9315041090459,J / kgK,0.99,0.0,0.01 -thickener:out1_liquidmerge:in3,12.482328042328042,kg / s,0.013748836912735735,m3 / s,5.0,bar,356.3626845089672,kJ / kg,104.99999999999858,C,-46.831079103069214,C,0.0011014641552531638,m3 / kg,0.0,-,1096.5687083290277,J / kgK,0.05833008358907411,0.6916699164109258,0.25 -thickener:out2_vapourextract1:in1,57.385396825396825,kg / s,0.060096661478604874,m3 / s,5.0,bar,440.55426498767247,kJ / kg,104.99999999999773,C,-46.83107910307007,C,0.0010472465958797402,m3 / kg,-1.0,-,1363.039002179117,J / kgK,0.0,1.0,0.0 -liquidmerge:out1_drier:in1,39.67280423280423,kg / s,0.044193935239153596,m3 / s,5.0,bar,281.925427729251,kJ / kg,92.28684488833983,C,-59.544234214727965,C,0.0011139604596594405,m3 / kg,0.0,-,880.7937574528644,J / kgK,0.052620909663170706,0.5700278468317559,0.3773512435050734 -drier:out1_meal:in1,18.95355673133452,kg / s,0.022841343955262276,m3 / s,5.0,bar,184.93088408428306,kJ / kg,100.00000000000051,C,-51.83107910306728,C,0.0012051217762996623,m3 / kg,0.0,-,559.4856087857008,J / kgK,0.1101439205955335,0.1,0.7898560794044664 -drier:out2_vapourextract2:in1,20.719247501469713,kg / s,34.63773627778022,m3 / s,1.0141799665682765,bar,2675.569884418101,kJ / kg,99.999999999137,C,0.0,C,1.6717661331727036,m3 / kg,1.0,-,7354.1191457120685,J / kgK,0.0,1.0,0.0 diff --git a/incompressiblesTests/diff.ipynb b/incompressiblesTests/diff.ipynb deleted file mode 100644 index e003dabae..000000000 --- a/incompressiblesTests/diff.ipynb +++ /dev/null @@ -1,215 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "m 2.220446e-16\n", - "p 0.000000e+00\n", - "h 6.494361e-12\n", - "T 2.223999e-12\n", - "v 0.000000e+00\n", - "vol 0.000000e+00\n", - "s 1.830358e-11\n", - "x 0.000000e+00\n", - "Td_bp 0.000000e+00\n", - "PHE 0.000000e+00\n", - "S800 0.000000e+00\n", - "Water 1.110223e-16\n", - "dtype: float64" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.read_csv(\"Ex4tespy070.csv\", index_col=0)\n", - "df.index = df.index.str.lower()\n", - "df_ref = pd.read_csv(\"Ex4EEMAP_ref.csv\", index_col=0)\n", - "df_ref.index = df_ref.index.str.lower()\n", - "(df.loc[:, df_ref.columns] - df_ref).abs().max()" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "m 0.000000e+00\n", - "p 0.000000e+00\n", - "h 0.000000e+00\n", - "T 5.684342e-14\n", - "v 0.000000e+00\n", - "vol 0.000000e+00\n", - "s 0.000000e+00\n", - "x 0.000000e+00\n", - "Td_bp 0.000000e+00\n", - "PHE 0.000000e+00\n", - "S800 0.000000e+00\n", - "Water 0.000000e+00\n", - "dtype: float64" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.read_csv(\"Ex1tespy070.csv\", index_col=0)\n", - "df.index = df.index.str.lower()\n", - "df_ref = pd.read_csv(\"Ex1EEMAP_ref.csv\", index_col=0)\n", - "df_ref.index = df_ref.index.str.lower()\n", - "(df.loc[:, df_ref.columns] - df_ref).abs().max()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "m 1.065814e-14\n", - "p 0.000000e+00\n", - "h 1.131468e-10\n", - "T 1.203944e-10\n", - "v 8.985868e-16\n", - "vol 9.996344e-17\n", - "s 1.285741e-09\n", - "x 0.000000e+00\n", - "Td_bp 0.000000e+00\n", - "PHE 2.775558e-16\n", - "S800 3.330669e-16\n", - "Water 6.661338e-16\n", - "dtype: float64" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.read_csv(\"Ex8tespy070_1.csv\", index_col=0)\n", - "df.index = df.index.str.lower()\n", - "df_ref = pd.read_csv(\"Ex8EEMAP_ref_1.csv\", index_col=0)\n", - "df_ref.index = df_ref.index.str.lower()\n", - "(df.loc[:, df_ref.columns] - df_ref).abs().max()" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "m 1.065814e-14\n", - "p 0.000000e+00\n", - "h 1.131468e-10\n", - "T 1.203944e-10\n", - "v 8.985868e-16\n", - "vol 9.996344e-17\n", - "s 1.285741e-09\n", - "x 0.000000e+00\n", - "Td_bp 0.000000e+00\n", - "PHE 2.775558e-16\n", - "S800 3.330669e-16\n", - "Water 6.661338e-16\n", - "dtype: float64" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.read_csv(\"Ex8tespy070_2.csv\", index_col=0)\n", - "df.index = df.index.str.lower()\n", - "df_ref = pd.read_csv(\"Ex8EEMAP_ref_2.csv\", index_col=0)\n", - "df_ref.index = df_ref.index.str.lower()\n", - "(df.loc[:, df_ref.columns] - df_ref).abs().max()" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "m 1.421085e-14\n", - "p 1.125842e-10\n", - "h 4.909452e-09\n", - "T 3.110756e-09\n", - "v 3.596284e-09\n", - "vol 1.735734e-10\n", - "s 3.728383e-08\n", - "x 0.000000e+00\n", - "Td_bp 0.000000e+00\n", - "Water 6.661338e-16\n", - "PHE 2.220446e-16\n", - "S800 1.040834e-16\n", - "dtype: float64" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df = pd.read_csv(\"Ex9tespy070.csv\", index_col=0)\n", - "df.index = df.index.str.lower()\n", - "df_ref = pd.read_csv(\"Ex9EEMAP_ref.csv\", index_col=0)\n", - "df_ref.index = df_ref.index.str.lower()\n", - "(df.loc[:, df_ref.columns] - df_ref).abs().max()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "tespy-env", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/incompressiblesTests/energySupply/energy-supply_energy-merge.py b/incompressiblesTests/energySupply/energy-supply_energy-merge.py deleted file mode 100644 index 951d291f5..000000000 --- a/incompressiblesTests/energySupply/energy-supply_energy-merge.py +++ /dev/null @@ -1,67 +0,0 @@ -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection, Ref, Bus -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.energySupplyComponents import * - -import logging -logging.basicConfig(level=logging.DEBUG) - -from CoolProp.CoolProp import PropsSI - - - - -fluid_list = ['INCOMP::Water'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -# Objects -PurchasedNaturalGas1 = Source('PurchasedNaturalGas1') -PurchasedNaturalGas2 = Source('PurchasedNaturalGas2') - -Merge = MergeEnergySupply('Merge',num_in = 2) - -Consumer = Sink('Consumer') - - -# Connections -c1 = Connection(PurchasedNaturalGas1, 'out1', Merge, 'in1') -c2 = Connection(PurchasedNaturalGas2, 'out1', Merge, 'in2') -c3 = Connection(Merge, 'out1', Consumer, 'in1') - -network.add_conns(c1,c2,c3) - -m0 = 4.428 - -c1.set_attr(m=m0) -c2.set_attr(m=m0/4) - -# guess -for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}, mixing_rule="incompressible") - -# arbitray values -c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) -c2.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) -c3.set_attr(h=0,p=1) -# merge already propergate h, p and fluid - -network.solve('design',init_only=True) - -for c in network.conns['object']: - print(c.p.val_SI) -for c in network.conns['object']: - print(c.h.val_SI) -for c in network.conns['object']: - print(c.T.val_SI) - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) - diff --git a/incompressiblesTests/energySupply/energy-supply_energy-split.py b/incompressiblesTests/energySupply/energy-supply_energy-split.py deleted file mode 100644 index 85558efbc..000000000 --- a/incompressiblesTests/energySupply/energy-supply_energy-split.py +++ /dev/null @@ -1,67 +0,0 @@ -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection, Ref, Bus -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.energySupplyComponents import * - -import logging -logging.basicConfig(level=logging.DEBUG) - -from CoolProp.CoolProp import PropsSI - - - - -fluid_list = ['INCOMP::Water'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -# Objects -PurchasedNaturalGas = Source('PurchasedNaturalGas') - -Splitter1 = SplitterEnergySupply('Splitter1',num_out = 2) - -Consumer1 = Sink('Consumer1') -Consumer2 = Sink('Consumer2') - - - -# Connections -c1 = Connection(PurchasedNaturalGas, 'out1', Splitter1, 'in1') -c2 = Connection(Splitter1, 'out1', Consumer1, 'in1') -c3 = Connection(Splitter1, 'out2', Consumer2, 'in1') - -network.add_conns(c1,c2,c3) - -m0 = 4.428 - -c1.set_attr(m=m0) -c2.set_attr(m=m0/4) - -# guess -for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}, mixing_rule="incompressible") - -# arbitray values -c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}) -c2.set_attr(h=0,p=1) -c3.set_attr(h=0,p=1) - -network.solve('design',init_only=True) - -for c in network.conns['object']: - print(c.p.val_SI) -for c in network.conns['object']: - print(c.h.val_SI) -for c in network.conns['object']: - print(c.T.val_SI) - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) - diff --git a/incompressiblesTests/energySupply/energy-supply_heat-pump.py b/incompressiblesTests/energySupply/energy-supply_heat-pump.py deleted file mode 100644 index fe84b6f73..000000000 --- a/incompressiblesTests/energySupply/energy-supply_heat-pump.py +++ /dev/null @@ -1,64 +0,0 @@ -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection, Ref, Bus -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.energySupplyComponents import * - -import logging -logging.basicConfig(level=logging.DEBUG) - -from CoolProp.CoolProp import PropsSI - - - - -fluid_list = ['INCOMP::Water'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -# Objects -PurchasedElectricity = Source('PurchasedElectricity') -HeatPump = MassFactorEnergySupply('HeatPump') -Heating = Sink('Consumer1') -Cooling = Sink('Consumer2') - -# Connections -c1 = Connection(PurchasedElectricity, 'out1', HeatPump, 'in1') -c2 = Connection(HeatPump, 'out1', Heating, 'in1') -c3 = Connection(HeatPump, 'out2', Cooling, 'in1') - -network.add_conns(c1,c2,c3) - -m0 = 4.428 -c1.set_attr(m=m0) -#c2.set_attr(m=m0*3.5) - -HeatPump.set_attr(COP=3) - - -# guess -for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}) - -# arbitray values -c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}, mixing_rule="incompressible") -c2.set_attr(h=0,p=1) -c3.set_attr(h=0,p=1) - -network.solve('design',init_only=True) - -for c in network.conns['object']: - print(c.p.val_SI) -for c in network.conns['object']: - print(c.h.val_SI) -for c in network.conns['object']: - print(c.T.val_SI) - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) diff --git a/incompressiblesTests/energySupply/energy-supply_loss.py b/incompressiblesTests/energySupply/energy-supply_loss.py deleted file mode 100644 index 1012f701e..000000000 --- a/incompressiblesTests/energySupply/energy-supply_loss.py +++ /dev/null @@ -1,65 +0,0 @@ -from tespy.components import Sink, Source, HeatExchangerSimple, Splitter -from tespy.connections import Connection, Ref, Bus -from tespy.networks import Network -import shutil -import numpy as np -import matplotlib.pyplot as plt - -from tespy.components import Separator,Merge,CycleCloser,Valve,Splitter -from tespy.components.energySupplyComponents import * - -import logging -logging.basicConfig(level=logging.DEBUG) - -from CoolProp.CoolProp import PropsSI - - - - -fluid_list = ['INCOMP::Water'] -network = Network(fluids=fluid_list, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -# Objects -PurchasedElectricity = Source('PurchasedElectricity') -LossModel = MassLossEnergySupply('LossModel') -Heating = Sink('Consumer1') -Cooling = Sink('Consumer2') - -# Connections -c1 = Connection(PurchasedElectricity, 'out1', LossModel, 'in1') -c2 = Connection(LossModel, 'out1', Heating, 'in1') -c3 = Connection(LossModel, 'out2', Cooling, 'in1') - -network.add_conns(c1,c2,c3) - -m0 = 4.428 -c1.set_attr(m=m0) -#c2.set_attr(m=m0*0.9) -LossModel.set_attr(Loss=0.1) - -# guess -for c in network.conns['object']: - c.set_attr(m0=m0,h0=0,p0=1,fluid0={'INCOMP::Water': 1}) - -# arbitray values -c1.set_attr(h=0,p=1,fluid={'INCOMP::Water': 1}, mixing_rule="incompressible") -c2.set_attr(h=0,p=1) -c3.set_attr(h=0,p=1) - -# c2 as split already propergate h, p and fluid -# c3 as split already propergate h, p and fluid - -network.solve('design',init_only=True) - -for c in network.conns['object']: - print(c.p.val_SI) -for c in network.conns['object']: - print(c.h.val_SI) -for c in network.conns['object']: - print(c.T.val_SI) - -# solve and print results -network.solve('design') - -network.print_results() -print(network.results['Connection']) diff --git a/incompressiblesTests/initialFoodTests/food-properties.py b/incompressiblesTests/initialFoodTests/food-properties.py deleted file mode 100644 index dbf17920c..000000000 --- a/incompressiblesTests/initialFoodTests/food-properties.py +++ /dev/null @@ -1,228 +0,0 @@ -# %% -# -*- coding: utf-8 -*- -""" -Created on Thu Dec 22 22:41:28 2022 - -@author: mrk -""" - -import CoolProp.CoolProp as CP -import numpy as np -import matplotlib.pyplot as plt -from decimal import Decimal - -print("loaded modules") - -# %% - -Temps = np.linspace(-40,150,50) - -cp = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -k = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -a = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -d = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -a2 = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } - -#Specific heat, kJ/(kg·K) -for T in Temps: - cp['Protein'] += [2.0082 + 1.2089 * 1e-3*T - 1.3129 * 1e-6*T**2] - cp['Fat'] += [1.9842 + 1.4733 * 1e-3*T - 4.8008 * 1e-6*T**2] - cp['Carbohydrate'] += [1.5488 + 1.9625 * 1e-3*T - 5.9399 * 1e-6*T**2] - cp['Fiber'] += [1.8459 + 1.8306 * 1e-3*T - 4.6509 * 1e-6*T**2] - cp['Ash'] += [1.0926 + 1.8896 * 1e-3*T - 3.6817 * 1e-6*T**2] - cp['Water'] += [4.1289 - 9.0864 * 1e-5*T + 5.4731 * 1e-6*T**2] - - k['Protein'] += [1.7881 * 1e-1 + 1.1958 * 1e-3*T - 2.7178 * 1e-6*T**2] - k['Fat'] += [1.8071 * 1e-1 - 2.7604 * 1e-4*T - 1.7749 * 1e-7*T**2] - k['Carbohydrate'] += [2.0141 * 1e-1 + 1.3874 * 1e-3*T - 4.3312 * 1e-6*T**2] - k['Fiber'] += [1.8331 * 1e-1 + 1.2497 * 1e-3*T - 3.1683 * 1e-6*T**2] - k['Ash'] += [3.2962 * 1e-1 + 1.4011 * 1e-3*T - 2.9069 * 1e-6*T**2] - k['Water'] += [5.7109 * 1e-1 + 1.7625 * 1e-3*T - 6.7036 * 1e-6*T**2] - - a['Protein'] += [6.8714 * 1e-8 + 4.7578 * 1e-10*T - 1.4646 * 1e-12*T**2] - a['Fat'] += [9.8777 * 1e-8 - 1.2569 * 1e-11*T - 3.8286 * 1e-14*T**2] - a['Carbohydrate'] += [8.0842 * 1e-8 + 5.3052 * 1e-10*T - 2.3218 * 1e-12*T**2] - a['Fiber'] += [7.3976 * 1e-8 + 5.1902 * 1e-10*T - 2.2202 * 1e-12*T**2] - a['Ash'] += [1.2461 * 1e-7 + 3.7321 * 1e-10*T - 1.2244 * 1e-12*T**2] - a['Water'] += [1.3168 * 1e-7 + 6.2477 * 1e-10*T - 2.4022 * 1e-12*T**2] - - d['Protein'] += [1.3299 * 1e3 - 5.1840 * 1e-1*T] - d['Fat'] += [9.2559 * 1e2 - 4.1757 * 1e-1*T] - d['Carbohydrate'] += [1.5991 * 1e3 - 3.1046 * 1e-1*T] - d['Fiber'] += [1.3115 * 1e3 - 3.6589 * 1e-1*T] - d['Ash'] += [2.4238 * 1e3 - 2.8063 * 1e-1*T] - d['Water'] += [9.9718 * 1e2 + 3.1439 * 1e-3*T - 3.7574 * 1e-3*T**2] - -a2['Protein'] = [k/(cp*d) for k,cp,d in zip(k['Protein'],cp['Protein'],d['Protein'])] -a2['Fat'] = [k/(cp*d) for k,cp,d in zip(k['Fat'],cp['Fat'],d['Fat'])] -a2['Carbohydrate'] = [k/(cp*d) for k,cp,d in zip(k['Carbohydrate'],cp['Carbohydrate'],d['Carbohydrate'])] -a2['Fiber'] = [k/(cp*d) for k,cp,d in zip(k['Fiber'],cp['Fiber'],d['Fiber'])] -a2['Ash'] = [k/(cp*d) for k,cp,d in zip(k['Ash'],cp['Ash'],d['Ash'])] -a2['Water'] = [k/(cp*d) for k,cp,d in zip(k['Water'],cp['Water'],d['Water'])] - - -fig, ax = plt.subplots(2, 2, figsize=(16, 8)) -ax = ax.flatten() -[a.grid() for a in ax] -[a.set_xlabel('temperature, C') for a in ax] - -for i,key in enumerate(cp): - ax[0].scatter(Temps, cp[key],label=str(key)) - -for i,key in enumerate(k): - ax[1].scatter(Temps, k[key],label=str(key)) - -for i,key in enumerate(a): - ax[2].scatter(Temps, [a/a2*1000 for a,a2 in zip(a[key],a2[key])],label=str(key)) - -for i,key in enumerate(d): - ax[3].scatter(Temps, d[key],label=str(key)) - -[a.legend() for a in ax] -ax[0].set_ylabel('cp') -ax[1].set_ylabel('k') -ax[2].set_ylabel('a') -ax[3].set_ylabel('d') - -fig.show - - -np.set_printoptions(precision=5,suppress=False) - -Temps -print('\n') - - -for key in [cp,k,d]: - print(np.array(key['Protein'])) -print('\n') -for key in [cp,k,d]: - print(np.array(key['Fat'])) -print('\n') -for key in [cp,k,d]: - print(np.array(key['Carbohydrate'])) -print('\n') -for key in [cp,k,d]: - print(np.array(key['Fiber'])) -print('\n') -for key in [cp,k,d]: - print(np.array(key['Ash'])) -print('\n') -for key in [cp,k,d]: - print(np.array(key['Water'])) - -# %% - - -CP.get_global_param_string("version") -fl = CP.get_global_param_string("FluidsList") - - -CP_cp = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -CP_k = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } -CP_d = {'Protein' : [], - 'Fat' : [], - 'Carbohydrate' : [], - 'Fiber' : [], - 'Ash' : [], - 'Water' : [] - } - -Temps[0] = Temps[0] +1e-4 -Temps[-1] = Temps[-1] -1e-4 - - -#Specific heat, kJ/(kg·K) -for T in Temps: - CP_cp['Protein'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] - CP_cp['Fat'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodFat')] - CP_cp['Carbohydrate'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] - CP_cp['Fiber'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] - CP_cp['Ash'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] - CP_cp['Water'] += [CP.PropsSI('C','T',T+273.15,'P',101325,'INCOMP::FoodWater')] - - CP_k['Protein'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] - CP_k['Fat'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodFat')] - CP_k['Carbohydrate'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] - CP_k['Fiber'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] - CP_k['Ash'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] - CP_k['Water'] += [CP.PropsSI('L','T',T+273.15,'P',101325,'INCOMP::FoodWater')] - - CP_d['Protein'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodProtein')] - CP_d['Fat'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodFat')] - CP_d['Carbohydrate'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodCarbohydrate')] - CP_d['Fiber'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodFiber')] - CP_d['Ash'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodAsh')] - CP_d['Water'] += [CP.PropsSI('D','T',T+273.15,'P',101325,'INCOMP::FoodWater')] - - - -fig, ax = plt.subplots(2, 2, figsize=(16, 8)) -ax = ax.flatten() -[a.grid() for a in ax] -[a.set_xlabel('temperature, C') for a in ax] - -for i,key in enumerate(CP_cp): - ax[0].scatter(Temps, CP_cp[key],label=str(key)) - -for i,key in enumerate(CP_k): - ax[1].scatter(Temps, CP_k[key],label=str(key)) - -# ax[2].scatter(Temps, [a/a2*1000 for a,a2 in zip(a[key],a2[key])],label=str(key)) - -for i,key in enumerate(CP_d): - ax[3].scatter(Temps, CP_d[key],label=str(key)) - -[a.legend() for a in ax] -ax[0].set_ylabel('cp') -ax[1].set_ylabel('k') -ax[3].set_ylabel('d') - - - -plt.show(block=True) - - - diff --git a/incompressiblesTests/newComponentsTests/2streamHX.py b/incompressiblesTests/newComponentsTests/2streamHX.py deleted file mode 100644 index bc2c044f3..000000000 --- a/incompressiblesTests/newComponentsTests/2streamHX.py +++ /dev/null @@ -1,130 +0,0 @@ -from tespy.components import Sink, Source, HeatExchanger -from tespy.components.newComponents import TwoStreamHeatExchanger - -from tespy.connections import Connection -from tespy.networks import Network -from tespy.tools import document_model -import shutil - -import logging -logging.basicConfig(level=logging.DEBUG) - - -nw = Network(T_unit='C', p_unit='bar', h_unit='kJ / kg', iterinfo=True) - - - -hot_i = Source('hot in') -hot_o = Sink('hot out') - -cold_i = Source('cold in') -cold_o = Sink('cold out') - -he = TwoStreamHeatExchanger('heat exchanger') -#he.component() - -hot_in_he = Connection(hot_i, 'out1', he, 'in1') -hot_he_out = Connection(he, 'out1', hot_o, 'in1') -cold_in_he = Connection(cold_i, 'out1', he, 'in2') -cold_he_out = Connection(he, 'out2', cold_o, 'in1') -nw.add_conns(hot_in_he, hot_he_out, cold_in_he, cold_he_out) - -for c in nw.conns['object']: - n_fl=3 - c.set_attr(m0=0.5,h0=1e2,p0=3, mixing_rule="incompressible") - #c.set_attr(fluid0={"HEOS::Water": 1/n_fl, 'INCOMP::PHE': 1/n_fl, 'INCOMP::S800': 1/n_fl}) - #c.set_attr(fluid0={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}) - c.set_attr(force_state='l') - c.set_attr(good_starting_values=True) - -he.set_attr(pr1=1, pr2=1) -cold_in_he.set_attr(fluid={'HEOS::Water': 1}, T=1, m=1, p=3,mixing_rule="incompressible") -hot_in_he.set_attr(fluid={'HEOS::Water': 0.8,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, T=35, m=0.5, p=3) -hot_he_out.set_attr(T=30) - -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - -# play with terminal -he.set_attr(ttd_l = 3) -hot_he_out.set_attr(T=None) -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - -# play with terminal -#he.set_attr(ttd_l = None,ttd_u = 3) # this is not possible because cold stream has lower capacitance flow -he.set_attr(ttd_l = None,ttd_min = 15) # using new model with pinch -hot_he_out.set_attr(T=None) -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - -Ti1 = nw.results['Connection']['T'][0] -To1 = nw.results['Connection']['T'][1] -Ti2 = nw.results['Connection']['T'][2] -To2 = nw.results['Connection']['T'][3] - -dTA = (Ti1-To2) -dTB = (To1-Ti2) -import numpy as np -LMDT = (dTA-dTB)/np.log(dTA/dTB) -UA = -he.Q.val/LMDT - -if not he.kA.val == UA: - raise Exception("UA did not compare") - -he.set_attr(ttd_l = None,ttd_min = None,kA=10e3) # using new model with pinch -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - - -# switch hot and cold -cold_in_he.set_attr(T=50, m=1, p=3,mixing_rule="incompressible") -hot_in_he.set_attr(T=20, m=0.5, p=3) -hot_he_out.set_attr(T=25) -he.set_attr(ttd_l = None,ttd_min = None,kA=None) # using new model with pinch -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - -# why negative Q and ttd_u and ttd_l - -cold_in_he.set_attr(T=50, m=1, p=3,mixing_rule="incompressible") -hot_in_he.set_attr(T=20, m=0.5, p=3) -hot_he_out.set_attr(T=None) -he.set_attr(ttd_l = None,ttd_min = 5) # using new model with pinch -nw.solve("design",print_results=True) -if not nw.converged: - raise Exception("not converged") -nw.print_results(colored=True, print_results=False) -print(nw.results['Connection'][[c for c in nw.results['Connection'].columns if not (c[-4:]=="unit" or c in ["v","Td_bp","s"])]]) - - - - -# nw.save('tmp') - -# round(ex_he.T.val - he_cw.T.val, 0) -# ex_he.set_attr(v=0.075) -# nw.solve('offdesign', design_path='tmp') -# round(he_cw.T.val, 1) -# round(he_ex.T.val, 1) -# ex_he.set_attr(v=0.1, T=40) -# nw.solve('offdesign', design_path='tmp') -# document_model(nw) -# round(he_cw.T.val, 1) -# round(he_ex.T.val, 1) -# shutil.rmtree('./tmp', ignore_errors=True) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py deleted file mode 100644 index cef5dd53a..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplit.py +++ /dev/null @@ -1,55 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -so = Source("Source") -se = SeparatorWithSpeciesSplits("Separator") -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") - -# set compositions -c2.set_attr(fluid={"INCOMP::Water": 0.85, "INCOMP::T66": 0.15}) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::Water', 'split_outlet' : "out1"}) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py deleted file mode 100644 index d4c595d20..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitDeltaP.py +++ /dev/null @@ -1,80 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaP("Separator",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -for c in nw.conns['object']: - n_fl = 2 # len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) - -# set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) -#c3.set_attr(fluid={"T66": 0.1}) - -se.set_attr(SFS={ - 'val': 0.65, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) - - -se.set_attr(deltaP=1.2) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - -# Now it is possible to set the pressures -c2.set_attr(p=4) -c3.set_attr(p=3) -se.set_attr(deltaP=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") \ No newline at end of file diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py deleted file mode 100644 index b10ec6640..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drier.py +++ /dev/null @@ -1,113 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH("Separator",num_out=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.0, h=1e2, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) -#c1.set_attr(T0=10) # it seems guess values are SI - -c2.set_attr(fluid={"HEOS::Water": 1, "INCOMP::T66": 0.0},force_state='g') -c3.set_attr(fluid={"HEOS::Water": 0.08},force_state='l') - -c2.set_attr(p=1.0,T=100) -c3.set_attr(p=1.0,T=100) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(Q=2.0e6) -c3.set_attr(fluid={"HEOS::Water": None}) -# c3.set_attr(fluid0={"INCOMP::Water": 0.08, "INCOMP::T66": 0.92}) -# c3.set_attr(T0=100) -#c3.set_attr(T=None) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - - - -se.set_attr(Q=None) -se.set_attr(KPI=1.5e5) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - - - -import sys -sys.exit() - - - - - - - - - -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -se.set_attr(deltaH=0.0) -c2.set_attr(T=None) -c3.set_attr(T=None) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py deleted file mode 100644 index 82710410a..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir.py +++ /dev/null @@ -1,121 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT - -from tespy.components.newAdvancedComponents import DrierWithAir - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -#fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -soAir = Source("SourceAir") -se = DrierWithAir("Separator",num_out=2,num_in=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") -c4 = Connection(soAir, "out1", se, "in2", label="4") - -nw.add_conns(c1, c2, c3, c4) - -# for c in nw.conns['object']: -# c.set_attr(m0=1, h0=100, p0=1.2) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::T66": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") -c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::T66": 0, "HEOS::Air": 1}, mixing_rule="incompressible") - -c2.set_attr(fluid={"INCOMP::T66": 0}) -c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) - - -#c2.set_attr(p=1.2,T=60,force_state='g') -c2.set_attr(p=1.0) -c3.set_attr(p=1.0) - -se.set_attr(deltaH=0) -se.set_attr(dfluid=0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -c2.set_attr(p=1.0,T0=30,force_state='g') -c3.set_attr(p=1.0,T0=30,force_state='l') - - -se.set_attr(dTwbProd=0) -se.set_attr(dfluid=0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c2.set_attr(p=1.0,T=None,force_state='g') -c3.set_attr(p=1.0,T=None,force_state='l') -se.set_attr(dTwbProd=0) -se.set_attr(dfluid=0) -#se.set_attr(eb=0) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - -c3.set_attr(fluid={"INCOMP::Water": None}) -se.set_attr(KPI=0.85) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -se.set_attr(KPI=None) -#c3.set_attr(fluid={"INCOMP::Water": 0.08}) -#c4.set_attr(m=None) -se.set_attr(WBeff=0.6) -#c2.set_attr(T=40) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(WBeff=None) -se.set_attr(kA=4.6e4) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py deleted file mode 100644 index f2b760a5f..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach.py +++ /dev/null @@ -1,121 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT - -from tespy.components.newAdvancedComponents import TwoStreamDrier - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -#fluids = ["INCOMP::Water", "INCOMP::FoodProtein"] -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -soAir = Source("SourceAir") -se = TwoStreamDrier("Separator",num_out=2,num_in=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") # vapor -c3 = Connection(se, "out2", si2, "in1", label="3") # liquid -c4 = Connection(soAir, "out1", se, "in2", label="4") - -nw.add_conns(c1, c2, c3, c4) - -# for c in nw.conns['object']: -# c.set_attr(m0=1, h0=100, p0=1.2) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "INCOMP::FoodProtein": 0.1, "HEOS::Air": 0}, mixing_rule="incompressible") -c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "INCOMP::FoodProtein": 0, "HEOS::Air": 1}, mixing_rule="incompressible") - -c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) -c2.set_attr(fluid={"INCOMP::FoodProtein": 0}) - - -#c3.set_attr(p=1.2,T=60,force_state='g') -c3.set_attr(p=1.0) -c2.set_attr(p=1.0) - -se.set_attr(deltaH=0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(deltaH=None) -c2.set_attr(p=1.0,T=None,force_state='g') -c3.set_attr(p=1.0,T=None,force_state='l') -se.set_attr(dTwbProd=0) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=se.Q.val) -se.set_attr(Q=1e6) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=2.250e6) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=None) -se.set_attr(kA=6.0e+04) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=None) -se.set_attr(kA=None) -se.set_attr(WBeff=0.4) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py deleted file mode 100644 index 3c02e8075..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH-drierWithAir_newApproach_MyWrapper.py +++ /dev/null @@ -1,132 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT - -from tespy.components.newAdvancedComponents import TwoStreamDrier - -logging.basicConfig(level=logging.DEBUG) - -from mywrapper.MyWrapper import MyWrapper -from tespy.tools.fluid_properties.wrappers import CoolPropWrapper - -# %% - -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -soAir = Source("SourceAir") -se = TwoStreamDrier("Separator",num_out=2,num_in=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") # vapor -c3 = Connection(se, "out2", si2, "in1", label="3") # liquid -c4 = Connection(soAir, "out1", se, "in2", label="4") - -nw.add_conns(c1, c2, c3, c4) - -# for c in nw.conns['object']: -# c.set_attr(m0=1, h0=100, p0=1.2) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.0, T=50, fluid={"HEOS::Water": 0.9, "protein": 0.1, "HEOS::Air": 0}, - fluid_engines = {"HEOS::Water": CoolPropWrapper, "protein" : MyWrapper, "HEOS::Air": CoolPropWrapper}, - fluid_coefs = { - "protein": { - "unit" : "C", - "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], - "d" : [1329.9, -0.5184, 0.0, 0.0], - } - }, - mixing_rule="incompressible") - -c4.set_attr(m=50, p=1.0, T=80, fluid={"HEOS::Water": 0, "protein": 0, "HEOS::Air": 1}, mixing_rule="incompressible") - -c3.set_attr(fluid={"HEOS::Water": 0.08, "HEOS::Air": 0}) -c2.set_attr(fluid={"protein": 0}) - - -#c3.set_attr(p=1.2,T=60,force_state='g') -c3.set_attr(p=1.0) -c2.set_attr(p=1.0) - -se.set_attr(deltaH=0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(deltaH=None) -c2.set_attr(p=1.0,T=None,force_state='g') -c3.set_attr(p=1.0,T=None,force_state='l') -se.set_attr(dTwbProd=0) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=se.Q.val) -se.set_attr(Q=1e6) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=2.250e6) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=None) -se.set_attr(kA=6.0e+04) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -c3.set_attr(fluid={"HEOS::Water": None}) -se.set_attr(Q=None) -se.set_attr(KPI=None) -se.set_attr(kA=None) -se.set_attr(WBeff=0.4) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py deleted file mode 100644 index 427cc4738..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaH.py +++ /dev/null @@ -1,96 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH("Separator",num_out=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) -#c1.set_attr(T0=10) # it seems guess values are SI - -c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}, - deltaP=0.0) - -se.set_attr(deltaH=50e3) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - -# Now it is possible to set the temperatures out of the separator differently -se.set_attr(deltaH=None) -c2.set_attr(T=20) -c3.set_attr(T=10) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -se.set_attr(deltaH=0.0) -c2.set_attr(T=None) -c3.set_attr(T=None) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py deleted file mode 100644 index 32c1e1f53..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaT.py +++ /dev/null @@ -1,81 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaT("Separator",num_out=2) -#se = SeparatorWithSpeciesSplits("Separator") #,num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=1e2, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -#c1.set_attr(m=1, p=1.2, T=50, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}) -#c1.set_attr(T0=10) # it seems guess values are SI - -c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) - -se.set_attr(deltaT=5) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - -# Now it is possible to set the temperatures out of the separator differently -se.set_attr(deltaT=None) -c2.set_attr(T=20) -c3.set_attr(T=10) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py deleted file mode 100644 index 33ad4d9c1..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-decanterTest.py +++ /dev/null @@ -1,120 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::FoodWater", "INCOMP::FoodFat", "INCOMP::FoodProtein"] -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaTDeltaP("Separator",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set global guess values -m0 = 76 # transform unit at some point [this is kt/yr] -h0 = 119 # global guess value in kJ/kg -p0 = 1 # global guess value in bar - -water = 'INCOMP::FoodWater' -#water = 'Water' # wrapper gets HEOS backend - -for c in nw.conns['object']: - n_fl = 3 # len(nw.fluids) - c.set_attr(m0=80,h0=h0,p0=p0,fluid0={'INCOMP::FoodWater': 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) - -# set some generic data for starting values -c1.set_attr(m=1, p=p0, T=95, fluid={'INCOMP::FoodWater': 0.902, "INCOMP::FoodFat": 0.023, "INCOMP::FoodProtein": 0.075}, mixing_rule="incompressible") -c2.set_attr(fluid={'INCOMP::FoodWater': 0.648, "INCOMP::FoodFat": 0.022, "INCOMP::FoodProtein": 0.33}) - -c3.set_attr(force_state='l') - -se.set_attr(SFS={ - 'val': 0.35, 'is_set': True, - 'split_fluid' : 'INCOMP::FoodProtein', 'split_outlet' : "out1"}) - - -# Now it is possible to set the temperatures out of the separator differently -c2.set_attr(T=90,p=p0) -c3.set_attr(T=90,p=p0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -else: - nw.print_results() - print(nw.results['Connection']) - print(f"\n converged ") - - - -import sys -sys.exit() - -# deltaT -se.set_attr(deltaT=5) -c2.set_attr(T=None) -c3.set_attr(T=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -# deltaT and different pressures -se.set_attr(deltaT=5) -c2.set_attr(p=4) -c3.set_attr(p=3) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -# deltaP -se.set_attr(deltaT=5,deltaP=1.2) -c2.set_attr(p=None) -c3.set_attr(p=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py deleted file mode 100644 index 90014891a..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP-evaporatorWithHot.py +++ /dev/null @@ -1,136 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP - -from tespy.components.newAdvancedComponents import TwoStreamEvaporator - - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["HEOS::Water", "INCOMP::FoodFat", "INCOMP::FoodProtein"] -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so1 = Source("Source 1") -so2 = Source("Source 2") -se = TwoStreamEvaporator("Separator",num_in=2,num_out=3) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") -si3 = Sink("Sink 3") - -c1 = Connection(so1, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") # vapor -c3 = Connection(se, "out2", si2, "in1", label="3") # liquid - -c4 = Connection(so2, "out1", se, "in2", label="4") -c5 = Connection(se, "out3", si3, "in1", label="5") # condensate - -nw.add_conns(c1, c2, c3, c4, c5) - -# set global guess values -m0 = 74.6 # transform unit at some point [this is kt/yr] -h0 = 323.3 # global guess value in kJ/kg -p0 = 1 # global guess value in bar - -# for c in nw.conns['object']: -# n_fl = 3 # len(nw.fluids) -# c.set_attr(m0=70,h0=h0,p0=p0,fluid0={'HEOS::Water': 0.92, 'INCOMP::FoodFat': 0.023, 'INCOMP::FoodProtein': 0.052}) - -# set some generic data for starting values -c1.set_attr(m=m0, p=p0, T=80, fluid={'HEOS::Water': 0.942, "INCOMP::FoodFat": 0.004, "INCOMP::FoodProtein": 0.054}, mixing_rule="incompressible") -c2.set_attr(x=1, T=40, force_state='g', fluid={'HEOS::Water': 1.0, "INCOMP::FoodFat": 0.0, "INCOMP::FoodProtein": 0.0}) -c3.set_attr(p=p0, T=40, force_state='l', fluid={"INCOMP::FoodProtein": 0.075}) - -# Now it is possible to set the temperatures out of the separator differently -c4.set_attr(m=25, p=p0, x=1, fluid={'HEOS::Water': 1.0}, mixing_rule="incompressible") -c5.set_attr(p=p0) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -c3.set_attr(fluid={"INCOMP::FoodProtein": None}) -c5.set_attr(p=p0,x=0) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c5.set_attr(x=None) -se.set_attr(Q=5e7) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -c5.set_attr(x=None) -se.set_attr(Q=None) -se.set_attr(kA=8e5) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -c5.set_attr(x=None) -se.set_attr(Q=None) -se.set_attr(kA=None) -se.set_attr(KPI=6e5) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -se.set_attr(KPI=None) -se.set_attr(kA=7e5) -se.set_attr(dTo=0) -c3.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) -c3.set_attr(T=None) -c2.set_attr(T=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - -# mass balance mode - -c3.set_attr(fluid={"INCOMP::FoodProtein": 0.075}) -c3.set_attr(p=p0, x=None, T=None, force_state=None) -c2.set_attr(p=p0, x=None, T=None, force_state=None) - -c5.set_attr(x=None, force_state=None) -se.set_attr(Q=None) -se.set_attr(kA=None) -se.set_attr(dTo=None) -se.set_attr(KPI=None) -se.set_attr(deltaH=0) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py deleted file mode 100644 index f26896be9..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaP.py +++ /dev/null @@ -1,114 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaTDeltaP("Separator",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -for c in nw.conns['object']: - n_fl = 2 # len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) - -# set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) - -#c3.set_attr(fluid={"INCOMP::Water": 0.95}) -#c3.set_attr(m=0.5) - -# Now it is possible to set the temperatures out of the separator differently -c2.set_attr(T=20,p=5) -c3.set_attr(T=10,p=5) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -# deltaT -se.set_attr(deltaT=5) -c2.set_attr(T=None) -c3.set_attr(T=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -# deltaT and different pressures -se.set_attr(deltaT=5) -c2.set_attr(p=4) -c3.set_attr(p=3) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - -# deltaP -se.set_attr(deltaT=5,deltaP=1.2) -c2.set_attr(p=None) -c3.set_attr(p=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - diff --git a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py b/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py deleted file mode 100644 index be3e97e91..000000000 --- a/incompressiblesTests/newComponentsTests/SpeciesFlowSplitWithDeltaTDeltaPBus.py +++ /dev/null @@ -1,78 +0,0 @@ -import logging - -from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection, Bus -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import \ - DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits, \ - SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaTDeltaP, SeparatorWithSpeciesSplitsDeltaTDeltaPBus,SimpleHeatExchangerDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e3], iterinfo=True) - -so = Source("Source") -se = SeparatorWithSpeciesSplitsDeltaTDeltaPBus("Separator",num_out=2) -si1 = Sink("Sink 1") -hx = SimpleHeatExchangerDeltaP("HX") -si2 = Sink("Sink 2") - - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", hx, "in1", label="3") -c4 = Connection(hx, "out1", si2, "in1", label="4") - -nw.add_conns(c1, c2, c3, c4) - -# set global guess values -m0 = 1 # transform unit at some point [this is kt/yr] -h0 = 1e2 # global guess value in kJ/kg -p0 = 5 # global guess value in bar - -for c in nw.conns['object']: - n_fl = 2 # len(nw.fluids) - c.set_attr(m0=m0,h0=h0,p0=p0,fluid0={'INCOMP::Water': 1/n_fl, 'INCOMP::T66': 1/n_fl}) - -# set some generic data for starting values -c1.set_attr(m=1, p=5, h=h0, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(fluid={"INCOMP::Water": 0.8, "INCOMP::T66": 0.2}) - -se.set_attr(SFS={ - 'val': 0.6, 'is_set': True, - 'split_fluid' : 'INCOMP::T66', 'split_outlet' : "out1"}) - -# Now it is possible to set the temperatures out of the separator differently -c2.set_attr(T=20,p=5) -c3.set_attr(T=10,p=5) - -#c4.set_attr(p=1) -hx.set_attr(deltaP=1) - - -heat_bus = Bus('total heat input', P=0) -heat_bus.add_comps({'comp': se, 'char': 1}, {'comp': hx, 'char': 1}) -nw.add_busses(heat_bus) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) -m_T66_c1 = c1.m.val * c1.fluid.val['T66'] -m_T66_c2 = c2.m.val * c2.fluid.val['T66'] -print(f"\n Species flow split is {m_T66_c2/m_T66_c1}") -print(f"\n") - - - diff --git a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py deleted file mode 100644 index 9b6da6c85..000000000 --- a/incompressiblesTests/newComponentsTests/SplitterWithDeltaP.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -so = Source("Source") -se = SplitterDeltaP("Splitter",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(m=0.6) - -c2.set_attr(p=1.1) -c3.set_attr(p=1.0) - -# add some guess values -#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -# use delta P -c2.set_attr(p=None) -c3.set_attr(p=None) -se.set_attr(deltaP=0.25) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py deleted file mode 100644 index f0a5ae5a3..000000000 --- a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitter.py +++ /dev/null @@ -1,71 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -so = Source("Source") -se = SplitterWithFlowSplitter("Splitter",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(m=0.6) - -#c2.set_attr(p=1.1) -#c3.set_attr(p=1.0) - -# add some guess values -#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -# use FS -c2.set_attr(m=None) -se.set_attr(FS={ - 'val': 0.65, 'is_set': True, - 'split_outlet' : "out1"}) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -# # use delta P -# c2.set_attr(p=None) -# c3.set_attr(p=None) -# se.set_attr(deltaP=0.25) - -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() -# print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py b/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py deleted file mode 100644 index 95748209f..000000000 --- a/incompressiblesTests/newComponentsTests/SplitterWithFlowSplitterDeltaP.py +++ /dev/null @@ -1,71 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits,SplitterWithFlowSplitter,SplitterWithFlowSplitterDeltaP - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -so = Source("Source") -se = SplitterWithFlowSplitterDeltaP("Splitter",num_out=2) -si1 = Sink("Sink 1") -si2 = Sink("Sink 2") - -c1 = Connection(so, "out1", se, "in1", label="1") -c2 = Connection(se, "out1", si1, "in1", label="2") -c3 = Connection(se, "out2", si2, "in1", label="3") - -nw.add_conns(c1, c2, c3) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(m=0.6) - -c2.set_attr(p=1.1) -c3.set_attr(p=1.0) - -# add some guess values -#c2.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) -#c3.set_attr(m0=0.5,p0=1.2,h0=1e5,T0=50,fluid0={"Water": 0.5, "T66": 0.5}) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -# use FS -c2.set_attr(m=None) -se.set_attr(FS={ - 'val': 0.65, 'is_set': True, - 'split_outlet' : "out1"}) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - -# use delta P -c2.set_attr(p=None) -c3.set_attr(p=None) -se.set_attr(deltaP=0.25) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) diff --git a/incompressiblesTests/newComponentsTests/heatex+merge.py b/incompressiblesTests/newComponentsTests/heatex+merge.py deleted file mode 100644 index 3f007f155..000000000 --- a/incompressiblesTests/newComponentsTests/heatex+merge.py +++ /dev/null @@ -1,136 +0,0 @@ -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -fluids = ["INCOMP::Water", "INCOMP::T66"] - - -#nw = Network(fluids=fluids, p_unit="bar", T_unit="C",h_range=[1.e3, 3.e+06]) -nw = Network(fluids=fluids, p_unit="bar", T_unit="C",h_range=[-5.e5, 3.e+06]) - -so = Source("Source") -so2 = Source("Source2") - -# Variant 2: Q is m (h_2 - h_1), Q_total is taking loss factor into account and represents the heat transfer over system -he = SimpleHeatExchangerDeltaPLossFactor("Heater") -me = MergeDeltaP("Merge") -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", me, "in1", label="2") -c3 = Connection(so2, "out1", me, "in2", label="3") -c4 = Connection(me, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2, c3, c4) - -for c in nw.conns['object']: - n_fl=2 - c.set_attr(m0=0.1,h0=0.5e5,p0=1.2,fluid0={"INCOMP::Water": 1/n_fl, 'INCOMP::T66': 1/n_fl}, mixing_rule="incompressible") - c.set_attr(force_state='l') - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(h=2.2e5) -# mix with pure water -c3.set_attr(m=0.05, p=1.2, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) - -# set pressure ratios of heater and merge -he.set_attr(deltaP=0) -me.set_attr(deltaP=0) -#c2.set_attr(p=2.2) -#c4.set_attr(p=2.2) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - -# use temperature to make it relatable -c1.set_attr(h=None, T=30) -c2.set_attr(h=None, T=50) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -# add some heat -c2.set_attr(T=None) -# # efficiency is used for postprocessing here -he.set_attr(Q=1e5, LF=0.1) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(Q=1e5, Q_total=1.1e5, LF=None) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(Q=1e5, Q_total=1.5e5) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -c2.set_attr(T=50) -# impose over system boundary heat transfer (cannot be lower than actual heat transfer, efficiency value cannot be > 1!) -# In this case, efficiency decreases -he.set_attr(Q=None, Q_total=1.1e5, LF=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -# with set efficiency, temperature cannot be set anymore -c2.set_attr(T=None) -he.set_attr(Q_total=1.1e5, LF=.5) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - -# now cooling instead of heating, CoolProp or TESPy have issues with freezing temperatures, so > 0°C -#c2.set_attr(T0=5) -c2.set_attr(h=-1e3) -he.set_attr(Q=None, LF=0.1, Q_total=None) - -#nw.solve("design",init_only=True) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -c2.set_attr(h=None) -c2.set_attr(T=5) -he.set_attr(Q_total=None, LF=0.1) - -#nw.solve("design",init_only=True) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(Q_total=-.6e5, LF=None) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() diff --git a/incompressiblesTests/newComponentsTests/heatex_alone.py b/incompressiblesTests/newComponentsTests/heatex_alone.py deleted file mode 100644 index 2cba2abab..000000000 --- a/incompressiblesTests/newComponentsTests/heatex_alone.py +++ /dev/null @@ -1,55 +0,0 @@ -# %% - -import logging - - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -so = Source("Source") -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta -he = DiabaticSimpleHeatExchanger("Heater") -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2) - -# set some generic data for starting values -c1.set_attr(m=1, p=1.2, T=30, fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") -c2.set_attr(T=50) - -# set pressure ratios of heater and merge -he.set_attr(pr=1) - -he.set_attr(eta=0.9) # MRK so eta is (1-hlf) heat loss factor - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -# print(nw.results['Connection']) -# he.Q.val -# he.Q_loss.val -# he.Q_total.val - diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py b/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py deleted file mode 100644 index e9ca3381f..000000000 --- a/incompressiblesTests/newComponentsTests/heatex_alone_DeltaPLfKpi.py +++ /dev/null @@ -1,122 +0,0 @@ -# %% - -import logging - - -from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import SimpleHeatExchangerDeltaPLfKpi,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? - -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -so = Source("Source") -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta - -he = SimpleHeatExchangerDeltaPLfKpi("Heater") -#he = SimpleHeatExchangerDeltaP("Heater") - - -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2) - -# set some generic data for starting values -c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") -c1.set_attr(m=1, p=2.2, T=30) - -c2.set_attr(T=50) - -# set pressure ratios of heater and merge -he.set_attr(deltaP=1) -he.set_attr(LF=0.1) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - -c2.set_attr(T=None) - -he.set_attr(LF=0.1) -#he.set_attr(KPI=74e3) -he.set_attr(Q=7.0e+04) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(LF=0.1) -he.set_attr(KPI=60e3) -he.set_attr(Q=None) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - -# he.set_attr(LF=None) -# he.set_attr(Q_total=8.16e+04) -# he.set_attr(Q_loss=-7.42e+03) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() - -# he.set_attr(LF=0.1) -# he.set_attr(Q_total=None) -# he.set_attr(Q_loss=-7.42e+03) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() - - - -# c2.set_attr(T=50) -# he.set_attr(LF=0.1) -# he.set_attr(Q_total=None) -# he.set_attr(Q_loss=None) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() - -# c2.set_attr(T=None) -# he.set_attr(Q=70e3) -# he.set_attr(LF=0.1) -# he.set_attr(Q_total=None) -# he.set_attr(Q_loss=None) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() - - -# he.set_attr(KPI=70e3) -# he.set_attr(Q=None) -# he.set_attr(LF=0.1) -# he.set_attr(Q_total=None) -# he.set_attr(Q_loss=None) -# nw.solve("design") -# if not nw.converged: -# raise Exception("not converged") -# nw.print_results() - diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py b/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py deleted file mode 100644 index e16b1a5ec..000000000 --- a/incompressiblesTests/newComponentsTests/heatex_alone_deltaP.py +++ /dev/null @@ -1,82 +0,0 @@ -# %% - -import logging - -from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import SimpleHeatExchangerDeltaP, SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -nw.set_attr(Q_unit='kW') - -so = Source("Source") -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta - -he = SimpleHeatExchangerDeltaP("Heater") -#he = SimpleHeatExchangerDeltaPLossFactor("Heater") - - -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2) - -# set some generic data for starting values -c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, m=1, T=30, p=1, mixing_rule="incompressible") -c2.set_attr(T=95) #,p=1) - -# set pressure ratios of heater and merge -he.set_attr(deltaP=0.1) -#he.set_attr(pr=1.1) - -#he.set_attr(Tamb=10) - -#he.set_attr(L=10) -#he.set_attr(D=0.3) - -#he.set_attr(Q=74000) -#he.set_attr(LF=0.1) # MRK so eta is (1-hlf) heat loss factor -#he.set_attr(Q_total=8.16e4) # MRK so eta is (1-hlf) heat loss factor -#he.set_attr(Q_loss=-7851.921461139966) # MRK so eta is (1-hlf) heat loss factor - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - -c2.set_attr(T=None) #,p=1) -he.set_attr(Q=2e2) - - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - - -# he.Q.val -# he.Q_loss.val -# he.Q_total.val - -# print(he.LF.val) -# print(he.Q_total.val) -# print(he.Q_loss.val) diff --git a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py b/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py deleted file mode 100644 index a526093c0..000000000 --- a/incompressiblesTests/newComponentsTests/heatex_alone_lossFactor.py +++ /dev/null @@ -1,85 +0,0 @@ -# %% - -import logging - - -from tespy.components import SimpleHeatExchanger, Source, Sink, Merge, Separator -from tespy.tools import ComponentProperties -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import SimpleHeatExchangerDeltaPLossFactor,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? - -nw = Network(m_unit='kg / s', p_unit='bar', T_unit='C',h_unit='kJ / kg', h_range=[-1e2,4e2], iterinfo=True) - -so = Source("Source") -# Variant 2: Q is m (h_2 - h_1), Q_total is taking efficiency into account and represents the heat transfer over system -# boundary. For heat transfer into the system: Q = Q_total * eta, for heat transfer from the system: Q_total = Q * eta - -he = SimpleHeatExchangerDeltaPLossFactor("Heater") -#he = SimpleHeatExchangerDeltaP("Heater") - - -si = Sink("Sink") - -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="4") - -nw.add_conns(c1, c2) - -# set some generic data for starting values -c1.set_attr(fluid={'INCOMP::Water': 0.80,'INCOMP::PHE': 0.15,'INCOMP::S800': 0.05}, mixing_rule="incompressible") -c1.set_attr(m=1, p=2.2, T=30) - -#c2.set_attr(T=50) - -# set pressure ratios of heater and merge -he.set_attr(deltaP=1) - -he.set_attr(LF=0.1) -he.set_attr(Q_total=8.16e+04) -#he.set_attr(Q_loss=-7.42e+03) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(LF=None) -he.set_attr(Q_total=8.16e+04) -he.set_attr(Q_loss=-7.42e+03) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - -he.set_attr(LF=0.1) -he.set_attr(Q_total=None) -he.set_attr(Q_loss=-7.42e+03) -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() - - - - - -# print(nw.results['Connection']) -# he.Q.val -# he.Q_loss.val -# he.Q_total.val - -print(he.LF.val) -print(he.Q_total.val) -#print(he.Q_loss.val) diff --git a/incompressiblesTests/newComponentsTests/merge_mrk.py b/incompressiblesTests/newComponentsTests/merge_mrk.py deleted file mode 100644 index 623fcd9ea..000000000 --- a/incompressiblesTests/newComponentsTests/merge_mrk.py +++ /dev/null @@ -1,57 +0,0 @@ -# %% -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink, Merge -from tespy.connections import Connection -from tespy.networks import Network -import numpy as np - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp - -from tespy.components.newComponents import DiabaticSimpleHeatExchanger,MergeDeltaP,SeparatorWithSpeciesSplits - -logging.basicConfig(level=logging.DEBUG) - -# %% - -# caution, must write "Water" (capital W) in INCOMP backend -> CoolProp bug? Intentional? - -nw = Network(p_unit="bar", T_unit="C") - -so = Source("Source") -so2 = Source("Source2") - -me = MergeDeltaP("Merge") -si = Sink("Sink") - -c1 = Connection(so, "out1", me, "in1", label="2") -c3 = Connection(so2, "out1", me, "in2", label="3") -c4 = Connection(me, "out1", si, "in1", label="4") - -nw.add_conns(c1, c3, c4) - -# set some generic data for starting values -c1.set_attr(m=1, p=2.1, h=0.5e5, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -# mix with pure water -c3.set_attr(m=0.05, p=2.2, h=0.5e5, fluid={"INCOMP::Water": 1, "INCOMP::T66": 0}) - -# set pressure ratios of heater and merge -me.set_attr(deltaP=1) -#c4.set_attr(p=1) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) - - -me.set_attr(deltaP=None) -c4.set_attr(p=1) - -nw.solve("design") -if not nw.converged: - raise Exception("not converged") -nw.print_results() -print(nw.results['Connection']) \ No newline at end of file diff --git a/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py b/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py deleted file mode 100644 index e2668571c..000000000 --- a/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper.py +++ /dev/null @@ -1,201 +0,0 @@ -import CoolProp.CoolProp as CP -from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper, CoolPropWrapper -import numpy as np -import matplotlib.pyplot as plt - -# # coefficients a b c d -# COEF = { -# "protein": { -# "unit" : "C", -# "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], -# "d" : [1329.9, -0.5184, 0.0, 0.0], -# } -# } - -class MyWrapper(FluidPropertyWrapper): - def __init__(self, fluid, back_end=None, Tref = 293.15, coefs=[]) -> None: - super().__init__(fluid, back_end) - if self.fluid not in coefs: - msg = "Fluid not available in database" - raise KeyError(msg) - - # get coefs (converted to kelvin) and calculate reference - self.T0 = Tref - self.get_coefs(coefs) - - self._molar_mass = 1 - self._T_min = 100 - self._T_max = 2000 - self._p_min = 1000 - self._p_max = 10000000 - - def get_coefs(self, coefs): - if coefs[self.fluid]["unit"] == "C": - self.C_c = coefs[self.fluid]["cp"] - self.C_d = coefs[self.fluid]["d"] - # convert coefficients - T_C = np.linspace(1,50) - cp = self.cp_pT(None,T_C) - d = self.d_pT(None,T_C) - T_K = np.linspace(1+273.15,50+273.15) - self.C_c = list(np.polyfit(T_K, cp, len(coefs[self.fluid]["cp"])-1)) - self.C_c = self.C_c[::-1] - self.C_d = list(np.polyfit(T_K, d, len(coefs[self.fluid]["d"])-1)) - self.C_d = self.C_d[::-1] - elif coefs[self.fluid]["unit"] == "K": - self.C_c = coefs[self.fluid]["cp"] - self.C_d = coefs[self.fluid]["d"] - else: - ValueError("unit is not C or K") - - def cp_pT(self, p, T): - return np.sum([self.C_c[i] * T**i for i in range(len(self.C_c))], axis=0) - - def d_pT(self, p, T, **kwargs): - return np.sum([self.C_d[i] * T**i for i in range(len(self.C_d))], axis=0) - - def u_pT(self, p, T): - integral = 0 - for i in range(len(self.C_c)): - integral += (1 / (i + 1)) * self.C_c[i] * (T**(i + 1) - self.T0**(i + 1)) - return integral - - def h_pT(self, p, T, **kwargs): - u = self.u_pT(p, T) - d = self.d_pT(p, T) - return u - p/d - - def s_pT(self, p, T, **kwargs): - integral = self.C_c[0] * np.log(T / self.T0) - for i in range(len(self.C_c) - 1): - integral += (1 / (i + 1)) * self.C_c[i + 1] * (T**(i + 1) - self.T0**(i + 1)) - return integral - - def T_ph(self, p, h): - return self.newton(self.h_pT, self.cp_pT, h, p) - - def T_ps(self, p, s): - return self.newton(self.s_pT, self.dsdT, s, p) - def dsdT(self, p, T): - return self.cp_pT(p, T)/T - def h_ps(self, p, s): - T = self.T_ps(p, s) - return self.h_pT(p, T) - - def s_ph(self, p, h): - T = self.T_ph(p, h) - return self.s_pT(p, T) - - def isentropic(self, p_1, h_1, p_2): - return self.h_ps(p_2, self.s_ph(p_1, h_1)) - - def newton(self, func, deriv, val, p): - # default valaues - T = 300 - valmin = -1000 - valmax = 3000 - max_iter = 10 - tol_rel = 1e-6 - # start newton loop - expr = True - i = 0 - while expr: - # calculate function residual and new value - res = val - func(p, T) - T += res / deriv(p, T) - # check for value ranges - if T < valmin: - T = valmin - if T > valmax: - T = valmax - i += 1 - if i > max_iter: - break - expr = abs(res / val) >= tol_rel - return T - - - -if __name__ == "__main__": - - fluidwrap = MyWrapper("protein") - - T = 300 - p = 1e5 - u = fluidwrap.u_pT(p, T) - d = fluidwrap.d_pT(p, T) - h = fluidwrap.h_pT(p, T) - s = fluidwrap.s_pT(p, T) - print(f"u = {u} d = {d} h = {h} s = {s}") - - T = 273.15 - u = fluidwrap.u_pT(p, T) - d = fluidwrap.d_pT(p, T) - h = fluidwrap.h_pT(p, T) - s = fluidwrap.s_pT(p, T) - print(f"u = {u} d = {d} h = {h} s = {s}") - - T = 373.15 - u = fluidwrap.u_pT(p, T) - d = fluidwrap.d_pT(p, T) - h = fluidwrap.h_pT(p, T) - s = fluidwrap.s_pT(p, T) - print(f"u = {u} d = {d} h = {h} s = {s}") - T = fluidwrap.T_ph(p,h) - s = fluidwrap.s_ph(p,h) - print(f"recalc: T = {T} s = {s}") - T = fluidwrap.T_ps(p,s) - h = fluidwrap.h_ps(p,s) - print(f"recalc: T = {T} h = {h}") - - CP_cp = [] - CP_k = [] - CP_d = [] - CP_h = [] - CP_s = [] - - wrap_cp = [] - wrap_d = [] - wrap_h = [] - wrap_s = [] - - p = 101325 * 5 - - #Specific heat, kJ/(kg·K) - Tplt = np.linspace(273.15,373.15) - for T in Tplt: - CP_cp += [CP.PropsSI('C','T',T,'P',p,'INCOMP::FoodProtein')] - CP_k += [CP.PropsSI('L','T',T,'P',p,'INCOMP::FoodProtein')] - CP_d += [CP.PropsSI('D','T',T,'P',p,'INCOMP::FoodProtein')] - CP_h += [CP.PropsSI('H','T',T,'P',p,'INCOMP::FoodProtein')] - CP_s += [CP.PropsSI('S','T',T,'P',p,'INCOMP::FoodProtein')] - wrap_cp += [fluidwrap.cp_pT(p, T)] - wrap_d += [fluidwrap.d_pT(p, T)] - wrap_h += [fluidwrap.h_pT(p, T)] - wrap_s += [fluidwrap.s_pT(p, T)] - - - - fig, ax = plt.subplots(2, 2, figsize=(16, 8)) - ax = ax.flatten() - [a.grid() for a in ax] - [a.set_xlabel('temperature, K') for a in ax] - - ax[0].plot(Tplt, wrap_cp) - ax[1].plot(Tplt, wrap_d) - ax[2].plot(Tplt, wrap_h) - ax[3].plot(Tplt, wrap_s) - - ax[0].scatter(Tplt, CP_cp) - ax[1].scatter(Tplt, CP_d) - ax[2].scatter(Tplt, CP_h) - ax[3].scatter(Tplt, CP_s) - - ax[0].set_ylabel('cp') - ax[1].set_ylabel('d') - ax[2].set_ylabel('h') - ax[3].set_ylabel('s') - - plt.show() - - print("hey") \ No newline at end of file diff --git a/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py b/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py deleted file mode 100644 index 015cb9aef..000000000 --- a/incompressiblesTests/newComponentsTests/mywrapper/MyWrapper_test.py +++ /dev/null @@ -1,74 +0,0 @@ -import numpy as np -from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper, CoolPropWrapper -#from tespy.tools.fluid_properties.wrappers import FluidPropertyWrapper -from tespy.tools.global_vars import gas_constants -from MyWrapper import MyWrapper -import logging -logging.basicConfig(level=logging.DEBUG) - - -# coefficients a b c d -COEF = { - "protein": { - "unit" : "C", - "cp": [2008.2, 1.2089, -1.3129*1e-3, 0.0], - "d" : [1329.9, -0.5184, 0.0, 0.0], - } -} - -myWrapper = MyWrapper("protein", Tref=298.15, coefs=COEF) # same as in CoolProp -h = myWrapper.h_pT(1e5, 400) -T = myWrapper.T_ph(1e5, h) - -# from tespy.tools.fluid_properties import CoolPropWrapper -# coolprop_water = CoolPropWrapper("H2O") -# h_cp = coolprop_water.h_pT(1e5, 400) -# T_cp = coolprop_water.T_ph(1e5, h_cp) - - -from tespy.components import Sink -from tespy.components import Source -from tespy.components import SimpleHeatExchanger -from tespy.connections import Connection -from tespy.networks import Network - -nwk = Network(T_unit="C", p_unit="bar", iterinfo=True) - -so = Source("Source") -hx = SimpleHeatExchanger("Heatex") -si = Sink("Sink") - -c1 = Connection(so, "out1", hx, "in1", label="1") -c2 = Connection(hx, "out1", si, "in1", label="2") - -nwk.add_conns(c1, c2) - -c1.set_attr( - m=1, - p=1, - T=20, - fluid = { - "protein": 0.5, - "water": 0.5 - }, - fluid_engines = { - "protein" : MyWrapper, - "water" : CoolPropWrapper - }, - fluid_coefs = COEF, - mixing_rule = "incompressible", -) -c2.set_attr(p=1, T=80) - -nwk.solve("design") -nwk.print_results() - - -# iterate Q -hx.set_attr(Q=1.5e5) -c2.set_attr(T=None) -nwk.solve("design") - -nwk.print_results() - -print("hey") diff --git a/incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py b/incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py deleted file mode 100644 index c4c9917ff..000000000 --- a/incompressiblesTests/newComponentsTests/simple_heatex_for_jorrit.py +++ /dev/null @@ -1,64 +0,0 @@ -# %% two fluids -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink -from tespy.connections import Connection -from tespy.networks import Network - -logging.basicConfig(level=logging.DEBUG) - -# fluid and network -fluids = ["INCOMP::Water", "INCOMP::T66"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -# components -so = Source("Source") -he = HeatExchangerSimple("Heater") -si = Sink("Sink") - -# connections -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="4") -nw.add_conns(c1, c2) - -# set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 0.9, "INCOMP::T66": 0.1}, mixing_rule="incompressible") -c2.set_attr(T=50) - -# set some conditions on component -he.set_attr(pr=1) - -nw.solve("design") -nw.print_results() - -# %% one fluid - -import logging - -from tespy.components import HeatExchangerSimple, Source, Sink -from tespy.connections import Connection -from tespy.networks import Network - -# fluid and network -fluids = ["INCOMP::Water"] -nw = Network(fluids=fluids, p_unit="bar", T_unit="C") - -# components -so = Source("Source") -he = HeatExchangerSimple("Heater") -si = Sink("Sink") - -# connections -c1 = Connection(so, "out1", he, "in1", label="1") -c2 = Connection(he, "out1", si, "in1", label="2") -nw.add_conns(c1, c2) - -# set some conditions on connections -c1.set_attr(m=1, p=1.2, T=30, fluid={"INCOMP::Water": 1}) -c2.set_attr(T=50) - -# set some conditions on component -he.set_attr(pr=1) - -nw.solve("design") -nw.print_results() diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 1c7136e08..000000000 --- a/poetry.lock +++ /dev/null @@ -1,1774 +0,0 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. - -[[package]] -name = "appnope" -version = "0.1.3" -description = "Disable App Nap on macOS >= 10.9" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, -] - -[[package]] -name = "asttokens" -version = "2.4.1" -description = "Annotate AST trees with source code positions" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, - {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, -] - -[package.dependencies] -six = ">=1.12.0" - -[package.extras] -astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] -test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] - -[[package]] -name = "certifi" -version = "2023.11.17" -description = "Python package for providing Mozilla's CA Bundle." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "dev" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "comm" -version = "0.2.0" -description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "comm-0.2.0-py3-none-any.whl", hash = "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001"}, - {file = "comm-0.2.0.tar.gz", hash = "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be"}, -] - -[package.dependencies] -traitlets = ">=4" - -[package.extras] -test = ["pytest"] - -[[package]] -name = "contourpy" -version = "1.2.0" -description = "Python library for calculating contours of 2D quadrilateral grids" -category = "main" -optional = false -python-versions = ">=3.9" -files = [ - {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, - {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, - {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, - {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, - {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, - {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, - {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, - {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, - {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, - {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, - {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, - {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, - {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, - {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, - {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, - {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, - {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, - {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, - {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, - {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, - {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, - {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, - {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, - {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, - {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, - {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, - {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, - {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, - {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, - {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, - {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, - {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, - {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, - {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, - {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, - {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, - {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, - {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, - {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, - {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, - {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, - {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, - {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, - {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, -] - -[package.dependencies] -numpy = ">=1.20,<2.0" - -[package.extras] -bokeh = ["bokeh", "selenium"] -docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] -mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] -test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] -test-no-images = ["pytest", "pytest-cov", "pytest-xdist", "wurlitzer"] - -[[package]] -name = "coolprop" -version = "6.6.0" -description = "Open-source thermodynamic and transport properties database" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "CoolProp-6.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e628b334548f5eaf7d7508b673d3a1bcf61c8691c0d020057eb0c9f842e8b702"}, - {file = "CoolProp-6.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8245dd194a8f0946d03f6d0bd62e143c7cb3dbf0c10c49879a888cb275e8038f"}, - {file = "CoolProp-6.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f79733ae173f095670d94d7faf2ecbbea21da76775c803fc3332e0ed22e2ef66"}, - {file = "CoolProp-6.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e401b2e7fa3fd03dcfdd3e2d8c782656d359031a51add7ebe4c5545a0b098a"}, - {file = "CoolProp-6.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d23642e904377984b6d6bacb428890bb89bd8a78a0496b8559b698ca2e001f23"}, - {file = "CoolProp-6.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d32580510054c4ba5c14d9dc0eeda77b5c0dc263b0cc153de7dff9b9de77e28b"}, - {file = "CoolProp-6.6.0-cp310-cp310-win32.whl", hash = "sha256:1febe6ebdb340635bf6c1bb58678fe7edb93c9698e605c3975e1c4749646ee34"}, - {file = "CoolProp-6.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:0bb213ea8d9f509ae0d4c0009dffbda2f52f370eac3b4576c974188f1cd3ced1"}, - {file = "CoolProp-6.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cfe23e785e27ac4d12e0b13708a8bdc087caee8133fa0840509efaaf1ad311ba"}, - {file = "CoolProp-6.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f374a948bc42babdf644f912958c79effa8ccc4f3f461a0f822715dcdf819c6b"}, - {file = "CoolProp-6.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b43e70dfd9825a4de138ce76365978e24532711fb2f4781dacf2b92b96985ed"}, - {file = "CoolProp-6.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c46edd2dad3b99402ad2bff227a53182e0aba954847cac12686e78abd37ae1d"}, - {file = "CoolProp-6.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b83370f50f85cf80ad6c010175b99d6ed7485e647ab70ca85772fecebdcfce86"}, - {file = "CoolProp-6.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9bf37b539640e787250075e9042590f89bf83a1859c62d1695d2269d95fe7cff"}, - {file = "CoolProp-6.6.0-cp311-cp311-win32.whl", hash = "sha256:7b72406779cb17b4197d8bfbb90601f60a5ebb44b8c0c5882e8353021163783a"}, - {file = "CoolProp-6.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:b22c30a23603ce3df88a18a445fad14f93fd9757720f43d3b8041549e93c4b93"}, - {file = "CoolProp-6.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2f738c22f4c81d7bc91567fe101502c5106cefc98a9afe884be72cf6908b3b7f"}, - {file = "CoolProp-6.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e2ef2de94f51ec8f095fe772cdb22593245feeb7df76d3616eb19c5da1d4ac7f"}, - {file = "CoolProp-6.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f3de22cfbdb31e9a2f19aefb8074c25c57abba7ba6302eb331694e7bcc4b11"}, - {file = "CoolProp-6.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f3339c3d590d2c86f9f2c055b9423001653344958000b8dcf7655710a5adee"}, - {file = "CoolProp-6.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c556df424dcf93ce2e4b41f1f52537b94050ddf595df67eb7a76a1dd0d92263e"}, - {file = "CoolProp-6.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:75dd59ea068a6385977815b0572dd824f8cb932a97432737392e3aba11782210"}, - {file = "CoolProp-6.6.0-cp312-cp312-win32.whl", hash = "sha256:bfc5729c00376c00b33538d4685f4243ea43e69d618f2edd31729003a0fb1440"}, - {file = "CoolProp-6.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:809a8572515009a42386ce7381f7d11fd5c785657637cb402f722edf266a6fb3"}, - {file = "CoolProp-6.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c11811e6730dda4c69fc3765e57697ee9390d9266fc7d0e3a40bfc841783b6c"}, - {file = "CoolProp-6.6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:addd2a7ae804e5bce85bdd3747fbea6c654fdb10b88212845b894c936a5162c9"}, - {file = "CoolProp-6.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c573ea9ebaffd85613322e8d8e1574268a4e12eca685742afbf5487cf3e37"}, - {file = "CoolProp-6.6.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:483babcc2cf2b3ce7761b3e8639e49700ff73828270956937b4e99451ad04476"}, - {file = "CoolProp-6.6.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:936bc62c1b33d6322b1b589f824284552e5654abc2c86d91313a952fca378fc9"}, - {file = "CoolProp-6.6.0-cp36-cp36m-win32.whl", hash = "sha256:efd4ec19f566aee8b119b2f9c6c91969e131baef0e2315fb1d66bd4b56edc1d5"}, - {file = "CoolProp-6.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:19cf50201ec36037ef402749bf67bd47eb6f68809c61ce4259d6703898876355"}, - {file = "CoolProp-6.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:60ff433382c801a8d473be57903adbd9957549adff189598ad65e8040626218b"}, - {file = "CoolProp-6.6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57b7e46d3d60962afe2deec068b042e4257e579b2a0d710202d2c2b2186eb2b3"}, - {file = "CoolProp-6.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1f4fe22c62fbc269d1aeee705a7dec23066a683b5615789020974504b76a520"}, - {file = "CoolProp-6.6.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c80fec6127bf9e18174609a4f117ec591e47a04e87e31f271e7d6e2daa4a81b7"}, - {file = "CoolProp-6.6.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e40acd6124d217881717fdd3218ef57d832cd010b22f40637d0f2330fdd0c330"}, - {file = "CoolProp-6.6.0-cp37-cp37m-win32.whl", hash = "sha256:8ba5530b8ca15d0715f86b397e0dc5b1dcc993bcc59175c5e54e27a9bbf4842e"}, - {file = "CoolProp-6.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:60ff22a0969dd6a163ef29fd62f62c72e00bfc80731f4c10b2c89e409a294de9"}, - {file = "CoolProp-6.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7b79982edf62364a4c710ef6804a6b2946696bd95a789e2616dcee741a80f7b1"}, - {file = "CoolProp-6.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c9c081df57cda0e156e78c40fde9d83fd3f1aa262ed74dc70a2ea8fdb816ac70"}, - {file = "CoolProp-6.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15f781be1e761002e95d3de3ac7a02a8ed81adbaa9915ec9942a0575c2cde15d"}, - {file = "CoolProp-6.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25a1117d8229a8d612a3a9ca18a3d994bc2e134de52bf9efb05530219ae19339"}, - {file = "CoolProp-6.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fbe7d8ec427e30a0e95716a77406da4fd7d1299e84f00cca228fa2f7a5ae4ec6"}, - {file = "CoolProp-6.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96065c6c3f17b9b9eeec9620369ffab3047de747c2967db9598f20b56d0cdf2c"}, - {file = "CoolProp-6.6.0-cp38-cp38-win32.whl", hash = "sha256:d02d8ddf1e7af355a334323cc649a391b8c457993631665242d700875b6f7887"}, - {file = "CoolProp-6.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:10b4fd508dc85e2045cf02f5a8ba55c6c5ac9d4ebefbe7940dbc33fe4b392127"}, - {file = "CoolProp-6.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:647102f943d449294e67a89c6f23cf8e59c3763880cc2c7642de21dca2c53631"}, - {file = "CoolProp-6.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b0df572addaf43679f986d76a3cdbe4d4cbd6f4ffe89f1d63be3bd8be38c9212"}, - {file = "CoolProp-6.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c41db6c9172d0ae79e2b3b74aab0e63edeabab999c9dd6a3ca8a0df63f8bfc0"}, - {file = "CoolProp-6.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a994a909a8950170e55a5dce831e2b7b5b6f7cb66a3b49f1afdb04e43b35f42"}, - {file = "CoolProp-6.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:09437ff654af822caf8c904bb2882844a1d7ddffa19c9c9c4c3ef9e9a0f50be1"}, - {file = "CoolProp-6.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9aa70af252e973f8e1e87cd6ab41b94aa4d563906c57b41c170a9d3cae854797"}, - {file = "CoolProp-6.6.0-cp39-cp39-win32.whl", hash = "sha256:dff965f4e44d3af623a02c8bd55f9887daf21990a3f3f1f4bfc46e462106b9fd"}, - {file = "CoolProp-6.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb0ace860286cf2f9346e98a07bc8fc4ca55cf17ee0b1972a5b72a8bfb2716ac"}, - {file = "CoolProp-6.6.0.tar.gz", hash = "sha256:cf6fad704b3ae00f4df309cfd1e2ee48d155886b569a73f2cc38a57eda463082"}, -] - -[[package]] -name = "cycler" -version = "0.12.1" -description = "Composable style cycles" -category = "main" -optional = false -python-versions = ">=3.8" -files = [ - {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, - {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, -] - -[package.extras] -docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] -tests = ["pytest", "pytest-cov", "pytest-xdist"] - -[[package]] -name = "cython" -version = "0.29.36" -description = "The Cython compiler for writing C extensions for the Python language." -category = "dev" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "Cython-0.29.36-py2.py3-none-any.whl", hash = "sha256:95bb13d8be507425d03ebe051f90d4b2a9fdccc64e4f30b35645fdb7542742eb"}, - {file = "Cython-0.29.36.tar.gz", hash = "sha256:41c0cfd2d754e383c9eeb95effc9aa4ab847d0c9747077ddd7c0dcb68c3bc01f"}, -] - -[[package]] -name = "debugpy" -version = "1.8.0" -description = "An implementation of the Debug Adapter Protocol for Python" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "debugpy-1.8.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb"}, - {file = "debugpy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada"}, - {file = "debugpy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f"}, - {file = "debugpy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637"}, - {file = "debugpy-1.8.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e"}, - {file = "debugpy-1.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6"}, - {file = "debugpy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b"}, - {file = "debugpy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153"}, - {file = "debugpy-1.8.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd"}, - {file = "debugpy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f"}, - {file = "debugpy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa"}, - {file = "debugpy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595"}, - {file = "debugpy-1.8.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8"}, - {file = "debugpy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332"}, - {file = "debugpy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6"}, - {file = "debugpy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926"}, - {file = "debugpy-1.8.0-py2.py3-none-any.whl", hash = "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4"}, - {file = "debugpy-1.8.0.zip", hash = "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0"}, -] - -[[package]] -name = "decorator" -version = "5.1.1" -description = "Decorators for Humans" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, -] - -[[package]] -name = "exceptiongroup" -version = "1.2.0" -description = "Backport of PEP 654 (exception groups)" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, - {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, -] - -[package.extras] -test = ["pytest (>=6)"] - -[[package]] -name = "executing" -version = "2.0.1" -description = "Get the currently executing AST node of a frame, and other information" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "executing-2.0.1-py2.py3-none-any.whl", hash = "sha256:eac49ca94516ccc753f9fb5ce82603156e590b27525a8bc32cce8ae302eb61bc"}, - {file = "executing-2.0.1.tar.gz", hash = "sha256:35afe2ce3affba8ee97f2d69927fa823b08b472b7b994e36a52a964b93d16147"}, -] - -[package.extras] -tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] - -[[package]] -name = "fonttools" -version = "4.46.0" -description = "Tools to manipulate font files" -category = "main" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4e69e2c7f93b695d2e6f18f709d501d945f65c1d237dafaabdd23cd935a5276"}, - {file = "fonttools-4.46.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:25852f0c63df0af022f698464a4a80f7d1d5bd974bcd22f995f6b4ad198e32dd"}, - {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adab73618d0a328b203a0e242b3eba60a2b5662d9cb2bd16ed9c52af8a7d86af"}, - {file = "fonttools-4.46.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf923a4a556ab4cc4c52f69a4a2db624cf5a2cf360394368b40c5152fe3321e"}, - {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:87c214197712cc14fd2a4621efce2a9c501a77041232b789568149a8a3161517"}, - {file = "fonttools-4.46.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:156ae342a1ed1fe38e180de471e98fbf5b2b6ae280fa3323138569c4ca215844"}, - {file = "fonttools-4.46.0-cp310-cp310-win32.whl", hash = "sha256:c506e3d3a9e898caee4dc094f34b49c5566870d5a2d1ca2125f0a9f35ecc2205"}, - {file = "fonttools-4.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:f8bc3973ed58893c4107993e0a7ae34901cb572b5e798249cbef35d30801ffd4"}, - {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:982f69855ac258260f51048d9e0c53c5f19881138cc7ca06deb38dc4b97404b6"}, - {file = "fonttools-4.46.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c23c59d321d62588620f2255cf951270bf637d88070f38ed8b5e5558775b86c"}, - {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0e94244ec24a940ecfbe5b31c975c8a575d5ed2d80f9a280ce3b21fa5dc9c34"}, - {file = "fonttools-4.46.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a9f9cdd7ef63d1b8ac90db335762451452426b3207abd79f60da510cea62da5"}, - {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ca9eceebe70035b057ce549e2054cad73e95cac3fe91a9d827253d1c14618204"}, - {file = "fonttools-4.46.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8be6adfa4e15977075278dd0a0bae74dec59be7b969b5ceed93fb86af52aa5be"}, - {file = "fonttools-4.46.0-cp311-cp311-win32.whl", hash = "sha256:7b5636f5706d49f13b6d610fe54ee662336cdf56b5a6f6683c0b803e23d826d2"}, - {file = "fonttools-4.46.0-cp311-cp311-win_amd64.whl", hash = "sha256:49ea0983e55fd7586a809787cd4644a7ae471e53ab8ddc016f9093b400e32646"}, - {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7b460720ce81773da1a3e7cc964c48e1e11942b280619582a897fa0117b56a62"}, - {file = "fonttools-4.46.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8bee9f4fc8c99824a424ae45c789ee8c67cb84f8e747afa7f83b7d3cef439c3b"}, - {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3d7b96aba96e05e8c911ce2dfc5acc6a178b8f44f6aa69371ab91aa587563da"}, - {file = "fonttools-4.46.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e6aeb5c340416d11a3209d75c48d13e72deea9e1517837dd1522c1fd1f17c11"}, - {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c779f8701deedf41908f287aeb775b8a6f59875ad1002b98ac6034ae4ddc1b7b"}, - {file = "fonttools-4.46.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ce199227ce7921eaafdd4f96536f16b232d6b580ce74ce337de544bf06cb2752"}, - {file = "fonttools-4.46.0-cp312-cp312-win32.whl", hash = "sha256:1c9937c4dd1061afd22643389445fabda858af5e805860ec3082a4bc07c7a720"}, - {file = "fonttools-4.46.0-cp312-cp312-win_amd64.whl", hash = "sha256:a9fa52ef8fd14d7eb3d813e1451e7ace3e1eebfa9b7237d3f81fee8f3de6a114"}, - {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c94564b1f3b5dd87e73577610d85115b1936edcc596deaf84a31bbe70e17456b"}, - {file = "fonttools-4.46.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4a50a1dfad7f7ba5ca3f99cc73bf5cdac67ceade8e4b355a877521f20ad1b63"}, - {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89c2c520f9492844ecd6316d20c6c7a157b5c0cb73a1411b3db28ee304f30122"}, - {file = "fonttools-4.46.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5b7905fd68eacb7cc56a13139da5c312c45baae6950dd00b02563c54508a041"}, - {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8485cc468288e213f31afdaf1fdda3c79010f542559fbba936a54f4644df2570"}, - {file = "fonttools-4.46.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:87c3299da7da55394fb324349db0ede38114a46aafd0e7dfcabfecd28cdd94c3"}, - {file = "fonttools-4.46.0-cp38-cp38-win32.whl", hash = "sha256:f5f1423a504ccc329efb5aa79738de83d38c072be5308788dde6bd419969d7f5"}, - {file = "fonttools-4.46.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d4a4ebcc76e30898ff3296ea786491c70e183f738319ae2629e0d44f17ece42"}, - {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9a0e422ab79e5cb2b47913be6a4b5fd20c4c7ac34a24f3691a4e099e965e0b8"}, - {file = "fonttools-4.46.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:13ac0cba2fc63fa4b232f2a7971f35f35c6eaf10bd1271fa96d4ce6253a8acfd"}, - {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:795150d5edc595e1a2cfb3d65e8f4f3d027704fc2579f8990d381bef6b188eb6"}, - {file = "fonttools-4.46.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d00fc63131dcac6b25f50a5a129758438317e54e3ce5587163f7058de4b0e933"}, - {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3033b55f401a622de2630b3982234d97219d89b058607b87927eccb0f922313c"}, - {file = "fonttools-4.46.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e26e7fb908ae4f622813e7cb32cd2db6c24e3122bb3b98f25e832a2fe0e7e228"}, - {file = "fonttools-4.46.0-cp39-cp39-win32.whl", hash = "sha256:2d0eba685938c603f2f648dfc0aadbf8c6a4fe1c7ca608c2970a6ef39e00f254"}, - {file = "fonttools-4.46.0-cp39-cp39-win_amd64.whl", hash = "sha256:5200b01f463d97cc2b7ff8a1e3584151f4413e98cb8419da5f17d1dbb84cc214"}, - {file = "fonttools-4.46.0-py3-none-any.whl", hash = "sha256:5b627ed142398ea9202bd752c04311592558964d1a765fb2f78dc441a05633f4"}, - {file = "fonttools-4.46.0.tar.gz", hash = "sha256:2ae45716c27a41807d58a9f3f59983bdc8c0a46cb259e4450ab7e196253a9853"}, -] - -[package.extras] -all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] -graphite = ["lz4 (>=1.7.4.2)"] -interpolatable = ["munkres", "scipy"] -lxml = ["lxml (>=4.0,<5)"] -pathops = ["skia-pathops (>=0.5.0)"] -plot = ["matplotlib"] -repacker = ["uharfbuzz (>=0.23.0)"] -symfont = ["sympy"] -type1 = ["xattr"] -ufo = ["fs (>=2.2.0,<3)"] -unicode = ["unicodedata2 (>=15.1.0)"] -woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] - -[[package]] -name = "idna" -version = "3.6" -description = "Internationalized Domain Names in Applications (IDNA)" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, - {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, -] - -[[package]] -name = "importlib-metadata" -version = "7.0.0" -description = "Read metadata from Python packages" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, - {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, -] - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] - -[[package]] -name = "importlib-resources" -version = "6.1.1" -description = "Read resources from Python packages" -category = "main" -optional = false -python-versions = ">=3.8" -files = [ - {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, - {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, -] - -[package.dependencies] -zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] - -[[package]] -name = "ipykernel" -version = "6.27.1" -description = "IPython Kernel for Jupyter" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "ipykernel-6.27.1-py3-none-any.whl", hash = "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686"}, - {file = "ipykernel-6.27.1.tar.gz", hash = "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6"}, -] - -[package.dependencies] -appnope = {version = "*", markers = "platform_system == \"Darwin\""} -comm = ">=0.1.1" -debugpy = ">=1.6.5" -ipython = ">=7.23.1" -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -matplotlib-inline = ">=0.1" -nest-asyncio = "*" -packaging = "*" -psutil = "*" -pyzmq = ">=20" -tornado = ">=6.1" -traitlets = ">=5.4.0" - -[package.extras] -cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] -pyqt5 = ["pyqt5"] -pyside6 = ["pyside6"] -test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "ipython" -version = "8.18.1" -description = "IPython: Productive Interactive Computing" -category = "dev" -optional = false -python-versions = ">=3.9" -files = [ - {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, - {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -decorator = "*" -exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} -jedi = ">=0.16" -matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -prompt-toolkit = ">=3.0.41,<3.1.0" -pygments = ">=2.4.0" -stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} - -[package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] -black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] -kernel = ["ipykernel"] -nbconvert = ["nbconvert"] -nbformat = ["nbformat"] -notebook = ["ipywidgets", "notebook"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] - -[[package]] -name = "jedi" -version = "0.19.1" -description = "An autocompletion tool for Python that can be used for text editors." -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, - {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, -] - -[package.dependencies] -parso = ">=0.8.3,<0.9.0" - -[package.extras] -docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] -qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] -testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] - -[[package]] -name = "jinja2" -version = "3.1.2" -description = "A very fast and expressive template engine." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, - {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jupyter-client" -version = "8.6.0" -description = "Jupyter protocol implementation and client libraries" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_client-8.6.0-py3-none-any.whl", hash = "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99"}, - {file = "jupyter_client-8.6.0.tar.gz", hash = "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7"}, -] - -[package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} -jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" -python-dateutil = ">=2.8.2" -pyzmq = ">=23.0" -tornado = ">=6.2" -traitlets = ">=5.3" - -[package.extras] -docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] -test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] - -[[package]] -name = "jupyter-core" -version = "5.5.0" -description = "Jupyter core package. A base package on which Jupyter projects rely." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jupyter_core-5.5.0-py3-none-any.whl", hash = "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805"}, - {file = "jupyter_core-5.5.0.tar.gz", hash = "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3"}, -] - -[package.dependencies] -platformdirs = ">=2.5" -pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} -traitlets = ">=5.3" - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] -test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "kiwisolver" -version = "1.4.5" -description = "A fast implementation of the Cassowary constraint solver" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, - {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, - {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, - {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, - {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, - {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, - {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, - {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, - {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, - {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, - {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, - {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, - {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, - {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, - {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, - {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, - {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, - {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, - {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, - {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, - {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, - {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, - {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, - {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, - {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, - {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, - {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, - {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, - {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, - {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, - {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, - {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, - {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, - {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, - {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, - {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, - {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, - {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, - {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, - {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, - {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, - {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, - {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, - {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, - {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, - {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, - {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, - {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, - {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, - {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, - {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, - {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, - {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, - {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, - {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, - {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, - {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, - {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, - {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, - {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, - {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, - {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, - {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, - {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, - {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, - {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, - {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, - {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, - {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, - {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, - {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, - {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, - {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, - {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, - {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, - {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, - {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, - {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, - {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, - {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, - {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, - {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, - {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, - {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, - {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, - {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, - {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, - {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, - {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, - {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, - {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, - {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, -] - -[[package]] -name = "markupsafe" -version = "2.1.3" -description = "Safely add untrusted strings to HTML/XML markup." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, - {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, - {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, - {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, - {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, - {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, - {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, -] - -[[package]] -name = "matplotlib" -version = "3.8.2" -description = "Python plotting package" -category = "main" -optional = false -python-versions = ">=3.9" -files = [ - {file = "matplotlib-3.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:09796f89fb71a0c0e1e2f4bdaf63fb2cefc84446bb963ecdeb40dfee7dfa98c7"}, - {file = "matplotlib-3.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6f9c6976748a25e8b9be51ea028df49b8e561eed7809146da7a47dbecebab367"}, - {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b78e4f2cedf303869b782071b55fdde5987fda3038e9d09e58c91cc261b5ad18"}, - {file = "matplotlib-3.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e208f46cf6576a7624195aa047cb344a7f802e113bb1a06cfd4bee431de5e31"}, - {file = "matplotlib-3.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:46a569130ff53798ea5f50afce7406e91fdc471ca1e0e26ba976a8c734c9427a"}, - {file = "matplotlib-3.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:830f00640c965c5b7f6bc32f0d4ce0c36dfe0379f7dd65b07a00c801713ec40a"}, - {file = "matplotlib-3.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d86593ccf546223eb75a39b44c32788e6f6440d13cfc4750c1c15d0fcb850b63"}, - {file = "matplotlib-3.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a5430836811b7652991939012f43d2808a2db9b64ee240387e8c43e2e5578c8"}, - {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9576723858a78751d5aacd2497b8aef29ffea6d1c95981505877f7ac28215c6"}, - {file = "matplotlib-3.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ba9cbd8ac6cf422f3102622b20f8552d601bf8837e49a3afed188d560152788"}, - {file = "matplotlib-3.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:03f9d160a29e0b65c0790bb07f4f45d6a181b1ac33eb1bb0dd225986450148f0"}, - {file = "matplotlib-3.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:3773002da767f0a9323ba1a9b9b5d00d6257dbd2a93107233167cfb581f64717"}, - {file = "matplotlib-3.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c318c1e95e2f5926fba326f68177dee364aa791d6df022ceb91b8221bd0a627"}, - {file = "matplotlib-3.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:091275d18d942cf1ee9609c830a1bc36610607d8223b1b981c37d5c9fc3e46a4"}, - {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b0f3b8ea0e99e233a4bcc44590f01604840d833c280ebb8fe5554fd3e6cfe8d"}, - {file = "matplotlib-3.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7b1704a530395aaf73912be741c04d181f82ca78084fbd80bc737be04848331"}, - {file = "matplotlib-3.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:533b0e3b0c6768eef8cbe4b583731ce25a91ab54a22f830db2b031e83cca9213"}, - {file = "matplotlib-3.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:0f4fc5d72b75e2c18e55eb32292659cf731d9d5b312a6eb036506304f4675630"}, - {file = "matplotlib-3.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:deaed9ad4da0b1aea77fe0aa0cebb9ef611c70b3177be936a95e5d01fa05094f"}, - {file = "matplotlib-3.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:172f4d0fbac3383d39164c6caafd3255ce6fa58f08fc392513a0b1d3b89c4f89"}, - {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7d36c2209d9136cd8e02fab1c0ddc185ce79bc914c45054a9f514e44c787917"}, - {file = "matplotlib-3.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5864bdd7da445e4e5e011b199bb67168cdad10b501750367c496420f2ad00843"}, - {file = "matplotlib-3.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ef8345b48e95cee45ff25192ed1f4857273117917a4dcd48e3905619bcd9c9b8"}, - {file = "matplotlib-3.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:7c48d9e221b637c017232e3760ed30b4e8d5dfd081daf327e829bf2a72c731b4"}, - {file = "matplotlib-3.8.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:aa11b3c6928a1e496c1a79917d51d4cd5d04f8a2e75f21df4949eeefdf697f4b"}, - {file = "matplotlib-3.8.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1095fecf99eeb7384dabad4bf44b965f929a5f6079654b681193edf7169ec20"}, - {file = "matplotlib-3.8.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:bddfb1db89bfaa855912261c805bd0e10218923cc262b9159a49c29a7a1c1afa"}, - {file = "matplotlib-3.8.2.tar.gz", hash = "sha256:01a978b871b881ee76017152f1f1a0cbf6bd5f7b8ff8c96df0df1bd57d8755a1"}, -] - -[package.dependencies] -contourpy = ">=1.0.1" -cycler = ">=0.10" -fonttools = ">=4.22.0" -importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} -kiwisolver = ">=1.3.1" -numpy = ">=1.21,<2" -packaging = ">=20.0" -pillow = ">=8" -pyparsing = ">=2.3.1" -python-dateutil = ">=2.7" - -[[package]] -name = "matplotlib-inline" -version = "0.1.6" -description = "Inline Matplotlib backend for Jupyter" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "matplotlib-inline-0.1.6.tar.gz", hash = "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304"}, - {file = "matplotlib_inline-0.1.6-py3-none-any.whl", hash = "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311"}, -] - -[package.dependencies] -traitlets = "*" - -[[package]] -name = "nest-asyncio" -version = "1.5.8" -description = "Patch asyncio to allow nested event loops" -category = "dev" -optional = false -python-versions = ">=3.5" -files = [ - {file = "nest_asyncio-1.5.8-py3-none-any.whl", hash = "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d"}, - {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, -] - -[[package]] -name = "numpy" -version = "1.26.2" -description = "Fundamental package for array computing in Python" -category = "main" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numpy-1.26.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3703fc9258a4a122d17043e57b35e5ef1c5a5837c3db8be396c82e04c1cf9b0f"}, - {file = "numpy-1.26.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cc392fdcbd21d4be6ae1bb4475a03ce3b025cd49a9be5345d76d7585aea69440"}, - {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36340109af8da8805d8851ef1d74761b3b88e81a9bd80b290bbfed61bd2b4f75"}, - {file = "numpy-1.26.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bcc008217145b3d77abd3e4d5ef586e3bdfba8fe17940769f8aa09b99e856c00"}, - {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ced40d4e9e18242f70dd02d739e44698df3dcb010d31f495ff00a31ef6014fe"}, - {file = "numpy-1.26.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b272d4cecc32c9e19911891446b72e986157e6a1809b7b56518b4f3755267523"}, - {file = "numpy-1.26.2-cp310-cp310-win32.whl", hash = "sha256:22f8fc02fdbc829e7a8c578dd8d2e15a9074b630d4da29cda483337e300e3ee9"}, - {file = "numpy-1.26.2-cp310-cp310-win_amd64.whl", hash = "sha256:26c9d33f8e8b846d5a65dd068c14e04018d05533b348d9eaeef6c1bd787f9919"}, - {file = "numpy-1.26.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b96e7b9c624ef3ae2ae0e04fa9b460f6b9f17ad8b4bec6d7756510f1f6c0c841"}, - {file = "numpy-1.26.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aa18428111fb9a591d7a9cc1b48150097ba6a7e8299fb56bdf574df650e7d1f1"}, - {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06fa1ed84aa60ea6ef9f91ba57b5ed963c3729534e6e54055fc151fad0423f0a"}, - {file = "numpy-1.26.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96ca5482c3dbdd051bcd1fce8034603d6ebfc125a7bd59f55b40d8f5d246832b"}, - {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:854ab91a2906ef29dc3925a064fcd365c7b4da743f84b123002f6139bcb3f8a7"}, - {file = "numpy-1.26.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f43740ab089277d403aa07567be138fc2a89d4d9892d113b76153e0e412409f8"}, - {file = "numpy-1.26.2-cp311-cp311-win32.whl", hash = "sha256:a2bbc29fcb1771cd7b7425f98b05307776a6baf43035d3b80c4b0f29e9545186"}, - {file = "numpy-1.26.2-cp311-cp311-win_amd64.whl", hash = "sha256:2b3fca8a5b00184828d12b073af4d0fc5fdd94b1632c2477526f6bd7842d700d"}, - {file = "numpy-1.26.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a4cd6ed4a339c21f1d1b0fdf13426cb3b284555c27ac2f156dfdaaa7e16bfab0"}, - {file = "numpy-1.26.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5d5244aabd6ed7f312268b9247be47343a654ebea52a60f002dc70c769048e75"}, - {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a3cdb4d9c70e6b8c0814239ead47da00934666f668426fc6e94cce869e13fd7"}, - {file = "numpy-1.26.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa317b2325f7aa0a9471663e6093c210cb2ae9c0ad824732b307d2c51983d5b6"}, - {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:174a8880739c16c925799c018f3f55b8130c1f7c8e75ab0a6fa9d41cab092fd6"}, - {file = "numpy-1.26.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f79b231bf5c16b1f39c7f4875e1ded36abee1591e98742b05d8a0fb55d8a3eec"}, - {file = "numpy-1.26.2-cp312-cp312-win32.whl", hash = "sha256:4a06263321dfd3598cacb252f51e521a8cb4b6df471bb12a7ee5cbab20ea9167"}, - {file = "numpy-1.26.2-cp312-cp312-win_amd64.whl", hash = "sha256:b04f5dc6b3efdaab541f7857351aac359e6ae3c126e2edb376929bd3b7f92d7e"}, - {file = "numpy-1.26.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4eb8df4bf8d3d90d091e0146f6c28492b0be84da3e409ebef54349f71ed271ef"}, - {file = "numpy-1.26.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1a13860fdcd95de7cf58bd6f8bc5a5ef81c0b0625eb2c9a783948847abbef2c2"}, - {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64308ebc366a8ed63fd0bf426b6a9468060962f1a4339ab1074c228fa6ade8e3"}, - {file = "numpy-1.26.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf8aab04a2c0e859da118f0b38617e5ee65d75b83795055fb66c0d5e9e9b818"}, - {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d73a3abcac238250091b11caef9ad12413dab01669511779bc9b29261dd50210"}, - {file = "numpy-1.26.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b361d369fc7e5e1714cf827b731ca32bff8d411212fccd29ad98ad622449cc36"}, - {file = "numpy-1.26.2-cp39-cp39-win32.whl", hash = "sha256:bd3f0091e845164a20bd5a326860c840fe2af79fa12e0469a12768a3ec578d80"}, - {file = "numpy-1.26.2-cp39-cp39-win_amd64.whl", hash = "sha256:2beef57fb031dcc0dc8fa4fe297a742027b954949cabb52a2a376c144e5e6060"}, - {file = "numpy-1.26.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1cc3d5029a30fb5f06704ad6b23b35e11309491c999838c31f124fee32107c79"}, - {file = "numpy-1.26.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94cc3c222bb9fb5a12e334d0479b97bb2df446fbe622b470928f5284ffca3f8d"}, - {file = "numpy-1.26.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe6b44fb8fcdf7eda4ef4461b97b3f63c466b27ab151bec2366db8b197387841"}, - {file = "numpy-1.26.2.tar.gz", hash = "sha256:f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea"}, -] - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pandas" -version = "2.1.3" -description = "Powerful data structures for data analysis, time series, and statistics" -category = "main" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pandas-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acf08a73b5022b479c1be155d4988b72f3020f308f7a87c527702c5f8966d34f"}, - {file = "pandas-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3cc4469ff0cf9aa3a005870cb49ab8969942b7156e0a46cc3f5abd6b11051dfb"}, - {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35172bff95f598cc5866c047f43c7f4df2c893acd8e10e6653a4b792ed7f19bb"}, - {file = "pandas-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59dfe0e65a2f3988e940224e2a70932edc964df79f3356e5f2997c7d63e758b4"}, - {file = "pandas-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0296a66200dee556850d99b24c54c7dfa53a3264b1ca6f440e42bad424caea03"}, - {file = "pandas-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:465571472267a2d6e00657900afadbe6097c8e1dc43746917db4dfc862e8863e"}, - {file = "pandas-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04d4c58e1f112a74689da707be31cf689db086949c71828ef5da86727cfe3f82"}, - {file = "pandas-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7fa2ad4ff196768ae63a33f8062e6838efed3a319cf938fdf8b95e956c813042"}, - {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4441ac94a2a2613e3982e502ccec3bdedefe871e8cea54b8775992485c5660ef"}, - {file = "pandas-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ded6ff28abbf0ea7689f251754d3789e1edb0c4d0d91028f0b980598418a58"}, - {file = "pandas-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fca5680368a5139d4920ae3dc993eb5106d49f814ff24018b64d8850a52c6ed2"}, - {file = "pandas-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:de21e12bf1511190fc1e9ebc067f14ca09fccfb189a813b38d63211d54832f5f"}, - {file = "pandas-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a5d53c725832e5f1645e7674989f4c106e4b7249c1d57549023ed5462d73b140"}, - {file = "pandas-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7cf4cf26042476e39394f1f86868d25b265ff787c9b2f0d367280f11afbdee6d"}, - {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72c84ec1b1d8e5efcbff5312abe92bfb9d5b558f11e0cf077f5496c4f4a3c99e"}, - {file = "pandas-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f539e113739a3e0cc15176bf1231a553db0239bfa47a2c870283fd93ba4f683"}, - {file = "pandas-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc77309da3b55732059e484a1efc0897f6149183c522390772d3561f9bf96c00"}, - {file = "pandas-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:08637041279b8981a062899da0ef47828df52a1838204d2b3761fbd3e9fcb549"}, - {file = "pandas-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b99c4e51ef2ed98f69099c72c75ec904dd610eb41a32847c4fcbc1a975f2d2b8"}, - {file = "pandas-2.1.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f7ea8ae8004de0381a2376662c0505bb0a4f679f4c61fbfd122aa3d1b0e5f09d"}, - {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd76d67ca2d48f56e2db45833cf9d58f548f97f61eecd3fdc74268417632b8a"}, - {file = "pandas-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1329dbe93a880a3d7893149979caa82d6ba64a25e471682637f846d9dbc10dd2"}, - {file = "pandas-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:321ecdb117bf0f16c339cc6d5c9a06063854f12d4d9bc422a84bb2ed3207380a"}, - {file = "pandas-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:11a771450f36cebf2a4c9dbd3a19dfa8c46c4b905a3ea09dc8e556626060fe71"}, - {file = "pandas-2.1.3.tar.gz", hash = "sha256:22929f84bca106921917eb73c1521317ddd0a4c71b395bcf767a106e3494209f"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.22.4,<2", markers = "python_version < \"3.11\""}, - {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.1" - -[package.extras] -all = ["PyQt5 (>=5.15.6)", "SQLAlchemy (>=1.4.36)", "beautifulsoup4 (>=4.11.1)", "bottleneck (>=1.3.4)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=0.8.1)", "fsspec (>=2022.05.0)", "gcsfs (>=2022.05.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.8.0)", "matplotlib (>=3.6.1)", "numba (>=0.55.2)", "numexpr (>=2.8.0)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pandas-gbq (>=0.17.5)", "psycopg2 (>=2.9.3)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.5)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "pyxlsb (>=1.0.9)", "qtpy (>=2.2.0)", "s3fs (>=2022.05.0)", "scipy (>=1.8.1)", "tables (>=3.7.0)", "tabulate (>=0.8.10)", "xarray (>=2022.03.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)", "zstandard (>=0.17.0)"] -aws = ["s3fs (>=2022.05.0)"] -clipboard = ["PyQt5 (>=5.15.6)", "qtpy (>=2.2.0)"] -compression = ["zstandard (>=0.17.0)"] -computation = ["scipy (>=1.8.1)", "xarray (>=2022.03.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.10)", "pyxlsb (>=1.0.9)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.3)"] -feather = ["pyarrow (>=7.0.0)"] -fss = ["fsspec (>=2022.05.0)"] -gcp = ["gcsfs (>=2022.05.0)", "pandas-gbq (>=0.17.5)"] -hdf5 = ["tables (>=3.7.0)"] -html = ["beautifulsoup4 (>=4.11.1)", "html5lib (>=1.1)", "lxml (>=4.8.0)"] -mysql = ["SQLAlchemy (>=1.4.36)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.8.10)"] -parquet = ["pyarrow (>=7.0.0)"] -performance = ["bottleneck (>=1.3.4)", "numba (>=0.55.2)", "numexpr (>=2.8.0)"] -plot = ["matplotlib (>=3.6.1)"] -postgresql = ["SQLAlchemy (>=1.4.36)", "psycopg2 (>=2.9.3)"] -spss = ["pyreadstat (>=1.1.5)"] -sql-other = ["SQLAlchemy (>=1.4.36)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.8.0)"] - -[[package]] -name = "parso" -version = "0.8.3" -description = "A Python Parser" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, - {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, -] - -[package.extras] -qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] -testing = ["docopt", "pytest (<6.0.0)"] - -[[package]] -name = "pexpect" -version = "4.9.0" -description = "Pexpect allows easy control of interactive console applications." -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, - {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, -] - -[package.dependencies] -ptyprocess = ">=0.5" - -[[package]] -name = "pillow" -version = "10.1.0" -description = "Python Imaging Library (Fork)" -category = "main" -optional = false -python-versions = ">=3.8" -files = [ - {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"}, - {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"}, - {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"}, - {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"}, - {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"}, - {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"}, - {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"}, - {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"}, - {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"}, - {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"}, - {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"}, - {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"}, - {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"}, - {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"}, - {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"}, - {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"}, - {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"}, - {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"}, - {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"}, - {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"}, - {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"}, - {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"}, - {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"}, - {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"}, - {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"}, - {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"}, - {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"}, - {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"}, - {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"}, - {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"}, - {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"}, - {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"}, - {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"}, -] - -[package.extras] -docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] - -[[package]] -name = "platformdirs" -version = "4.1.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, - {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, -] - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] - -[[package]] -name = "prompt-toolkit" -version = "3.0.41" -description = "Library for building powerful interactive command lines in Python" -category = "dev" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "prompt_toolkit-3.0.41-py3-none-any.whl", hash = "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2"}, - {file = "prompt_toolkit-3.0.41.tar.gz", hash = "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0"}, -] - -[package.dependencies] -wcwidth = "*" - -[[package]] -name = "psutil" -version = "5.9.6" -description = "Cross-platform lib for process and system monitoring in Python." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, - {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, - {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, - {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, - {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, - {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, - {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, - {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, - {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, - {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, - {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, - {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, - {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, -] - -[package.extras] -test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] - -[[package]] -name = "ptyprocess" -version = "0.7.0" -description = "Run a subprocess in a pseudo terminal" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, - {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, -] - -[[package]] -name = "pure-eval" -version = "0.2.2" -description = "Safely evaluate AST nodes without side effects" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, - {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, -] - -[package.extras] -tests = ["pytest"] - -[[package]] -name = "pycparser" -version = "2.21" -description = "C parser in Python" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, - {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, -] - -[[package]] -name = "pygments" -version = "2.17.2" -description = "Pygments is a syntax highlighting package written in Python." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, -] - -[package.extras] -plugins = ["importlib-metadata"] -windows-terminal = ["colorama (>=0.4.6)"] - -[[package]] -name = "pyparsing" -version = "3.1.1" -description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "main" -optional = false -python-versions = ">=3.6.8" -files = [ - {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, - {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, -] - -[package.extras] -diagrams = ["jinja2", "railroad-diagrams"] - -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "pytz" -version = "2023.3.post1" -description = "World timezone definitions, modern and historical" -category = "main" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, - {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, -] - -[[package]] -name = "pywin32" -version = "306" -description = "Python for Window Extensions" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, - {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, - {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, - {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, - {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, - {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, - {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, - {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, - {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, - {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, - {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, - {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, - {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, - {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, - {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, - {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, - {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, - {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, - {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, - {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, - {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, - {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, - {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, - {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, - {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, - {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, - {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, - {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, -] - -[[package]] -name = "pyzmq" -version = "25.1.2" -description = "Python bindings for 0MQ" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4"}, - {file = "pyzmq-25.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0"}, - {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e"}, - {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872"}, - {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d"}, - {file = "pyzmq-25.1.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75"}, - {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6"}, - {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979"}, - {file = "pyzmq-25.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08"}, - {file = "pyzmq-25.1.2-cp310-cp310-win32.whl", hash = "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886"}, - {file = "pyzmq-25.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6"}, - {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c"}, - {file = "pyzmq-25.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1"}, - {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348"}, - {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642"}, - {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840"}, - {file = "pyzmq-25.1.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d"}, - {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b"}, - {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b"}, - {file = "pyzmq-25.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3"}, - {file = "pyzmq-25.1.2-cp311-cp311-win32.whl", hash = "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097"}, - {file = "pyzmq-25.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9"}, - {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a"}, - {file = "pyzmq-25.1.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e"}, - {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27"}, - {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30"}, - {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee"}, - {file = "pyzmq-25.1.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537"}, - {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181"}, - {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe"}, - {file = "pyzmq-25.1.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737"}, - {file = "pyzmq-25.1.2-cp312-cp312-win32.whl", hash = "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d"}, - {file = "pyzmq-25.1.2-cp312-cp312-win_amd64.whl", hash = "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7"}, - {file = "pyzmq-25.1.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438"}, - {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b"}, - {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0"}, - {file = "pyzmq-25.1.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7"}, - {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561"}, - {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a"}, - {file = "pyzmq-25.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16"}, - {file = "pyzmq-25.1.2-cp36-cp36m-win32.whl", hash = "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc"}, - {file = "pyzmq-25.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68"}, - {file = "pyzmq-25.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92"}, - {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b"}, - {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003"}, - {file = "pyzmq-25.1.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62"}, - {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70"}, - {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec"}, - {file = "pyzmq-25.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b"}, - {file = "pyzmq-25.1.2-cp37-cp37m-win32.whl", hash = "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7"}, - {file = "pyzmq-25.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd"}, - {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41"}, - {file = "pyzmq-25.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8"}, - {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae"}, - {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7"}, - {file = "pyzmq-25.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df"}, - {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220"}, - {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f"}, - {file = "pyzmq-25.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755"}, - {file = "pyzmq-25.1.2-cp38-cp38-win32.whl", hash = "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07"}, - {file = "pyzmq-25.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088"}, - {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6"}, - {file = "pyzmq-25.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8"}, - {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565"}, - {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add"}, - {file = "pyzmq-25.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b"}, - {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82"}, - {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6"}, - {file = "pyzmq-25.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2"}, - {file = "pyzmq-25.1.2-cp39-cp39-win32.whl", hash = "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289"}, - {file = "pyzmq-25.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e"}, - {file = "pyzmq-25.1.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05"}, - {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8"}, - {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e"}, - {file = "pyzmq-25.1.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4"}, - {file = "pyzmq-25.1.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d"}, - {file = "pyzmq-25.1.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde"}, - {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8"}, - {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b"}, - {file = "pyzmq-25.1.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96"}, - {file = "pyzmq-25.1.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d"}, - {file = "pyzmq-25.1.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98"}, - {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244"}, - {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73"}, - {file = "pyzmq-25.1.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611"}, - {file = "pyzmq-25.1.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc"}, - {file = "pyzmq-25.1.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314"}, - {file = "pyzmq-25.1.2.tar.gz", hash = "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226"}, -] - -[package.dependencies] -cffi = {version = "*", markers = "implementation_name == \"pypy\""} - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "setuptools" -version = "67.8.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "setuptools-67.8.0-py3-none-any.whl", hash = "sha256:5df61bf30bb10c6f756eb19e7c9f3b473051f48db77fddbe06ff2ca307df9a6f"}, - {file = "setuptools-67.8.0.tar.gz", hash = "sha256:62642358adc77ffa87233bc4d2354c4b2682d214048f500964dbe760ccedf102"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "stack-data" -version = "0.6.3" -description = "Extract data from python stack frames and tracebacks for informative displays" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, - {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, -] - -[package.dependencies] -asttokens = ">=2.1.0" -executing = ">=1.2.0" -pure-eval = "*" - -[package.extras] -tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] - -[[package]] -name = "tabulate" -version = "0.9.0" -description = "Pretty-print tabular data" -category = "main" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, - {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, -] - -[package.extras] -widechars = ["wcwidth"] - -[[package]] -name = "tornado" -version = "6.4" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -category = "dev" -optional = false -python-versions = ">= 3.8" -files = [ - {file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"}, - {file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"}, - {file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"}, - {file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"}, - {file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"}, - {file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"}, - {file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"}, -] - -[[package]] -name = "traitlets" -version = "5.14.0" -description = "Traitlets Python configuration system" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "traitlets-5.14.0-py3-none-any.whl", hash = "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33"}, - {file = "traitlets-5.14.0.tar.gz", hash = "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772"}, -] - -[package.extras] -docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] -test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<7.5)", "pytest-mock", "pytest-mypy-testing"] - -[[package]] -name = "typing-extensions" -version = "4.8.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, -] - -[[package]] -name = "tzdata" -version = "2023.3" -description = "Provider of IANA time zone data" -category = "main" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, - {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, -] - -[[package]] -name = "urllib3" -version = "2.1.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -category = "dev" -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, - {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "wcwidth" -version = "0.2.12" -description = "Measures the displayed width of unicode strings in a terminal" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "wcwidth-0.2.12-py2.py3-none-any.whl", hash = "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c"}, - {file = "wcwidth-0.2.12.tar.gz", hash = "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02"}, -] - -[[package]] -name = "wheel" -version = "0.40.0" -description = "A built-package format for Python" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "wheel-0.40.0-py3-none-any.whl", hash = "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247"}, - {file = "wheel-0.40.0.tar.gz", hash = "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873"}, -] - -[package.extras] -test = ["pytest (>=6.0.0)"] - -[[package]] -name = "zipp" -version = "3.17.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -category = "main" -optional = false -python-versions = ">=3.8" -files = [ - {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, - {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] - -[metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "dd70d1f72e5bb26d5bc836e3ebc8adb1001dcc907d1e8f89a307cf7dd3ca176c" diff --git a/pyproject_.toml b/pyproject_.toml deleted file mode 100644 index 23cf6d7e1..000000000 --- a/pyproject_.toml +++ /dev/null @@ -1,6 +0,0 @@ -[build-system] -requires = [ - "setuptools>=30.3.0", - "wheel", - "setuptools_scm>=3.3.1", -] diff --git a/src/tespy/components/energySupplyComponents.py b/src/tespy/components/energySupplyComponents.py deleted file mode 100644 index 971e262a3..000000000 --- a/src/tespy/components/energySupplyComponents.py +++ /dev/null @@ -1,839 +0,0 @@ -import logging - -from tespy.components import Merge, Splitter -from tespy.components import Sink - -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import ComponentPropertiesArray as dc_cpa - -from tespy.components.nodes.base import NodeBase -from tespy.tools.data_containers import SimpleDataContainer as dc_simple - - -# Fictious Energy Supply models (energy flows modelled as mass flows) -# No real use for tespy I guess - -class HeatPumpEnergySupply(Splitter): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=1) - return self.outlets() - - def get_parameters(self): - variables = super().get_parameters() - variables["COP"] = dc_cp( - min_val=0, - deriv=self.COP_deriv, - func=self.COP_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables['Heating'] = dc_cp(min_val=0, is_result=True) - variables['Cooling'] = dc_cp(min_val=0, is_result=True) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - del constraints['mass_flow_constraints'] - return constraints - - def COP_func(self): - r""" - Equation for COP. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI - - def COP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.COP.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - self.Heating.val = self.outl[0].m.val_SI - self.Cooling.val = -(self.outl[0].m.val_SI-self.inl[0].m.val_SI) - - - -class HeatPumpUsefullLossEnergySupply(Splitter): - - """ - COP sets self.outl[0].m.val_SI - UsefullCoolingRatio sets self.outl[1].m.val_SI - """ - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["COP"] = dc_cp( - min_val=0, - deriv=self.COP_deriv, - func=self.COP_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["UsefullCoolingRatio"] = dc_cp( - min_val=0, - deriv=self.usefull_deriv, - func=self.usefull_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["NonUseFullCooling"] = dc_cp(min_val=0, is_result=True) - variables['Heating'] = dc_cp(min_val=0, is_result=True) - variables['Cooling'] = dc_cp(min_val=0, is_result=True) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - del constraints['mass_flow_constraints'] - return constraints - - def COP_func(self): - return self.inl[0].m.val_SI * self.COP.val - self.outl[0].m.val_SI - - def COP_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.COP.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def usefull_func(self): - return self.inl[0].m.val_SI * (self.COP.val-1) * self.UsefullCoolingRatio.val + self.outl[1].m.val_SI # cooling negative - - def usefull_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[1] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = (self.COP.val-1) * self.UsefullCoolingRatio.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = 1 - - def calc_parameters(self): - super().calc_parameters() - # if not self.COP.is_set: - # self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) - self.Heating.val = self.outl[0].m.val_SI - self.Cooling.val = self.outl[1].m.val_SI - self.NonUseFullCooling.val = self.inl[0].m.val_SI * (self.COP.val - 1) * (1 - self.UsefullCoolingRatio.val) - - -class RefUnitEnergySupply(Splitter): - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=1) - return self.outlets() - - def get_parameters(self): - variables = super().get_parameters() - variables["COP"] = dc_cp( - min_val=0, - deriv=self.COP_deriv, - func=self.COP_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables['Heating'] = dc_cp(min_val=0, is_result=True) - variables['Cooling'] = dc_cp(min_val=0, is_result=True) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - del constraints['mass_flow_constraints'] - return constraints - - def COP_func(self): - r""" - Equation for COP. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - return self.inl[0].m.val_SI * self.COP.val + self.outl[0].m.val_SI - - def COP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - """ - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.COP.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = 1 - - def calc_parameters(self): - super().calc_parameters() - self.Cooling.val = self.outl[0].m.val_SI - self.Heating.val = -self.outl[0].m.val_SI + self.inl[0].m.val_SI - - -class RefUnitUsefullLossEnergySupply(Splitter): - - """ - COP sets self.outl[1].m.val_SI - UsefullHeatingRatio sets self.outl[0].m.val_SI - """ - - - @staticmethod - def component(): - return 'mass factor vapor compression cycle using COP for converting electricity to heat and cooling (energy flows modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["COP"] = dc_cp( - min_val=0, - deriv=self.COP_deriv, - func=self.COP_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["UsefullHeatingRatio"] = dc_cp( - min_val=0, - deriv=self.usefull_deriv, - func=self.usefull_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["NonUseFullHeating"] = dc_cp(min_val=0, is_result=True) - variables['Heating'] = dc_cp(min_val=0, is_result=True) - variables['Cooling'] = dc_cp(min_val=0, is_result=True) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - del constraints['mass_flow_constraints'] - return constraints - - def COP_func(self): - return self.inl[0].m.val_SI * self.COP.val + self.outl[1].m.val_SI # cooling negative - - def COP_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[1] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.COP.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = 1 - - def usefull_func(self): - return self.inl[0].m.val_SI * (self.COP.val + 1) * self.UsefullHeatingRatio.val - self.outl[0].m.val_SI - - def usefull_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = (self.COP.val + 1) * self.UsefullHeatingRatio.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - # if not self.COP.is_set: - # self.COP.val = self.outl[0].m.val_SI / (self.outl[0].m.val_SI - (-self.outl[1].m.val_SI)) - self.Heating.val = self.outl[0].m.val_SI - self.Cooling.val = self.outl[1].m.val_SI - self.NonUseFullHeating.val = self.inl[0].m.val_SI * (self.COP.val + 1) * (1 - self.UsefullHeatingRatio.val) - - - -class MassLossEnergySupply(Splitter): - - @staticmethod - def component(): - return 'mass loss model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["LossRatio"] = dc_cp( - min_val=0, - deriv=self.Loss_deriv, - func=self.Loss_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables['Energy'] = dc_cp(min_val=0, is_result=True) - variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) - return variables - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=1) - return self.outlets() - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['mass_flow_constraints'] - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - - def Loss_func(self): - return self.inl[0].m.val_SI * (1-self.LossRatio.val) - sum([o.m.val_SI for o in self.outl]) - - def Loss_deriv(self, increment_filter, k): - inl = self.inl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = (1-self.LossRatio.val) - for o in self.outl: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - mout = sum([o.m.val_SI for o in self.outl]) - if not self.LossRatio.is_set: - self.LossRatio.val = (self.inl[0].m.val_SI - mout)/self.inl[0].m.val_SI - self.EnergyLoss.val = self.inl[0].m.val_SI - mout - self.Energy.val = mout - -class BoilerEffEnergySupply(Splitter): - - @staticmethod - def component(): - return 'mass efficiency model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["BoilerEff"] = dc_cp( - min_val=0, - deriv=self.Eff_deriv, - func=self.Eff_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables['Energy'] = dc_cp(min_val=0, is_result=True) - variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) - return variables - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=1) - return self.outlets() - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['mass_flow_constraints'] - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - - def Eff_func(self): - return self.inl[0].m.val_SI * self.BoilerEff.val - sum([o.m.val_SI for o in self.outl]) - - def Eff_deriv(self, increment_filter, k): - inl = self.inl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.BoilerEff.val - for o in self.outl: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - mout = sum([o.m.val_SI for o in self.outl]) - if not self.BoilerEff.is_set: - self.BoilerEff.val = mout/self.inl[0].m.val_SI - self.EnergyLoss.val = self.inl[0].m.val_SI - mout - self.Energy.val = mout - - - -class BoilerEffUsefullLossEnergySupply(Splitter): - - """ - BoilerEff defines self.outl[0].m.val_SI - UsefullLossRatio defines self.outl[1].m.val_SI - """ - - @staticmethod - def component(): - return 'mass efficiency model for splitting energy flows (modelled using tespy mass balances)' - - def get_parameters(self): - variables = super().get_parameters() - variables["BoilerEff"] = dc_cp( - min_val=0, - deriv=self.Eff_deriv, - func=self.Eff_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["UsefullLossRatio"] = dc_cp( - min_val=0, - deriv=self.usefull_deriv, - func=self.usefull_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables['Energy'] = dc_cp(min_val=0, is_result=True) - variables['EnergyLoss'] = dc_cp(min_val=0, is_result=True) - variables['EnergyLossUsefull'] = dc_cp(min_val=0, is_result=True) - return variables - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=2) - return self.outlets() - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['mass_flow_constraints'] - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - - def Eff_func(self): - return self.inl[0].m.val_SI * self.BoilerEff.val - self.outl[0].m.val_SI - - def Eff_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[0] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = self.BoilerEff.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def usefull_func(self): - return self.inl[0].m.val_SI * (1-self.BoilerEff.val) * self.UsefullLossRatio.val - self.outl[1].m.val_SI - - def usefull_deriv(self, increment_filter, k): - inl = self.inl[0] - outl = self.outl[1] - if inl.m.is_var: - self.jacobian[k, inl.m.J_col] = (1-self.BoilerEff.val) * self.UsefullLossRatio.val - if outl.m.is_var: - self.jacobian[k, outl.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - # mout = sum([o.m.val_SI for o in self.outl]) - # if not self.BoilerEff.is_set: - # self.BoilerEff.val = mout/self.inl[0].m.val_SI - self.EnergyLossUsefull.val = self.outl[1].m.val_SI - self.EnergyLoss.val = self.inl[0].m.val_SI - sum([o.m.val_SI for o in self.outl]) - self.Energy.val = self.outl[0].m.val_SI - - - -class MergeEnergySupply(Merge): - - @staticmethod - def component(): - return 'merge without pressure/energy constraints' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - -class SplitterEnergySupply(Splitter): - - @staticmethod - def component(): - return 'Splitter without pressure/energy constraints' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - - - -# class SourceEnergy(NodeBase): - -# def __init__(self, label, **kwargs): -# #self.set_attr(**kwargs) -# # need to assign the number of outlets before the variables are set -# for key in kwargs: -# if key == 'num_out': -# self.num_out=kwargs[key] -# super().__init__(label, **kwargs) - -# @staticmethod -# def component(): -# return 'Source' - -# def get_parameters(self): -# variables = super().get_parameters() -# variables['num_out'] = dc_simple() -# variables["Energy"] = dc_cp( -# min_val=0, -# deriv=self.mass_flow_deriv, -# func=self.mass_flow_func, -# latex=self.mass_flow_func_doc, -# num_eq=1 -# ) -# return variables - -# def get_mandatory_constraints(self): -# return {} - -# def outlets(self): -# if self.num_out.is_set: -# return ['out' + str(i + 1) for i in range(self.num_out.val)] -# else: -# self.set_attr(num_out=2) -# return self.outlets() - -# @staticmethod -# def is_branch_source(): -# return True - -# def start_branch(self): -# branches = {} -# for outconn in self.outl: -# branch = { -# "connections": [outconn], -# "components": [self, outconn.target], -# "subbranches": {} -# } -# outconn.target.propagate_to_target(branch) -# branches[outconn.label] = branch -# return branches - -# def start_fluid_wrapper_branch(self): -# branches = {} -# for outconn in self.outl: -# branch = { -# "connections": [outconn], -# "components": [self] -# } -# outconn.target.propagate_wrapper_to_target(branch) -# branches[outconn.label] = branch -# return branches - -# def mass_flow_func(self): -# r""" -# Calculate the residual value for mass flow balance equation. - -# Returns -# ------- -# res : float -# Residual value of equation. - -# .. math:: - -# 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; -# \forall i \in inlets, \forall j \in outlets -# """ -# res = self.Energy.val -# for o in self.outl: -# res -= o.m.val_SI -# return res - -# def mass_flow_deriv(self, increment_filter, k): -# r""" -# Calculate partial derivatives for mass flow equation. - -# Returns -# ------- -# deriv : list -# Matrix with partial derivatives for the fluid equations. -# """ -# for o in self.outl: -# if o.m.is_var: -# self.jacobian[k, o.m.J_col] = -1 - -# def calc_parameters(self): -# super().calc_parameters() -# if not self.Energy.is_set: -# self.Energy.val = sum([o.m.val_SI for o in self.outl]) - - -class SourceEnergy(NodeBase): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - super().__init__(label, **kwargs) - - @staticmethod - def component(): - return 'Source' - - def get_parameters(self): - variables = super().get_parameters() - variables['num_out'] = dc_simple() - variables["Energy"] = dc_cp( - min_val=0, - deriv=self.mass_flow_deriv, - func=self.mass_flow_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - variables["EnergyArray"] = dc_cpa( - min_val=0, - deriv=self.mass_flow_array_deriv, - func=self.mass_flow_array_func, - latex=self.mass_flow_func_doc, - #num_eq=self.num_out - ) - - return variables - - def get_mandatory_constraints(self): - return {} - - def outlets(self): - if self.num_out.is_set: - return ['out' + str(i + 1) for i in range(self.num_out.val)] - else: - self.set_attr(num_out=2) - return self.outlets() - - @staticmethod - def is_branch_source(): - return True - - def start_branch(self): - branches = {} - for outconn in self.outl: - branch = { - "connections": [outconn], - "components": [self, outconn.target], - "subbranches": {} - } - outconn.target.propagate_to_target(branch) - branches[outconn.label] = branch - return branches - - def start_fluid_wrapper_branch(self): - branches = {} - for outconn in self.outl: - branch = { - "connections": [outconn], - "components": [self] - } - outconn.target.propagate_wrapper_to_target(branch) - branches[outconn.label] = branch - return branches - - def mass_flow_func(self): - res = self.Energy.val - for o in self.outl: - res -= o.m.val_SI - return res - - def mass_flow_deriv(self, increment_filter, k): - for o in self.outl: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - def mass_flow_array_func(self): - residual = [] - for i,is_set in enumerate(self.EnergyArray.is_set): - if is_set: - o = self.outl[i] - residual += [self.EnergyArray.val[i] - o.m.val_SI] - return residual - - def mass_flow_array_deriv(self, increment_filter, k): - m=0 - for i,is_set in enumerate(self.EnergyArray.is_set): - if is_set: - o = self.outl[i] - self.jacobian[k + m, o.m.J_col] = -1 - m=m+1 - - def calc_parameters(self): - super().calc_parameters() - if not self.Energy.is_set: - self.Energy.val = sum([o.m.val_SI for o in self.outl]) - for i,o in enumerate(self.outl): - self.EnergyArray.val[i] = o.m.val_SI - - -class SinkEnergy(Sink): - - @staticmethod - def component(): - return 'sink with energy ' - - def get_parameters(self): - variables = super().get_parameters() - variables["Energy"] = dc_cp( - min_val=0, - deriv=self.mass_flow_deriv, - func=self.mass_flow_func, - latex=self.mass_flow_func_doc, - num_eq=1 - ) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - return constraints - - - def mass_flow_func(self): - r""" - Calculate the residual value for mass flow balance equation. - - Returns - ------- - res : float - Residual value of equation. - - .. math:: - - 0 = \sum \dot{m}_{in,i} - \sum \dot{m}_{out,j} \; - \forall i \in inlets, \forall j \in outlets - """ - res = self.Energy.val - for i in self.inl: - res -= i.m.val_SI - return res - - def mass_flow_func_doc(self, label): - pass - - def mass_flow_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives for mass flow equation. - - Returns - ------- - deriv : list - Matrix with partial derivatives for the fluid equations. - """ - for i in self.inl: - if i.m.is_var: - self.jacobian[k, i.m.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - if not self.Energy.is_set: - self.Energy.val = self.inl[0].m.val_SI - - -class FlowEnergy(Splitter): - - @staticmethod - def component(): - return 'flow with energy ' - - def get_parameters(self): - variables = super().get_parameters() - variables["Energy"] = dc_cp( - min_val=0, - deriv=self.Energy_mass_flow_deriv, - func=self.Energy_mass_flow_func, - latex=self.Energy_mass_flow_func_doc, - num_eq=1 - ) - return variables - - def outlets(self): - self.set_attr(num_out=1) - return ['out1'] - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - #del constraints['mass_flow_constraints'] - del constraints['pressure_constraints'] - del constraints['energy_balance_constraints'] - return constraints - - def Energy_mass_flow_func(self): - res = self.Energy.val - for i in self.inl: - res -= i.m.val_SI - return res - - def Energy_mass_flow_deriv(self, increment_filter, k): - for i in self.inl: - if i.m.is_var: - self.jacobian[k, i.m.J_col] = -1 - - def Energy_mass_flow_func_doc(self, label): - pass - - def calc_parameters(self): - super().calc_parameters() - if not self.Energy.is_set: - self.Energy.val = self.inl[0].m.val_SI \ No newline at end of file diff --git a/src/tespy/components/newAdvancedComponents.py b/src/tespy/components/newAdvancedComponents.py deleted file mode 100644 index a0bdb1622..000000000 --- a/src/tespy/components/newAdvancedComponents.py +++ /dev/null @@ -1,1089 +0,0 @@ -import logging - -from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter, HeatExchanger -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import SimpleDataContainer as dc_simple -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.tools.fluid_properties import T_mix_ph, h_mix_pT -from tespy.tools.helpers import TESPyComponentError - -from tespy.components.component import Component - -from tespy.tools.fluid_properties import dT_mix_dph -from tespy.tools.fluid_properties import dT_mix_pdh - -from CoolProp.HumidAirProp import HAPropsSI - -import warnings - -import numpy as np - -from .newComponents import SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP - - -def get_Twb(port,T): - M = port.fluid.val["Water"]/(port.fluid.val["Water"]+port.fluid.val["Air"]) - W = M/(1-M) - return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) - - - -class TwoStreamEvaporator(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - - def __init__(self, label, **kwargs): - super().__init__(label, **kwargs) - - def outlets(self): - return ['out1', # vapor - 'out2', # liquid - 'out3'] # steam condensate - - def inlets(self): - return ['in1', 'in2'] - - @staticmethod - def component(): - return 'separator with species flow splits and dH on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["num_in"] = dc_simple() - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=2 - ) - variables["Q"] = dc_cp( - max_val=0, func=self.energy_balance_hot_func, num_eq=1, - deriv=self.energy_balance_hot_deriv, - latex=self.pr_func_doc) - variables["KPI"] = dc_cp( - deriv=self.KPI_deriv, - func=self.KPI_func, - latex=self.pr_func_doc, - num_eq=1) - #variables["Qout"] = dc_cpa() - variables['kA'] = dc_cp( - min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, - deriv=self.kA_deriv) - variables['td'] = dc_cp(min_val=0, is_result=True) - variables['dTo'] = dc_cp( - min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, - deriv=self.dTo_deriv) - variables['deltaPhot'] = dc_cp( - min_val=0, num_eq=1, func=self.deltaPhot_func, latex=self.pr_func_doc, - deriv=self.deltaPhot_deriv) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - constraints['energy_balance_constraints'] = { - 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - constraints['mass_flow_constraints'] = { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 1} - return constraints - - - @staticmethod - def is_branch_source(): - # trigger start_branch - return True - - def start_branch(self): - branches = {} - for outconn in [self.outl[0],self.outl[1]]: - branch = { - "connections": [outconn], - "components": [self, outconn.target], - "subbranches": {} - } - outconn.target.propagate_to_target(branch) - - branches[outconn.label] = branch - return branches - - def propagate_to_target(self, branch): - inconn = branch["connections"][-1] - conn_idx = self.inl.index(inconn) - if conn_idx == 1: - # connect in2 with with out3 - othervice stop the connections - outconn = self.outl[2] - branch["connections"] += [outconn] - branch["components"] += [outconn.target] - outconn.target.propagate_to_target(branch) - - def propagate_wrapper_to_target(self, branch): - inconn = branch["connections"][-1] - conn_idx = self.inl.index(inconn) - if conn_idx == 1: - # connect in2 with with out3 - outconn = self.outl[2] - branch["connections"] += [outconn] - branch["components"] += [self] - outconn.target.propagate_wrapper_to_target(branch) - elif conn_idx == 0: - # propagate wrapper to new start branches - branch["components"] += [self] - for outconn in [self.outl[0],self.outl[1]]: - branch["connections"] += [outconn] - outconn.target.propagate_wrapper_to_target(branch) - - def deltaPhot_func(self): - return self.inl[1].p.val_SI - self.deltaPhot.val*1e5 - self.outl[2].p.val_SI - - def deltaPhot_deriv(self, increment_filter, k): - if self.inl[1].p.is_var: - self.jacobian[k, self.inl[1].p.J_col] = 1 - if self.outl[2].p.is_var: - self.jacobian[k, self.outl[2].p.J_col] = -1 - - def fluid_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - # hi = [self.inl[1]] - # ho = [self.outl[2]] - residual = [] - for fluid in self.variable_fluids: - res = 0 - for i in ci: - res += i.fluid.val[fluid] * i.m.val_SI - for o in co: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - # for fluid in self.variable_fluids: - # res = 0 - # for i in hi: - # res += i.fluid.val[fluid] * i.m.val_SI - # for o in ho: - # res -= o.fluid.val[fluid] * o.m.val_SI - # residual += [res] - return residual - - def fluid_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - # hi = [self.inl[1]] - # ho = [self.outl[2]] - for fluid in self.variable_fluids: - for o in co: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - for i in ci: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - k += 1 - # for fluid in self.variable_fluids: - # for o in ho: - # if self.is_variable(o.m): - # self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - # if fluid in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - # for i in hi: - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - # if fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - # k += 1 - - def mass_flow_func(self): - r""" - Calculate the residual value for mass flow balance equation. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - # hi = [self.inl[1]] - # ho = [self.outl[2]] - residuals = [] - res = 0 - for i in ci: - res += i.m.val_SI - for o in co: - res -= o.m.val_SI - residuals += [res] - # res = 0 - # for i in hi: - # res += i.m.val_SI - # for o in ho: - # res -= o.m.val_SI - # residuals += [res] - return residuals - - def mass_flow_deriv(self, k): - r""" - Calculate partial derivatives for mass flow equation. - """ - ci = [self.inl[0]] - co = [self.outl[0],self.outl[1]] - # hi = [self.inl[1]] - # ho = [self.outl[2]] - for i in ci: - if i.m.is_var: - self.jacobian[k, i.m.J_col] = 1 - for o in co: - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - # k = k + 1 - # for i in hi: - # if i.m.is_var: - # self.jacobian[k, i.m.J_col] = 1 - # for o in ho: - # if o.m.is_var: - # self.jacobian[k, o.m.J_col] = -1 - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in [self.outl[0],self.outl[1]]: - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in [self.outl[0],self.outl[1]]: - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def energy_balance_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - - hi = self.inl[1] - ho = self.outl[2] - return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) + hi.m.val_SI * (ho.h.val_SI - hi.h.val_SI) - - def energy_balance_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - hi = self.inl[1] - ho = self.outl[2] - - if self.is_variable(hi.m): - self.jacobian[k, hi.m.J_col] = (ho.h.val_SI - hi.h.val_SI) - if self.is_variable(hi.h): - self.jacobian[k, hi.h.J_col] = -hi.m.val_SI - if self.is_variable(ho.h): - self.jacobian[k, ho.h.J_col] = ho.m.val_SI - - - def dTo_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - return T0 - T1 - self.dTo.val - - def dTo_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - for c in [self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) - - def energy_balance_hot_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - return self.inl[1].m.val_SI * ( - self.outl[2].h.val_SI - self.inl[1].h.val_SI - ) + self.Q.val - - def energy_balance_hot_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[1] - o = self.outl[2] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = -i.m.val_SI - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = i.m.val_SI - - def KPI_func(self): - r""" - Equation for total heat flow rate - """ - return self.inl[1].m.val_SI * ( - self.outl[2].h.val_SI - self.inl[1].h.val_SI - ) + self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']*self.KPI.val - - - def KPI_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[1] - o = self.outl[2] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = -i.m.val_SI - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = i.m.val_SI - ci = self.inl[0] - if self.is_variable(ci.m): - self.jacobian[k, ci.m.J_col] = ci.fluid.val['Water']*self.KPI.val - if 'Water' in ci.fluid.is_var: - self.jacobian[k, ci.fluid.J_col['Water']] = ci.m.val_SI*self.KPI.val - - def kA_func(self): - r""" - Calculate heat transfer from heat transfer coefficient. - """ - - Tcold = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) # vapor out - #Thot = self.outl[2].calc_T(T0=self.outl[2].T.val_SI) - Thot = self.inl[1].calc_T_sat() # liquid out - self.td.val = (Thot-Tcold) - - return self.inl[1].m.val_SI * ( - self.outl[2].h.val_SI - self.inl[1].h.val_SI - ) + self.kA.val * self.td.val - - def kA_deriv(self, increment_filter, k): - r""" - Partial derivatives of heat transfer coefficient function. - """ - - i = self.inl[1] - o = self.outl[2] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) - if self.is_variable(i.p): - self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = i.m.val_SI - c = self.outl[0] - if self.is_variable(c.p): - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - if self.is_variable(c.h): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) - - def calc_parameters(self): - super().calc_parameters() - i = self.inl[0] - - if not self.Q.is_set: - self.Q.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) # np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - if not self.KPI.is_set: - self.KPI.val = - self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI) / (self.inl[0].m.val_SI*self.inl[0].fluid.val['Water']) - - hmin = min([o.h.val_SI for o in self.outl]) - hmax = max([o.h.val_SI for o in self.outl]) - if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): - self.deltaH.val = i.h.val_SI - hmin - else: - self.deltaH.val = i.h.val_SI - hmax - - if not self.kA.is_set: - Tcold = self.outl[0].T.val_SI # vapor out - #Thot = self.outl[2].T.val_SI - Thot = self.inl[1].calc_T_sat() # liquid out - self.td.val = (Thot-Tcold) - if Thot == Tcold: - self.kA.val = np.NaN - else: - self.kA.val = -self.inl[1].m.val_SI * (self.outl[2].h.val_SI - self.inl[1].h.val_SI)/self.td.val - - - - -class TwoStreamDrier(SeparatorWithSpeciesSplitsDeltaH,SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaP): - - def __init__(self, label, **kwargs): - super().__init__(label, **kwargs) - - def outlets(self): - return ['out1', # vapor - 'out2'] # liquid - - def inlets(self): - return ['in1', 'in2'] - - @staticmethod - def component(): - return 'separator with species flow splits and dH on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["num_in"] = dc_simple() - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=1 - ) - variables["dTwbProd"] = dc_cp( - deriv=self.dTwbProd_deriv, - func=self.dTwbProd_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["Q"] = dc_cp( - max_val=0, func=self.energy_balance_hot_func, num_eq=1, - deriv=self.energy_balance_hot_deriv, - latex=self.pr_func_doc) - variables["KPI"] = dc_cp( - deriv=self.KPI_deriv, - func=self.KPI_func, - latex=self.pr_func_doc, - num_eq=1) - #variables["Qout"] = dc_cpa() - variables['kA'] = dc_cp( - min_val=0, num_eq=1, func=self.kA_func, latex=self.pr_func_doc, - deriv=self.kA_deriv) - variables['td_log'] = dc_cp(min_val=0, is_result=True) - variables["WBeff"] = dc_cp( - min_val=0,max_val=1, - deriv=self.WBeff_deriv, - func=self.WBeff_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables['RH'] = dc_cp(min_val=0, max_val=100, is_result=True) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - #self.variable_product_fluids = [fluid for fluid in self.variable_fluids if not fluid in ['Water','Air']] - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - constraints['energy_balance_constraints'] = { - 'func': self.energy_balance_func, 'deriv': self.energy_balance_deriv, - 'constant_deriv': False, 'latex': self.energy_balance_func_doc, - 'num_eq': 1} - constraints['mass_flow_constraints'] = { - 'func': self.mass_flow_func, 'deriv': self.mass_flow_deriv, - 'constant_deriv': True, 'latex': self.mass_flow_func_doc, - 'num_eq': 2} - return constraints - - - # @staticmethod - # def is_branch_source(): - # # trigger start_branch - # return True - - # def start_branch(self): - # branches = {} - # for outconn in [self.outl[0],self.outl[1]]: - # branch = { - # "connections": [outconn], - # "components": [self, outconn.target], - # "subbranches": {} - # } - # outconn.target.propagate_to_target(branch) - - # branches[outconn.label] = branch - # return branches - - # def propagate_to_target(self, branch): - # inconn = branch["connections"][-1] - # conn_idx = self.inl.index(inconn) - # if conn_idx == 1: - # # connect in2 with with out3 - othervice stop the connections - # outconn = self.outl[2] - # branch["connections"] += [outconn] - # branch["components"] += [outconn.target] - # outconn.target.propagate_to_target(branch) - - # def propagate_wrapper_to_target(self, branch): - # inconn = branch["connections"][-1] - # conn_idx = self.inl.index(inconn) - # if conn_idx == 1: - # # connect in2 with with out3 - # outconn = self.outl[2] - # branch["connections"] += [outconn] - # branch["components"] += [self] - # outconn.target.propagate_wrapper_to_target(branch) - # elif conn_idx == 0: - # # propagate wrapper to new start branches - # branch["components"] += [self] - # for outconn in [self.outl[0],self.outl[1]]: - # branch["connections"] += [outconn] - # outconn.target.propagate_wrapper_to_target(branch) - - - def fluid_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - residual = [] - for fluid in self.variable_fluids: - res = 0 - for i in self.inl: - res += i.fluid.val[fluid] * i.m.val_SI - for o in self.outl: - res -= o.fluid.val[fluid] * o.m.val_SI - residual += [res] - return residual - - def fluid_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - for fluid in self.variable_fluids: - for o in self.outl: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - for i in self.inl: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI - k += 1 - - def mass_flow_func(self): - r""" - Calculate the residual value for mass flow balance equation. - """ - i1 = self.inl[0] - i2 = self.inl[1] # air - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - residuals = [] - residuals += [i1.m.val_SI - o2.m.val_SI - m_evap] - residuals += [i2.m.val_SI - o1.m.val_SI + m_evap] - - return residuals - - def mass_flow_deriv(self, k): - r""" - Calculate partial derivatives for mass flow equation. - """ - i1 = self.inl[0] - i2 = self.inl[1] # air - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - fluid = 'Water' - - if i1.m.is_var: - self.jacobian[k, i1.m.J_col] = 1 - i1.fluid.val[fluid] - if o2.m.is_var: - self.jacobian[k, o2.m.J_col] = -1 + o2.fluid.val[fluid] - if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = - i1.m.val_SI - if fluid in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col[fluid]] = + o2.m.val_SI - - k = k + 1 - - if i2.m.is_var: - self.jacobian[k, i2.m.J_col] = 1 - if o1.m.is_var: - self.jacobian[k, o1.m.J_col] = -1 - if i1.m.is_var: - self.jacobian[k, i1.m.J_col] = + i1.fluid.val[fluid] - if o2.m.is_var: - self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] - if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = + i1.m.val_SI - if fluid in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in [self.outl[1]]: # liquid -- let energy balance solve the other - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in [self.outl[1]]: # liquid -- let energy balance solve the other - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def energy_balance_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - i1 = self.inl[0] - i2 = self.inl[1] # air - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - return i1.m.val_SI * i1.h.val_SI + i2.m.val_SI * i2.h.val_SI \ - - o2.m.val_SI * o2.h.val_SI - o1.m.val_SI * o1.h.val_SI - - def energy_balance_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i1 = self.inl[0] - i2 = self.inl[1] # air - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - for i in [i1,i2]: - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = i.h.val_SI - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = i.m.val_SI - for o in [o2,o1]: - if self.is_variable(o.m): - self.jacobian[k, o.m.J_col] = -o.h.val_SI - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -o.m.val_SI - - - def dTwbProd_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i = self.inl[1] - T_in = i.calc_T(T0=i.T.val_SI) - T_wb = get_Twb(i,T_in) - o = self.outl[1] # liquid - T_out = o.calc_T(T0=o.T.val_SI) - return T_out - T_wb - self.dTwbProd.val - - def dTwbProd_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - # for c in [self.inl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = dT_mix_dph(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = dT_mix_pdh(c.p.val_SI, c.h.val_SI, c.fluid_data, c.mixing_rule,T0 = c.T.val_SI,force_state=c.force_state) - # T_wb is nonlinear and we cannot differentiate easily - for c in [self.inl[1],self.outl[1]]: # in and liquid - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTwbProd_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTwbProd_func, 'h', c) - - - def energy_balance_hot_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - - i1 = self.inl[0] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - return (Q_evap - self.Q.val)/(self.Q.val+1e-6) - - # i1 = self.inl[0] - # i2 = self.inl[1] # air - # o1 = self.outl[0] # vapor - # o2 = self.outl[1] # liquid - - # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To1 = o1.calc_T(T0=o1.T.val_SI) - - # m_air = i2.m.val_SI*i2.fluid.val['Air'] - # Q_air = m_air * (i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) - # -o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state)) - - # return (Q_air - self.Q.val)/self.Q.val - - def energy_balance_hot_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - - # i1 = self.inl[0] - # i2 = self.inl[1] # air - # o1 = self.outl[0] # vapor - # o2 = self.outl[1] # liquid - - # fluid = 'Air' - # Ti2 = i2.calc_T(T0=i2.T.val_SI) - # To1 = o1.calc_T(T0=o1.T.val_SI) - # hi2 = i2.fluid_data[fluid]['wrapper'].h_pT(i2.p.val_SI,Ti2,force_state=i2.force_state) - # ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - - # # Q_air = i2.m.val_SI*i2.fluid.val['Air'] * (hi2 - ho1) - - # if self.is_variable(i2.m): - # self.jacobian[k, i2.m.J_col] = i2.fluid.val[fluid] * (hi2 - ho1) - # if fluid in i2.fluid.is_var: - # self.jacobian[k, i2.fluid.J_col[fluid]] = i2.m.val_SI * (hi2 - ho1) - - # for c in [i2,o1]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # for c in [i2,o1]: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) - - # # let's just do numerical derivative of them all - # i1 = self.inl[0] - # i2 = self.inl[1] - # o1 = self.outl[0] # vapor - # o2 = self.outl[1] # liquid - - # for c in [i1,i2,o2,o1]: - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - fluid = 'Water' - Ti1 = i1.calc_T(T0=i1.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - - ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) - - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho1 - hi1)/(self.Q.val+1e-6) - if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho1 - hi1)/(self.Q.val+1e-6) - - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(self.Q.val+1e-6) - if fluid in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(self.Q.val+1e-6) - - # for c in [i1,i2,o2,o1]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'p', c) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'h', c) - # if self.is_variable(c.m): #, increment_filter): - # self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.energy_balance_hot_func, 'm', c) - # #for c in [i1,o2,o1]: - # for fluid in self.variable_fluids: - # if fluid in c.fluid.is_var: - # self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.energy_balance_hot_func, fluid, c) - - - def KPI_func(self): - r""" - Equation for total heat flow rate - """ - - i1 = self.inl[0] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val - return (Q_evap - Q)/(Q+1e-6) - - def KPI_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - fluid = 'Water' - Ti1 = i1.calc_T(T0=i1.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - - ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) - Q = i1.m.val_SI*i1.fluid.val['Water']*self.KPI.val - - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = (i1.fluid.val[fluid] - i1.m.val_SI*self.KPI.val) * (ho1 - hi1)/(Q+1e-6) - if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = (i1.m.val_SI - i1.fluid.val['Water']*self.KPI.val) * (ho1 - hi1)/(Q+1e-6) - - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) - if fluid in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(Q+1e-6) - - def calculate_td_log(self,T_i,T_wb,T_o): - # temperature value manipulation for convergence stability - T_i1 = T_i - T_o1 = T_o - T_i2 = T_wb - T_o2 = T_wb - - if T_i1 <= T_o2: - T_i1 = T_o2 + 0.01 - if T_i1 <= T_o2: - T_o2 = T_i1 - 0.01 - if T_i1 <= T_o2: - T_o1 = T_i2 + 0.02 - if T_o1 <= T_i2: - T_i2 = T_o1 - 0.02 - - ttd_u = T_i1 - T_o2 - ttd_l = T_o1 - T_i2 - - if ttd_u == ttd_l: - td_log = ttd_l - else: - td_log = (ttd_l - ttd_u) / np.log((ttd_l) / (ttd_u)) - - return td_log - - def kA_func(self): - r""" - Calculate heat transfer from heat transfer coefficient. - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - Ti2 = i2.calc_T(T0=i2.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - Twb = get_Twb(i2,Ti2) - self.td_log.val = self.calculate_td_log(Ti2,Twb,To1) - - Ti1 = i1.calc_T(T0=i1.T.val_SI) - m_evap = i1.m.val_SI*i1.fluid.val['Water'] - o2.m.val_SI*o2.fluid.val['Water'] - Q_evap = m_evap * (o1.fluid_data['Water']['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - -i1.fluid_data['Water']['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state)) - - Q = self.kA.val * self.td_log.val - return (Q_evap - Q)/(Q+1e-6) - - def kA_deriv(self, increment_filter, k): - r""" - Partial derivatives of heat transfer coefficient function. - """ - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - fluid = 'Water' - Ti1 = i1.calc_T(T0=i1.T.val_SI) - To1 = o1.calc_T(T0=o1.T.val_SI) - - ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,To1,force_state=o1.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,Ti1,force_state=i1.force_state) - - # Q_evap = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) - Q = self.kA.val * self.td_log.val - - if self.is_variable(i1.m): - self.jacobian[k, i1.m.J_col] = i1.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) - if fluid in i1.fluid.is_var: - self.jacobian[k, i1.fluid.J_col[fluid]] = i1.m.val_SI * (ho1 - hi1)/(Q+1e-6) - - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = - o2.fluid.val[fluid] * (ho1 - hi1)/(Q+1e-6) - if fluid in o2.fluid.is_var: - self.jacobian[k, o2.fluid.J_col[fluid]] = - o2.m.val_SI * (ho1 - hi1)/(Q+1e-6) - - # i = self.inl[1] - # o = self.outl[2] - # if self.is_variable(i.m): - # self.jacobian[k, i.m.J_col] = o.h.val_SI - i.h.val_SI - # if self.is_variable(i.h): - # self.jacobian[k, i.h.J_col] = self.numeric_deriv(self.kA_func, 'h', i) - # if self.is_variable(i.p): - # self.jacobian[k, i.p.J_col] = self.numeric_deriv(self.kA_func, 'p', i) - # if self.is_variable(o.h): - # self.jacobian[k, o.h.J_col] = i.m.val_SI - # c = self.outl[1] - # if self.is_variable(c.p): - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.kA_func, 'p', c) - # if self.is_variable(c.h): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.kA_func, 'h', c) - - - def WBeff_func(self): - r""" - Calculate the vector of residual values for fluid balance equations. - """ - i2 = self.inl[1] - Ti2 = i2.calc_T(T0=i2.T.val_SI) - T_wb = get_Twb(i2,Ti2) - o2 = self.outl[0] # vapor - To2 = o2.calc_T(T0=o2.T.val_SI) - - return (Ti2-To2) - (Ti2-T_wb)*self.WBeff.val - - def WBeff_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of fluid balance. - """ - - # let's just do numerical derivative of them all - i1 = self.inl[0] - i2 = self.inl[1] - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - for c in [i1,i2,o1,o2]: - if self.is_variable(c.m): #, increment_filter): - self.jacobian[k, c.m.J_col] = self.numeric_deriv(self.WBeff_func, 'm', c) - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.WBeff_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.WBeff_func, 'h', c) - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.WBeff_func, fluid, c) - - def calc_parameters(self): - super().calc_parameters() - i = self.inl[0] - - i1 = self.inl[0] - i2 = self.inl[1] # air - o1 = self.outl[0] # vapor - o2 = self.outl[1] # liquid - - # m_air = i2.m.val_SI*i2.fluid.val['Air'] #i2.m.val_SI # *i2.fluid.val['Air'] - # Q_air = + m_air * (o1.fluid_data['Air']['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) - # -i2.fluid_data['Air']['wrapper'].h_pT(i2.p.val_SI,i2.T.val_SI,force_state=i2.force_state)) - - if not self.Q.is_set: - fluid = 'Water' - ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) - self.Q.val = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) - if not self.KPI.is_set: - fluid = 'Water' - ho1 = o1.fluid_data[fluid]['wrapper'].h_pT(o1.p.val_SI,o1.T.val_SI,force_state=o1.force_state) - hi1 = i1.fluid_data[fluid]['wrapper'].h_pT(i1.p.val_SI,i1.T.val_SI,force_state=i1.force_state) - self.KPI.val = (i1.m.val_SI*i1.fluid.val[fluid] - o2.m.val_SI*o2.fluid.val[fluid]) * (ho1 - hi1) / (i1.m.val_SI*i1.fluid.val['Water']) - - hmin = min([o.h.val_SI for o in self.outl]) - hmax = max([o.h.val_SI for o in self.outl]) - if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): - self.deltaH.val = i.h.val_SI - hmin - else: - self.deltaH.val = i.h.val_SI - hmax - - Thot_in = i2.T.val_SI - Thot_out = o1.T.val_SI - Tcold = get_Twb(i2,Thot_in) - if not self.kA.is_set: - ttd_u = Thot_in - Tcold - ttd_l = Thot_out - Tcold - if ttd_u < 0 or ttd_l < 0: - self.td_log.val = np.nan - elif ttd_l == ttd_u: - self.td_log.val = ttd_l - else: - self.td_log.val = ((ttd_l - ttd_u) / np.log(ttd_l / ttd_u)) - self.kA.val = self.Q.val / self.td_log.val - - if not self.WBeff.is_set: - self.WBeff.val = (Thot_in-Thot_out)/(Thot_in-Tcold) - if self.WBeff.val > 1.0: - TESPyComponentError("efficiency cannot be greater than 1.0, try increase air mass flow") - - M_o = o1.fluid.val["Water"] - W_o = M_o/(1-M_o) - Wmax = HAPropsSI('W','P',o1.p.val_SI,'T',o1.T.val_SI,'R',1) - if W_o > Wmax: - self.RH.val = W_o/Wmax*100 - TESPyComponentError("Relative humidity cannot be greater than 100 %, try increase air mass flow") - else: - self.RH.val = 100 * HAPropsSI('R','P',o1.p.val_SI,'T',o1.T.val_SI,'W',W_o) \ No newline at end of file diff --git a/src/tespy/components/newComponents.py b/src/tespy/components/newComponents.py deleted file mode 100644 index cb01f61e9..000000000 --- a/src/tespy/components/newComponents.py +++ /dev/null @@ -1,1307 +0,0 @@ -import logging - -from tespy.components import SimpleHeatExchanger, Merge, Separator, Splitter, HeatExchanger -from tespy.tools.data_containers import ComponentProperties as dc_cp -from tespy.tools.data_containers import SimpleDataContainer as dc_simple -from tespy.tools.data_containers import GroupedComponentProperties as dc_gcp -from tespy.tools.fluid_properties import T_mix_ph, h_mix_pT -from tespy.tools.helpers import TESPyComponentError - -from tespy.components.component import Component - -from tespy.tools.fluid_properties import dT_mix_dph -from tespy.tools.fluid_properties import dT_mix_pdh - -from CoolProp.HumidAirProp import HAPropsSI - -import warnings - -import numpy as np - - -def get_Twb(port,T): - M = port.fluid.val["Water"]/(port.fluid.val["Water"]+port.fluid.val["Air"]) - W = M/(1-M) - return HAPropsSI('Twb','P',port.p.val_SI,'T',T,'W',W) - -class DiabaticSimpleHeatExchanger(SimpleHeatExchanger): - - @staticmethod - def component(): - return 'diabatic simple heat exchanger' - - def get_parameters(self): - variables = super().get_parameters() - variables["eta"] = dc_cp(min_val=1e-5, val=1, max_val=1) - variables["Q_loss"] = dc_cp(max_val=0, val=0, is_result=True) - variables["Q_total"] = dc_cp(is_result=True) - variables["energy_group"] = dc_gcp( - elements=['Q_total', 'eta'], - num_eq=1, - latex=self.energy_balance_func_doc, - func=self.energy_balance2_func, deriv=self.energy_balance2_deriv - ) - - return variables - - def energy_balance2_func(self): - r""" - Equation for pressure drop calculation. - - Returns - ------- - residual : float - Residual value of equation: - - .. math:: - - 0 =\dot{m}_{in}\cdot\left( h_{out}-h_{in}\right) -\dot{Q} - """ - if self.Q_total.val < 0: - return self.inl[0].m.val_SI * ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI - ) * self.eta.val - self.Q_total.val - else: - return self.inl[0].m.val_SI * ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI - ) - self.Q_total.val * self.eta.val - - def energy_balance2_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of derivatives in Jacobian matrix (k-th equation). - """ - - - i = self.inl[0] - o = self.outl[0] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI) - if i.h.is_var: - self.jacobian[k, i.h.J_col] = -i.m.val_SI - if o.h.is_var: - self.jacobian[k, o.h.J_col] = i.m.val_SI - # custom variable Q - if self.Q_total.is_var: - if self.Q_total.val < 0: - self.jacobian[k, self.Q_total.J_col] = -1 - else: - self.jacobian[k, self.Q_total.J_col] = -self.eta.val - - if self.eta.is_var: - if self.Q_total.val < 0: - self.jacobian[k, self.eta.J_col] = self.inl[0].m.val_SI * ( - self.outl[0].h.val_SI - self.inl[0].h.val_SI - ) - else: - self.jacobian[k, self.eta.J_col] = -self.Q_total.val - - def calc_parameters(self): - super().calc_parameters() - - if self.eta.is_set: - if self.Q.val < 0: - self.Q_loss.val = self.Q.val * (1 - self.eta.val) - else: - self.Q_loss.val = -self.Q.val * (1 / self.eta.val - 1) - - self.Q_total.val = self.Q.val - self.Q_loss.val - - -class SimpleHeatExchangerDeltaP(SimpleHeatExchanger): - - @staticmethod - def component(): - return 'simple heat exchanger with pressure drop' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaP"] = dc_cp( - min_val=0, - deriv=self.deltaP_deriv, - func=self.deltaP_func, - latex=self.pr_func_doc, - num_eq=1, - ) - return variables - - def deltaP_func(self): - r""" - Equation for pressure drop. - - Returns - ------- - residual : float - Residual value of equation. - - .. math:: - - 0 = p_\mathrm{in,1} \cdot pr - p_\mathrm{out,1} - """ - - return self.inl[0].p.val_SI - self.deltaP.val*1e5 - self.outl[0].p.val_SI - - def deltaP_deriv(self, increment_filter, k, pr='', inconn=0, outconn=0): - r""" - Calculate the partial derivatives for pressure drop. - - Parameters - ---------- - increment_filter : ndarray - Matrix for filtering non-changing variables. - - k : int - Position of equation in Jacobian matrix. - - pr : str - Component parameter to evaluate the pr_func on, e.g. - :code:`pr1`. - - inconn : int - Connection index of inlet. - - outconn : int - Connection index of outlet. - """ - - deltaP = self.get_attr("deltaP") - i = self.inl[inconn] - o = self.outl[inconn] - if i.p.is_var: - self.jacobian[k, i.p.J_col] = 1 - if o.p.is_var: - self.jacobian[k, o.p.J_col] = -1 - if deltaP.is_var: - self.jacobian[k, self.pr.J_col] = 1 - - - def calc_parameters(self): - super().calc_parameters() - self.deltaP.val = (self.inl[0].p.val_SI - self.outl[0].p.val_SI)/1e5 - - -class SimpleHeatExchangerDeltaPLossFactor(SimpleHeatExchangerDeltaP): - - @staticmethod - def component(): - return 'diabatic simple heat exchanger' - - def get_parameters(self): - variables = super().get_parameters() - variables["LF"] = dc_cp(min_val=0, val=0, max_val=1, is_result=True) - variables["Q_loss"] = dc_cp(is_result=True) - variables["Q_total"] = dc_cp(is_result=True) - variables["energy_group1"] = dc_gcp( - elements=['LF', 'Q_total'], - func=self.Q_total_func, - deriv=self.Q_total_deriv, - latex=self.energy_balance_func_doc, num_eq=1) - variables["energy_group2"] = dc_gcp( - elements=['Q_loss', 'Q_total'], - func=self.Q_total_func, - deriv=self.Q_total_deriv, - latex=self.energy_balance_func_doc, num_eq=1) - variables["energy_group3"] = dc_gcp( - elements=['Q_loss', 'LF'], - func=self.Q_total_func, - deriv=self.Q_total_deriv, - latex=self.energy_balance_func_doc, num_eq=1) - return variables - - def Q_total_func(self): - r""" - Equation for total heat flow rate - - """ - # self.Q_loss.val is negative and Q_total is positive (and vice versa) - - if self.energy_group2.is_set: - self.LF.val = -self.Q_loss.val/(self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)) - if self.energy_group3.is_set: - self.Q_total.val = -self.Q_loss.val*(1+self.LF.val)/self.LF.val - - return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q_total.val - - - def Q_total_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of Q_total - - """ - - i = self.inl[0] - o = self.outl[0] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) - if i.h.is_var: - self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) - if o.h.is_var: - self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) - if self.Q_total.is_var: - self.jacobian[k, self.Q_total.J_col] = -1 - if self.LF.is_var: - self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - if self.Q_loss.is_var: - self.jacobian[k, self.Q_loss.J_col] = -(1+self.LF.val)/self.LF.val - - def calc_parameters(self): - super().calc_parameters() - - # repeat calculations to ensure variables are assigned - if self.Q_total.is_set: - self.Q_loss.val = self.Q.val-self.Q_total.val - self.LF.val = -self.Q_loss.val / self.Q.val - elif self.LF.is_set: - self.Q_total.val = self.Q.val * (1+self.LF.val) - self.Q_loss.val = self.Q.val-self.Q_total.val - else: - self.Q_total.val = self.Q.val-self.Q_loss.val - self.LF.val = -self.Q_loss.val/self.Q.val - - -class SimpleHeatExchangerDeltaPLfKpi(SimpleHeatExchangerDeltaP): - - @staticmethod - def component(): - return 'simple heat exchanger with loss factor and KPI' - - def get_parameters(self): - variables = super().get_parameters() - variables["LF"] = dc_cp(min_val=0, val=0, max_val=1, is_result=True) - variables["Q_loss"] = dc_cp(is_result=True) - variables["KPI"] = dc_cp( - deriv=self.KPI_deriv, - func=self.KPI_func, - latex=self.pr_func_doc, - num_eq=1) - return variables - - def energy_balance_func(self): - r""" - Equation for total heat flow rate - - """ - - return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.Q.val - - def energy_balance_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of Q_total - - """ - - i = self.inl[0] - o = self.outl[0] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) - if i.h.is_var: - self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) - if o.h.is_var: - self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) - if self.Q.is_var: - self.jacobian[k, self.Q.J_col] = -1 - if self.LF.is_var: - self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - - def KPI_func(self): - r""" - Equation for total heat flow rate - - """ - return self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - self.KPI.val * self.inl[0].m.val_SI - - def KPI_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of Q_total - - """ - i = self.inl[0] - o = self.outl[0] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = (o.h.val_SI - i.h.val_SI)*(1+self.LF.val) - self.KPI.val - if i.h.is_var: - self.jacobian[k, i.h.J_col] = -i.m.val_SI*(1+self.LF.val) - if o.h.is_var: - self.jacobian[k, o.h.J_col] = i.m.val_SI*(1+self.LF.val) - if self.LF.is_var: - self.jacobian[k, self.LF.J_col] = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI) - if self.KPI.is_var: - self.jacobian[k, self.Q_loss.J_col] = -self.inl[0].m.val_SI - - def calc_parameters(self): - super().calc_parameters() - self.Q.val = self.inl[0].m.val_SI * (self.outl[0].h.val_SI - self.inl[0].h.val_SI)*(1+self.LF.val) - # repeat calculations to ensure variables are assigned - if self.KPI.is_set: - self.Q.val = self.KPI.val * self.inl[0].m.val_SI - else: - self.KPI.val = self.Q.val / self.inl[0].m.val_SI - self.Q_loss.val = - self.LF.val * self.Q.val - - -class TwoStreamHeatExchanger(HeatExchanger): - - @staticmethod - def component(): - return 'two stream heat exchanger with min ttd (pinch)' - - def get_parameters(self): - variables = super().get_parameters() - variables['ttd_min'] = dc_cp( - min_val=0, num_eq=1, func=self.ttd_min_func, - deriv=self.ttd_min_deriv, latex=self.ttd_u_func_doc) - return variables - - def _calc_dTs(self): - i1 = self.inl[0] - o1 = self.outl[0] - i2 = self.inl[1] - o2 = self.outl[1] - - T_i1 = i1.calc_T(T0=i1.T.val_SI) - T_o1 = o1.calc_T(T0=o1.T.val_SI) - T_i2 = i2.calc_T(T0=i2.T.val_SI) - T_o2 = o2.calc_T(T0=o2.T.val_SI) - - if T_i1 > T_i2: - dTa = T_i1-T_o2 - dTb = T_o1-T_i2 - else: - dTa = -T_i1+T_o2 - dTb = -T_o1+T_i2 - - return dTa,dTb - - def ttd_min_func(self): - r""" - Equation for minimum terminal temperature difference. - """ - - dTa,dTb = self._calc_dTs() - - if dTa < dTb: - return self.ttd_min.val - dTa - else: - return self.ttd_min.val - dTb - - # T_o2 = o.calc_T(T0=o.T.val_SI) - # return self.ttd_u.val - T_i1 + T_o2 - - - def ttd_min_deriv(self, increment_filter, k): - """ - Calculate partial derivates for minimum terminal temperature difference.. - - """ - f = self.ttd_min_func - for c in [self.inl[0], self.inl[1], self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(f, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(f, 'h', c) - - def calc_parameters(self): - super().calc_parameters() - if not self.ttd_min.is_set: - self.ttd_min.val = min(self._calc_dTs()) - - - - -class MergeDeltaP(Merge): - - @staticmethod - def component(): - return 'merge with pressure losses' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaP"] = dc_cp( - min_val=0, - deriv=self.deltaP_deriv, - func=self.deltaP_func, - latex=self.pr_func_doc, - num_eq=1, - ) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - return constraints - - def deltaP_func(self): - r""" - Equation for pressure drop. - - """ - p_in_min = min([i.p.val_SI for i in self.inl]) - return p_in_min - self.deltaP.val*1e5 - self.outl[0].p.val_SI - - def deltaP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for pressure drop. - - """ - p_in = [i.p.val_SI for i in self.inl] - p_min_index = p_in.index(min(p_in)) - - if self.inl[p_min_index].p.is_var: - self.jacobian[k, self.inl[p_min_index].p.J_col] = 1 #self.pr.val - if self.outl[0].p.is_var: - self.jacobian[k, self.outl[0].p.J_col] = -1 - - def calc_parameters(self): - super().calc_parameters() - Pmin = min([i.p.val_SI for i in self.inl]) - Pmax = max([i.p.val_SI for i in self.inl]) - if abs(self.outl[0].p.val_SI - Pmin) >= abs(self.outl[0].p.val_SI - Pmax): - self.deltaP.val = (Pmin - self.outl[0].p.val_SI)/1e5 - else: - self.deltaP.val = (Pmax - self.outl[0].p.val_SI)/1e5 - - -class SeparatorWithSpeciesSplits(Separator): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - self.num_out = 2 # default - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - super().__init__(label, **kwargs) - - - @staticmethod - def component(): - return 'separator with species flow splits' - - def get_parameters(self): - variables = super().get_parameters() - variables["SFS"] = dc_cp_SFS( - min_val=0, - deriv=self.SFS_deriv, - func=self.SFS_func, - latex=self.pr_func_doc, - num_eq=1, - ) - variables["SF"] = dc_cp_SFS( - min_val=0, - deriv=self.SF_deriv, - func=self.SF_func, - latex=self.pr_func_doc, - num_eq=1, - ) - return variables - - def SF_func(self): - r""" - Equation for SF. - - """ - - fluid = self.SF.split_fluid - out_i = int(self.SF.split_outlet[3:]) - 1 - i = self.inl[0] - o = self.outl[out_i] - - res = self.SF.val - o.fluid.val[fluid] * o.m.val_SI - - return res - - def SF_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for SF. - - """ - - fluid = self.SF.split_fluid - out_i = int(self.SF.split_outlet[3:]) - 1 - - o = self.outl[out_i] - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - - def SFS_func(self): - r""" - Equation for SFS. - - """ - - fluid = self.SFS.split_fluid - out_i = int(self.SFS.split_outlet[3:]) - 1 - i = self.inl[0] - o = self.outl[out_i] - - res = i.fluid.val[fluid] * i.m.val_SI * self.SFS.val \ - - o.fluid.val[fluid] * o.m.val_SI - - return res - - def SFS_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for SFS. - - """ - - fluid = self.SFS.split_fluid - out_i = int(self.SFS.split_outlet[3:]) - 1 - - i = self.inl[0] - o = self.outl[out_i] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = i.fluid.val[fluid] * self.SFS.val - if fluid in i.fluid.is_var: - self.jacobian[k, i.fluid.J_col[fluid]] = i.m.val_SI * self.SFS.val - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -o.fluid.val[fluid] - if fluid in o.fluid.is_var: - self.jacobian[k, o.fluid.J_col[fluid]] = -o.m.val_SI - - def calc_parameters(self): - super().calc_parameters() - - i = self.inl[0] - if self.SFS.is_set: - fluid = self.SFS.split_fluid - self.SF.val = self.SFS.val* i.fluid.val[fluid] * i.m.val_SI - if self.SF.is_set: - fluid = self.SF.split_fluid - self.SFS.val = self.SF.val / (i.fluid.val[fluid] * i.m.val_SI) - -class SeparatorWithSpeciesSplitsDeltaT(SeparatorWithSpeciesSplits): - - @staticmethod - def component(): - return 'separator with species flow splits and dT on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaT"] = dc_cp( - deriv=self.energy_balance_deltaT_deriv, # same as before - func=self.energy_balance_deltaT_func, - latex=self.pr_func_doc, - num_eq=self.num_out - ) - variables["Q"] = dc_cp(is_result=True) - #variables["Qout"] = dc_cpa() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - if constraints.get("energy_balance_constraints",False): - del constraints['energy_balance_constraints'] - return constraints - - def energy_balance_deltaT_func(self): - r""" - Calculate deltaT residuals. - - """ - T_in = self.inl[0].calc_T(T0=self.inl[0].T.val_SI) - residual = [] - for o in self.outl: - residual += [T_in - self.deltaT.val - o.calc_T(T0=T_in)] # use T_in as guess - return residual - - def energy_balance_deltaT_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - dT_dp_in = dT_mix_dph(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) - dT_dh_in = dT_mix_pdh(i.p.val_SI, i.h.val_SI, i.fluid_data, i.mixing_rule,T0 = i.T.val_SI,force_state=i.force_state) - # dT_dfluid_in = {} - # for fluid in i.fluid.is_var: - # dT_dfluid_in[fluid] = dT_mix_ph_dfluid(i) - for o in self.outl: - if self.is_variable(i.p): - self.jacobian[k, i.p.J_col] = dT_dp_in - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = dT_dh_in - # for fluid in i.fluid.is_var: - # self.jacobian[k, i.fluid.J_col[fluid]] = dT_dfluid_in[fluid] - args = (o.p.val_SI, o.h.val_SI, o.fluid_data, o.mixing_rule,i.T.val_SI,o.force_state) - if self.is_variable(o.p): - self.jacobian[k, o.p.J_col] = -dT_mix_dph(*args) - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -dT_mix_pdh(*args) - # for fluid in o.fluid.is_var: - # self.jacobian[k, o.fluid.J_col[fluid]] = -dT_mix_ph_dfluid(o) - k += 1 - - # deriv = [d for d in self.jacobian.items()] - # [print(d) for d in deriv] - # deriv - - def calc_parameters(self): - super().calc_parameters() - i = self.inl[0] - if not self.Q.is_set: - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - - Tmin = min([o.T.val_SI for o in self.outl]) - Tmax = max([o.T.val_SI for o in self.outl]) - if abs(i.T.val_SI - Tmin) >= abs(i.T.val_SI - Tmax): - self.deltaT.val = i.T.val_SI - Tmin - else: - self.deltaT.val = i.T.val_SI - Tmax - -class SeparatorWithSpeciesSplitsDeltaH(SeparatorWithSpeciesSplits): - - @staticmethod - def component(): - return 'separator with species flow splits and dH on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaH"] = dc_cp( - deriv=self.energy_balance_deltaH_deriv, # same as before - func=self.energy_balance_deltaH_func, - latex=self.pr_func_doc, - num_eq=self.num_out - ) - variables["Q"] = dc_cp( - func=self.Q_func, num_eq=1, - deriv=self.Q_deriv, - latex=self.pr_func_doc) - variables["KPI"] = dc_cp( - deriv=self.KPI_deriv, - func=self.KPI_func, - latex=self.pr_func_doc, - num_eq=1) - variables['dTo'] = dc_cp( - min_val=0, num_eq=1, func=self.dTo_func, latex=self.pr_func_doc, - deriv=self.dTo_deriv) - #variables["Qout"] = dc_cpa() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - if constraints.get("energy_balance_constraints",False): - del constraints['energy_balance_constraints'] - return constraints - - def energy_balance_deltaH_func(self): - r""" - Calculate deltaH residuals. - - """ - i = self.inl[0] - residual = [] - for o in self.outl: - residual += [i.h.val_SI - self.deltaH.val - o.h.val_SI] - return residual - - def energy_balance_deltaH_deriv(self, increment_filter, k): - r""" - Calculate partial derivatives of energy balance. - """ - i = self.inl[0] - for o in self.outl: - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = 1 - if self.is_variable(o.h): - self.jacobian[k, o.h.J_col] = -1 - k += 1 - - def Q_func_Tequality(self,port1,port2): - return port1.calc_T(T0=port1.T.val_SI) - port2.calc_T(T0=port2.T.val_SI) - - def Q_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - # #res = [] - # #res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val] - # #res += [self.Q_func_Tequality(o1,o2)] - # #return res - return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.Q.val - - def Q_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - # k = k + 1 - # for c in [self.outl[0], self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) - - def KPI_func(self): - r""" - Equation for total heat flow rate - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - # res = [] - # res += [o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI] - # res += [self.Q_func_Tequality(o1,o2)] - # return res - return o1.m.val_SI * (o1.h.val_SI - i.h.val_SI) + o2.m.val_SI * (o2.h.val_SI - i.h.val_SI) - self.KPI.val * i.m.val_SI - - def KPI_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - i = self.inl[0] - o1 = self.outl[0] - o2 = self.outl[1] - if self.is_variable(i.m): - self.jacobian[k, i.m.J_col] = - self.KPI.val - if self.is_variable(i.h): - self.jacobian[k, i.h.J_col] = - o1.m.val_SI - o2.m.val_SI - if self.is_variable(o1.m): - self.jacobian[k, o1.m.J_col] = o1.h.val_SI - i.h.val_SI - if self.is_variable(o2.m): - self.jacobian[k, o2.m.J_col] = o2.h.val_SI - i.h.val_SI - if self.is_variable(o1.h): - self.jacobian[k, o1.h.J_col] = o1.m.val_SI - if self.is_variable(o2.h): - self.jacobian[k, o2.h.J_col] = o2.m.val_SI - - # k = k + 1 - # for c in [self.outl[0], self.outl[1]]: - # if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - # self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'p', c, port1 = self.outl[0], port2 = self.outl[1]) - # if self.is_variable(c.h): #, increment_filter): - # self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.Q_func_Tequality, 'h', c, port1 = self.outl[0], port2 = self.outl[1]) - - def dTo_func(self): - r""" - Equation for hot side heat exchanger energy balance. - """ - T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - return T0 - T1 - self.dTo.val - - def dTo_deriv(self, increment_filter, k): - r""" - Partial derivatives for hot side heat exchanger energy balance. - """ - #T0 = self.outl[0].calc_T(T0=self.outl[0].T.val_SI) - #T1 = self.outl[1].calc_T(T0=self.outl[1].T.val_SI) - for c in [self.outl[0], self.outl[1]]: - if self.is_variable(c.p): #, increment_filter): increment filter may detect no change on the wrong end - self.jacobian[k, c.p.J_col] = self.numeric_deriv(self.dTo_func, 'p', c) - if self.is_variable(c.h): #, increment_filter): - self.jacobian[k, c.h.J_col] = self.numeric_deriv(self.dTo_func, 'h', c) - for fluid in self.variable_fluids: - if fluid in c.fluid.is_var: - self.jacobian[k, c.fluid.J_col[fluid]] = self.numeric_deriv(self.dTo_func, fluid, c) - - def calc_parameters(self): - super().calc_parameters() - i = self.inl[0] - - if not self.Q.is_set: - self.Q.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) - if not self.KPI.is_set: - self.KPI.val = np.sum([o.m.val_SI * (o.h.val_SI - i.h.val_SI) for o in self.outl]) / i.m.val_SI - - hmin = min([o.h.val_SI for o in self.outl]) - hmax = max([o.h.val_SI for o in self.outl]) - if abs(i.h.val_SI - hmin) >= abs(i.h.val_SI - hmax): - self.deltaH.val = i.h.val_SI - hmin - else: - self.deltaH.val = i.h.val_SI - hmax - - -class SeparatorWithSpeciesSplitsDeltaP(SeparatorWithSpeciesSplits): - - @staticmethod - def component(): - return 'separator with species flow splits and dT and Pr on outlets' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaP"] = dc_cp( - min_val=0, - deriv=self.deltaP_deriv, - func=self.deltaP_func, - latex=self.pr_func_doc, - num_eq=self.num_out, - ) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - self.variable_fluids = self.variable_fluids = set(self.inl[0].fluid.back_end.keys()) - num_fluid_eq = len(self.variable_fluids) - constraints['fluid_constraints'] = { - 'func': self.fluid_func, 'deriv': self.fluid_deriv, - 'constant_deriv': False, 'latex': self.fluid_func_doc, - 'num_eq': num_fluid_eq} - del constraints['pressure_constraints'] - return constraints - - def deltaP_func(self): - r""" - Equation for pressure drop. - - """ - residual = [] - p_in = self.inl[0].p.val_SI - for o in self.outl: - residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] - return residual - - def deltaP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for pressure drop - - """ - i = self.inl[0] - for o in self.outl: - if i.p.is_var: - self.jacobian[k, i.p.J_col] = 1 - if o.p.is_var: - self.jacobian[k, o.p.J_col] = -1 - k += 1 - - def calc_parameters(self): - super().calc_parameters() - - Pmin = min([i.p.val_SI for i in self.outl]) - Pmax = max([i.p.val_SI for i in self.outl]) - if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): - self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 - else: - self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 - - -class SeparatorWithSpeciesSplitsDeltaTDeltaP(SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaP): - - @staticmethod - def component(): - return 'separator with species flow splits and dT and Pr on outlets' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - #del constraints['pressure_constraints'] - #del constraints['energy_balance_constraints'] - return constraints - -class SeparatorWithSpeciesSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaT, SeparatorWithSpeciesSplitsDeltaP): - - @staticmethod - def component(): - return 'separator with species flow splits and dT, dH and dP on outlets' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - #del constraints['pressure_constraints'] - #del constraints['energy_balance_constraints'] - return constraints - - - -class SeparatorWithSpeciesSplitsDeltaTDeltaPBus(SeparatorWithSpeciesSplitsDeltaTDeltaP): - - @staticmethod - def component(): - return 'separator with species flow splits and dT and Pr on outlets + Bus connection on Q' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def bus_func(self, bus): - r""" - Calculate the value of the bus function. - - """ - return np.sum([o.m.val_SI * (o.h.val_SI - self.inl[0].h.val_SI) for o in self.outl]) - - def bus_func_doc(self, bus): - r""" - Return LaTeX string of the bus function. - - Parameters - ---------- - bus : tespy.connections.bus.Bus - TESPy bus object. - - Returns - ------- - latex : str - LaTeX string of bus function. - """ - return ( - r'\dot{m}_\mathrm{in} \cdot \left(h_\mathrm{out} - ' - r'h_\mathrm{in} \right)') - - def bus_deriv(self, bus): - r""" - Calculate partial derivatives of the bus function. - - """ - - f = self.calc_bus_value - if self.inl[0].m.is_var: - if self.inl[0].m.J_col not in bus.jacobian: - bus.jacobian[self.inl[0].m.J_col] = 0 - bus.jacobian[self.inl[0].m.J_col] -= self.numeric_deriv(f, 'm', self.inl[0], bus=bus) - - if self.inl[0].h.is_var: - if self.inl[0].h.J_col not in bus.jacobian: - bus.jacobian[self.inl[0].h.J_col] = 0 - bus.jacobian[self.inl[0].h.J_col] -= self.numeric_deriv(f, 'h', self.inl[0], bus=bus) - - for o in self.outl: - if o.h.is_var: - if o.h.J_col not in bus.jacobian: - bus.jacobian[o.h.J_col] = 0 - bus.jacobian[o.h.J_col] -= self.numeric_deriv(f, 'h', o, bus=bus) - if o.m.is_var: - if o.m.J_col not in bus.jacobian: - bus.jacobian[o.m.J_col] = 0 - bus.jacobian[o.m.J_col] -= self.numeric_deriv(f, 'm', o, bus=bus) - - -class SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH(SeparatorWithSpeciesSplitsDeltaT,SeparatorWithSpeciesSplitsDeltaH, SeparatorWithSpeciesSplitsDeltaP): - - @staticmethod - def component(): - return 'separator with species flow splits and dT, dH and dP on outlets' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - #del constraints['pressure_constraints'] - #del constraints['energy_balance_constraints'] - return constraints - - def get_parameters(self): - variables = super().get_parameters() - variables["FS"] = dc_cp_FS( - min_val=0, - deriv=self.FS_deriv, - func=self.FS_func, - latex=self.pr_func_doc, - num_eq=1, - ) - return variables - - def FS_func(self): - r""" - Equation for flow split. - - """ - - out_i = int(self.FS.split_outlet[3:]) - 1 - res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI - return res - - def FS_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for flow split - - """ - - out_i = int(self.FS.split_outlet[3:]) - 1 - - i = self.inl[0] - o = self.outl[out_i] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = self.FS.val - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - - -class SplitterDeltaP(Splitter): - - def __init__(self, label, **kwargs): - #self.set_attr(**kwargs) - # need to assign the number of outlets before the variables are set - for key in kwargs: - if key == 'num_out': - self.num_out=kwargs[key] - super().__init__(label, **kwargs) - - @staticmethod - def component(): - return 'Splitter with pressure losses' - - def get_parameters(self): - variables = super().get_parameters() - variables["deltaP"] = dc_cp( - min_val=0, - deriv=self.deltaP_deriv, - func=self.deltaP_func, - latex=self.pr_func_doc, - num_eq=self.num_out, - ) - return variables - - def get_mandatory_constraints(self): - constraints = super().get_mandatory_constraints() - del constraints['pressure_constraints'] - return constraints - - def deltaP_func(self): - r""" - Equation for pressure drop. - - """ - #return self.inl[0].p.val_SI * self.pr.val - self.outl[0].p.val_SI - residual = [] - p_in = self.inl[0].p.val_SI - for o in self.outl: - residual += [p_in - self.deltaP.val*1e5 - o.p.val_SI] - return residual - - def deltaP_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for combustion pressure ratio. - - """ - - i = self.inl[0] - for o in self.outl: - if i.p.is_var: - self.jacobian[k, i.p.J_col] = 1 - if o.p.is_var: - self.jacobian[k, o.p.J_col] = -1 - k += 1 - - def calc_parameters(self): - super().calc_parameters() - - Pmin = min([i.p.val_SI for i in self.outl]) - Pmax = max([i.p.val_SI for i in self.outl]) - if abs(self.inl[0].p.val_SI - Pmin) >= abs(self.inl[0].p.val_SI - Pmax): - self.deltaP.val = (self.inl[0].p.val_SI - Pmin)/1e5 - else: - self.deltaP.val = (self.inl[0].p.val_SI - Pmax)/1e5 - -class SplitterWithFlowSplitter(Splitter): - - @staticmethod - def component(): - return 'splitter with flow split ratios' - - def get_parameters(self): - variables = super().get_parameters() - variables["FS"] = dc_cp_FS( - min_val=0, - deriv=self.FS_deriv, - func=self.FS_func, - latex=self.pr_func_doc, - num_eq=1, - ) - return variables - - def FS_func(self): - r""" - Equation for flow split. - - """ - - out_i = int(self.FS.split_outlet[3:]) - 1 - res = self.inl[0].m.val_SI * self.FS.val - self.outl[out_i].m.val_SI - return res - - def FS_deriv(self, increment_filter, k): - r""" - Calculate the partial derivatives for flow split - - """ - - out_i = int(self.FS.split_outlet[3:]) - 1 - - i = self.inl[0] - o = self.outl[out_i] - if i.m.is_var: - self.jacobian[k, i.m.J_col] = self.FS.val - if o.m.is_var: - self.jacobian[k, o.m.J_col] = -1 - - -class SplitterWithFlowSplitterDeltaP(SplitterWithFlowSplitter, SplitterDeltaP): - - @staticmethod - def component(): - return 'splitter with flow split ratios and pressure drop' - - def get_parameters(self): - variables = super().get_parameters() - return variables - - -#%% Class containers - -class dc_cp_SFS(dc_cp): - """ - Data container for simple properties. - + SFS_fluid - + SFS_outlet - """ - @staticmethod - def attr(): - attributes = dc_cp.attr() - attributes.update({'split_fluid' : None, 'split_outlet' : None}) - return attributes - - @staticmethod - def _serializable_keys(): - keys = dc_cp._serializable_keys() - keys.append("split_fluid") - keys.append("split_outlet") - return keys - -class dc_cp_FS(dc_cp): - """ - Data container for component properties. - + FS_outlet - """ - @staticmethod - def attr(): - attributes = dc_cp.attr() - attributes.update({'split_outlet' : None}) - return attributes - - @staticmethod - def _serializable_keys(): - keys = dc_cp._serializable_keys() - keys.append("split_outlet") - return keys - - -# class MergeWithPressureLoss(MergeDeltaP): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component MergeWithPressureLoss will change with " -# "the next major release, please import MergeDeltaP instead." -# ) -# warnings.warn(msg, FutureWarning) - -# class SeparatorWithSpeciesSplitsAndDeltaT(SeparatorWithSpeciesSplitsDeltaT): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SeparatorWithSpeciesSplitsAndDeltaT will change with " -# "the next major release, please import SeparatorWithSpeciesSplitsDeltaT instead." -# ) -# warnings.warn(msg, FutureWarning) - -# class SeparatorWithSpeciesSplitsAndDeltaTAndPr(SeparatorWithSpeciesSplitsDeltaTDeltaP): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPr will change with " -# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaP instead." -# ) -# warnings.warn(msg, FutureWarning) - -# class SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus(SeparatorWithSpeciesSplitsDeltaTDeltaPBus): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPrAndBus will change with " -# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaPBus instead." -# ) -# warnings.warn(msg, FutureWarning) - - -# class SplitterWithPressureLoss(SplitterDeltaP): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SeparatorWithSpeciesSplitsAndDeltaTAndPr will change with " -# "the next major release, please import SeparatorWithSpeciesSplitsDeltaTDeltaP instead." -# ) -# warnings.warn(msg, FutureWarning) - -# class SplitterWithPressureLoss(SplitterDeltaP): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SplitterWithPressureLoss will change with " -# "the next major release, please import SplitterDeltaP instead." -# ) -# warnings.warn(msg, FutureWarning) - - - - -# class SplitWithFlowSplitter(SplitterWithFlowSplitter): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SplitWithFlowSplitter will change with " -# "the next major release, please import SplitterWithFlowSplitter instead." -# ) -# warnings.warn(msg, FutureWarning) - - -# class SplitWithFlowSplitterDeltaP(SplitterWithFlowSplitterDeltaP): - -# def __init__(self, label, **kwargs): -# super().__init__(label, **kwargs) -# msg = ( -# "The API for the component SplitWithFlowSplitterDeltaP will change with " -# "the next major release, please import SplitterWithFlowSplitterDeltaP instead." -# ) -# warnings.warn(msg, FutureWarning) From 9720117e65c3cc3cecd07a58bd8996e8634cd88e Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:53:23 +0200 Subject: [PATCH 103/105] Remove unused imports --- src/tespy/components/__init__.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/tespy/components/__init__.py b/src/tespy/components/__init__.py index dca0441da..d459df9af 100644 --- a/src/tespy/components/__init__.py +++ b/src/tespy/components/__init__.py @@ -27,9 +27,3 @@ from .turbomachinery.compressor import Compressor # noqa: F401 from .turbomachinery.pump import Pump # noqa: F401 from .turbomachinery.turbine import Turbine # noqa: F401 - -# New components -from .newComponents import * -from .newAdvancedComponents import * -from .energySupplyComponents import * - From 360b9f20046a01ee4fb48add3893f340052d6022 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 18:55:22 +0200 Subject: [PATCH 104/105] Fix more imports --- src/tespy/networks/network_reader.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/tespy/networks/network_reader.py b/src/tespy/networks/network_reader.py index 0e4cd8fe4..f2e81771b 100644 --- a/src/tespy/networks/network_reader.py +++ b/src/tespy/networks/network_reader.py @@ -15,8 +15,6 @@ import json import os -import pandas as pd - from tespy.components import CombustionChamber from tespy.components import CombustionEngine from tespy.components import Compressor @@ -41,8 +39,6 @@ from tespy.components import Turbine from tespy.components import Valve from tespy.components import WaterElectrolyzer -from tespy.components.newAdvancedComponents import * -from tespy.components.newComponents import * from tespy.connections import Bus from tespy.connections import Connection from tespy.connections import Ref @@ -84,15 +80,6 @@ 'Compressor': Compressor, 'Pump': Pump, 'Turbine': Turbine, - 'MergeDeltaP' :MergeDeltaP, - 'SeparatorWithSpeciesSplits' : SeparatorWithSpeciesSplits, - 'SeparatorWithSpeciesSplitsDeltaT' : SeparatorWithSpeciesSplitsDeltaT, - 'SeparatorWithSpeciesSplitsDeltaTDeltaP' : SeparatorWithSpeciesSplitsDeltaTDeltaP, - 'SeparatorWithSpeciesSplitsDeltaP' : SeparatorWithSpeciesSplitsDeltaP, - 'SimpleHeatExchangerDeltaPLossFactor' : SimpleHeatExchangerDeltaPLossFactor, - 'SimpleHeatExchangerDeltaP' : SimpleHeatExchangerDeltaP, - 'SimpleHeatExchangerDeltaPLfKpi' : SimpleHeatExchangerDeltaPLfKpi, - 'SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH' : SeparatorWithSpeciesSplitsAndFlowSplitsDeltaTDeltaPDeltaH, } ENGINE_TARGET_CLASSES = { From f14d53565db71035f0cd522b2f11f746a6b5051c Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 19:22:41 +0200 Subject: [PATCH 105/105] Add a value sanity check for fluid mass fraction to prevent tiny differences from the bounds --- src/tespy/networks/network.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index 7dee94869..bf36fc20d 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -2589,6 +2589,15 @@ def postprocessing(self): def process_connections(self): """Process the Connection results.""" for c in self.conns['object']: + + # fluid mass fractions sometimes end up with tiny deviations from + # the bound, e.g. mass fractions of 1e-12 or similar. + for fluid in c.fluid.val: + if c.fluid.val[fluid] > 1 - ERR ** 2: + c.fluid.val[fluid] = 1 + elif c.fluid.val[fluid] < ERR ** 2: + c.fluid.val[fluid] = 0 + c.good_starting_values = True c.calc_results()