Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
408ef53
Prepare the possibility to specify wrapper kwrags in the form of a dict
fwitte Jan 4, 2026
1a3dc9a
Implement a simple test method to check if kwargs can be injected via…
fwitte Jan 4, 2026
3bc57af
Merge branch 'dev' into feature/#876-incompressiblefluidwrapper
fwitte Jan 5, 2026
edfbb4f
Also propagate the fluid wrapper kwargs
fwitte Jan 5, 2026
ab5c920
Implement a simple way for Arrhenius viscosity model and linear densi…
fwitte Jan 5, 2026
7afb0d1
Update changelog
fwitte Jan 5, 2026
77363eb
Add testing for the newly implemented wrapper
fwitte Jan 5, 2026
f2daf98
Run isort
fwitte Jan 5, 2026
58c3ad8
Change minimum number of datapoints
fwitte Jan 5, 2026
76d7242
Fix heat capacity data
fwitte Jan 5, 2026
9d1caff
Write some docs
fwitte Jan 5, 2026
3e6910b
Insert missing newlines
fwitte Jan 6, 2026
bac5921
Clean up a bit
fwitte Jan 6, 2026
2c41acb
Add entropy
fwitte Jan 6, 2026
793e349
Fix isentropic calculation by only considering pressure change and as…
fwitte Jan 6, 2026
8041ad3
Add a fitting report and change viscosity to higher order polynomial
fwitte Jan 7, 2026
a3bcc3b
Make error tolerance more strict
fwitte Jan 7, 2026
fee7e3c
Add a legend and proper axis labels for the plots
fwitte Jan 9, 2026
25d8ce7
Move some methods from the network to the respective connection classes
fwitte Jan 10, 2026
bb51297
Check in a new HumidAirConnection class with some basic functionality
fwitte Jan 10, 2026
327b753
Add relative humidity equation
fwitte Jan 10, 2026
a7fbdea
Try to improve the convergence stabilization
fwitte Jan 10, 2026
8dc7e97
Make some quick and dirty adjustments to reuse _mix_ph methods with h…
fwitte Jan 10, 2026
0f6b40c
Make a much simpler implementation
fwitte Jan 11, 2026
cd17f16
Add one sample notebook
fwitte Jan 11, 2026
59fa5e3
Use MovingBoundary instead of Condenser
fwitte Jan 12, 2026
1486716
Go back to normal logo
fwitte Jan 12, 2026
cf7faf5
Update tutorial based on latest API capabilities
fwitte Jan 12, 2026
3f95cf9
Update meeting information
fwitte Jan 12, 2026
9b1399d
Merge branch 'main' into dev
fwitte Jan 12, 2026
e3f38d0
Add a conductivity fitting test
fwitte Jan 13, 2026
ee1b999
Also test conductivity high level access
fwitte Jan 13, 2026
c53d9f0
UPdate docs
fwitte Jan 13, 2026
def2b27
Update fitting description for viscosity and add a cautionary note
fwitte Jan 13, 2026
15c6714
Issue a future warning for specification of Ref and numerical value a…
fwitte Jan 13, 2026
0d63967
Add some class docstring
fwitte Jan 13, 2026
953570f
Add to FAQ
fwitte Jan 13, 2026
6b6fa5a
Merge branch 'feature/#876-incompressiblefluidwrapper' into feature/#…
fwitte Jan 13, 2026
d525c6f
Merge branch 'feature/#597-fluidwrapper-kwargs' into dev
fwitte Jan 13, 2026
0fc5362
Merge branch 'dev' into fix/#885-Ref-not-unsetting-numerical-value
fwitte Jan 13, 2026
7f86bfd
Update warning text
fwitte Jan 13, 2026
5e89d3a
Merge branch 'fix/#885-Ref-not-unsetting-numerical-value' into dev
fwitte Jan 13, 2026
15a1bd2
Make it possible to specify relative humidity as equation to the model
fwitte Jan 14, 2026
57c5f70
Make quick and dirty convergence helpers for humidair mixing_rule
fwitte Jan 14, 2026
bb82005
Remove outputs
fwitte Jan 14, 2026
f808a84
Fix an issue where vector dependents are not correctly handled by aut…
fwitte Jan 14, 2026
85465c1
Add a first draft to consider freezing in energy balance
fwitte Jan 14, 2026
f7d7ea7
Merge branch 'dev' into feature/humid-air-connection
fwitte Jan 14, 2026
1b35835
Externalize identification of dQ to function and fix calculation of h…
fwitte Jan 15, 2026
8c24995
Fix compatibility
fwitte Jan 15, 2026
cd616f3
Slightly adjust the convergence helper critereons
fwitte Jan 16, 2026
aafff43
Improve combustion convergence helpers
fwitte Jan 16, 2026
4cd06e2
Change logging level to debug and adjust error message
fwitte Jan 16, 2026
23acfdb
Update changelog
fwitte Jan 16, 2026
69a97cb
Merge branch 'fix/#892-logging-level-changes' into dev
fwitte Jan 16, 2026
91a1cf2
Merge branch 'dev' into feature/humid-air-connection
fwitte Jan 16, 2026
9543fa6
Move humid air context out of Connection into HAConnection
fwitte Jan 16, 2026
d4b97cd
Rename method for better clarity
fwitte Jan 16, 2026
4792362
Make it an f string
fwitte Jan 16, 2026
72c109d
Make sure water and air are in the fluid vector
fwitte Jan 16, 2026
a4bfb3a
Allow specification of fluid composition through w
fwitte Jan 16, 2026
1c8f0d8
Clean up the example
fwitte Jan 16, 2026
39af317
Implement presolving of T for the HAConnection
fwitte Jan 20, 2026
017e20d
Fix a bug in the enthalpy value limitations
fwitte Jan 20, 2026
71848e0
ONly make a guess if there is no value imposed or precalculated and i…
fwitte Jan 20, 2026
9151ff2
Relaxing and helping the UA equation
JacobCHP Jan 22, 2026
c8706ee
Allow to store design cases as strings instead of files. makes sense …
jowr Feb 1, 2026
798758c
Allow to store design cases as strings instead of files. makes sense …
jowr Feb 1, 2026
ad2c0e6
Merge remote-tracking branch 'origin/feature/humid-air-connection' in…
jowr Feb 1, 2026
903ee0e
Limit the humidity to 100% RH
jowr Feb 9, 2026
153c284
directly calculate condensate flow next to the humid air. Can be used…
jowr Feb 9, 2026
785e214
Bugfix of seeding in HAConnection init
JacobCHP Feb 11, 2026
74af82b
Fix all uses of a random number generator
jowr Feb 11, 2026
e888404
fix a typo
jowr Feb 11, 2026
805e96b
Increasing relaxation
JacobCHP Feb 12, 2026
ac0a969
helper function for the sorted residual index values
jowr Feb 12, 2026
d65af03
changed relaxation
jowr Feb 12, 2026
7b97b3e
Make a hack to allow local_offdesign to work for the heat exchanger kA
fwitte Feb 13, 2026
16c049b
Slightly adjust the convergence helpers
fwitte Feb 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,17 +124,16 @@ use.
Get in touch
============

