# Air in a tank

A spherical metal tank stores hot air, initially at 200°C and 350 psi.
The tank is made out of stainless steel, with specific heat capacity 471 J/kg-K and density 7902 kg/m$^3$. The tank wall is 0.35 mm thick and initially at 20°C; the inner radius is 10 cm and the outer wall is insulated. 

Treat the air in the tank as an ideal gas and the stainless steel tank wall as an incompressible substance.

Eventually the air reaches thermal equilibrium with the tank wall. Find the final temperature of the air and the tank, and the final pressure of the air.


```python
import numpy as np
from scipy import optimize
import cantera as ct

from pint import UnitRegistry
ureg = UnitRegistry()
Q_ = ureg.Quantity
```


```python
# input data
tank_specific_heat = Q_(471, 'J/(kg*K)')
tank_density = Q_(7902, 'kg/m^3')
tank_radius = Q_(10, 'cm')
tank_thickness = Q_(0.35, 'mm')

tank_temp1 = Q_(20, 'degC')

air_temp1 = Q_(200, 'degC')
air_pres1 = Q_(350, 'psi')

# use an ideal gas mixture to represent air
air1 = ct.Solution('air.cti')
air1.TPX = (
    air_temp1.to('K').magnitude, 
    air_pres1.to('Pa').magnitude, 
    'O2:1.0, N2:3.76'
    )
```


```python
air_volume = 4.0 * np.pi * tank_radius**3 / 3.0
air_mass = air_volume / Q_(air1.v, 'm^3/kg')

tank_volume = (4. * np.pi / 3.) * (
    (tank_radius + tank_thickness)**3 - tank_radius**3
    )
tank_mass = tank_volume * tank_density
```

During the equilibration process, the specific volume of the air does not change:
\begin{equation}
v_{a,2} = v_{a,1} \;.
\end{equation}

We can perform an energy balance on the system that contains both the tank and air:

$$
0 = m_t ( u_{t,2} - u_{t,1} ) + m_a ( u_{a,2} - u_{a,1} ) \\
0 = m_t c_{\text{steel}} (T_{t,2} - T_{t,1}) - m_a ( u_{a,2} - u_{a,1} )
$$

and we know that at equilibrium the temperatures are the same: $T_{t,2} = T_{a,2}$.

So, we fundamentally have **one** unknown, the final temperature, which we can solve using the final version of the energy balance:


```python
def tank_energy(T2, air_mass, air1, tank_mass, tank_specific_heat, tank_temp1):
    '''Returns value of energy balance equation based on input T2
    
    This equation should return zero, if the correct T2 is input.
    '''
    # the temperatures are the same
    tank_temp2 = Q_(T2, 'K')
    air_temp2 = Q_(T2, 'K')
    
    air_specific_volume2 = Q_(air1.v, 'm^3/kg')
    air_density2 = 1.0 / air_specific_volume2

    air2 = ct.Solution('air.cti')
    air2.TDX = (
        air_temp2.to('K').magnitude,
        air_density2.to('kg/m^3').magnitude,
        'O2:1.0, N2:3.76'
        )
    
    return (
        tank_mass * tank_specific_heat * (tank_temp2 - tank_temp1) +
        air_mass * (Q_(air2.u, 'J/kg') - Q_(air1.u, 'J/kg'))
        ).to('J').magnitude
```


```python
# find the root of the equation, with an initial guess of 300 K
sol = optimize.root(
    tank_energy, 300.0, 
    args=(air_mass, air1, tank_mass, tank_specific_heat, tank_temp1)
    )

# the solution is the first element of the sol.x list
temp2 = Q_(sol.x[0], 'K')
print(f'Final temperature: {temp2.to("degC"): .2f}')

air2 = ct.Solution('air.cti')
air2.TDX = (
    temp2.to('K').magnitude,
    air1.density,
    'O2:1.0, N2:3.76'
    )
air_pres2 = Q_(air2.P, 'Pa')
print(f'Final air pressure: {air_pres2.to("psi"): .2f}')
```

    Final temperature: 64.83 degree_Celsius
    Final air pressure: 250.01 pound_force_per_square_inch


