Octopus was designed primarily to model nitrous oxide (N2O) flow through a rocket injector. To start working with the module, a octopus.main.Fluid must be initiated. Throughout this example we will be using nitrous oxide, with a Helmholz EOS, and IPA, using thermo’s EOS as it is a better-behaved fluid.

>>> from octopus import Fluid
>>> nitrous_oxide = Fluid('N2O',method='helmholz')
>>> isopropanol = Fluid('isopropanol',P=18e5,T=293)

If using the helmholz EOS, P and T may not be specified (they are not used, as they are thermo-inherited properties, however the method parameter must be specified as “helmholz” as “thermo” is the default. Currently, “helmholz” is only available for N2O, but it will not throw an error if you add your own data for another fluid.

Next, we can define a octopus.main.PropertySource object to represent the initial properties of nitrous_oxide. A PropertySource is simply an object that has p and T properties (note: lowercase p), which the octopus.main.Manifold class uses to define its inlet conditions. The octopus.main.Fluid object itself is not used, as its properties change throughout the system, yet the same object is passed to all classes.

>>> from octopus import PropertySource, Manifold
>>> nitrous_manifold = Manifold(nitrous_oxide,PropertySource(p=18e5,T=250))
>>> ipa_manifold = Manifold(isopropanol,PropertySource(p=18e5,T=293))

Next we can define :class:`octopus.main.Orifice`s that draw fluid from the manifolds defined above, and an Element to connect the two.

>>> from octopus import Orifice,Element
>>> nitrous_orifice = Orifice(nitrous_manifold,L=1e-2,D=2e-3,orifice_type=Orifice.STRAIGHT)
>>> ipa_orifice = Orifice(ipa_manifold,L=1e-2,D=1e-3,orifice_type=Orifice.STRAIGHT)
>>> n2o_ipa_element = Element([nitrous_orifice],[ipa_orifice]) # in progress

If we simply want to use the EOS from the Fluid class, there are many methods available if method='helmholz' is set. The next example will show how to get the saturation properties at 250K. We assume an all- liquid state, and never use the bare property methods (Fluid.p()) as they may return invalid results.

To get one of p,chi,h,s as a function of [rho,T]:

>>> T = 250
>>> rho = nitrous.rho_l(T)
>>> properties = nitrous.get_properties(rho,T)
>>> p = properties['p']

To access a property, we can use the properties dictionary to return it using its name as a key. In order to compute rho or T, we need a non-linear solver:

>>> from scipy.optimize import least_squares

To get [rho,T] as a funtion of two of p,chi,h,s (see octopus.main.Fluid.fun_ps()):

>>> p=18e5          # pressure we want
>>> chi=0           # vapour fraction we want (all liquid)
>>> x0 = [800,250]  # initial values of rho and T near to the answer
>>> u = ['p','chi'] # names of dependent variables we know
>>> y = [p,chi]     # values of dependent variables we know (same order)
>>> properties = least_squares(nitrous.fun_ps,x0,args=(u,y))
>>> rho,T = properties.x

The above code is used in octopus.main.Orifice.m_dot_HEM() to calculate the inital and final conditions, and hence that is a good example to look to for further context.


To get density and vapour fraction as a function of T and one of p,chi,h,s, i.e. average density and vapour fraction in a 5MPa tank at ambient temperature:

>>> T = 293         # temperature we want
>>> p = 50e5      # vapour fraction we want
>>> x0 = [800,T]    # guess of density, and known temperature
>>> u = ['T','p'] # T and chi are known
>>> y = [T,p]
>>> properties = least_squares(nitrous.fun_ps,x0,args=(u,y))
>>> rho = properties.x[0]
>>> chi = nitrous.get_properties(rho,T)['p']