Online "Stammtisch"
-------------------
Community meetings
------------------

We have decided to start a reoccurring "Stammtisch" meeting for all interested
TESPy users and (potential) developers. You are invited to join us on every 3rd
Monday of a month at 17:00 CE(S)T for a casual get together. The first meeting
will be held at June, 20, 2022. The intent of this meeting is to establish a
more active and well-connected network of TESPy users and developers.
There are online QA meetings every month, please check the
`oemof calendar <https://oemof.org/calendar/>`__ for date, time and meeting
link. You are invited to join us with your questions, issues and suggestions!

If you are interested, you can simply join the meeting at
https://meet.jit.si/tespy_user_meeting. We are looking forward to seeing you!
Furthermore, there are in-person community meetings. These are held once or
twice a year. To learn about upcoming meetings, follow the blog over at
`<https://oemof.org/>`__ for the announcements.

User forum
----------
Expand Down
143 changes: 133 additions & 10 deletions docs/advanced_features/fluid_properties.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ Fluid properties
================
The default fluid property engine `CoolProp <https://coolprop.org/>`_. All
available fluids can be found on their homepage. Also see :cite:`Bell2014`.
Since version 0.7 of TESPy it is possible to use other engines. TESPy comes with
two additional predefined engines, i.e.
Since version 0.7 of TESPy it is possible to use other engines. TESPy supports
one additional predefined engine, which can be used to fit functions to simple
custom fluid property data, the :code:`IncompressibleFluidWrapper`. See
:ref:`this section <incompressible_wrapper_label>` for more information.

