forked from modelica/ModelicaStandardLibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
package.mo
8533 lines (7747 loc) · 344 KB
/
package.mo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
within Modelica;
package Media "Library of media property models"
extends Modelica.Icons.Package;
import Modelica.Units.SI;
import Cv = Modelica.Units.Conversions;
package UsersGuide "User's Guide of Media Library"
extends Modelica.Icons.Information;
package MediumUsage "Medium usage"
extends Modelica.Icons.Information;
class BasicUsage "Basic usage"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<h4>Basic usage of medium model</h4>
<p>
Media models in Modelica.Media are provided by packages, inheriting from the
partial package Modelica.Media.Interfaces.PartialMedium. Every package defines:
</p>
<ul>
<li> Medium <strong>constants</strong> (such as the number of chemical substances,
molecular data, critical properties, etc.).</li>
<li> A BaseProperties <strong>model</strong>, to compute the basic thermodynamic
properties of the fluid;</li>
<li> <strong>setState_XXX</strong> functions to compute the thermodynamic state record from
different input arguments (such as density, temperature, and composition which
would be setState_dTX);</li>
<li> <strong>Functions</strong> to compute additional properties (such as saturation
properties, viscosity, thermal conductivity, etc.).</li>
</ul>
<p>
There are - as stated above - two different basic ways of using the Media library which
will be described in more details in the following section. One way is to use the model BaseProperties.
Every instance of BaseProperties for any medium model provides <strong>3+nXi
equations</strong> for the following <strong>5+nXi variables</strong> that are declared in
the medium model (nXi is the number of independent mass fractions, see
explanation below):
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Variable</strong></td>
<td><strong>Unit</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>T</td>
<td>K</td>
<td>temperature</td></tr>
<tr><td>p</td>
<td>Pa</td>
<td>absolute pressure</td></tr>
<tr><td>d</td>
<td>kg/m3</td>
<td>density</td></tr>
<tr><td>u</td>
<td>J/kg</td>
<td>specific internal energy</td></tr>
<tr><td>h</td>
<td>J/kg</td>
<td>specific enthalpy (h = u + p/d)</td></tr>
<tr><td>Xi[nXi]</td>
<td>kg/kg</td>
<td>independent mass fractions m_i/m</td></tr>
<tr><td>X[nX]</td>
<td>kg/kg</td>
<td>All mass fractions m_i/m. X is defined in BaseProperties by:<br>
X = <strong>if</strong> reducedX <strong>then</strong> vector([Xi; 1-<strong>sum</strong>(Xi)])
<strong>else</strong> Xi </td></tr>
</table>
<p>
<strong>Two</strong> variables out of p, d, h, or u, as well as the
<strong>mass fractions</strong> Xi are the <strong>independent</strong> variables and the
medium model basically provides equations to compute
the remaining variables, including the full mass fraction vector X
(more details to Xi and X are given further below).
</p>
<p>
In a component, the most basic usage of a medium model is as follows
</p>
<blockquote><pre>
<strong>model</strong> Pump
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
Medium.BaseProperties medium_a \"Medium properties at location a (e.g., port_a)\";
// Use medium variables (medium_a.p, medium_a.T, medium_a.h, ...)
...
<strong>end</strong> Pump;
</pre></blockquote>
<p>
The second way is to use the setState_XXX functions to compute the thermodynamic state
record from which all other thermodynamic state variables can be computed (see
<a href=\"modelica://Modelica.Media.UsersGuide.MediumDefinition.BasicDefinition\">
Basic definition of medium</a> for further details on ThermodynamicState). The setState_XXX functions
accept either X or Xi (see explanation below) and will decide internally which of these two compositions
is provided by the user. The four fundamental setState_XXX functions are provided in PartialMedium
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Function</strong></td>
<td><strong>Description</strong></td>
<td><strong>Short-form for<br>single component medium</strong></td></tr>
<tr><td>setState_dTX</td>
<td>computes ThermodynamicState from density, temperature, and composition X or Xi</td>
<td>setState_dT</td></tr>
<tr><td>setState_phX</td>
<td>computes ThermodynamicState from pressure, specific enthalpy, and composition X or Xi</td>
<td>setState_ph</td></tr>
<tr><td>setState_psX</td>
<td>computes ThermodynamicState from pressure, specific entropy, and composition X or Xi</td>
<td>setState_ps</td></tr>
<tr><td>setState_pTX</td>
<td>computes ThermodynamicState from pressure, temperature, and composition X or Xi</td>
<td>setState_pT</td></tr>
</table>
<p>
The simple example that explained the basic usage of BaseProperties would then become
</p>
<blockquote><pre>
<strong>model</strong> Pump
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
Medium.ThermodynamicState state_a \"Thermodynamic state record at location a (e.g., port_a)\";
// Compute medium variables from thermodynamic state record (pressure(state_a), temperature(state_a),
// specificEnthalpy(state_a), ...)
...
<strong>end</strong> Pump;
</pre></blockquote>
<p>
All media models are directly or indirectly a subpackage of package
Modelica.Media.Interfaces.PartialMedium. Therefore,
a medium model in a component should inherit from this
partial package. Via the annotation \"choicesAllMatching = true\" it
is defined that the tool should display a selection box with
all loaded packages that inherit from PartialMedium. An example
is given in the next figure:
</p>
<div>
<img src=\"modelica://Modelica/Resources/Images/Media/UsersGuide/MediumUsage/mediumMenu.png\" alt=\"medium selection menu\">
</div>
<p>
A selected medium model leads, e.g., to the following equation:
</p>
<blockquote><pre>
Pump pump(<strong>redeclare package</strong> Medium = Modelica.Media.Water.SimpleLiquidWater);
</pre></blockquote>
<p>
Usually, a medium model is associated with the variables of a
fluid connector. Therefore, equations have to be defined in a model
that relate the variables in the connector with the variables
in the medium model:
</p>
<blockquote><pre>
<strong>model</strong> Pump
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
Medium.BaseProperties medium_a \"Medium properties of port_a\";
// definition of the fluid port port_a
...
<strong>equation</strong>
medium.p = port_a.p;
medium.h = port_a.h;
medium.Xi = port_a.Xi;
...
<strong>end</strong> Pump;
</pre></blockquote>
in the case of using BaseProperties or
<blockquote><pre>
<strong>model</strong> Pump
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
Medium.ThermodynamicState state_a \"Thermodynamic state record of medium at port_a\";
// definition of the fluid port port_a
...
<strong>equation</strong>
state_a = Medium.setState_phX(port_a.p, port_a.h, port_a.Xi) // if port_a contains the variables
// p, h, and Xi
...
<strong>end</strong> Pump;
</pre></blockquote>
<p>
in the case of using ThermodynamicState.
</p>
<p>
If a component model shall treat both single and multiple
substance fluids, equations for the mass fractions have to be
present (above: medium.Xi = port_a.Xi) in the model. According
to the Modelica semantics, the equations of the mass fractions
are ignored, if the dimension of Xi is zero, i.e., for a single-component
medium. Note, by specific techniques sketched in section
\"Medium definition\", the independent variables in the medium model
need not to be the same as the variables in the connector and still
get the same efficiency, as if the same variables would be used.
</p>
<p>
If a fluid consists of a single
substance, <strong>nXi = 0</strong> and the vector of mass fractions Xi is not
present. If a fluid consists of nS substances,
the medium model may define the number of independent
mass fractions <strong>nXi</strong> to be <strong>nS</strong>, <strong>nS-1</strong>, or zero.
In all cases, balance equations for nXi substances have to be
given in the corresponding component (see discussion below).
Note, that if nXi = nS, the constraint \"sum(Xi)=1\" between the mass
fractions is <strong>not</strong> present in the model; in that case, it is necessary to
provide consistent start values for Xi such that sum(Xi) = 1.
</p>
<p>
The reason for this definition of Xi is that a fluid component library
can be implemented by using only the independent mass fractions Xi and
then via the medium it is defined how Xi is interpreted:
</p>
<ul>
<li> If Xi = nS, then the constraint equation sum(X) = 1 is neglected
during simulation. By making sure that the initial conditions of X
fulfill this constraint, it can usually be guaranteed that small
errors in sum(X) = 1 remain small although this constraint equation is
not explicitly used during the simulation. This approach is usually useful
if components of the mixture can become very small. If such a small
quantity is computed via the equation 1 - sum(X[1:nX-1]), there might
be large numerical errors and it is better to compute it via
the corresponding balance equation.</li>
<li> If Xi = nS-1, then the true independent mass fractions are used
in the fluid component and the last component of X is computed via
X[nX] = 1 - sum(Xi). This is useful for, e.g., MoistAir, where the
number of states should be as small as possible without introducing
numerical problems.</li>
<li> If Xi = 0, then the reference value of composition reference_X is
assumed. This case is useful to avoid composition states in all
the cases when the composition will always be constant, e.g., with
circuits having fixed composition sources.</li>
</ul>
<p>
The full vector of mass fractions <strong>X[nX]</strong> is computed in
PartialMedium.BaseProperties based on Xi, reference_X, and the information whether Xi = nS or nS-1. For single-substance media, nX = 0, so there's also no X vector. For multiple-substance media, nX = nS, and X always contains the full vector of mass fractions. In order to reduce confusion for the user of a fluid component library, \"Xi\" has the annotation \"HideResult=true\", meaning, that this variable is not shown in the plot window. Only X is shown in the plot window and this vector always contains all mass fractions.
</p>
</html>"));
end BasicUsage;
class BalanceVolume "Balance volume"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Fluid libraries usually have balance volume components with one fluid connector
port that fulfill the mass and energy balance and on a different grid components that
fulfill the momentum balance. A balance volume component, called junction
volume below, should be primarily implemented in the following way
(see also the implementation in
<a href=\"modelica://Modelica.Media.Examples.Utilities.PortVolume\">
Modelica.Media.Examples.Utilities.PortVolume</a>):
</p>
<blockquote><pre>
<strong>model</strong> JunctionVolume
<strong>import</strong> Modelica.Units.SI;
<strong>import</strong> Modelica.Media.Examples.Utilities.FluidPort_a;
<strong>parameter</strong> SI.Volume V = 1e-6 \"Fixed size of junction volume\";
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
FluidPort_a port(<strong>redeclare package</strong> Medium = Medium);
Medium.BaseProperties medium(preferredMediumStates = <strong>true</strong>);
SI.Energy U \"Internal energy of junction volume\";
SI.Mass M \"Mass of junction volume\";
SI.Mass MX[Medium.nXi] \"Independent substance masses of junction volume\";
<strong>equation</strong>
medium.p = port.p;
medium.h = port.h;
medium.Xi = port.Xi;
M = V*medium.d; // mass of JunctionVolume
MX = M*medium.Xi; // mass fractions in JunctionVolume
U = M*medium.u; // internal energy in JunctionVolume
<strong>der</strong>(M) = port.m_flow; // mass balance
<strong>der</strong>(MX) = port.mX_flow; // substance mass balance
<strong>der</strong>(U) = port.H_flow; // energy balance
<strong>end</strong> JunctionVolume;
</pre></blockquote>
<p>
Assume the Modelica.Media.Air.SimpleAir medium model is used with
the JunctionVolume model above. This medium model uses pressure p
and temperature T as independent variables. If the flag
\"preferredMediumStates\" is set to <strong>true</strong> in the declaration
of \"medium\", then the independent variables of this medium model
get the attribute \"stateSelect = StateSelect.prefer\", i.e., the
Modelica translator should use these variables as states, if this
is possible. Basically, this means that
constraints between the
potential states p,T and the potential states U,M are present.
A Modelica tool will therefore <strong>automatically</strong>
differentiate medium equations and will use the following
equations for code generation (note the equations related to X are
removed, because SimpleAir consists of a single substance only):
</p>
<blockquote><pre>
M = V*medium.d;
U = M*medium.u;
// balance equations
<strong>der</strong>(M) = port.m_flow;
<strong>der</strong>(U) = port.H_flow;
// abbreviations introduced to get simpler terms
p = medium.p;
T = medium.T;
d = medium.d;
u = medium.u;
h = medium.h;
// medium equations
d = fd(p,T);
h = fh(p,T);
u = h - p/d;
// equations derived <strong>automatically</strong> by a Modelica tool due to index reduction
<strong>der</strong>(U) = <strong>der</strong>(M)*u + M*<strong>der</strong>(u);
<strong>der</strong>(M) = V*<strong>der</strong>(d);
<strong>der</strong>(u) = <strong>der</strong>(h) - <strong>der</strong>(p)/d - p/<strong>der</strong>(d);
<strong>der</strong>(d) = <strong>der</strong>(fd,p)*<strong>der</strong>(p) + <strong>der</strong>(fd,T)*<strong>der</strong>(T);
<strong>der</strong>(h) = <strong>der</strong>(fh,p)*<strong>der</strong>(p) + <strong>der</strong>(fd,T)*<strong>der</strong>(T);
</pre></blockquote>
<p>
Note, that \"der(y,x)\" is an operator that characterizes
in the example above the partial derivative of y with respect to x
(this operator will be included in one of the next Modelica language
releases).
All media models in this library are written in such a way that
at least the partial derivatives of the medium variables with
respect to the independent variables are provided, either because
the equations are directly given (= symbolic differentiation is possible)
or because the derivative of the corresponding function (such as fd above)
is provided. A Modelica tool will transform the equations above
in differential equations with p and T as states, i.e., will
generate equations to compute <strong>der</strong>(p) and <strong>der</strong>(T) as function of p and T.
</p>
<p>
Note, when preferredMediumStates = <strong>false</strong>, no differentiation
will take place and the Modelica translator will use the variables
appearing differentiated as states, i.e., M and U. This has the
disadvantage that for many media non-linear systems of equations are
present to compute the intrinsic properties p, d, T, u, h from
M and U.
</p>
</html>"));
end BalanceVolume;
class ShortPipe "Short pipe"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Fluid libraries have components with two ports that store
neither mass nor energy and fulfill the
momentum equation between their two ports, e.g., a short pipe. In most
cases this means that an equation is present relating the pressure
drop between the two ports and the mass flow rate from one to the
other port. Since no mass or energy is stored, no differential
equations for thermodynamic variables are present. A component model of this type
has therefore usually the following structure
(see also the implementation in
<a href=\"modelica://Modelica.Media.Examples.Utilities.ShortPipe\">
Modelica.Media.Examples.Utilities.ShortPipe</a>):
</p>
<blockquote><pre>
<strong>model</strong> ShortPipe
<strong>import</strong> Modelica.Units.SI;
<strong>import</strong> Modelica.Media.Examples.Utilities;
// parameters defining the pressure drop equation
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model\" <strong>annotation</strong> (choicesAllMatching = <strong>true</strong>);
Utilities.FluidPort_a port_a (<strong>redeclare package</strong> Medium = Medium);
Utilities.FluidPort_b port_b (<strong>redeclare package</strong> Medium = Medium);
SI.Pressure dp = port_a.p - port_b.p \"Pressure drop\";
Medium.BaseProperties medium_a \"Medium properties in port_a\";
Medium.BaseProperties medium_b \"Medium properties in port_b\";
<strong>equation</strong>
// define media models of the ports
medium_a.p = port_a.p;
medium_a.h = port_a.h;
medium_a.Xi = port_a.Xi;
medium_b.p = port_b.p;
medium_b.h = port_b.h;
medium_b.Xi = port_b.Xi;
// Handle reverse and zero flow (semiLinear is a built-in Modelica operator)
port_a.H_flow = <strong>semiLinear</strong>(port_a.m_flow, port_a.h, port_b.h);
port_a.mXi_flow = <strong>semiLinear</strong>(port_a.m_flow, port_a.Xi, port_b.Xi);
// Energy, mass and substance mass balance
port_a.H_flow + port_b.H_flow = 0;
port_a.m_flow + port_b.m_flow = 0;
port_a.mXi_flow + port_b.mXi_flow = zeros(Medium.nXi);
// Provide equation: port_a.m_flow = f(dp)
<strong>end</strong> ShortPipe;
</pre></blockquote>
<p>
The <strong>semiLinear</strong>(..) operator is basically defined as:
</p>
<blockquote><pre>
semiLinear(m_flow, ha, hb) = if m_flow ≥ 0 then m_flow*ha else m_flow*hb;
</pre></blockquote>
<p>
that is, it computes the enthalpy flow rate either from the port_a or
from the port_b properties, depending on flow direction. The exact
details of this operator are given in
<a href=\"modelica://ModelicaReference.Operators.'semiLinear()'\">
ModelicaReference.Operators.'semiLinear()'</a>. Especially, rules
are defined in the Modelica specification that m_flow = 0 can be treated
in a \"meaningful way\". Especially, if n fluid components (such as pipes)
are connected together and the fluid connector from above is used,
a linear system of equations appear between
medium1.h, medium2.h, medium3.h, ..., port1.h, port2.h, port3.h, ...,
port1.H_flow, port2.H_flow, port3.H_flow, .... The rules for the
semiLinear(..) operator allow the following solution of this
linear system of equations:
</p>
<ul>
<li> n = 2 (two components are connected):<br>
The linear system of equations can be analytically solved
with the result
<blockquote><pre>
medium1.h = medium2.h = port1.h = port2.h
0 = port1.H_flow + port2.H_flow
</pre></blockquote>
Therefore, no problems with zero mass flow rate are present.</li>
<li> n > 2 (more than two components are connected together):<br>
The linear system of equations is solved numerically during simulation.
For m_flow = 0, the linear system becomes singular and has an
infinite number of solutions. The simulator could use the solution t
that is closest to the solution in the previous time step
(\"least squares solution\"). Physically, the solution is determined
by diffusion which is usually neglected. If diffusion is included,
the linear system is regular.</li>
</ul>
</html>"));
end ShortPipe;
class OptionalProperties "Optional properties"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
In some cases additional medium properties are needed.
A component that needs these optional properties has to call
one of the functions listed in the following table. They are
defined as partial functions within package
<a href=\"modelica://Modelica.Media.Interfaces.PartialMedium\">PartialMedium</a>,
and then (optionally) implemented in actual medium packages.
If a component calls such an optional function and the
medium package does not provide a new implementation for this
function, an error message is printed at translation time,
since the function is \"partial\", i.e., incomplete.
The argument of all functions is the <strong>state</strong> record,
automatically defined by the BaseProperties model or specifically computed using the
setState_XXX functions, which contains the
minimum number of thermodynamic variables needed to compute all the additional
properties. In the table it is assumed that there is a declaration of the
form:
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium;
Medium.ThermodynamicState state;
</pre></blockquote>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Function call</strong></td>
<td><strong>Unit</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>Medium.dynamicViscosity(state)</td>
<td>Pa.s</td>
<td>dynamic viscosity</td></tr>
<tr><td>Medium.thermalConductivity(state)</td>
<td>W/(m.K)</td>
<td>thermal conductivity</td></tr>
<tr><td>Medium.prandtlNumber(state)</td>
<td>1</td>
<td>Prandtl number</td></tr>
<tr><td>Medium.specificEntropy(state)</td>
<td>J/(kg.K)</td>
<td>specific entropy</td></tr>
<tr><td>Medium.specificHeatCapacityCp(state)</td>
<td>J/(kg.K)</td>
<td>specific heat capacity at constant pressure</td></tr>
<tr><td>Medium.specificHeatCapacityCv(state)</td>
<td>J/(kg.K)</td>
<td>specific heat capacity at constant density</td></tr>
<tr><td>Medium.isentropicExponent(state)</td>
<td>1</td>
<td>isentropic exponent</td></tr>
<tr><td>Medium.isentropicEnthatlpy(pressure, state)</td>
<td>J/kg</td>
<td>isentropic enthalpy</td></tr>
<tr><td>Medium.velocityOfSound(state)</td>
<td>m/s</td>
<td>velocity of sound</td></tr>
<tr><td>Medium.isobaricExpansionCoefficient(state)</td>
<td>1/K</td>
<td>isobaric expansion coefficient</td></tr>
<tr><td>Medium.isothermalCompressibility(state)</td>
<td>1/Pa</td>
<td>isothermal compressibility</td></tr>
<tr><td>Medium.density_derp_h(state)</td>
<td>kg/(m3.Pa)</td>
<td>derivative of density by pressure at constant enthalpy</td></tr>
<tr><td>Medium.density_derh_p(state)</td>
<td>kg2/(m3.J)</td>
<td>derivative of density by enthalpy at constant pressure</td></tr>
<tr><td>Medium.density_derp_T(state)</td>
<td>kg/(m3.Pa)</td>
<td>derivative of density by pressure at constant temperature</td></tr>
<tr><td>Medium.density_derT_p(state)</td>
<td>kg/(m3.K)</td>
<td>derivative of density by temperature at constant pressure</td></tr>
<tr><td>Medium.density_derX(state)</td>
<td>kg/m3</td>
<td>derivative of density by mass fraction</td></tr>
<tr><td>Medium.molarMass(state)</td>
<td>kg/mol</td>
<td>molar mass</td></tr>
</table>
<p>
There are also some short forms provided for user convenience that allow the computation of certain
thermodynamic state variables without using the ThermodynamicState record explicitly. Those short forms
are for example useful to compute consistent start values in the initial equation section. Let's
consider the function temperature_phX(p,h,X) as an example. This function computes the temperature
from pressure, specific enthalpy, and composition X (or Xi) and is a short form for writing
</p>
<blockquote><pre>
temperature(setState_phX(p,h,X))
</pre></blockquote>
<p>
The following functions are predefined in PartialMedium (other functions can be added in the actual
medium implementation package if they are useful)
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td>Medium.specificEnthalpy_pTX(p,T,X)</td>
<td>J/kg</td>
<td>Specific enthalpy at p, T, X </td></tr>
<tr><td>Medium.temperature_phX(p,h,X)</td>
<td>K</td>
<td>Temperature at p, h, X</td></tr>
<tr><td>Medium.density_phX(p,h,X)</td>
<td>kg/m3</td>
<td>Density at p, h, X</td></tr>
<tr><td>Medium.temperature_psX(p,s,X)</td>
<td>K</td>
<td>Temperature at p, s, X</td></tr>
<tr><td>Medium.specificEnthalpy_psX(p,s,X)</td>
<td>J/(kg.K)</td>
<td>Specific entropy at p, s, X</td></tr>
</table>
<p>
Assume for example that the dynamic viscosity eta is needed in
the pressure drop equation of a short pipe. Then, the
model of a short pipe has to be changed to:
</p>
<blockquote><pre>
<strong>model</strong> ShortPipe
...
Medium.BaseProperties medium_a \"Medium properties in port_a\";
Medium.BaseProperties medium_b \"Medium properties in port_b\";
...
Medium.DynamicViscosity eta;
...
eta = <strong>if</strong> port_a.m_flow > 0 <strong>then</strong>
Medium.dynamicViscosity(medium_a.state)
<strong>else</strong>
Medium.dynamicViscosity(medium_b.state);
// use eta in the pressure drop equation: port_a.m_flow = f(dp, eta)
<strong>end</strong> ShortPipe;
</pre></blockquote>
<p>
Note, \"Medium.DynamicViscosity\" is a type defined in Modelica.Interfaces.PartialMedium
as
</p>
<blockquote><pre>
<strong>import</strong> Modelica.Units.SI;
<strong>type</strong> DynamicViscosity = SI.DynamicViscosity (
min=0,
max=1.e8,
nominal=1.e-3,
start=1.e-3);
</pre></blockquote>
<p>
Every medium model may modify the attributes, to provide, e.g.,
min, max, nominal, and start values adapted to the medium.
Also, other types, such as AbsolutePressure, Density, MassFlowRate,
etc. are defined in PartialMedium. Whenever possible, these medium
specific types should be used in a model in order that medium information,
e.g., about nominal or start values, are automatically utilized.
</p>
</html>"));
end OptionalProperties;
class Constants "Constants"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Every medium model provides the following <strong>constants</strong>. For example,
if a medium is declared as:
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium;
</pre></blockquote>
<p>
then constants \"Medium.mediumName\", \"Medium.nX\", etc. are defined:
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Type</strong></td>
<td><strong>Name</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>String</td><td>mediumName</td>
<td>Unique name of the medium (is usually used to check whether
the media in different components connected together
are the same, by providing Medium.mediumName as quantity
attribute of the mass flow rate in the connector)</td></tr>
<tr><td>String</td><td>substanceNames[nS]</td>
<td>Names of the substances that make up the medium.
If only one substance is present, substanceNames = {mediumName}.</td></tr>
<tr><td>String</td><td>extraPropertiesNames[nC]</td>
<td>Names of the extra transported substances, outside of mass and
energy balances.</td></tr>
<tr><td>Boolean</td><td>singleState</td>
<td>= <strong>true</strong>, if u and d are not a function of pressure, and thus only
a function of a single thermal variable (temperature or enthalpy) and
of Xi for a multiple substance medium. Usually, this flag is
<strong>true</strong> for incompressible media. It is used in a model to determine
whether 1+nXi (singleState=<strong>true</strong>) or 2+nXi (singleState=<strong>false</strong>)
initial conditions have to be provided for a volume element that
contains mass and energy balance.</td></tr>
<tr><td>AbsolutePressure</td><td>reference_p</td>
<td>Reference pressure for the medium</td></tr>
<tr><td>MassFraction</td><td>reference_X[nX]</td>
<td>Reference composition for the medium</td></tr>
<tr><td>AbsolutePressure</td><td>p_default</td>
<td>Default value for pressure of medium (for initialization)</td></tr>
<tr><td>Temperature</td><td>T_default</td>
<td>Default value for temperature of medium (for initialization)</td></tr>
<tr><td>SpecificEnthalpy</td><td>h_default</td>
<td>Default value for specific enthalpy of medium (for initialization)</td></tr>
<tr><td>MassFraction</td><td>X_default[nX]</td>
<td>Default value for mass fractions of medium (for initialization)</td></tr>
<tr><td>Integer</td><td>nS</td>
<td>number of substances contained in the medium.</td></tr>
<tr><td>Integer</td><td>nX</td>
<td>Size of the full mass fraction vector X nX=nS.</td></tr>
<tr><td>Integer</td><td>nXi</td>
<td>Number of independent mass fractions. If there is a single substance,
then nXi = 0. </td></tr>
<tr><td>Boolean</td><td>reducedX</td>
<td>= <strong>true</strong>, if the medium has a single substance, or if the medium model
has multiple substances and contains the equation sum(X) = 1.
In both cases, nXi = nS - 1 (unless fixedX = true).<br>
= <strong>false</strong>, if the medium has multiple substances and does not contain the
equation sum(X)=1, i.e., nXi = nX = nS (unless fixedX = true).
</td></tr>
<tr><td>Boolean</td><td>fixedX</td>
<td>= <strong>false</strong>: the composition of the medium can vary, and is
determined by nXi independent mass fractions (see reducedX above).<br>
= <strong>true</strong>: the composition of the medium is always reference_X,
and nXi = 0.</td></tr>
<tr><td>FluidConstants</td><td>fluidConstants[nS]</td>
<td>Critical, triple, molecular and other
standard data that are provided for
every substance of a medium.</td></tr>
</table>
<p>
The record FluidConstants that is defined in PartialMedium contains the following elements
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Type</strong></td>
<td><strong>Name</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>String</td>
<td>iupacName</td>
<td>complete IUPAC name</td></tr>
<tr><td>String</td>
<td>casRegistryNumber</td>
<td>chemical abstracts sequencing number</td></tr>
<tr><td>String</td>
<td>chemicalFormula</td>
<td>Chemical formula, (brutto, nomenclature according to Hill)</td></tr>
<tr><td>String</td>
<td>structureFormula</td>
<td>Chemical structure formula</td></tr>
<tr><td>MolarMass</td>
<td>molarMass</td>
<td>molar mass</td></tr>
</table>
<p> This record is extended in the partial packages further down the hierarchy (such as
PartialTwoPhaseMedium or PartialMixtureMedium) and may contain some or all of the following
elements</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td>Temperature</td>
<td>criticalTemperature</td>
<td>critical temperature</td></tr>
<tr><td>AbsolutePressure</td>
<td>criticalPressure</td>
<td>critical pressure</td></tr>
<tr><td>MolarVolume</td>
<td>criticalMolarVolume</td>
<td>critical molar Volume</td></tr>
<tr><td>Real</td>
<td>acentricFactor</td>
<td>Pitzer acentric factor</td></tr>
<tr><td>Temperature</td>
<td>triplePointTemperature</td>
<td>triple point temperature</td></tr>
<tr><td>AbsolutePressure</td>
<td>triplePointPressure</td>
<td>triple point pressure</td></tr>
<tr><td>Temperature</td>
<td>meltingPoint</td>
<td>melting point at 101325 Pa</td></tr>
<tr><td>Temperature</td>
<td>normalBoilingPoint</td>
<td>normal boiling point (at 101325 Pa)</td></tr>
<tr><td>DipoleMoment</td>
<td>dipoleMoment</td>
<td>dipole moment of molecule in Debye (1 debye = 3.33564e10-30 C.m)</td></tr>
<tr><td>Boolean</td>
<td>hasIdealGasHeatCapacity</td>
<td>true, if ideal gas heat capacity is available</td></tr>
<tr><td>Boolean</td>
<td>hasCriticalData</td>
<td>true, if critical data are known</td></tr>
<tr><td>Boolean</td>
<td>hasDipoleMoment</td>
<td>true, if a dipole moment known</td></tr>
<tr><td>Boolean</td>
<td>hasFundamentalEquation</td>
<td>true, if a fundamental equation</td></tr>
<tr><td>Boolean</td>
<td>hasLiquidHeatCapacity</td>
<td>true, if liquid heat capacity is available</td></tr>
<tr><td>Boolean</td>
<td>hasSolidHeatCapacity</td>
<td>true, if solid heat capacity is available</td></tr>
<tr><td>Boolean</td>
<td>hasAccurateViscosityData</td>
<td>true, if accurate data for a viscosity function is available</td></tr>
<tr><td>Boolean</td>
<td>hasAccurateConductivityData</td>
<td>true, if accurate data for thermal conductivity is available</td></tr>
<tr><td>Boolean</td>
<td>hasVapourPressureCurve</td>
<td>true, if vapour pressure data, e.g., Antoine coefficients are known</td></tr>
<tr><td>Boolean</td>
<td>hasAcentricFactor</td>
<td>true, if Pitzer acentric factor is known</td></tr>
<tr><td>SpecificEnthalpy</td>
<td>HCRIT0</td>
<td>Critical specific enthalpy of the fundamental equation</td></tr>
<tr><td>SpecificEntropy</td>
<td>SCRIT0</td>
<td>Critical specific entropy of the fundamental equation</td></tr>
<tr><td>SpecificEnthalpy</td>
<td>deltah</td>
<td>Difference between specific enthalpy model
(h_m) and f.eq. (h_f) (h_m - h_f)</td></tr>
<tr><td>SpecificEntropy</td>
<td>deltas</td>
<td>Difference between specific enthalpy model (s_m) and f.eq.
(s_f) (s_m - s_f)</td></tr>
</table>
</html>"));
end Constants;
class TwoPhase "Two-phase media"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Models for media which can exist in one-phase or two-phase conditions inherit
from <a href=\"modelica://Modelica.Media.Interfaces.PartialTwoPhaseMedium\">
Modelica.Media.Interfaces.PartialTwoPhaseMedium</a>
(which inherits from PartialMedium). The basic usage of these
media models is the same as described in the previous sections. However, additional
functionalities are provided, which apply only to potentially two-phase media.
</p>
<p>
The following additional medium <strong>constants</strong> are provided:
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Type</strong></td>
<td><strong>Name</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>Boolean</td>
<td>smoothModel</td>
<td>If this flag is false (default value), then events are triggered
whenever the saturation boundary is crossed; otherwise, no events
are generated.</td></tr>
<tr><td>Boolean</td>
<td>onePhase</td>
<td>If this flag is true, then the medium model assumes it will be never
called in the two-phase region. This can be useful to speed up
the computations in a two-phase medium, when the user is sure it will
always work in the one-phase region. Default value: false.</td></tr>
</table>
<p>
The setState_ph(), setState_ps(), setState_dT() and setState_pT() functions have
one extra input, named <em>phase</em>. If the phase input is not specified, or if
it is given a value of zero, then the setState function will determine the phase,
based on the other input values. An input phase = 1 will force the setState
function to return a state vector corresponding to a one-phase state, while
phase = 2 will force the setState value to return a state vector corresponding
to a two-phase state, as shown in the following example;
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialTwoPhaseMedium;
Medium.ThermodynamicState state, state1, state2;
<strong>equation</strong>
// Set the state, given the pressure and the specific enthalpy
// the phase is determined by the (p, h) values, and can be retrieved
// from the state record
state = Medium.setState_ph(p, h);
phase = state1.phase;
// Force the computation of the state with one-phase
// equations of state, irrespective of the (p, h) values
state1 = Medium.setState_ph(p, h, 1);
// Force the computation of the state with 2-phase
// equations of state, irrespective of the (p, h) values
state2 = Medium.setState_ph(p, h, 2);
</pre></blockquote>
<p>
This feature can be used for the following purposes:
</p>
<ul>
<li> saving computational time, if one knows in advance the phase of the medium;</li>
<li> unambiguously determine the phase, when the two inputs correspond to a point on the saturation boundary (the derivative functions have substantially different values on either side);</li>
<li> get the properties of metastable states, like superheated water or subcooled vapour.</li>
</ul>
<p>
Many additional optional functions are defined to compute properties of
saturated media, either liquid (bubble point) or vapour (dew point).
The argument to such functions is a SaturationProperties record, which can be
set starting from either the saturation pressure or the saturation temperature,
as shown in the following example.
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialTwoPhaseMedium;
Medium.SaturationProperties sat_p;
Medium.SaturationProperties sat_T;
<strong>equation</strong>
// Set sat_p to saturation properties at pressure p
sat_p = Medium.setSat_p(p);
// Compute saturation properties at pressure p
saturationTemperature_p = Medium.saturationTemperature_sat(sat_p);
bubble_density_p = Medium.bubbleDensity(sat_p);
dew_enthalpy_p = Medium.dewEnthalpy(sat_p);
// Set sat_T to saturation properties at temperature T
sat_T = Medium.setSat_T(T);
// Compute saturation properties at temperature T
saturationTemperature_T = Medium.saturationPressure_sat(sat_T);
bubble_density_T = Medium.bubbleDensity(sat_T);
dew_enthalpy_T = Medium.dewEnthalpy(sat_T);
</pre></blockquote>
<p>With reference to a model defining a pressure p, a temperature T, and a
SaturationProperties record sat, the following functions are provided:
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Function call</strong></td>
<td><strong>Unit</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>Medium.saturationPressure(T)</td>
<td>Pa</td>
<td>Saturation pressure at temperature T</td></tr>
<tr><td>Medium.saturationTemperature(p)</td>
<td>K</td>
<td>Saturation temperature at pressure p</td></tr>
<tr><td>Medium.saturationTemperature_derp(p)</td>
<td>K/Pa</td>
<td>Derivative of saturation temperature with respect to pressure</td></tr>
<tr><td>Medium.saturationTemperature_sat(sat)</td>
<td>K</td>
<td>Saturation temperature</td></tr>
<tr><td>Medium.saturationPressure_sat(sat)</td>
<td>Pa</td>
<td>Saturation pressure</td></tr>
<tr><td>Medium.bubbleEnthalpy(sat)</td>
<td>J/kg</td>
<td>Specific enthalpy at bubble point</td></tr>
<tr><td>Medium.dewEnthalpy(sat)</td>
<td>J/kg</td>
<td>Specific enthalpy at dew point</td></tr>
<tr><td>Medium.bubbleEntropy(sat)</td>
<td>J/(kg.K)</td>
<td>Specific entropy at bubble point</td></tr>
<tr><td>Medium.dewEntropy(sat)</td>
<td>J/(kg.K)</td>
<td>Specific entropy at dew point</td></tr>
<tr><td>Medium.bubbleDensity(sat)</td>
<td>kg/m3</td>
<td>Density at bubble point</td></tr>
<tr><td>Medium.dewDensity(sat)</td>
<td>kg/m3</td>
<td>Density at dew point</td></tr>
<tr><td>Medium.saturationTemperature_derp_sat(sat)</td>
<td>K/Pa</td>
<td>Derivative of saturation temperature with respect to pressure</td></tr>
<tr><td>Medium.dBubbleDensity_dPressure(sat)</td>
<td>kg/(m3.Pa)</td>
<td>Derivative of density at bubble point with respect to pressure</td></tr>
<tr><td>Medium.dDewDensity_dPressure(sat)</td>
<td>kg/(m3.Pa)</td>
<td>Derivative of density at dew point with respect to pressure</td></tr>
<tr><td>Medium.dBubbleEnthalpy_dPressure(sat)</td>
<td>J/(kg.Pa)</td>
<td>Derivative of specific enthalpy at bubble point with respect to pressure</td></tr>
<tr><td>Medium.dDewEnthalpy_dPressure(sat)</td>
<td>J/(kg.Pa)</td>
<td>Derivative of specific enthalpy at dew point with respect to pressure</td></tr>
<tr><td>Medium.surfaceTension(sat)</td>
<td>N/m</td>
<td>Surface tension between liquid and vapour phase</td></tr>
</table>
<p>
Sometimes it can be necessary to compute fluid properties in the thermodynamic
plane, just inside or outside the saturation dome. In this case, it is possible
to obtain an instance of a ThermodynamicState state vector, and then use it
to call the additional functions already defined for one-phase media.
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Function call</strong></td>
<td><strong>Description</strong></td></tr>
<tr><td>Medium.setBubbleState(sat, phase)</td>
<td>Obtain the thermodynamic state vector
corresponding to the bubble point. If phase==1 (default), the state is
on the one-phase side; if phase==2, the state is on the two-phase
side </td></tr>
<tr><td>Medium.setDewState(sat, phase)</td>
<td>Obtain the thermodynamic state vector
corresponding to the dew point. If phase==1 (default), the state is
on the one-phase side; if phase==2, the state is on the two-phase
side </td></tr>
</table>
<p>
Here are some examples:
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialTwoPhaseMedium;