| 1 |
REQUIRE "thermodynamics.a4l"; |
| 2 |
REQUIRE "stream_holdup.a4l"; |
| 3 |
|
| 4 |
MODEL clfr_base; |
| 5 |
(* no variables *) |
| 6 |
METHODS |
| 7 |
METHOD default_self; |
| 8 |
(* do nothing *) |
| 9 |
END default_self; |
| 10 |
END clfr_base; |
| 11 |
|
| 12 |
ATOM mass_energy REFINES solver_var |
| 13 |
DIMENSION L^2/T^2 |
| 14 |
DEFAULT 2000 {kJ/kg}; |
| 15 |
lower_bound := -1e50{kJ/kg}; |
| 16 |
upper_bound := 1e50{kJ/kg}; |
| 17 |
nominal := 1000.0{kJ/kg}; |
| 18 |
END mass_energy; |
| 19 |
|
| 20 |
ATOM mass_volume REFINES solver_var |
| 21 |
DIMENSION L^3/M |
| 22 |
DEFAULT 0.001 {m^3/kg}; |
| 23 |
lower_bound := 0 {m^3/kg}; |
| 24 |
upper_bound := 1e50{m^3/kg}; |
| 25 |
nominal := 0.001 {m^3/kg}; |
| 26 |
END mass_volume; |
| 27 |
|
| 28 |
ATOM mass_entropy REFINES solver_var |
| 29 |
DIMENSION L^2/T^2/TMP |
| 30 |
DEFAULT 2000 {kJ/kg/K}; |
| 31 |
lower_bound := -1e50{kJ/kg/K}; |
| 32 |
upper_bound := 1e50{kJ/kg/K}; |
| 33 |
nominal := 1000.0{kJ/kg/K}; |
| 34 |
END mass_entropy; |
| 35 |
|
| 36 |
(*-------------------- |
| 37 |
Model of two-phase steam state |
| 38 |
|
| 39 |
We will be modelling with the 'homogeneous' two-phase model, which |
| 40 |
assumes that vapor and liquid phases are always in equilibrium. |
| 41 |
*) |
| 42 |
MODEL steam_state REFINES clfr_base; |
| 43 |
(* we're only dealing with water here but we add a trace of methane because |
| 44 |
otherwise the thermo properties don't converge |
| 45 |
*) |
| 46 |
cd IS_A components_data(['water','methane'],'water'); |
| 47 |
|
| 48 |
(* our stream is vapour-and-liquid *) |
| 49 |
pd IS_A phases_data('VL','Pitzer_vapor_mixture','UNIFAC_liquid_mixture','none'); |
| 50 |
|
| 51 |
(* this value determines whether constant relative volatility |
| 52 |
(FALSE) or full equilibrium models (TRUE) are used. *) |
| 53 |
equilibrated IS_A boolean; |
| 54 |
|
| 55 |
(* set up the thermodynamics object, ripped from stream_holdup.a4l *) |
| 56 |
phases ALIASES pd.phases; |
| 57 |
FOR j IN phases CREATE |
| 58 |
smt[j] IS_A select_mixture_type(cd, pd.phase_type[j]); |
| 59 |
END FOR; |
| 60 |
|
| 61 |
FOR j IN phases CREATE |
| 62 |
phase[j] ALIASES smt[j].phase; |
| 63 |
END FOR; |
| 64 |
|
| 65 |
thermo IS_A thermodynamics(cd, pd, phase, equilibrated); |
| 66 |
|
| 67 |
(* the molar mass of water is 18.015 kg/kg_mole *) |
| 68 |
M IS_A molar_weight_constant; |
| 69 |
v IS_A mass_volume; |
| 70 |
h IS_A mass_energy; |
| 71 |
g IS_A mass_energy; |
| 72 |
p IS_A pressure; |
| 73 |
T IS_A temperature; |
| 74 |
rho IS_A mass_density; |
| 75 |
|
| 76 |
u IS_A mass_energy; |
| 77 |
s IS_A mass_entropy; |
| 78 |
x IS_A fraction; |
| 79 |
|
| 80 |
(* link up the local properties with those inside the thermodynamics model *) |
| 81 |
M, cd.data['water'].mw ARE_THE_SAME; |
| 82 |
M * v = thermo.V; |
| 83 |
M * h = thermo.H - cd.data['water'].H0; |
| 84 |
M * g = thermo.G; (* subtract a correction factor here?? *) |
| 85 |
|
| 86 |
p, thermo.P ARE_THE_SAME; |
| 87 |
T, thermo.T ARE_THE_SAME; |
| 88 |
x, thermo.phase_fraction['vapor'] ARE_THE_SAME; (* can't set this to FIXED, causes struct singularity *) |
| 89 |
|
| 90 |
(* equations allowing calculation of s and u *) |
| 91 |
h = u + p*v; |
| 92 |
h = g + T*(s + cd.data['water'].S0); (* correction factor?? *) |
| 93 |
|
| 94 |
(* density is the reciprocal of specific volume *) |
| 95 |
v * rho = 1; |
| 96 |
|
| 97 |
METHODS |
| 98 |
|
| 99 |
METHOD default_self; |
| 100 |
RUN ClearAll; |
| 101 |
RUN specify; |
| 102 |
RUN values; |
| 103 |
END default_self; |
| 104 |
|
| 105 |
METHOD specify; |
| 106 |
(* this is a 'mode' variable, not a solver_var, so we set it here: *) |
| 107 |
equilibrated := FALSE; |
| 108 |
|
| 109 |
(* internal thermodynamics stuff that needs to be fixed *) |
| 110 |
FIX thermo.phase['vapor'].alpha['water']; |
| 111 |
FIX thermo.alpha_bar['vapor']; |
| 112 |
FIX thermo.y['water']; |
| 113 |
FIX thermo.y['methane']; |
| 114 |
|
| 115 |
(* unless overridden, steam_state will use p,T to define other properties *) |
| 116 |
FIX T; |
| 117 |
FIX rho; |
| 118 |
END specify; |
| 119 |
|
| 120 |
METHOD values; |
| 121 |
(* internal thermo stuff *) |
| 122 |
thermo.phase['vapor'].alpha['water'] := 1; |
| 123 |
thermo.alpha_bar['vapor'] := 1; |
| 124 |
thermo.y['water'] := 1.0; |
| 125 |
thermo.y['methane'] := 0.0; |
| 126 |
|
| 127 |
(* set some typical values for steam *) |
| 128 |
T := 290 {K}; |
| 129 |
rho := 997 {kg/m^3}; |
| 130 |
(* |
| 131 |
h := 4864 {kJ/kg_mole}; |
| 132 |
u := 4800 {kJ/kg_mole}; |
| 133 |
v := 0.2 {kg/m^3}; |
| 134 |
s := 7 {kJ/kg/K}; |
| 135 |
*) |
| 136 |
END values; |
| 137 |
|
| 138 |
END steam_state; |
| 139 |
|
| 140 |
(*------------------------ |
| 141 |
Steam Stream |
| 142 |
Simplified container for any (possibly two phase) water/steam stream. |
| 143 |
Is a extension of the the 'steam_state' type with the addition of a |
| 144 |
mass flow rate. |
| 145 |
*) |
| 146 |
MODEL steam_stream REFINES steam_state; |
| 147 |
mdot IS_A molar_rate; |
| 148 |
|
| 149 |
METHODS |
| 150 |
METHOD specify; |
| 151 |
(* |
| 152 |
This method exists to allow checking of completeness; in practise |
| 153 |
'specify' will be overridden by the model which uses stream_stream |
| 154 |
as one of its inputs or outputs. |
| 155 |
*) |
| 156 |
RUN steam_state.specify; |
| 157 |
FIX mdot; |
| 158 |
END specify; |
| 159 |
|
| 160 |
METHOD values; |
| 161 |
mdot := 1 {kg/s}; |
| 162 |
END values; |
| 163 |
|
| 164 |
END steam_stream; |
| 165 |
|
| 166 |
(*------------------------ |
| 167 |
Steam equipment |
| 168 |
Single-input, single-output steam component. |
| 169 |
*) |
| 170 |
MODEL steam_equipment( |
| 171 |
in WILL_BE steam_stream; |
| 172 |
out WILL_BE steam_stream; |
| 173 |
); |
| 174 |
|
| 175 |
END steam_equipment; |