On top, there are two additional predefined engines, which are untested but may
serve as an inspiration for you to create your onw one, i.e.

- the `iapws <https://github.com/jjgomera/iapws/>`_ library and
- the `pyromat <https://github.com/chmarti1/PYroMat/>`_ library.
Expand Down Expand Up @@ -62,19 +67,131 @@ If you are looking for heat transfer fluids, the list of incompressible
might be interesting for you. In contrast to the pure fluids, the properties
cover liquid state only.

If you have measurement data or data from manufacturer data sheets and want to
use these in your TESPy model, TESPy can create fitting functions for these
with the :code:`IncompressibleFluidWrapper`. See
:ref:`this section <incompressible_wrapper_label>` for more information.

Fluid mixtures
++++++++++++++
TESPy provides support for three types of mixtures:

- ideal: Mixtures for gases only.
- ideal-cond: Mixture for gases with condensation calculation for water share.
- incompressible: Mixtures for incompressible fluids.
- incompressible: Mixtures for CoolProp-based incompressible fluids.

These mixtures are handled externally by TESPy by using the pure fluid
properties of CoolProp and then applying the respective mixing rules, read more
about it :ref:`here <mixture_routines_label>`.

More accurate formulations are available directly through CoolProp, which
provides a back end for predefined mixtures. This back end is rather instable
when using HEOS. In general, to use the mixture feature of CoolProp we
recommend using the REFPROP back end instead of HEOS. Also note, the CoolProp
mixture back end is not tested thoroughly. Please reach out if you would like
to support us in adopting the TESPy implementation.

.. _incompressible_wrapper_label:

IncompressibleFluidWrapper
--------------------------
You can use the :code:`IncompressibleFluidWrapper` engine of TESPy to model a
fluid based on your own data. To do this, you need tabular data as function of
temperature:

- Mass density
- Mass specific heat capacity
- Dynamic viscosity

The :code:`IncompressibleFluidWrapper` will automatically fit functions to your
data:

- density and heat capacity through linear interpolation:
:math:`f\left(T\right) = A + B \cdot T`
- viscosity through an exponential polynomial equation
:math:`\eta\left(T\right) = e ^ {\frac{A}{T ^ 3} + \frac{B}{T ^ 2} + \frac{C}{T} + D}`

We can make use of the engine as shown in the example below. First, we set up
a very simple system, just a flow of fluid through a heat exchanger.

.. code-block:: python

>>> 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
>>> from tespy.tools.fluid_properties import IncompressibleFluidWrapper
>>> import numpy as np
>>> nw = Network(iterinfo=False)
>>> nw.units.set_defaults(
... temperature="°C",
... pressure="bar",
... heat="kW"
... )

>>> heatexchanger = SimpleHeatExchanger("heat exchanger")

>>> so = Source("source")
>>> si = Sink("sink")

>>> c1 = Connection(so, "out1", heatexchanger, "in1", label="c1")
>>> c2 = Connection(heatexchanger, "out1", si, "in1", label="c2")

>>> nw.add_conns(c1, c2)