## Alternate solution

If we wanted, we could also solve this problem with a larger number of equations and unknowns, although as seen above this is not necessary. For example, we can treat $v_{a,2}$, $T_{a,2}$, $T_{t,2}$, and $u_{a,2}$ as the four unknowns, with the equations

$$
v_{a,2} = v_{a,1} \\
T_{a,2} = T_{t,2} \\
u_{a,2} = f \left( T_{a,2}, v_{a,2} \right)
$$

being added to the one used above.


```python
def tank_energy2(x, air_mass, air1, tank_mass, tank_specific_heat, tank_temp1):
    '''Returns value of energy balance equation based on input T2
    
    This equation should return zero, if the correct values are input.
    
    x: T_t2, v_a2, T_a2, u_a2
    '''
    tank_temp2 = Q_(x[0], 'K')
    air_specific_volume2 = Q_(x[1], 'm^3/kg')
    air_temp2 = Q_(x[2], 'K')
    air_internal_energy2 = Q_(x[3], 'J/kg')
    
    air_density2 = 1.0 / air_specific_volume2

    air2 = ct.Solution('air.cti')
    air2.TDX = (
        air_temp2.to('K').magnitude,
        air_density2.to('kg/m^3').magnitude,
        'O2:1.0, N2:3.76'
        )
    
    return [
        (tank_mass * tank_specific_heat * (tank_temp2 - tank_temp1) +
         air_mass * (Q_(air2.u, 'J/kg') - Q_(air1.u, 'J/kg'))
         ).to('J').magnitude,
        (air_specific_volume2 - Q_(air1.v, 'm^3/kg')).to('m^3/kg').magnitude,
        (air_temp2 - tank_temp2).to('K').magnitude,
        (air_internal_energy2 - Q_(air2.u, 'J/kg')).to('J/kg').magnitude
        ]

# now we have to give guesses for all four variables
sol = optimize.root(
    tank_energy2, [300.0, air1.v, 300.0, air1.u], 
    args=(air_mass, air1, tank_mass, tank_specific_heat, tank_temp1)
    )

# the solution is the first element of the sol.x list
tank_temp2 = Q_(sol.x[0], 'K')
print(f'Final temperature of tank: {tank_temp2.to("degC"): .2f}')
air_temp2 = Q_(sol.x[2], 'K')
print(f'Final temperature of air: {air_temp2.to("degC"): .2f}')

air2 = ct.Solution('air.cti')
air2.TDX = (
    air_temp2.to('K').magnitude,
    1.0 / sol.x[1],
    'O2:1.0, N2:3.76'
    )
air_pres2 = Q_(air2.P, 'Pa')
print(f'Final air pressure: {air_pres2.to("psi"): .2f}')
```

    Final temperature of tank: 64.83 degree_Celsius
    Final temperature of air: 64.83 degree_Celsius
    Final air pressure: 250.01 pound_force_per_square_inch


As expected, we get the same answer as before, without any real benefits. In fact, this is a bit more work, since we had to specify four guess values instead of one.

1250c912763b984834664455453db930f3c94d6c
ipynb
Jupyter Notebook
book/content/first-law/air-tank.ipynb
kyleniemeyer/computational-thermo
3f0d1d4a6d4247ac3bf3b74867411f2090c70cbd
CC-BY-4.0 BSD-3-Clause
2020-04-01T05:52:06.000Z
2022-03-27T20:25:59.000Z
book/content/first-law/air-tank.ipynb
kyleniemeyer/computational-thermo
3f0d1d4a6d4247ac3bf3b74867411f2090c70cbd
CC-BY-4.0 BSD-3-Clause
2020-04-28T04:02:05.000Z
2020-04-29T17:49:52.000Z
book/content/first-law/air-tank.ipynb
kyleniemeyer/computational-thermo
3f0d1d4a6d4247ac3bf3b74867411f2090c70cbd
CC-BY-4.0 BSD-3-Clause
2020-04-03T14:52:24.000Z
2022-03-29T02:29:43.000Z
Qwen/Qwen-72B
1. YES
2. YES