<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Tutorial
This tutorial will guide you in the basic use of ThermoState. The ThermoState
package is designed to ease the evaluation of thermodynamic properties for
common substances used in Mechanical Engineering courses. Rather than looking up
the information in a table and interpolating, we can input properties for the
states directly, and all unknown values are automatically calculated.
ThermoState uses CoolProp and Pint to enable easy property evaluation in any unit system. The first thing we need to do is import the parts of ThermoState that we will use. This adds them to the set of local variables
Step1:  Pint and Units
Now that the interface has been imported, we can create some properties. For instance, let's say we're given the pressure and temperature properties for water, and asked to determine the specific volume. First, let's create variables that set the pressure and temperature. We will use the Pint Quantity function, which we have called Q_. The syntax for the Q_ function is Q_(value, 'units').
Step2:  We can use whatever units we'd like, Pint supports a wide variety of units.
Step3:  Another way to specify the units is to use the units class that we imported. This class has a number of attributes (text following a period) that can be used to create a quantity with units by multiplying a number with the unit. 
```python
units.degR
^^^^
This is the attribute
```
Let's set the temperature now. The available units of temperature are degF (fahrenheit), degR (rankine), degC (celsius), and K (kelvin).
Step4:  The two ways of creating the units are equivalent. The following cell should print True to demonstrate this.
Step5:  Note the convention we are using here
Step6:  Now we need to create the State and assign values for the properties. Properties of the state are set as arguments to the State class, and they must always be set in pairs, we cannot set a single property at a time. The syntax is
st = State(substance, property_1=value, property_2=value)
<div class="alert alert-warning">
**Warning**
Remember that two independent and intensive properties are required to set the state!
</div>
To demonstrate, we will set the T and p properties of the state and set them equal to the temperature and pressure we defined above. Note that the capitalization of the properties is important! The p is lower case while the T is upper case (lower case t means time).
Step7:  Note again the convention we are using here
Step8:  <div class="alert alert-warning">
**Warning**
To avoid confusing yourself, name your variables to something useful. For instance, use the property symbol, then an underscore, then the state number, as in `p_1 = Q_(1.0, 'atm')` to indicate the pressure at state 1. In my notes and solutions, this is the convention that I will follow, and I will use `st_#` to indicate a `State` (e.g., `st_1` is state 1, `st_2` is state 2, and so forth).
</div>
In theory, any two pairs of independent properties can be used to set the state. In reality, the pairs of properties available to set the state is slightly limited because of the way the equation of state is written. The available pairs of properties are
Tp
Ts
Tv
Tx
pu
ps
pv
ph
px
uv
sv
hs
hv
The reverse of any of these pairs is also possible and totally equivalent.
By setting two properties in this way, the State class will calculate all the other properties we might be interested in. We can access the value of any property by getting the attribute for that property. The available properties are T (temperature), p (pressure), v (mass-specific volume), u (mass-specific internal energy), h (mass-specific enthalpy), s (mass-specific entropy), x (quality), cp (specific heat at constant pressure), cv (specific heat at constant volume), and phase (the phase of this state). The syntax is
State.property
or
st_1.T  # Gets the temperature
st_1.p  # Gets the pressure
st_1.v  # Gets the specific volume
st_1.u  # Gets the internal energy
st_1.h  # Gets the enthalpy
st_1.s  # Gets the entropy
st_1.x  # Gets the quality
st_1.cp  # Gets the specific heat at constant pressure
st_1.cv  # Gets the specific heat at constant volume
st_1.phase  # Gets the phase at this state
<div class="alert alert-info">
**Note**
Capitalization is important! The temperature has upper case `T`, while the other properties are lower case to indicate that they are mass-specific quantities.
</div>
Step9:  In this case, the value for the quality is the special Python value None. This is because at 400 K and 101325 Pa, the state of water is a superheated vapor and the quality is undefined except in the vapor dome. To access states in the vapor dome, we cannot use T and p as independent properties, because they are not independent inside the vapor dome. Instead, we have to use the pairs involving the other properties (possibly including the quality) to set the state. When we define the quality, the units are dimensionless or percent. For instance
Step10:  In addition, whether you use the 'dimensionless' "units" for the quality as above, or use the 'percent' "units", the result is exactly equivalent. The next cell should print True to the screen to demonstrate this.
Step11:  From these results, we can see that the units of the units of the properties stored in the State are always SI units - Kelvin, Pascal, m<sup>3</sup>/kg, J/kg, and J/(kg-Kelvin). We can use the to function to convert the units to anything we want, provided the dimensions are compatible. The syntax is State.property.to('units').
Step12:  <div class="alert alert-info">
**Note**
The values are always converted in the `State` to SI units, no matter what the input units are. Therefore, if you want EE units as an output, you have to convert.
</div>
If we try to convert to a unit with incompatible dimensions, Pint will raise a DimenstionalityError exception.
<div class="alert alert-warning">
**Warning**
If you get a `DimensionalityError`, examine your conversion very closely. The error message will tell you why the dimensions are incompatible!
</div>
Step13:  Here we have tried to convert from 'kelvin' to 'joule' and the error message which is the last line says
DimensionalityError
Step14:  Default Units
Default units can be set either through the set_default_units("units") function, when creating a state, or after a state has been set to change the Units of the state. Units can be set either with "SI" or "EE" for the corresponding sets of units.
Step15:  Other Common Errors
Other common errors generated from using ThermoState will raise StateErrors. These errors may be due to
Not specifying enough properties to fix the state, or specifying too many properties to fix the state
Specifying a pair of properties that are not independent at the desired condtions
Entering an unsupported pair of property inputs (the currently unsupported pairs are Tu, Th, and us, due to limitations in CoolProp)
Specifying a Quantity with incorrect dimensions for the property input
An example demonstrating #4 from above
Step16:  Summary
In summary, we need to use two (2) independent and intensive properties to fix the state of any simple compressible system. We need to define these quantities with units using Pint, and then use them to set the conditions of a State. Then, we can access the other properties of the State by using the attributes.
<ASSISTANT_TASK:>
Python Code:
from thermostate import State, Q_, units, set_default_units
Explanation: Tutorial
This tutorial will guide you in the basic use of ThermoState. The ThermoState
package is designed to ease the evaluation of thermodynamic properties for
common substances used in Mechanical Engineering courses. Rather than looking up
the information in a table and interpolating, we can input properties for the
states directly, and all unknown values are automatically calculated.
ThermoState uses CoolProp and Pint to enable easy property evaluation in any unit system. The first thing we need to do is import the parts of ThermoState that we will use. This adds them to the set of local variables
End of explanation
p_1 = Q_(101325, 'Pa')
Explanation: Pint and Units
Now that the interface has been imported, we can create some properties. For instance, let's say we're given the pressure and temperature properties for water, and asked to determine the specific volume. First, let's create variables that set the pressure and temperature. We will use the Pint Quantity function, which we have called Q_. The syntax for the Q_ function is Q_(value, 'units').
End of explanation
p_1 = Q_(1.01325, 'bar')
p_1 = Q_(14.7, 'psi')
p_1 = Q_(1.0, 'atm')
Explanation: We can use whatever units we'd like, Pint supports a wide variety of units.
End of explanation
T_1 = 460*units.degR
T_1 = 25*units.degC
T_1 = 75*units.degF
T_1 = 400*units.K
Explanation: Another way to specify the units is to use the units class that we imported. This class has a number of attributes (text following a period) that can be used to create a quantity with units by multiplying a number with the unit. 
```python
units.degR
^^^^
This is the attribute
```
Let's set the temperature now. The available units of temperature are degF (fahrenheit), degR (rankine), degC (celsius), and K (kelvin).
End of explanation
Q_(101325, 'Pa') == 1.0*units.atm
Explanation: The two ways of creating the units are equivalent. The following cell should print True to demonstrate this.
End of explanation
substance = 'water'
Explanation: Note the convention we are using here: the variables are named with the property, followed by an underscore, then the number of the state. In this case, we are setting properties for state 1, hence T_1 and p_1.
ThermoState
Now that we have defined two properties with units, let's define a state. First, we create a variable to hold the State and tell ThermoState what substance we want to use with that state. The available substances are:
water
air
R134a
R22
propane
ammonia
isobutane
carbondioxide
oxygen
nitrogen
Note that the name of the substance is case-insensitive (it doesn't matter whether you use lower case or upper case). It is often easiest to set the name of the substance in a variable, like:
End of explanation
print('T = {}, p = {}'.format(T_1, p_1))
st_1 = State(substance, T=T_1, p=p_1)
Explanation: Now we need to create the State and assign values for the properties. Properties of the state are set as arguments to the State class, and they must always be set in pairs, we cannot set a single property at a time. The syntax is
st = State(substance, property_1=value, property_2=value)
<div class="alert alert-warning">
**Warning**
Remember that two independent and intensive properties are required to set the state!
</div>
To demonstrate, we will set the T and p properties of the state and set them equal to the temperature and pressure we defined above. Note that the capitalization of the properties is important! The p is lower case while the T is upper case (lower case t means time).
End of explanation
luke = Q_(1.0, 'atm')
leia = Q_(400.0, 'K')
print('Does luke equal p_1?', luke == p_1)
print('Does leia equal T_1?', leia == T_1)
st_starwars = State(substance, T=leia, p=luke)
print('Does st_starwars equal st_1?', st_starwars == st_1)
Explanation: Note again the convention we are using here: The state is labeled by st, then an underscore, then the number of the state.
The variables that we use on the right side of the equal sign in the State function can be named anything we want. For instance, the following code is exactly equivalent to what we did before.
End of explanation
print('T_1 = {}'.format(st_1.T))
print('p_1 = {}'.format(st_1.p))
print('v_1 = {}'.format(st_1.v))
print('u_1 = {}'.format(st_1.u))
print('h_1 = {}'.format(st_1.h))
print('s_1 = {}'.format(st_1.s))
print('x_1 = {}'.format(st_1.x))
print('cp_1 = {}'.format(st_1.cp))
print('cv_1 = {}'.format(st_1.cv))
print('phase_1 = {}'.format(st_1.phase))
Explanation: <div class="alert alert-warning">
**Warning**
To avoid confusing yourself, name your variables to something useful. For instance, use the property symbol, then an underscore, then the state number, as in `p_1 = Q_(1.0, 'atm')` to indicate the pressure at state 1. In my notes and solutions, this is the convention that I will follow, and I will use `st_#` to indicate a `State` (e.g., `st_1` is state 1, `st_2` is state 2, and so forth).
</div>
In theory, any two pairs of independent properties can be used to set the state. In reality, the pairs of properties available to set the state is slightly limited because of the way the equation of state is written. The available pairs of properties are
Tp
Ts
Tv
Tx
pu
ps
pv
ph
px
uv
sv
hs
hv
The reverse of any of these pairs is also possible and totally equivalent.
By setting two properties in this way, the State class will calculate all the other properties we might be interested in. We can access the value of any property by getting the attribute for that property. The available properties are T (temperature), p (pressure), v (mass-specific volume), u (mass-specific internal energy), h (mass-specific enthalpy), s (mass-specific entropy), x (quality), cp (specific heat at constant pressure), cv (specific heat at constant volume), and phase (the phase of this state). The syntax is
State.property
or
st_1.T  # Gets the temperature
st_1.p  # Gets the pressure
st_1.v  # Gets the specific volume
st_1.u  # Gets the internal energy
st_1.h  # Gets the enthalpy
st_1.s  # Gets the entropy
st_1.x  # Gets the quality
st_1.cp  # Gets the specific heat at constant pressure
st_1.cv  # Gets the specific heat at constant volume
st_1.phase  # Gets the phase at this state
<div class="alert alert-info">
**Note**
Capitalization is important! The temperature has upper case `T`, while the other properties are lower case to indicate that they are mass-specific quantities.
</div>
End of explanation
T_2 = Q_(100.0, 'degC')
x_2 = Q_(0.1, 'dimensionless')
st_2 = State('water', T=T_2, x=x_2)
print('T_2 = {}'.format(st_2.T))
print('p_2 = {}'.format(st_2.p))
print('v_2 = {}'.format(st_2.v))
print('u_2 = {}'.format(st_2.u))
print('h_2 = {}'.format(st_2.h))
print('s_2 = {}'.format(st_2.s))
print('x_2 = {}'.format(st_2.x))
Explanation: In this case, the value for the quality is the special Python value None. This is because at 400 K and 101325 Pa, the state of water is a superheated vapor and the quality is undefined except in the vapor dome. To access states in the vapor dome, we cannot use T and p as independent properties, because they are not independent inside the vapor dome. Instead, we have to use the pairs involving the other properties (possibly including the quality) to set the state. When we define the quality, the units are dimensionless or percent. For instance:
End of explanation
x_2 == Q_(10.0, 'percent')
Explanation: In addition, whether you use the 'dimensionless' "units" for the quality as above, or use the 'percent' "units", the result is exactly equivalent. The next cell should print True to the screen to demonstrate this.
End of explanation
print(st_2.T.to('degF'))
print(st_2.s.to('BTU/(lb*degR)'))
Explanation: From these results, we can see that the units of the units of the properties stored in the State are always SI units - Kelvin, Pascal, m<sup>3</sup>/kg, J/kg, and J/(kg-Kelvin). We can use the to function to convert the units to anything we want, provided the dimensions are compatible. The syntax is State.property.to('units').
End of explanation
print(st_2.T.to('joule'))
Explanation: <div class="alert alert-info">
**Note**
The values are always converted in the `State` to SI units, no matter what the input units are. Therefore, if you want EE units as an output, you have to convert.
</div>
If we try to convert to a unit with incompatible dimensions, Pint will raise a DimenstionalityError exception.
<div class="alert alert-warning">
**Warning**
If you get a `DimensionalityError`, examine your conversion very closely. The error message will tell you why the dimensions are incompatible!
</div>
End of explanation
Q_(1000.0, 'joule').to('watt')## Other Common Errors
Explanation: Here we have tried to convert from 'kelvin' to 'joule' and the error message which is the last line says
DimensionalityError: Cannot convert from 'kelvin' ([temperature]) to 'joule' ([length] ** 2 * [mass] / [time] ** 2)
The dimensions of a temperature are, well, temperature. The formula for energy (Joule) is $mad$ (mass times acceleration times distance), and in terms of dimensions, $ML/T^2L = L^2M/T^2$ (where in dimensions, capital $T$ is time). Clearly, these dimensions are incompatible. A more subtle case might be trying to convert energy to power* (again, not allowed):
End of explanation
set_default_units("EE")
st_3 = State("water", T = Q_(100, 'degC'), p = Q_(1.0, 'atm'))
print(st_3.s)
st_4 = State("water", T = Q_(100, 'degC'), p = Q_(1.0, 'atm'), units = "SI")
print(st_4.s)
st_4.units = None
print(st_4.s)
set_default_units(None)
Explanation: Default Units
Default units can be set either through the set_default_units("units") function, when creating a state, or after a state has been set to change the Units of the state. Units can be set either with "SI" or "EE" for the corresponding sets of units.
End of explanation
State('water', v=Q_(1000.0, 'degC'), p=Q_(1.0, 'bar'))
Explanation: Other Common Errors
Other common errors generated from using ThermoState will raise StateErrors. These errors may be due to
Not specifying enough properties to fix the state, or specifying too many properties to fix the state
Specifying a pair of properties that are not independent at the desired condtions
Entering an unsupported pair of property inputs (the currently unsupported pairs are Tu, Th, and us, due to limitations in CoolProp)
Specifying a Quantity with incorrect dimensions for the property input
An example demonstrating #4 from above:
End of explanation
h_5 = Q_(2000.0, 'kJ/kg')
s_5 = Q_(3.10, 'kJ/(kg*K)')
st_5 = State('water', h=h_5, s=s_5)
print('T_5 = {}'.format(st_5.T))
print('p_5 = {}'.format(st_5.p))
print('v_5 = {}'.format(st_5.v))
print('u_5 = {}'.format(st_5.u))
print('h_5 = {}'.format(st_5.h))
print('s_5 = {}'.format(st_5.s))
print('x_5 = {}'.format(st_5.x))
Explanation: Summary
In summary, we need to use two (2) independent and intensive properties to fix the state of any simple compressible system. We need to define these quantities with units using Pint, and then use them to set the conditions of a State. Then, we can access the other properties of the State by using the attributes.
End of explanation
<END_TASK>