From 0cf8a03d327e0907b04f6e0b1f422973dc09e19b Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 08:27:49 +0100 Subject: [PATCH 01/97] 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 a0c63617a5b79d9f90d25be6a47ddbf08922042f Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 10:32:23 +0100 Subject: [PATCH 02/97] 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 | 66 +- 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, 3157 insertions(+), 46 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 3f0de59ed..64cec34ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,29 +1,4 @@ -[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.3" description = "Thermal Engineering Systems in Python (TESPy)" @@ -56,25 +31,28 @@ dependencies = [ ] 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" + +[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" -[project.optional-dependencies] -dev = [ - "build", - "flit", - "furo", - "iapws", - "pyromat", - "pytest", - "sphinx>=7.2.2", - "sphinx-copybutton", - "sphinx-design", - "sphinxcontrib.bibtex", - "tox", + +[build-system] +requires = [ + "poetry-core", + "setuptools>=30.3.0", + "wheel", + "setuptools_scm>=3.3.1", ] [tool.pytest.ini_options] 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 4e5937786..ce3ebbf6c 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -24,6 +24,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 @@ -209,6 +210,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 7c5f22923..1ec6d0ac1 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1689,7 +1689,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) @@ -1789,7 +1789,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. @@ -1813,11 +1813,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 fae107d4d..d81e52556 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -577,3 +577,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 0a52301d8f077ccb5644852df5513717c2eca765 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 09:28:47 +0100 Subject: [PATCH 03/97] 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 929a9eec8a877e60c44073801b41cccc6e0cd150 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 12:00:49 +0100 Subject: [PATCH 04/97] 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 5a69098b5782f78a4986cef2e8926e95bdcf2dd3 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 13:03:01 +0100 Subject: [PATCH 05/97] 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 64cec34ce..52ab7b030 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,6 +47,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 1dc1b104a38e4ca86e2c5978ed440b96596971b9 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:35:59 +0100 Subject: [PATCH 06/97] 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 13e01454985df35088fe98d1c40317b1ef5cc49d Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:46:37 +0100 Subject: [PATCH 07/97] fsolving 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 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tespy/tools/fluid_properties/wrappers.py b/src/tespy/tools/fluid_properties/wrappers.py index 565c98bf4..e6332afa9 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -191,6 +191,11 @@ def h_ps(self, p, s): return self.AS.hmass() 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) return self.AS.hmass() From 09f487514b13fc48050c4ff93e077b6ef07cdffb Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 15:47:28 +0100 Subject: [PATCH 08/97] 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 73b14ad84ab8445dd0c12f240a7fd1c8ced2e6ec Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 20:56:28 +0100 Subject: [PATCH 09/97] 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 6a1fd9325c9c7851308b9b9626b28aa60d7d0ca3 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 1 Nov 2023 21:42:47 +0100 Subject: [PATCH 10/97] 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 2da06de0dc7be2501662fd5af3650b0bb4d8dc0a Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 11:56:03 +0100 Subject: [PATCH 11/97] 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 e6332afa9..d8ee8c027 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -190,12 +190,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() @@ -229,6 +234,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() @@ -241,6 +248,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() @@ -249,6 +258,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 171c940b6fc0765e64358a5268b95a118502915f Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 12:01:30 +0100 Subject: [PATCH 12/97] 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 5cbbd388405cbc98b7b1c8c448ff362e87e4936e Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 12:04:21 +0100 Subject: [PATCH 13/97] 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 2ae1851f15abe3ece3f10002e8811ac36e3dc578 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:11:10 +0100 Subject: [PATCH 14/97] 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 5432a8d626aef04ebbac9d3fb5121734b944cdb6 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:32:59 +0100 Subject: [PATCH 15/97] 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 c5231d022d48a004b7feb787acaa8a304368472d Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 14:34:28 +0100 Subject: [PATCH 16/97] 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 ed31e2679f4052271ec82803d7aa20ea49288028 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 16:53:25 +0100 Subject: [PATCH 17/97] 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 c085a4509..e69668908 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -69,6 +69,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 or T0 == 0 or np.isnan(T0): T0 = (valmin + valmax) / 2.0 + T0 = max(valmin,min(valmax,T0)) valmax *= 2 From 5f42e741d873626bcf7cf8ec3aabf687526910a9 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:29:58 +0100 Subject: [PATCH 18/97] 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 bf8a7be85..1b4811ff0 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 b5233fefc4077aac84e91aaa0eb73122101e14d5 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:31:14 +0100 Subject: [PATCH 19/97] 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 d29249c57c417daec57382d5c670ec39720f2ee7 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:33:03 +0100 Subject: [PATCH 20/97] 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 dd85c7e381e81e961473835cfc3a645d054e7114 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 20:42:30 +0100 Subject: [PATCH 21/97] 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 230c7a7ae9a02937f2276d3a25580296c1a62fa2 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:25:14 +0100 Subject: [PATCH 22/97] 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 0ec3f772ee7540d9c50e80b3f4b7c2b46930fd70 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:31:47 +0100 Subject: [PATCH 23/97] 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 2fc7a4ea45d9b2bce736ce272a466057e3f6385d Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 2 Nov 2023 21:34:03 +0100 Subject: [PATCH 24/97] 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 cc69ce17cb08735b534aed171182a6eea840e370 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 3 Nov 2023 13:33:40 +0100 Subject: [PATCH 25/97] 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 c9d910a534cab9c02fa2352b0a99475035eb06de Mon Sep 17 00:00:00 2001 From: mrk Date: Sun, 5 Nov 2023 20:35:41 +0100 Subject: [PATCH 26/97] 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 4c3f339292bfbadb3d57752c1f674316f4a962a7 Mon Sep 17 00:00:00 2001 From: mrk Date: Sun, 5 Nov 2023 20:36:13 +0100 Subject: [PATCH 27/97] 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 1ec6d0ac1..ab786472d 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1068,17 +1068,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 e7156aad608fb61f3136bdfe6773353a9224e000 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 6 Nov 2023 11:40:20 +0100 Subject: [PATCH 28/97] 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 d81e52556..c0e26507e 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -112,8 +112,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 edb1a0dcf1862caa6923cf0a0bd74562677d97bf Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 6 Nov 2023 11:45:07 +0100 Subject: [PATCH 29/97] 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 c0e26507e..f35c0e0be 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -113,7 +113,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 9af1ca981324c60050f477656c69bde3edfe6bc4 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 16:12:11 +0100 Subject: [PATCH 30/97] need force_state, limit_increments and RobustRelax --- src/tespy/components/newcomponents.py | 17 +++- src/tespy/connections/connection.py | 48 +++++---- 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 | 10 +- src/tespy/tools/fluid_properties/mixtures.py | 10 +- src/tespy/tools/fluid_properties/wrappers.py | 56 ++++++----- 9 files changed, 200 insertions(+), 114 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 b60261628..f5c5b2d65 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -260,6 +260,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 = { @@ -459,6 +462,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 + '.' @@ -594,7 +603,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): @@ -652,14 +661,14 @@ 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._solved = True - self.T._solved = True + 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._solved = True - self.Td_bp._solved = True + 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._solved = True @@ -741,7 +750,7 @@ def primary_ref_deriv(self, k, **kwargs): def calc_T(self, T0=None): if T0 is None: T0 = self.T.val_SI - 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 @@ -749,15 +758,15 @@ 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: 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): @@ -793,7 +802,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 @@ -888,10 +897,7 @@ def fluid_balance_deriv(self, k, **kwargs): self.jacobian[k, self.fluid.J_col[f]] = -self.fluid.val[f] def calc_s(self): - try: - return s_mix_ph(self.p.val_SI, self.h.val_SI, self.fluid_data, self.mixing_rule, T0=self.T.val_SI) - except NotImplementedError: - return np.nan + 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) @@ -908,7 +914,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 @@ -978,7 +984,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 @@ -996,7 +1002,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 @@ -1035,8 +1041,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 ab786472d..03f1a1eb4 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1689,7 +1689,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) @@ -1785,7 +1785,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 @@ -1813,18 +1813,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 @@ -2245,36 +2238,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 f35c0e0be..7ae398110 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -112,7 +112,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 f97ce42d1..75fe4cb12 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -85,7 +85,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) @@ -93,42 +93,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): @@ -181,26 +181,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) @@ -208,18 +208,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): @@ -236,13 +236,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): @@ -254,10 +254,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 e69668908..8b6eeb2ad 100644 --- a/src/tespy/tools/fluid_properties/helpers.py +++ b/src/tespy/tools/fluid_properties/helpers.py @@ -64,19 +64,17 @@ def get_molar_fractions(fluid_data): return {key: value / molarflow_sum for key, value in molarflow.items()} -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 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 = { + 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 645537783..08298dde4 100644 --- a/src/tespy/tools/fluid_properties/mixtures.py +++ b/src/tespy/tools/fluid_properties/mixtures.py @@ -80,8 +80,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 @@ -126,7 +126,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 @@ -171,7 +171,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 @@ -227,7 +227,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 d8ee8c027..a5f77ed14 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -190,18 +190,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): @@ -233,10 +249,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): @@ -247,20 +261,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 5436622859cb47681e30a616188c3744d2ea73f5 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 16:12:29 +0100 Subject: [PATCH 31/97] 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 5f0c9bdee2a29812a82e0c9770c5cb5f0225c1b9 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 7 Nov 2023 20:46:56 +0100 Subject: [PATCH 32/97] 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 08298dde4..997b4bc76 100644 --- a/src/tespy/tools/fluid_properties/mixtures.py +++ b/src/tespy/tools/fluid_properties/mixtures.py @@ -29,7 +29,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 @@ -93,7 +93,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 @@ -139,7 +139,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 db2b320e2c9bd22eb0045c587f11a62b16daea82 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 09:30:41 +0100 Subject: [PATCH 33/97] 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 f5c5b2d65..df1216a21 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1036,11 +1036,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 03f1a1eb4..8f4a0fad8 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -2394,7 +2394,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]: @@ -2407,11 +2407,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 5e4bee9c30db56bdab6f280f54f68e693251cccc Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 10:24:32 +0100 Subject: [PATCH 34/97] 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 23eb7a282933e467e4f6c1bd94fdbb6a27a99b8d Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 13:42:06 +0100 Subject: [PATCH 35/97] 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 df1216a21..05496e694 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1035,12 +1035,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 95b40f50d6d0d56fe979a27d71e0dd9048679205 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 14:28:02 +0100 Subject: [PATCH 36/97] 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 05496e694..97cb04755 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -1026,7 +1026,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. @@ -1039,24 +1039,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 8f4a0fad8..206025508 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -2417,7 +2417,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 9116bcc095ce79facea32f77d0a436f2b8cddc73 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 8 Nov 2023 17:43:37 +0100 Subject: [PATCH 37/97] 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 87d4685adb8d282d1c0e2374fee09afbd8c21c54 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 9 Nov 2023 10:03:53 +0100 Subject: [PATCH 38/97] 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 aa9bf255a1a7a3ea9504dff56f292b6cec33321b Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 9 Nov 2023 12:06:44 +0100 Subject: [PATCH 39/97] 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 206025508..651e794f5 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -219,7 +219,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') @@ -2244,7 +2244,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: @@ -2253,7 +2253,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 ef5b5ec64fae4956aca904e435b587d5fcc96599 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 10 Nov 2023 13:37:22 +0100 Subject: [PATCH 40/97] 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 f2baac39603606c634cdb81f4dcea8356fba4f46 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 10 Nov 2023 18:50:13 +0100 Subject: [PATCH 41/97] 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 97cb04755..19dc677b3 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -846,7 +846,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 @@ -913,7 +913,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 @@ -948,7 +948,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 75fe4cb12..0720896bf 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -90,12 +90,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): @@ -170,8 +216,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): @@ -186,9 +243,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 42/97] calculate incompressible two-phase states based on HEOS::Water --- ...sFlowSplitWithDeltaTDeltaP-decanterTest.py | 2 +- src/tespy/connections/connection.py | 25 ++- src/tespy/networks/network_reader.py | 1 + src/tespy/tools/fluid_properties/functions.py | 178 +++++++----------- 4 files changed, 81 insertions(+), 125 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 19dc677b3..74d9897b7 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -665,23 +665,22 @@ 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._solved = True - self.x._solved = True - + 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.T._solved = True - self.x._solved = True - self.p._solved = True - self.h._solved = True + 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 def get_parameters(self): return { @@ -1040,10 +1039,10 @@ def check_temperature_bounds(self, iter): for f, w in self.fluid.wrapper.items(): if self.fluid.val[f] > ERR and self.fluid.val[f] < 1-ERR: Tminlist.append(w._T_min) - Tmaxlist.append(w._T_max) + Tmaxlist.append(w._T_max) if iter < 8: - Tmin = max(Tminlist) * 1.01 + Tmin = max(Tminlist) * 1.01 Tmax = min(Tmaxlist) * 0.99 else: Tmin = max(Tminlist) * (1+ERR) 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 0720896bf..781b094cb 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -90,34 +90,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): @@ -216,19 +200,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): @@ -243,28 +219,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 43/97] 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 5489ae535..f601c1a55 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -201,7 +201,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": @@ -210,8 +210,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 a11f45cb56474056e016a9592a43f7eba879fb90 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 13 Nov 2023 16:15:02 +0100 Subject: [PATCH 44/97] 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 781b094cb..6e7d35eca 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -93,9 +93,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 45/97] 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 575fcfe2b50d1b62e18671e773ec77ba5407354e Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 22 Nov 2023 22:41:27 +0100 Subject: [PATCH 46/97] 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 74d9897b7..5c5a33605 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -851,11 +851,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 6e7d35eca..49bda7377 100644 --- a/src/tespy/tools/fluid_properties/functions.py +++ b/src/tespy/tools/fluid_properties/functions.py @@ -155,8 +155,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 ddeae5ae2d426e7abd1945047121642680f5d700 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 23 Nov 2023 09:47:01 +0100 Subject: [PATCH 47/97] 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 8e387341d4d85494cb98cdef07f24bdcc8f2951b Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 23 Nov 2023 15:45:01 +0100 Subject: [PATCH 48/97] 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 1b4811ff0..55e0f768c 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 5c5a33605..b0f8275e4 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -752,7 +752,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 651e794f5..ac369a227 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1108,7 +1108,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: @@ -2317,6 +2317,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 f601c1a55..cb6a82714 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -195,7 +195,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: @@ -203,18 +203,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 8bc1472d5f36e87e6d9aa9841a6d6f290278e447 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 24 Nov 2023 08:51:11 +0100 Subject: [PATCH 49/97] 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 55e0f768c..1b4811ff0 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 c1fab6b68726f67607a78389eb300177923f8061 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 24 Nov 2023 15:48:59 +0100 Subject: [PATCH 50/97] 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 cb6a82714..19e54f1c2 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -204,7 +204,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 d581f1fd9e9c2695176be8012b369576a0998d9b Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 13:45:30 +0100 Subject: [PATCH 51/97] 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 ac369a227..5f5d82849 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1789,6 +1789,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 dbca66f082a471714b9a3c1637452f58a3910e39 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 14:31:43 +0100 Subject: [PATCH 52/97] 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 3f19deb8036546297866ceccb5d81dcb7faf2e74 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 15:06:31 +0100 Subject: [PATCH 53/97] 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 0edbc3849eedd511fddfcdc22269212ac4fd0de5 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 27 Nov 2023 17:12:04 +0100 Subject: [PATCH 54/97] 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 522b1183c3198b8049923d248218dade555cfbf4 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 09:35:21 +0100 Subject: [PATCH 55/97] 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 5f5d82849..752544304 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -1671,6 +1671,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 950b8c8e92d5e9034743acd70a9aaafdfb617c38 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 13:14:23 +0100 Subject: [PATCH 56/97] 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 791741ce3a6db653f0d0a0d2e4ddd44f0c783698 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 28 Nov 2023 16:46:43 +0100 Subject: [PATCH 57/97] 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 a2d410bcc8de8477bd0f1943446ee1e0cf5f31b3 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 29 Nov 2023 14:37:31 +0100 Subject: [PATCH 58/97] 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 54943d173d694aee4ad793773d5197a8af01fdc4 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 29 Nov 2023 16:27:32 +0100 Subject: [PATCH 59/97] 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 679e502c99fc390123a9e421c4daae05a76eb390 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 09:25:02 +0100 Subject: [PATCH 60/97] 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 b0f8275e4..fdb8b8ddb 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -497,7 +497,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 cfca0d92e19379d21ed5d25addd98ead473b81b0 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:33:46 +0100 Subject: [PATCH 61/97] 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 fdb8b8ddb..707e732c5 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -914,7 +914,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 752544304..cc0c09480 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -722,6 +722,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 ee7e6fc2a116bc001d133f0e4c9c9cf99a08bbfe Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:38:39 +0100 Subject: [PATCH 62/97] 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 e38b7e0eb2effd4633f505f5836909822ccbec52 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 30 Nov 2023 14:51:21 +0100 Subject: [PATCH 63/97] 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 bfa8b570a41cba7e0dcf947472510796ee1324be Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 1 Dec 2023 09:24:50 +0100 Subject: [PATCH 64/97] 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 cc0c09480..e2c245202 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -728,7 +728,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) @@ -751,6 +752,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 e7c00fccf06b03852128f590750ccfb935b55d4f Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 08:34:19 +0100 Subject: [PATCH 65/97] 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 95a6dbb6fa454e2412ae1b17d7051d893b69d12a Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 15:42:08 +0100 Subject: [PATCH 66/97] 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 fa4414fe7a05714ddeade18e7763253719d2290a Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 4 Dec 2023 17:00:22 +0100 Subject: [PATCH 67/97] 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 761defc14ffd15d003179b2f5188b1709b70f7d7 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 5 Dec 2023 12:58:17 +0100 Subject: [PATCH 68/97] 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 416b1fc16a9db78919330dcfdc207d719deb9cd6 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 5 Dec 2023 14:30:13 +0100 Subject: [PATCH 69/97] 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 623da437baf5db78d01eeee881ccedeb539a0031 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 11:04:35 +0100 Subject: [PATCH 70/97] 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 52ab7b030..05dbe498f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,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 7d747efc0e6ad4e11471bc8ae3abf81f432ee565 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 11:14:47 +0100 Subject: [PATCH 71/97] 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 19e54f1c2..41559e825 100644 --- a/src/tespy/tools/fluid_properties/wrappers.py +++ b/src/tespy/tools/fluid_properties/wrappers.py @@ -206,7 +206,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: @@ -214,7 +214,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 ba72fc5f6390cce6eedc638ab9c12c734accf37e Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 7 Dec 2023 20:07:08 +0100 Subject: [PATCH 72/97] 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 30d5334c16894064057344e12b34c7db82928c43 Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Fri, 8 Dec 2023 15:04:12 +0100 Subject: [PATCH 73/97] 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 e4df9a2bb65e8e4ee85aa401d580a0d6af537297 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 8 Dec 2023 22:29:47 +0100 Subject: [PATCH 74/97] 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 90767c3a8143e0586b6ae3c276b0acf5bf36fc52 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 13:11:54 +0100 Subject: [PATCH 75/97] thandling 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 | 14 +++++- 5 files changed, 85 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 e2c245202..b22ad1c71 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -34,6 +34,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: @@ -212,6 +214,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]) @@ -270,6 +276,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(): @@ -284,6 +294,24 @@ def set_attr(self, **kwargs): msg = f'Allowed units for {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 f'{prop}_range' in kwargs: @@ -1251,6 +1279,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 = {} @@ -2571,6 +2609,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 7ae398110..be0517159 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -290,6 +290,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 @@ -304,7 +311,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, @@ -318,7 +325,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 8cd773f1a..cdbcfa94c 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -14,6 +14,18 @@ gas_constants = {} gas_constants['uni'] = 8.314462618 +component_property_data = { + '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 = { 'm': { 'text': 'mass flow', diff --git a/src/tespy/tools/helpers.py b/src/tespy/tools/helpers.py index d7dab3f10..8a46a68f9 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 +from tespy.tools.global_vars import fluid_property_data, component_property_data +from tespy.tools.global_vars import molar_masses def get_all_subdictionaries(data): @@ -109,6 +110,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 d479cbddf9f3738c1e7d294bcf0c2d48a82d8830 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 14:05:19 +0100 Subject: [PATCH 76/97] 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 65058e28783569b43a09635deb7f0556e946b366 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 13 Dec 2023 14:05:36 +0100 Subject: [PATCH 77/97] adding more variables for component units --- src/tespy/tools/global_vars.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/tespy/tools/global_vars.py b/src/tespy/tools/global_vars.py index cdbcfa94c..5188c1f42 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -19,13 +19,41 @@ '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 = { 'm': { 'text': 'mass flow', From 50370258f3e96e09e9989b1bfc6536a4735957d8 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 09:43:44 +0100 Subject: [PATCH 78/97] more units for components --- src/tespy/networks/network_reader.py | 1 - src/tespy/tools/global_vars.py | 23 +++++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 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 5188c1f42..61cba8363 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -43,11 +43,30 @@ #'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}'} } @@ -60,7 +79,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 aa9cbfe3b80e800b967cde152584ba0050e590db Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 17:29:56 +0100 Subject: [PATCH 79/97] 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 61cba8363..b6fdb62b8 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -65,7 +65,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}'} @@ -79,7 +79,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 17f2625ed33efc214db86122c2874abffd964f15 Mon Sep 17 00:00:00 2001 From: mrk Date: Thu, 14 Dec 2023 22:50:13 +0100 Subject: [PATCH 80/97] 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 b6fdb62b8..5f2553167 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -19,25 +19,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}'} @@ -55,7 +47,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}'} @@ -65,13 +67,17 @@ '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}'} } } +component_property_data['Q_loss'] = component_property_data['Q'] +component_property_data['Q_total'] = component_property_data['Q'] + + fluid_property_data = { 'm': { @@ -79,7 +85,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 f33052972b34dac53f68a765265355152597ff94 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:01:56 +0100 Subject: [PATCH 81/97] 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 f47f768b38c41568cf88be07e4dcf2ca13db7fe7 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:02:49 +0100 Subject: [PATCH 82/97] 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 bf9260236402bee4b22b2b8c52e721184bf7e6f7 Mon Sep 17 00:00:00 2001 From: mrk Date: Fri, 15 Dec 2023 16:05:15 +0100 Subject: [PATCH 83/97] 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 | 83 +++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/src/tespy/networks/network.py b/src/tespy/networks/network.py index b22ad1c71..35d1dc769 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -294,7 +294,7 @@ def set_attr(self, **kwargs): msg = f'Allowed units for {fpd[prop]["text"]} are: {keys}' logger.error(msg) raise ValueError(msg) - + for prop in cpd.keys(): unit = prop + '_unit' if unit in kwargs: @@ -310,7 +310,7 @@ def set_attr(self, **kwargs): 'Allowed units for ' + cpd[prop]['text'] + ' are: ' + keys) logger.error(msg) - raise ValueError(msg) + raise ValueError(msg) for prop in ['m', 'p', 'h']: @@ -757,7 +757,7 @@ def create_massflow_and_fluid_branches(self): 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 + self.branchesNames[k] += " -> " + comp.label msg = (self.branchesNames[k]) logger.debug(msg) @@ -1284,11 +1284,11 @@ def init_design(self): 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 + 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 = {} @@ -1857,11 +1857,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): @@ -2099,12 +2100,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 @@ -2235,18 +2244,26 @@ def iterinfo_body(self, print_results=True): fluid = 'NaN' component = 'NaN' - progress_val = -1 + 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: - 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. if residual_norm > np.finfo(float).eps * 100: progress_min = np.log(ERR) @@ -2278,7 +2295,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.""" @@ -2337,17 +2354,17 @@ def _limit_increments(self,valmin,valmax,val,increment): return increment def update_variables(self): - - if self.iter < 2: + + if self.iter < 2: RobustRelax = 0.1 - elif self.iter < 4: + elif self.iter < 4: RobustRelax = 0.25 - elif self.iter < 6: - RobustRelax = 0.5 - else: + elif self.iter < 6: + RobustRelax = 0.5 + else: RobustRelax = 1 - #RobustRelax = 1 + #RobustRelax = 1 # add the increment for data in self.variables_dict.values(): @@ -2377,14 +2394,14 @@ def update_variables(self): 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 - + 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) @@ -2611,7 +2628,7 @@ def process_components(self): 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 + # 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) From 6418176bb0f5d3c8b3c037cc18e643ee676f6af2 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 19 Dec 2023 16:33:10 +0100 Subject: [PATCH 84/97] 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 35d1dc769..71b8c21e7 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -808,7 +808,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 2cbeb8a0a74b2ad088f3b549ebd51373599f6cf0 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 30 Jan 2024 08:25:21 +0100 Subject: [PATCH 85/97] 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 5f2553167..d0b5cd03f 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -84,7 +84,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 fafc390a06483793e1a1a27dbd65375fc43cbc40 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 31 Jan 2024 12:13:03 +0100 Subject: [PATCH 86/97] 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 71b8c21e7..edde84c3b 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -773,7 +773,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 db1a26fb998f0adb631c450dd74d8849ae74e64e Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Wed, 31 Jan 2024 14:19:13 -0300 Subject: [PATCH 87/97] 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 d0b5cd03f..50b074360 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -22,13 +22,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 91b2a072c36caefa72230408635760d4bbffd079 Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 6 Feb 2024 13:19:20 +0100 Subject: [PATCH 88/97] 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 eb82fd978895a7ce1e05504c4b4f5dbed2db4960 Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 7 Feb 2024 14:55:57 +0100 Subject: [PATCH 89/97] 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 ce3ebbf6c..96ceb0822 100644 --- a/src/tespy/components/component.py +++ b/src/tespy/components/component.py @@ -211,42 +211,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 896aa8d763357412ddd934d111b8c37bb2193dac Mon Sep 17 00:00:00 2001 From: mrk Date: Wed, 7 Feb 2024 15:46:22 +0100 Subject: [PATCH 90/97] 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 c509c110b2c0bbfca862962c0049ce31775d7201 Mon Sep 17 00:00:00 2001 From: Vily-ipu Date: Wed, 21 Feb 2024 13:56:06 +0100 Subject: [PATCH 91/97] 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 50b074360..83f0df18a 100644 --- a/src/tespy/tools/global_vars.py +++ b/src/tespy/tools/global_vars.py @@ -45,7 +45,7 @@ #'documentation': {'float_fmt': '{:,.3f}'} '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 f0aaeb97236f8aacd95711b218e03e6aedb4e11b Mon Sep 17 00:00:00 2001 From: mrk Date: Tue, 2 Apr 2024 15:01:43 +0200 Subject: [PATCH 92/97] 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 82280db0df0f8b77845a9792d7bdfcaf1d839bb9 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 14:35:49 +0200 Subject: [PATCH 93/97] 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 | 6 +- 5 files changed, 290 insertions(+), 18 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 707e732c5..c1d108e9f 100644 --- a/src/tespy/connections/connection.py +++ b/src/tespy/connections/connection.py @@ -510,6 +510,9 @@ def _fluid_specification(self, key, value): elif key == "fluid_balance": self.fluid_balance.is_set = value + elif key == "fluid_coefs": + self.fluid.fluid_coefs = value + else: msg = f"Connections do not have an attribute named {key}" logger.error(msg) @@ -624,7 +627,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 edde84c3b..8e1beb87f 100644 --- a/src/tespy/networks/network.py +++ b/src/tespy/networks/network.py @@ -960,6 +960,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] @@ -967,6 +968,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 @@ -1012,7 +1015,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): @@ -2283,19 +2287,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 be0517159..167e1ba11 100644 --- a/src/tespy/tools/data_containers.py +++ b/src/tespy/tools/data_containers.py @@ -116,7 +116,7 @@ def set_attr(self, **kwargs): if "::" in kwargs[key]: _, fluid = kwargs[key].split("::") else: - fluid = kwargs[key] + fluid = kwargs[key] self.__dict__.update({key: fluid}) else: self.__dict__.update({key: kwargs[key]}) @@ -296,7 +296,7 @@ class ComponentProperties(DataContainer): unit : boolean Has the unit for this property been specified manually by the user? - default: unit_set=False. + default: unit_set=False. """ @staticmethod @@ -372,6 +372,7 @@ def attr(): 'wrapper': dict(), 'back_end': dict(), 'engine': dict(), + 'fluid_coefs': dict(), "is_var": set(), "J_col": dict(), } @@ -605,4 +606,3 @@ def attr(): '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 5cd9c06fdc0c88edcb806d6ae52787c0244e8bb2 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:14:14 +0200 Subject: [PATCH 94/97] 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 141193b96bd0c61e5ff71c048ddb21c271506ccb Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:51:33 +0200 Subject: [PATCH 95/97] 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 56a3ab7e6e075859646c1ca2d76fed7f02491da4 Mon Sep 17 00:00:00 2001 From: mrk Date: Mon, 15 Apr 2024 15:52:07 +0200 Subject: [PATCH 96/97] 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 0ac907c03c5dbeb498c2221722253200731f2632 Mon Sep 17 00:00:00 2001 From: Francesco Witte Date: Tue, 16 Apr 2024 00:31:05 +0200 Subject: [PATCH 97/97] Delete application specific files --- .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)