Furthermore, CoolProp provides a back end for predefined mixtures, which is
rather instable using HEOS. Using the CoolProp mixture back-end is not tested,
reach out if you would like to support us in adopting the TESPy implementation.
In general, to use the mixture feature of CoolProp we recommend using the
REFPROP back end instead of HEOS.
Next, we have to prepare our data to be utilized by TESPy. The information
required needs to be passed in SI units and must be gridded with the same
spacing of temperature for all measurements.

.. attention

Please note, that this example is purely for showing how to utilize this
implementation. In the example only 2 datapoints are available. This works
well for density and heat capacity as linear fitting functions are applied.
For viscosity this is somewhat sketchy, since you would need at least 4
datapoints to fit a function of polynomial 3!

.. code-block:: python

>>> fluid_kwargs = {
... "temperature_data": np.array([273.15, 373.15]), # K
... "density_data": np.array([1000, 1100]), # kg/m3
... "heat_capacity_data": np.array([4000, 4100]) * 1e3, # J/kg
... "viscosity_data": np.array([0.05, 0.00025]) # Pa*s
... }

.. attention::

The keys of the dictionary must be named :code:`temperature_data`,
:code:`density_data`, :code:`heat_capacity_data` and
:code:`viscosity_data`!

Then, we can specify the fluid on one of our connections by providing two
additional keywords:

- :code:`fluid_engines` indicating which fluid uses which wrapper class.
- :code:`fluid_wrapper_kwargs` providing for each fluid (if applicable) the
required data.

.. code-block:: python

>>> c1.set_attr(
... fluid={"f": 1},
... fluid_engines={"f": IncompressibleFluidWrapper},
... fluid_wrapper_kwargs={"f": fluid_kwargs},
... )

We can specify missing boundary conditions and solve the problem.

.. code-block:: python

>>> c1.set_attr(v=2, p=1, T=30)
>>> c2.set_attr(p=0.9)
>>> heatexchanger.set_attr(Q=10)

>>> nw.solve("design")
>>> nw.assert_convergence()

Using other engines
-------------------
Expand Down Expand Up @@ -150,6 +267,11 @@ enthalpy to the temperature. Lastly, to make the calculation of isentropic
efficiencies possible, we can add the equation for change in enthalpy on
isentropic change of pressure for an ideal gas.

.. tip::

You can also inject :code:`kwargs` from the connection specification to
your concrete wrapper instance, see the section on
:ref:`incompressible fluids <incompressible_wrapper_label>`.

.. code-block:: python

Expand All @@ -160,7 +282,7 @@ isentropic change of pressure for an ideal gas.

>>> class KKHWrapper(FluidPropertyWrapper):
...
... def __init__(self, fluid, back_end=None, reference_temperature=298.15) -> None:
... def __init__(self, fluid, back_end=None, reference_temperature=298.15, **kwargs) -> None:
... super().__init__(fluid, back_end)
...
... if self.fluid not in COEF:
Expand Down Expand Up @@ -271,7 +393,6 @@ the previous section:

.. code-block:: python


>>> from tespy.components import Sink
>>> from tespy.components import Source
>>> from tespy.components import Turbine
Expand Down Expand Up @@ -304,6 +425,8 @@ the previous section:
>>> round(c2.T.val, 1)
306.3

.. _mixture_routines_label:

Mixture routines in TESPy
-------------------------
Different types of mixture routines are implemented in TESPy. You can select,
Expand Down
77 changes: 41 additions & 36 deletions docs/advanced_tutorials/heat_pump_steps.rst
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ decides the overall mass flow in the systems.
In this tutorial we will first build the system with parameters that
ensure stable starting values for a simulation, which in the end will be
switched to reasonable values for the individual parts of the system. For
example, instead of the evaporation pressure we will use the terminal
example, instead of the evaporation pressure we will use the pinch
temperature difference at the condenser instead.

.. literalinclude:: /../tutorial/advanced/stepwise.py
Expand All @@ -152,11 +152,11 @@ decides the overall mass flow in the systems.

