forked from modelica/ModelicaStandardLibrary
-
Notifications
You must be signed in to change notification settings - Fork 0
/
package.mo
1756 lines (1584 loc) · 81.6 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 Fluid "Library of 1-dim. thermo-fluid flow models using the Modelica.Media media description"
extends Modelica.Icons.Package;
import Modelica.Units.SI;
import Cv = Modelica.Units.Conversions;
package UsersGuide "User's Guide"
extends Modelica.Icons.Information;
class Overview "Overview"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
The Modelica.Fluid library provides basic interfaces and
components to model 1-dimensional thermo-fluid flow in networks of pipes.
It is not the intention that this library covers all
application cases because the fluid flow area is too large and
because for special applications it is possible to implement
libraries with simpler component interfaces.
Instead, the goal is that the Modelica.Fluid library provides
a <strong>reasonable set of components</strong> and that it <strong>demonstrates</strong>
how to implement components of a fluid flow library in Modelica,
in particular to cope with difficult issues such as connector
design, reversing flow and initialization.
</p>
<p>
This library has the following main features:
</p>
<ul>
<li> The connectors Modelica.Fluid.Interfaces.FluidPort_a/_b are designed
for one-dimensional flow of a <strong>single substance</strong>
or of a <strong>mixture of substances</strong> with optional <strong>multiple phases</strong>.
All media models from Modelica.Media can be utilized when
connecting components. For one substance media, the additional arrays for
multiple
substance media have zero dimension and are therefore removed
from the code during translation. The general connector definition
therefore does not introduce an overhead for special cases.<br> </li>
<li> All the components of the Modelica.Fluid library are designed
that they can be utilized for all media models from
Modelica.Media if this is possible. For example, all media can
be utilized for the Modelica.Fluid.Sensors/Sources components.
For some components only special media are possible, since additional
functionality is required. For example,
Modelica.Fluid.Components.Evaporator requires a two phase medium
(extending from Modelica.Media.Interfaces.PartialTwoPhaseMedium).
<br> </li>
<li> In order to simplify the initialization in the components,
there is the restriction that only media models are supported
that have T, (p,T), (p,h), (T,X), (p,T,X) or (p,h,X) as
independent variables. Other media models would be possible,
e.g., with (T,d) as independent variables. However, this requires
to rewrite the code for the component initialization.
(Note, T is temperature, p is pressure, d is density,
h is specific enthalpy, and X is a mass fraction vector).
<br> </li>
<li> All components work for <strong>incompressible</strong> and <strong>compressible</strong> media.
This is implemented by a small change in the initialization of a
component, if the medium is incompressible. Otherwise, the equations
of the components are not influenced by this property.<br> </li>
<li> All components allow fluid flow in both directions, i.e.,
<strong>reversing flow</strong> is supported. However, it is possible to declare that
the flow through a component only has the design direction, in order to
obtain faster simulation code.<br> </li>
<li> Two or more components can be connected together. This means that
the pressures of all connected ports are equal and the mass flow rates
sum up to zero. Specific enthalpy, mass fractions and trace substances are
mixed according to the mass flow rates.<br> </li>
<li> The <strong>momentum balance</strong> and the <strong>energy balance</strong> are only fulfilled exactly if
<strong>two ports of equal diameter</strong> are connected. In all other cases, the balances
are approximated, because kinetic and friction effect are neglected. An explicit fitting
or junction should be used if these are important for the specific problem at hand.
In all circuits where friction dominates, or components such as pumps determine the flow rate,
kinetic pressure is typically irrelevant. You can consider the
<a href=\"modelica://Modelica.Fluid.Examples.Explanatory.MomentumBalanceFittings\">Modelica.Fluid.Examples.Explanatory.MomentumBalanceFittings</a> model (and its documentation)
to see one case where the momentum balance essentially depends on kinetic pressure,
so it is necessary to use explicit fittings in order to obtain correct results.
<br> </li>
<li> Given the above-mentioned limitations, there is no restriction how components can be connected
together. The resulting simulation performance however often strongly depends on the
model structure and modeling assumptions made. In particular the direct connection of
fluid volumes generally results in high-index DAEs for the pressures. The direct
connection of flow models generally results in systems of implicit nonlinear algebraic
equations.<br> </li>
</ul>
</html>"));
end Overview;
class GettingStarted "Getting started"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Please explore the
<a href=\"modelica://Modelica.Fluid.Examples\">Examples</a>,
which provide simple models for a broad variety of applications.
</p>
</html>"));
end GettingStarted;
package ComponentDefinition "Component definition"
extends Modelica.Icons.Information;
class FluidConnectors "Fluid connectors"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
In this section the design of the fluid connectors is
explained.
</p>
<p>
Fluid connectors represent the points in a device (e.g., the
flanges) through which a fluid can flow into or out of the component, carrying its
thermodynamic properties; these flanges are assumed to be fixed in space.
</p>
<p>
A major design goal is that components can be arbitrarily
connected and that the important balance equations are automatically
fulfilled when 2 or more components are connected together at
one point as shown in the next figure:
</p>
<div>
<img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/MixingConnections.png\"
alt=\"MixingConnections.png\">
</div>
<p>
In such a case the balance equations define <strong>ideal mixing</strong>,
i.e., the upstream discretization scheme of each component uses
values that result from ideal mixing in
an infinitely small time period. If more realistic modelling
is desired that takes into account mixing losses, an explicit
model has to be used in the connection point.
</p>
<h4>Single substance media</h4>
<p>
For a single substance medium, the connector definition in
Modelica.Fluid.Interfaces.FluidPort reduces to
</p>
<blockquote><pre>
<strong>connector</strong> FluidPort
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model of the fluid\";
<strong>flow</strong> Medium.MassFlowRate m_flow
\"Mass flow rate from the connection point into the component\";
Medium.AbsolutePressure p
\"Thermodynamic pressure in the connection point\";
<strong>stream</strong> Medium.SpecificEnthalpy h_outflow
\"Specific thermodynamic enthalpy close to the connection point if m_flow < 0\";
<strong>end</strong> FluidPort;
</pre></blockquote>
<p>
The first statement defines the Medium flowing through the connector.
In a medium, medium specific types such as \"Medium.AbsolutePressure\"
are defined that contain medium specific values for the min, max and
nominal attributes. Furthermore, Medium.MassFlowRate is defined as:
</p>
<blockquote><pre>
<strong>type</strong> MassFlowRate = SI.MassFlowRate(
quantity = \"MassFlowRate.\" + mediumName);
</pre></blockquote>
<p>
Generally, with the current library design, it is necessary to explicitly select the medium
model for each component in a circuit. This model is then propagated to the ports,
and a Modelica translator will check that the quantity and unit attributes
of connected interfaces are identical. Therefore, an error occurs,
if connected FluidPorts do not have a medium with the same medium name.<br>
Automatic propagation of fluid models through the ports is not directly possible with the
Modelica 3.6 specification, but might be supported by the Modelica tool. For example,
in Dymola the option <code>Advanced.MediaPropagation</code>=<code>1</code> can be set
to apply automatic propagation of media models in a circuit.
</p>
<p>
The thermodynamic pressure is an <em>effort</em> variable, which means that the connection
of two or more ports states that the port pressures are the same.
</p>
<p>
The mass flow rate is a <em>flow</em> variable, which means that the connection of two or
more ports states that the sum of all flow rates is zero.
</p>
<p>
The last variable is a <em>stream</em> variable, i.e., a specific quantity carried by the
flow variable. The quantity on the connector always
corresponds to the value close to the connection point, assuming that the fluid is
flowing out of the connector, regardless of the actual direction of the flow. This helps
avoiding singularities when the mass flow goes through zero. The stream properties for the
other flow direction can be inquired with the built-in operator inStream(..), while the
value of the stream variable corresponding to the actual flow direction can be inquired
through the built-in operator <a href=\"https://specification.modelica.org/maint/3.6/operators-and-expressions.html#modelica:actualStream\">actualStream(…)</a>.
</p>
<p>
The actual equations corresponding to these operators are introduced and solved automatically
by the tool. In principle, they correspond to the balance equation
sum(flow_variable) = 0 and sum(flow_variable*stream_variable_at_connection) = 0 applied to the set of connected ports. In this case the first equation is the mass balance sum(m_flow) = 0, and the second is the energy balance at the connection point sum(m_flow*h_connection) = 0.
</p>
<p>
In the simpler case of a one-to-one connections between port_a and port_b,
inStream(port_a.h_outflow) just returns port_b.h_outflow. For multiple-way connections,
mixing equations are generated, and special care is taken in order to avoid discontinuities
around zero flow rates. For more details, see this
<a href=\"modelica://Modelica/Resources/Documentation/Fluid/Stream-Connectors-Overview-Rationale.pdf\">presentation</a>
which illustrates the stream concept rationale and the underlying technicalities.
</p>
<p>
A connector should have only the minimal number of variables to
describe the interface, otherwise there will be connection
restrictions in certain cases. Therefore, in the connector
no redundant variables are present, e.g., the temperature T
is not present because it can be computed from the connector
variables pressure p and specific enthalpy h.
</p>
<p>
Here are two simple examples to illustrate modeling with stream connectors. The first
one is a rigid adiabatic volume mixing two flows, where the kinetic and gravitational
terms in the energy balance are neglected for simplicity.
</p>
<blockquote><pre>
<strong>model</strong> MixingVolume \"Volume that mixes two flows\"
<strong>import</strong> Modelica.Units.SI;
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialPureSubstance;
FluidPort port_a(redeclare package Medium = Medium) \"Fluid connector a\";
FluidPort port_b(redeclare package Medium = Medium) \"Fluid connector b\";
<strong>parameter</strong> SI.Volume V \"Volume of device\";
SI.Mass m \"Mass in device\";
SI.Energy U \"Inner energy in device\";
Medium.BaseProperties medium(preferredMediumStates=true) \"Medium in the device\";
<strong>equation</strong>
// Definition of port variables
port_a.p = medium.p;
port_b.p = medium.p;
port_a.h_outflow = medium.h; // The stream variable always corresponds to the
port_b.h_outflow = medium.h; // properties of the fluid holdup (outgoing flow)
// Total quantities
m = V*medium.d;
U = m*medium.u;
// Mass and energy balance (actualStream(..) is a built-in operator for streams to
// compute the right h, depending on the flow direction)
der(m) = port_a.m_flow + port_b.m_flow;
der(U) = port_a.m_flow*actualStream(port_a.h_outflow) +
port_b.m_flow*actualStream(port_b.h_outflow);
<strong>end</strong> MixingVolume;
</pre></blockquote>
<p>
The second example is the model of a component describing a lumped pressure loss
between two ports, with no energy storage and no heat transfer. An isenthalpic
transformation is assumed (changes in kinetic and potential energy between
inlet and outlet are neglected).
</p>
<blockquote><pre>
<strong>model</strong> PressureLoss \"Pressure loss component\"
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialPureSubstance;
FluidPort port_a(redeclare package Medium = Medium) \"Fluid connector a\";
FluidPort port_b(redeclare package Medium = Medium) \"Fluid connector b\";
Medium.ThermodynamicState port_a_state_inflow \"State at port_a if inflowing\";
Medium.ThermodynamicState port_b_state_inflow \"State at port_b if inflowing\";
Medium.Density d_a \"Density at port a if inflowing\";
Medium.Density d_b \"Density at port b if inflowing\";
<strong>replaceable</strong> function f = SomeSpecificMassFlowFunction
\"Function to compute the mass flow rate\";
<strong>equation</strong>
// Medium states for inflowing fluid
port_a_state_inflow = Medium.setState_phX(port_a.p, inStream(port_a.h_outflow));
port_b_state_inflow = Medium.setState_phX(port_b.p, inStream(port_b.h_outflow));
// Mass balance
0 = port_a.m_flow + port_b.m_flow;
// Instantaneous propagation of enthalpy flow between the ports with
// isenthalpic state transformation (no storage and no loss of energy)
port_a.h_outflow = inStream(port_b.h_outflow);
port_b.h_outflow = inStream(port_a.h_outflow);
// (Regularized) Momentum balance
port_a.m_flow = f(port_a.p - port_b.p, d_a, d_b);
<strong>end</strong> PressureLoss;
</pre></blockquote>
<p>
If many such components are connected in series between two models with storage, the
specific enthalpies are propagated in both directions and available to all pressure
loss components, without problems when the mass flow goes through zero. The function f
then uses either d_a or d_b depending on the sign of port_a.p-port_b.p, with a
suitable regularization around zero to avoid discontinuities.
</p>
<p>
Please note that these models are highly idealized in order to explain the stream connector
concept. Device models in the library are much more complete, handling issues such as
initialization, steady vs. dynamic modelling, heat transfer from the outside, etc.
</p>
<h4>Multiple-substance media</h4>
<p>
Modelica.Fluid can handle models where the fluid contains multiple substances, so that its
composition can be characterized by mass fraction vectors.
</p>
<blockquote><pre>
<strong>connector</strong> FluidPort
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
\"Medium model of the fluid\";
<strong>flow</strong> Medium.MassFlowRate m_flow
\"Mass flow rate from the connection point into the component\";
Medium.AbsolutePressure p
\"Thermodynamic pressure in the connection point\";
<strong>stream</strong> Medium.SpecificEnthalpy h_outflow
\"Specific thermodynamic enthalpy close to the connection point if m_flow < 0\";
<strong>stream</strong> Medium.MassFraction Xi_outflow[Medium.nXi]
\"Independent mixture mass fractions m_i/m close to the connection point if m_flow < 0\";
<strong>stream</strong> Medium.ExtraProperty C_outflow[Medium.nC]
\"Properties c_i/m close to the connection point if m_flow < 0\";
<strong>end</strong> FluidPort;
</pre></blockquote>
<p>
The mass fraction vectors Xi and C are also stream quantities, as they are carried by the mass
flow rate. The corresponding connection equations are sum(m_flow*Xi) and sum(m_flow*C), which correspond to mass balances for the single substances. The vector Xi contains the mass fractions
of the main components of the fluid, and is used together with p and h to determine the
thermodynamic state of the fluid. The vector C contains the mass fraction of the trace components,
which are accounted for in mass balances, but is ignored when computing the fluid properties. This
allows to easily declare and use medium models with trace components starting from existing medium
models (e.g., adding CO<sub>2</sub> traces to Moist Air for air conditioning models).
</p>
<h4>Approximations in balance equations at connection point</h4>
<p>
Summing up, when two or more ports of the type FluidPort are connected, the following
equations are generated by the tool:
</p>
<blockquote><pre>
sum(port_j.m_flow) = 0; // Total Mass balance
port_j = port_k; // Momentum balance
sum(port_j.m_flow*h_connection) = 0; // Energy balance
sum(port_j.m_flow*Xi_connection) = 0; // Single component mass balances
sum(port_j.m_flow*C_connection) = 0; // Trace components mass balances
</pre></blockquote>
<p>
It is <strong>very important</strong> to bear in mind that
</p>
<ul>
<li> the mass balances are always exact;</li>
<li> the momentum and energy balance are only exact when two port with the same
diameter are connected, because there is no friction and no change in fluid velocity.</li>
</ul>
<p>
In all other cases, i.e., different port diameters and/or multiple port connections:
</p>
<ul>
<li> The momentum balance does not consider friction effects and changes of pressure due to changes
in velocity.</li>
<li> There might thus be errors in the momentum balance of the order of magnitude
of the dynamic pressure ρv<sup>2</sup>/2.</li>
<li> The energy balance does not consider the kinetic terms (gravity terms cancel out due
to the infinitesimal size of the connection volume). There might thus be errors in the momentum balance of the order of magnitude of the kinetic energy v^2/2.</li>
</ul>
<p>
In many applications, where fluid speeds are low and thermal phenomena are mainly of interest,
these approximations are commonly made and lead to acceptable results.
In all other cases, explicit fitting and junction models should be used, that model explicitly
all the kinetic phenomena with the appropriate level of detail.
</p></html>"));
end FluidConnectors;
class BalanceEquations "Balance equations"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
For one-dimensional flow
along the coordinate \"x\", the following partial differential
equations hold
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td> Mass balance</td>
<td> <img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/massBalance.png\"
alt=\"massBalance.png\"></td>
</tr>
<tr><td> Momentum balance</td>
<td> <img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/momentumBalance.png\"
alt=\"momentumBalance.png\"></td>
</tr>
<tr><td> Energy balance 1</td>
<td> <img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/energyBalance1.png\"
alt=\"energyBalance1.png\"></td>
</tr>
<tr><td> Pipe friction</td>
<td> <img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/pipeFriction.png\"
alt=\"pipeFriction.png\"></td>
</tr>
<tr><td></td>
<td>x: independent spatial coordinate (flow is along coordinate x)<br>
t: time<br>
v(x,t): mean velocity<br>
p(x,t): mean pressure<br>
T(x,t): mean temperature<br>
ρ(x,t): mean density<br>
u(x,t): specific internal energy<br>
z(x): height over ground<br>
A(x): area perpendicular to direction x<br>
g: gravity constant<br>
f: Fanning friction factor<br>
S: circumference</td>
</tr>
</table>
<p>
An alternative energy balance can be derived by multiplying
the momentum balance with \"v\" and subtracting it
from the energy balance 1 above. This results in
the \"energy balance 2\":
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td> Energy balance 2</td>
<td> <img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/energyBalance2.png\"
alt=\"energyBalance2.png\"></td>
</tr>
</table>
<p>
This formulation separates the internal energy of the fluid from the kinetic energy of fluid flow.
The internal energy is treated by the energy balance 2, the kinetic energy is treated by the momentum balance equally well.
The evaluation of medium properties, which are independent of the kinetic energy, and the formulation of many fluid models is simplified with the energy balance 2.
The overall conservation of energy is achieved by considering the mutual dependencies of energy and momentum balance.
</p>
<p>
Some components in the library, like DynamicPipe, provide a rigorous implementation of mass,
momentum and energy balance, using the energy balance 2 equation. Other components, like Valves and
Fittings, neglect the impact of changes of the kinetic energy and potential energy on the energy
balance, because they are usually irrelevant compared to changes due to heat flows. The StaticPipe
component neglects the effect of kinetic energy, but includes the potential energy in the balance,
which might be substantial.
</p>
<p>
All modelling assumptions and simplifications are stated in the component documentation; please note that some of the assumptions might be stated in the base classes the
component inherits from.
</p>
</html>"));
end BalanceEquations;
class UpstreamDiscretization "Upstream discretization"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
When implementing a Fluid component, the difficult arises that
the value of intensive quantities (such as p, T, ρ)
shall be accessed from the
<strong>upstream</strong> volume. For example, if the fluid flows
from volume A to volume B, then the intensive quantities of
volume B have no influence on the fluid between the
two volumes. On the other hand, if the flow direction is reversed,
the intensive quantities of volume A have no influence
on the fluid between the two volumes.
</p>
<p>
In the Modelica.Fluid library, such a situation is handled
with the following code fragment
(from Interfaces.PartialTwoPortTransport):
</p>
<blockquote><pre>
<strong>replaceable package</strong> Medium = Modelica.Media.Interfaces.PartialMedium
<strong>annotation</strong>(choicesAllMatching = <strong>true</strong>);
Interfaces.FluidPort_a port_a(<strong>redeclare package</strong> Medium = Medium);
Interfaces.FluidPort_b port_b(<strong>redeclare package</strong> Medium = Medium);
Medium.ThermodynamicState port_a_state_inflow
\"Medium state close to port_a for inflowing mass flow\";
Medium.ThermodynamicState port_b_state_inflow
\"Medium state close to port_b for inflowing mass flow\";
<strong>equation</strong>
// Isenthalpic state transformation (no storage and no loss of energy)
port_a.h_outflow = <strong>inStream</strong>(port_b.h_outflow);
port_b.h_outflow = <strong>inStream</strong>(port_a.h_outflow);
port_a.Xi_outflow = <strong>inStream</strong>(port_b.Xi_outflow);
port_b.Xi_outflow = <strong>inStream</strong>(port_a.Xi_outflow);
// Mass balance
port_a.m_flow + port_b.m_flow = 0;
// Medium states for inflowing medium
port_a_state_inflow = Medium.setState_phX(port_a.p, port_b.h_outflow, port_b.Xi_outflow);
port_b_state_inflow = Medium.setState_phX(port_b.p, port_a.h_outflow, port_a.Xi_outflow);
// Densities close to the parts when mass flows in to the respective port
port_a_rho_inflow = Medium.density(port_a_state_inflow);
port_b_rho_inflow = Medium.density(port_b_state_inflow);
// Pressure drop correlation (k_ab, k_ba are the loss factors for the two flow
// directions; e.g., for a circular device: k = 8*zeta/(pi*diameter)^2)^2)
m_flow = Utilities.regRoot2(port_a.p - port_b.p, dp_small,
port_a_rho_inflow/k1, port_b_rho_inflow/k2);
</pre></blockquote>
<p>
The medium states for inflowing media can be used to compute density and dynamic
viscosity which in turn can be use to formulate the pressure drop equation.
The standard pressure drop equation
</p>
<blockquote><pre>
dp = port_a - port_b;
m_flow = sqrt(2/(zeta*diameter))*if dp >= 0 then sqrt(dp)
else -sqrt(-dp)
</pre></blockquote>
<p>
cannot be used, since the function has an infinite derivative at dp=0.
Instead the region around zero mass flow rate must be regularized using
one of the regularization functions of Modelica.Fluid.Utilities.
This requires to have density and/or other medium properties for both
flow directions at the same time. These media properties can be computed
from the medium states of the inflowing fluid at the two ports.
</p>
<p>
If the above component is connected between two volumes, i.e.,
the independent medium variables in port_a and port_b are
usually states, then port_a.h and port_b.h are either states
(i.e., known quantities in the model) or are computed from
states. In either case they are \"known\". In such a situation,
all equations can be directly evaluated without any problems.
Zero or reversed mass flow rate does not pose any problems because
the medium properties are always computed for both flow directions
and are then used in the regularization function.
</p>
<p>
If 3 or more components are connected together, it can be shown
that a system of non-linear algebraic equations appear.
The equations are written by purpose in such a form, that
a tool can select mass flow rates and pressures as iteration
variables of this system. The advantage is that these iteration
variables are continuous and even often differentiable. The
alternative to use the medium states as iteration variables
is not good, because T,h,d are discontinuous for reversing flow
direction.
</p>
</html>"));
end UpstreamDiscretization;
class RegularizingCharacteristics "Regularizing characteristics"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
Pressure drop equations and other fluid characteristics are usually
computed by <strong>semi-empirical</strong> equations. Unfortunately, the developers
of semi-empirical equations nearly never take into account that the
equation might be used in a simulation program. As a consequence, these
semi-empirical equations can nearly never be used blindly but must
be slightly modified or adapted in order that obvious
simulation problems are avoided. Below, examples are given to
demonstrate what problems occur and how to regularize the characteristics:
</p>
<h4>Square root function</h4>
<p>
In several empirical formulae, expressions of the following form
are present, e.g., for turbulent flow in a pipe:
</p>
<blockquote><pre>
y = <strong>if</strong> x < 0 <strong>then</strong> -<strong>sqrt</strong>( <strong>abs</strong>(x) ) <strong>else</strong> <strong>sqrt</strong>(x)
</pre></blockquote>
<p>
A plot of this characteristic is shown in the next figure:
</p>
<div>
<img src=\"modelica://Modelica/Resources/Images/Fluid/UsersGuide/ComponentDefinition/sqrt.png\"
alt=\"sqrt.png\">
</div>
<p>
The difficulty with this function is that the derivative at x=0 is infinity.
In reality, such a function does not exist. E.g., for pipe flow,
the flow becomes laminar for small velocities and therefore around zero the
sqrt() function is replaced by a linear function. Since the laminar region is
usually of not much practical interest, the above approximation is used.
</p>
<p>
The direct implementation above does not work in Modelica, because
an event is generated when x < 0 changes sign. In order to detect
this event, an event iteration takes place. During the event iteration,
the active if-branch is not changed. For example, assume that x is positive
(= \"else\" branch) and shall become negative. During the event iteration
x is slightly negative and the else branch, i.e., sqrt(x), is evaluated.
Since this results in an imaginary number, an error occurs.
It would be possible to fix this, by using the <strong>noEvent</strong>() operator
to explicitly switch of an event:
</p>
<blockquote><pre>
y = <strong>if</strong> <strong>noEvent</strong>(x < 0) <strong>then</strong> -<strong>sqrt</strong>( <strong>abs</strong>(x) ) <strong>else</strong> <strong>sqrt</strong>(x)
</pre></blockquote>
<p>
Still, it is highly likely that good integrators will not work well
around x=0, because they will recognize that the derivative changes very
sharply and will reduce the step size drastically.
</p>
<p>
There are several solutions around this problem: Around x=0, the sqrt() function
can be replaced by a polynomial of 3rd order which is determined in such a way
that it smoothly touches the sqrt() function, i.e., the whole function is continuous
and continuously differentiable. In the Modelica.Fluid library, implementations of
such critical functions are provided in sublibrary Modelica.Fluid.Utilities.
The above sqrt() type function is computed by function <strong>Utilities.regRoot</strong>().
This function is defined as:
</p>
<blockquote><pre>
y := x/(x*x+delta*delta)^0.25;
</pre></blockquote>
<p>
where \"delta\" is the size of the small region around zero where the
sqrt() function is approximated by another function. The plot of the
function above is practically identical to the one of the original function.
However, it has a finite derivative at x=0 and is differentiable up to
any order. With the default value of delta=0.01, the difference between
the function above and regRoot(x) is 16% around x=0.01, 0.25% around x=0.1
and 0.0025% around x=1.
</p>
</html>"));
end RegularizingCharacteristics;
class WallFriction "Wall friction"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
One important special case for a pressure loss is the friction at the
wall of a pipe under the assumption of quasi steady state flow (i.e., the
mass flow rate varies only slowly). In this section it is explained how this case is
handled in the Modelica.Fluid library for pipes with
<strong>nonuniform roughness</strong>, including the smooth pipe
as a special case (see
<a href=\"modelica://Modelica.Fluid.Pipes.BaseClasses.WallFriction\">Pipes.BaseClasses.WallFriction</a>).
The treatment is non-standard in order to get a
numerically well-posed description.
</p>
<p>
For pipes with circular cross section the pressure drop is computed as:
</p>
<blockquote><pre>
dp = λ(Re,Δ)*(L/D)*ρ*v*|v|/2
= λ(Re,Δ)*8*L/(π^2*D^5*ρ)*m_flow*|m_flow|
= λ2(Re,Δ)*k2*sign(m_flow);
with
Re = |v|*D*ρ/μ
= |m_flow|*4/(π*D*μ)
m_flow = A*v*ρ
A = π*(D/2)^2
λ2 = λ*Re^2
k2 = L*μ^2/(2*D^3*ρ)
</pre></blockquote>
<p>
where
</p>
<ul>
<li> L is the length of the pipe.</li>
<li> D is the diameter of the pipe. If the pipe has not a
circular cross section, D = 4*A/P, where A is the cross section
area and P is the wetted perimeter.</li>
<li> λ = λ(Re,Δ) is the \"usual\" wall friction coefficient.</li>
<li> λ2 = λ*Re^2 is the used friction coefficient to get a numerically
well-posed formulation.</li>
<li> Re = |v|*D*ρ/μ is the Reynolds number.</li>
<li> Δ = δ/D is the relative roughness where
\"δ\" is
the absolute \"roughness\", i.e., the averaged height of asperities in the pipe
(δ may change over time due to growth of surface asperities during
service, see <em>[Idelchik 1994, p. 85, Tables 2-1, 2-2])</em>.</li>
<li> ρ is the upstream density.</li>
<li> μ is the upstream dynamic viscosity.</li>
<li> v is the mean velocity.</li>
</ul>
<p>
The first form with λ is used and presented in textbooks,
see \"blue\" curve in the next figure:
</p>
<div>
<img src=\"modelica://Modelica/Resources/Images/Fluid/Pipes/BaseClasses/PipeFriction1.png\" alt=\"PipeFriction1\">
</div>
<p>
This form is not suited for a simulation program since
λ = 64/Re if Re < 2000, i.e., a division by zero occurs for
zero mass flow rate because Re = 0 in this case.
More useful for a simulation model is the friction coefficient
λ2 = λ*Re^2, because λ2 = 64*Re if Re < 2000 and
therefore no problems for zero mass flow rate occur.
The characteristic of λ2 is shown in the next figure and is
used in Modelica.Fluid:
</p>
<div>
<img src=\"modelica://Modelica/Resources/Images/Fluid/Pipes/BaseClasses/PipeFriction2.png\" alt=\"PipeFriction2\">
</div>
<p>
The pressure loss characteristic is divided into three regions:
</p>
<ul>
<li> <strong>Region 1</strong>:
For <strong>Re ≤ 2000</strong>, the flow is <strong>laminar</strong> and the exact solution of the
3-dim. Navier-Stokes equations (momentum and mass balance) is used under the
assumptions of steady flow, constant pressure gradient and constant
density and viscosity (= Hagen-Poiseuille flow) leading to λ2 = 64*Re.
Therefore:
<blockquote><pre>
dp = 128*μ*L/(π*D^4*ρ)*m_flow
</pre></blockquote>
</li>
<li> <strong>Region 3</strong>:
For <strong>Re ≥ 4000</strong>, the flow is <strong>turbulent</strong>.
Depending on the calculation direction (see \"inverse formulation\"
below) either of two explicit equations are used. If the pressure drop dp
is assumed to be known, λ2 = |dp|/k2. The
Colebrook-White equation
<em>[Colebrook 1939; Idelchik 1994, p. 83, eq. (2-9)]</em>:
<blockquote><pre>1/sqrt(λ) = -2*lg( 2.51/(Re*sqrt(λ)) + 0.27*Δ)</pre></blockquote>
gives an implicit relationship between Re and λ.
Inserting λ2 = λ*Re^2 allows to solve this equation analytically
for Re: <blockquote><pre>Re = -2*sqrt(λ2)*lg(2.51/sqrt(λ2) + 0.27*Δ)</pre></blockquote>
Finally, the mass flow rate m_flow is computed from Re via
m_flow = Re*π*D*μ/4*sign(dp).
These are the <strong>red</strong> curves in the diagrams above.<br>
If the mass flow rate is assumed known (and therefore implicitly
also the Reynolds number), then λ2 is computed by an
approximation of the inverse of the Colebrook-White equation
<em>[Swamee and Jain 1976;
Miller 1990, p. 191, eq.(8.4)]</em> adapted to λ2:
<blockquote><pre>
λ2 = 0.25*(Re/lg(Δ/3.7 + 5.74/Re^0.9))^2
</pre></blockquote>
The pressure drop is then computed as dp = k2*λ2*sign(m_flow).
These are the <strong>blue</strong> curves in the diagrams above.<br> </li>
<li> <strong>Region 2</strong>:
For <strong>2000 ≤ Re ≤ 4000</strong> there is a transition region between laminar
and turbulent flow. The value of λ2 depends on more factors as just
the Reynolds number and the relative roughness, therefore only crude
approximations are possible in this area.<br>
The deviation from the laminar region depends on the
relative roughness. A laminar flow at Re=2000 is only reached for smooth pipes.
The deviation Reynolds number Re1 is computed according to
<em>[Samoilenko 1968; Idelchik 1994, p. 81, sect. 2.1.21]</em> as:
<blockquote><pre>Re1 = 745*e^(if Δ ≤ 0.0065 then 1 else 0.0065/Δ)</pre></blockquote>
These are the <strong>blue</strong> curves in the diagrams above.<br>
Between Re1=Re1(δ/D) and Re2=4000,
λ2 is approximated by a cubic
polynomial in the \"lg(λ2) - lg(Re)\" chart (see figures above) such that the
first derivative is continuous at these two points. In order to avoid
the solution of non-linear equations, two different cubic polynomials are used
for the direct and the inverse formulation. This leads to some discrepancies
in λ2 (= differences between the red and the blue curves).
This is acceptable, because the transition region is anyway not
precisely known since the actual friction coefficient depends on
additional factors and since the operating points are usually
not in this region.</li>
</ul>
<p>
The absolute roughness δ has usually to
be estimated. In <em>[Idelchik 1994, pp. 105-109,
Table 2-5; Miller 1990, p. 190, Table 8-1]</em> many examples are given.
As a short summary:
</p>
<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\">
<tr><td><strong>Smooth pipes</strong></td>
<td>Drawn brass, copper, aluminium, glass, etc.</td>
<td>δ = 0.0025 mm</td>
</tr>
<tr><td rowspan=\"3\"><strong>Steel pipes</strong></td>
<td>New smooth pipes</td>
<td>δ = 0.025 mm</td>
</tr>
<tr><td>Mortar lined, average finish</td>
<td>δ = 0.1 mm</td>
</tr>
<tr><td>Heavy rust</td>
<td>δ = 1 mm</td>
</tr>
<tr><td rowspan=\"3\"><strong>Concrete pipes</strong></td>
<td>Steel forms, first class workmanship</td>
<td>δ = 0.025 mm</td>
</tr>
<tr><td>Steel forms, average workmanship</td>
<td>δ = 0.1 mm</td>
</tr>
<tr><td>Block linings</td>
<td>δ = 1 mm</td>
</tr>
</table>
<p>
The equations above are valid for incompressible flow.
They can also be applied for <strong>compressible</strong> flow up to about <strong>Ma = 0.6</strong>
(Ma is the Mach number) with a maximum error in λ of about 3 %.
The effect of gas compressibility in a wide region can be taken into
account by the following formula derived by Voronin
<em>[Voronin 1959; Idelchik 1994, p. 97, sect. 2.1.81]</em>:
</p>
<blockquote><pre>
λ_comp = λ*(1 + (κ-1)/2 * Ma^2)^(-0.47)
</pre></blockquote>
<p>
where κ is the isentropic coefficient
(for ideal gases, κ is the ratio of specific heat capacities cp/cv).
An appreciable decrease in the coefficient \"λ_comp\" is observed
only in a narrow transonic region and also at supersonic flow velocities
by about 15% <em>[Idelchik 1994, p. 97, sect. 2.1.81]</em>.
This effect is not yet included in Modelica.Fluid.
Another restriction is that the pressure drop model is valid
only for steady state or slowly changing mass flow rate.
For large fluid acceleration, the pressure drop depends additionally
on the frequency of the changing mass flow rate.
</p>
<h4>Inverse formulation</h4>
<p>
In the \"Advanced menu\" it is possible via parameter
\"from_dp\" to define in which form the
pressure drop equation is actually evaluated (<strong>default</strong> is from_dp = <strong>true</strong>):
</p>
<blockquote><pre>
from_dp = <strong>true</strong>: m_flow = f1(dp)
= <strong>false</strong>: dp = f2(m_flow)
</pre></blockquote>
<p>
\"from_dp\" can be useful to avoid nonlinear systems of equations
in cases where the inverse pressure loss function is needed.
</p>
<h4>Summary</h4>
<p>
A detailed pressure drop model for pipe wall friction is
provided in the form m_flow = f1(dp, Δ) or
dp = f2(m_flow, Δ).
These functions are continuous and differentiable,
are provided in an explicit form without solving non-linear equations,
and do behave well also at small mass flow rates. This pressure drop
model can be used stand-alone in a static momentum balance and in
a dynamic momentum balance as the friction pressure drop term.
It is valid for incompressible and compressible flow up to a Mach number of 0.6.
</p>
<h4>References</h4>
<dl><dt>Colebrook F. (1939):</dt>
<dd><strong>Turbulent flow in pipes with particular reference to the transition
region between the smooth and rough pipe laws</strong>.
J. Inst. Civ. Eng. no. 4, 14-25.</dd>
<dt>Idelchik I.E. (1994):</dt>
<dd><a href=\"http://www.bookfinder.com/dir/i/Handbook_of_Hydraulic_Resistance/0849399084/\"><strong>Handbook of Hydraulic Resistance</strong></a>. 3rd edition, Begell House, ISBN 0-8493-9908-4</dd>
<dt>Miller D. S. (1990):</dt>
<dd><strong>Internal flow systems</strong>.
2nd edition. Cranfield:BHRA(Information Services).</dd>
<dt>Samoilenko L.A. (1968):</dt>
<dd><strong>Investigation of the Hydraulic Resistance of Pipelines in the
Zone of Transition from Laminar into Turbulent Motion</strong>.
Thesis (Cand. of Technical Science), Leningrad.</dd>
<dt>Swamee P.K. and Jain A.K. (1976):</dt>
<dd><strong>Explicit equations for pipe-flow problems</strong>.
Proc. ASCE, J.Hydraul. Div., 102 (HY5), pp. 657-664.</dd>
<dt>Voronin F.S. (1959):</dt>
<dd><strong>Effect of contraction on the friction coefficient in a
turbulent gas flow</strong>.
Inzh. Fiz. Zh., vol. 2, no. 11, pp. 81-85.</dd>
</dl>
</html>"));
end WallFriction;
class ValveCharacteristics "Valve characteristics"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
The control valves in
<a href=\"modelica://Modelica.Fluid.Valves\">Modelica.Fluid.Valves</a>
have the parameters <strong>Kv</strong> and <strong>Cv</strong>. They are defined
as unit-less variables, but in the description text a unit
is given. The reason for this definition is the following:
</p>
<p>
The basic equation for valves is:
</p>
<blockquote><pre>
q = Av*sqrt(dp/rho)
</pre></blockquote>
<p>
In SI units, [q] is m3/s, [dp] is Pascal, [rho] is [kg/m3], and Av is an area, thus [Av] = m2. Basically, the equation stems from Bernoulli's law. Av is roughly 1.4 times the area of the valve throat. Now, usually valves aren't so big that their throat area is of the order of magnitude of square meters - depending on the applications it is from a few square millimeters to a few square centimeters. Therefore, in the common engineering practice, the following equations are used:
</p>
<p>
Europe:
</p>
<blockquote><pre>
q = Kv sqrt(dp/(rho/rho0)) , with [q] = m3/h, [dp] = bar
</pre></blockquote>
<p>
US:
</p>
<blockquote><pre>
q = Cv sqrt(dp/(rho/rho0)) , with [q] = USG/min, [dp] = psi
</pre></blockquote>
<p>
In both cases rho0 is the density of cold water at 4 °C, 999 kg/m3. Note that these equations use relative, not absolute densities.
</p>
<p>
It turns out that Kv = 1e6/27.7*Av and Cv = 1e6/24*Av, so both US and EU engineers get more or less the same numbers (just by sheer luck), with a range between a few units and a few hundred units for typical industrial applications, and everybody is happy.
</p>
<p>
Now, we've got two problems here. First, depending on the unit, we change the equation: with SI units, we use the density, with non-SI units, we use the relative density. So the quantities (not only the units!) of Av and Cv/Kv are different.
</p>
<p>
Second, the units of Kv and Cv are usually labeled \"m3/h\" and \"USG/min\", but as a matter of fact they are different, as can be seen from the equations above: they are actually
m3/(h*sqrt(bar)) and USG/(min*sqrt(psi)). If I have a valve with Kv = 10 m3/h, it means I get 10 m3/h \"for a pressure drop of 1 bar\". Unfortunately, this is not correct from the point of view of strict dimensional analysis, but nobody uses sqrt(Pa) or sqrt(bar).
</p>
<p>
You might think this is crazy (it is, especially when you try to explain it), but as a matter of fact the valve coefficient is <strong>never</strong> given in square meters in any catalog or datasheet; Cv is still the most used (even in Europe), followed by Kv. So, it will be very inconvenient for users to type in Av in square meters.
</p>
<p>
The pragmatic approach used in Modelica.Fluid.ControlValves is to accept the fact that m3/h and USG/min are not the real units of Cv and Kv, so we can't use the general unit conversion mechanism, put them just as mnemonic labels in the comment, use non-dimensional coefficients in the interface, and then define properly dimensioned unit conversion within the model
</p>
</html>"));
end ValveCharacteristics;
annotation (Documentation(info="<html>
<p>
In this section it is described how the components
of the Modelica.Fluid library are implemented.
If you would like to introduce new components either in
Modelica.Fluid or your own library, you should be aware
of the issues discussed in this section.
</p>
<p>
This section is partly based on the following paper:
</p>
<dl>
<dt> Elmqvist H., Tummescheit H., and Otter M.:</dt>
<dd> <strong>Object-Oriented Modeling of Thermo-Fluid Systems</strong>.
Modelica 2003 Conference, Linköping, Sweden,
pp. 269-286, Nov. 3-4, 2003.
Download from:
<a href=\"https://www.modelica.org/events/Conference2003/papers/h40_Elmqvist_fluid.pdf\">https://www.modelica.org/events/Conference2003/papers/h40_Elmqvist_fluid.pdf</a>
</dd>
</dl>
Please note that the design of the connectors has been changed with respect to the design presented in that paper.
</html>"));
end ComponentDefinition;
package BuildingSystemModels "Building system models"
extends Modelica.Icons.Information;
class SystemComponent "System component"
extends Modelica.Icons.Information;
annotation (Documentation(info="<html>
<p>
The Modelica.Fluid library is designed so that each model of a system must
include an instance <code>system</code> of the <code>System</code> component at the top level, in the same way as the <code>World</code> model of the MultiBody Library. The System component contains the parameters that
describe the environment surrounding the components (ambient pressure and
temperature, gravity acceleration), and also provides default settings
for many parameters which are used consistently by the models in the library.
These parameters are then propagated to the individual components
using the inner/outer variable mechanism. In case the system model is structured
hierarchically, it is possible to either put a single System
component at the top level, or possibly to put many of them at different levels,
which will only influence the system components from that level down.
</p>
<p>All the parameters defined in the System model are used as default values for the parameters of the individual components of the system model. Note that it is always possible to override these defaults locally by changing the value of the parameters in the specific component instance.