In order to calculate this network further parametrization is necessary, as
e.g. the fluids are not determined yet: At the hot inlet of the condenser we
define the temperature, pressure and the fluid informaton. A good guess for
pressure can be obtained from CoolProp's PropsSI function. We know that the
condensation temperature must be higher than the consumer's feed flow
temperature. Therefore, we can set the pressure to a slightly higher value of
that temperature's corresponding condensation pressure.
define the temperature and the fluid information. On top we can define the
pressure level by specifying the dew line temperature. We know, that the
condensation temperature will be slightly below the heat demand feed flow
temperature. Therefore, we can set the dew line temperature to a slightly lower
value of that temperature.

The same needs to be done for the consumer cycle. We suggest setting the
parameters at the pump's inlet. On top, we assume that the consumer requires a
Expand Down Expand Up @@ -240,7 +240,9 @@ Connections
Since the old connection :code:`1` lead to a sink, we have to replace this
connection in the network. We can do that by using the method
:code:`del_conns` passing :code:`c1`. After that, we can create the new
connections and add them to the network as we did before.
connections and add them to the network as we did before. Do not forget to add
the :code:`x=0` specification to make liquid saturated state at the outlet of
the condenser.

The valve connects to the drum at the inlet :code:`'in1'`. The drum's outlet
:code:`'out1'` is saturated liquid and connects to the evaporator's cold side
Expand All @@ -264,16 +266,16 @@ connections to the model:
Parametrization
+++++++++++++++
Previous parametrization stays untouched. Regarding the evaporator, we specify
pressure ratios on hot side as well as the evaporation pressure, for which we
can obtain a good initial guess based on the ambient temperature level using
CoolProp. From this specification the pinch point layout will be a result,
similar as in waste heat steam generators. The pressure ratio of the cold side
*MUST NOT* be specified in this setup as the drum assumes pressure equality
for all inlets and outlets.
pressure ratios on hot side. On top, the evaporation pressure is indirectly
defined through the evaporation temperature and the fact, that we are in
two-phase region. From this specification the pinch point layout will be a
result, similar as in waste heat steam generators. The pressure ratio of the
cold side *MUST NOT* be specified in this setup as the drum assumes pressure
equality for all inlets and outlets.

The superheater will also use the pressure ratios on hot and cold side.
Further we set a value for the enthalpy at the working fluid side outlet. This
determines the degree of overheating and is again based on a good guess.
Further we set a value for the degree of superheating :code:`td_dew` at the
working fluid side outlet.

.. literalinclude:: /../tutorial/advanced/stepwise.py
:language: python
Expand Down Expand Up @@ -308,8 +310,8 @@ Compressor system
To complete the heat pump, we will add the compressor system to our existing
network. This requires to change the connections 0, 6 and 17. The connection 6
has to be changed to include the compressor. After the last compressor stage,
connection 0 has to redefined, since we need to include the CycleCloser of the
working fluid's cycle. The connection 17 has to be connected to the heat
connection 0 has to be redefined, since we need to include the CycleCloser of
the working fluid's cycle. The connection 17 has to be connected to the heat
exchanger for intermittent cooling as well as the bypass.

.. figure:: /_static/images/tutorials/heat_pump_stepwise/flowsheet.svg
Expand Down Expand Up @@ -375,18 +377,21 @@ pressure losses on both sides.
:start-after: [sec_14]
:end-before: [sec_15]

Regarding the connections we set enthalpy values for all working fluid side
connections. After the superheater and intermittent cooling the value will be
near saturation (enthalpy value of connection c5), after the compressors it
will be higher.
Regarding the connections we set degree of superheating at the outlet of the
superheater and intermittent cooling, since these values will be near
saturation. The temperature at both compressor exits will be higher than those,
we can implicitly define this through the enthalpy fixed to the saturated gas
enthalpy multiplied by a bit. This specification is for numerical stability, it
will be changed in the next step.

For the ambient side, we set temperature, pressure and fluid
at connection 11. On top of that, we can specify the temperature of the
ambient water after leaving the intermittent cooler.

With re-adding of connection 0 we have to set the fluid and the pressure again,
but not the temperature value, because this value will be a result of the
condensation pressure and the given enthalpy at the compressor's outlet.
With re-adding of connection 0 we have to set the fluid and the dew line
temperature again, but not the actual temperature value, because this value
will be a result of the condensation pressure and the given enthalpy at the
compressor's outlet.

.. literalinclude:: /../tutorial/advanced/stepwise.py
:language: python
Expand All @@ -398,18 +403,16 @@ Solve and Set Final System Parameters
Now we solve again. After that, we can exchange our good guesses with actual
useful parameters:

The condensation and evaporation pressure levels will be replaced by terminal
temperature values of the condenser and the evaporator respectively. The lower
terminal temperature value of the evaporator :code:`ttd_l` defines the pinch
point. The upper terminal temperature value :code:`ttd_u` of the condenser
defines the condensation pressure.
The condensation dew line temperature and evaporation temperature will be
replaced by pinch temperature difference of the condenser and terminal
temperature difference of the evaporator respectively. The lower terminal
temperature value of the evaporator :code:`ttd_l` is identical to its pinch
point temperature difference.

The degree of superheating in the superheater will be determined by the upper
terminal temperature instead of the enthalpy value at connection 6. The outlet
terminal temperature instead of the superheating specification. The outlet
enthalpies after both compressors are replaced by the isentropic efficiency
values. Finally, the enthalpy after the intermittent cooling is replaced by
the temperature difference to the boiling point. With this we can ensure, the
working fluid does not start to condensate at the intermittent cooler.
values.

.. literalinclude:: /../tutorial/advanced/stepwise.py
:language: python
Expand Down Expand Up @@ -439,8 +442,9 @@ The changes we want to apply can be summarized as follows:

- All heat exchangers should be calculated based on their heat transfer
coefficient with a characteristic for correction of that value depending
on the change of mass flow (:code:`kA_char`). Therefore, terminal temperature
value specifications need to be added to the design parameters. Also, the
on the change of mass flow (:code:`kA_char` and :code:`UA_cecchinato` for the
condenser). Therefore, pinch temperature difference and terminal temperature
difference value specifications need to be design parameters. Also, the
temperature at connection 14 cannot be specified anymore, since it will be a
result of the intermittent cooler's characteristics.
- Pumps and compressors will have a characteristic function for their
Expand All @@ -454,7 +458,8 @@ On top of that, for the evaporator the characteristic function of the heat
transfer coefficient should follow different data than the default
characteristic. The name of that line is 'EVAPORATING FLUID' for the cold
side. The default line 'DEFAULT' will be kept for the hot side. These lines
are available in the :ref:`tespy.data <data_label>` module.
are available in the :ref:`tespy.data <data_label>` module. For the condenser
the specifications are inspired from this paper :cite:`cecchinato2010`.

.. attention::

Expand Down
23 changes: 10 additions & 13 deletions docs/community/community.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,14 @@ about using the software, you are invited to start a discussion there.

Monthly online meeting
======================
There is a monthly online meeting for all TESPy users and developers. You are
invited to join us on **every 3rd Monday of a month at 17:00 CE(S)T** for a
casual get together. The intent of this meeting is to establish a more active
and well connected network of TESPy users and developers. You can bring your
challenges, questions and ideas and we will discuss them together or plan
potential follow-up meetings.
There are online QA meetings every month, please check the
`oemof calendar <https://oemof.org/calendar/>`__ for date, time and meeting
link. You are invited to join us with your questions, issues and suggestions!
Please also check the announcement banner at the top of the documentation
pages, you will get updates on rescheduled date/time.

If you are interested, you can simply join the meeting at
https://meet.jit.si/tespy_user_meeting. We are looking forward to seeing you!

.. attention::

Please also check the announcement banner at the top of the documentation
pages, you will get updates on rescheduled date/time.
In-person meetings
==================
Furthermore, there are in-person community meetings. These are held once or
twice a year. To learn about upcoming meetings, follow the blog over at
`<https://oemof.org/>`__ for the announcements.
Loading