tespy 0.3.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,507 @@
1
+ # -*- coding: utf-8
2
+
3
+ """Module for basic components.
4
+
5
+ Components in this module:
6
+
7
+ - :func:`tespy.components.basics.source`
8
+ - :func:`tespy.components.basics.sink`
9
+ - :func:`tespy.components.basics.subsystem_interface`
10
+ - :func:`tespy.components.basics.cycle_closer`
11
+
12
+
13
+ This file is part of project TESPy (github.com/oemof/tespy). It's copyrighted
14
+ by the contributors recorded in the version control history of the file,
15
+ available from its original location tespy/components/basics.py
16
+
17
+ SPDX-License-Identifier: MIT
18
+ """
19
+
20
+ import numpy as np
21
+
22
+ from tespy.components.components import component
23
+ from tespy.tools.data_containers import dc_cp
24
+ from tespy.tools.data_containers import dc_simple
25
+
26
+ # %%
27
+
28
+
29
+ class cycle_closer(component):
30
+ r"""
31
+ Component for closing cycles.
32
+
33
+ Equations
34
+
35
+ **mandatory equations**
36
+
37
+ .. math::
38
+
39
+ 0 = p_{in} - p_{out}
40
+
41
+ 0 = h_{in} - h_{out}
42
+
43
+ Image not available
44
+
45
+ Parameters
46
+ ----------
47
+ label : str
48
+ The label of the component.
49
+
50
+ design : list
51
+ List containing design parameters (stated as String).
52
+
53
+ offdesign : list
54
+ List containing offdesign parameters (stated as String).
55
+
56
+ design_path: str
57
+ Path to the components design case.
58
+
59
+ local_offdesign : boolean
60
+ Treat this component in offdesign mode in a design calculation.
61
+
62
+ local_design : boolean
63
+ Treat this component in design mode in an offdesign calculation.
64
+
65
+ char_warnings: boolean
66
+ Ignore warnings on default characteristics usage for this component.
67
+
68
+ printout: boolean
69
+ Include this component in the network's results printout.
70
+
71
+ Note
72
+ ----
73
+ This component can be used to close a cycle process. The system of
74
+ equations describing your plant will overdetermined, if you close a cycle
75
+ without this component or a cut the cycle with a sink and a source at
76
+ some point of the cycle. This component can be used instead of cutting
77
+ the cycle.
78
+
79
+ Example
80
+ -------
81
+ Create a cycle containing a pump and a pipe. The pump increases pressure
82
+ the pipe cools the liquid and destroys the pressure rise. The heat
83
+ extracted at the pipe must be the same value of the power input at the
84
+ pump (but negative), as there is no other in- or outputs of energy in the
85
+ system.
86
+
87
+ >>> from tespy.components import cycle_closer, pipe, pump
88
+ >>> from tespy.connections import connection
89
+ >>> from tespy.networks import network
90
+ >>> nw = network(['water'], p_unit='bar', T_unit='C', iterinfo=False)
91
+ >>> pi = pipe('pipe')
92
+ >>> pu = pump('pump')
93
+ >>> cc = cycle_closer('cycle closing component')
94
+ >>> cc.component()
95
+ 'cycle closer'
96
+ >>> pu_pi = connection(pu, 'out1', pi, 'in1')
97
+ >>> pi_cc = connection(pi, 'out1', cc, 'in1')
98
+ >>> cc_pu = connection(cc, 'out1', pu, 'in1')
99
+ >>> nw.add_conns(pu_pi, pi_cc, cc_pu)
100
+ >>> pi_cc.set_attr(p=1, T=20, fluid={'water': 1})
101
+ >>> pu_pi.set_attr(p=10)
102
+ >>> pu.set_attr(eta_s=0.8, P=1000)
103
+ >>> nw.solve('design')
104
+ >>> round(pi.Q.val, 1) == -round(pu.P.val, 1)
105
+ True
106
+ """
107
+
108
+ @staticmethod
109
+ def component():
110
+ return 'cycle closer'
111
+
112
+ @staticmethod
113
+ def attr():
114
+ return {
115
+ 'mass_deviation': dc_cp(val=0, max_val=1e-3, printout=False),
116
+ 'fluid_deviation': dc_cp(val=0, max_val=1e-5, printout=False)
117
+ }
118
+
119
+ @staticmethod
120
+ def inlets():
121
+ return ['in1']
122
+
123
+ @staticmethod
124
+ def outlets():
125
+ return ['out1']
126
+
127
+ def comp_init(self, nw):
128
+
129
+ component.comp_init(self, nw)
130
+
131
+ # number of mandatroy equations for
132
+ # pressure: 1
133
+ # enthalpy: 1
134
+ self.num_eq = 2
135
+
136
+ self.jacobian = np.zeros((
137
+ self.num_eq,
138
+ self.num_i + self.num_o + self.num_vars,
139
+ self.num_nw_vars))
140
+
141
+ self.residual = np.ones(self.num_eq)
142
+ # derivatives for pressure
143
+ self.jacobian[0, 0, 1] = 1
144
+ self.jacobian[0, 1, 1] = -1
145
+ # derivatives for enthalpy
146
+ self.jacobian[1, 0, 2] = 1
147
+ self.jacobian[1, 1, 2] = -1
148
+
149
+ def equations(self):
150
+ r"""Calculate residual vector with results of equations."""
151
+ k = 0
152
+ ######################################################################
153
+ # equation for pressure
154
+ self.residual[k] = self.inl[0].p.val_SI - self.outl[0].p.val_SI
155
+ k += 1
156
+
157
+ ######################################################################
158
+ # equation for enthalpy
159
+ self.residual[k] = self.inl[0].h.val_SI - self.outl[0].h.val_SI
160
+ k += 1
161
+
162
+ def derivatives(self, vek_z):
163
+ r"""Calculate partial derivatives for given equations."""
164
+ ######################################################################
165
+ # all derivatives are static
166
+
167
+ def calc_parameters(self):
168
+
169
+ # calculate deviation in mass flow
170
+ self.mass_deviation.val = np.abs(
171
+ self.inl[0].m.val_SI - self.outl[0].m.val_SI)
172
+
173
+ # calculate deviation in fluid composition
174
+ d1 = self.inl[0].fluid.val
175
+ d2 = self.outl[0].fluid.val
176
+ diff = [d1[key] - d2[key] for key in d1.keys()]
177
+ self.fluid_deviation.val = np.linalg.norm(diff)
178
+
179
+ self.check_parameter_bounds()
180
+
181
+ # %%
182
+
183
+
184
+ class sink(component):
185
+ r"""
186
+ A flow drains in a sink.
187
+
188
+ Equations
189
+ This component is unconstrained.
190
+
191
+ Parameters
192
+ ----------
193
+ label : str
194
+ The label of the component.
195
+
196
+ design : list
197
+ List containing design parameters (stated as String).
198
+
199
+ offdesign : list
200
+ List containing offdesign parameters (stated as String).
201
+
202
+ design_path: str
203
+ Path to the components design case.
204
+
205
+ local_offdesign : boolean
206
+ Treat this component in offdesign mode in a design calculation.
207
+
208
+ local_design : boolean
209
+ Treat this component in design mode in an offdesign calculation.
210
+
211
+ char_warnings: boolean
212
+ Ignore warnings on default characteristics usage for this component.
213
+
214
+ printout: boolean
215
+ Include this component in the network's results printout.
216
+
217
+ Example
218
+ -------
219
+ Create a sink and specify a label.
220
+
221
+ >>> from tespy.components import sink
222
+ >>> si = sink('a labeled sink')
223
+ >>> si.component()
224
+ 'sink'
225
+ >>> si.label
226
+ 'a labeled sink'
227
+ """
228
+
229
+ @staticmethod
230
+ def component():
231
+ return 'sink'
232
+
233
+ @staticmethod
234
+ def inlets():
235
+ return ['in1']
236
+
237
+ # %%
238
+
239
+
240
+ class source(component):
241
+ r"""
242
+ A flow originates from a source.
243
+
244
+ Equations
245
+ This component is unconstrained.
246
+
247
+ Parameters
248
+ ----------
249
+ label : str
250
+ The label of the component.
251
+
252
+ design : list
253
+ List containing design parameters (stated as String).
254
+
255
+ offdesign : list
256
+ List containing offdesign parameters (stated as String).
257
+
258
+ design_path: str
259
+ Path to the components design case.
260
+
261
+ local_offdesign : boolean
262
+ Treat this component in offdesign mode in a design calculation.
263
+
264
+ local_design : boolean
265
+ Treat this component in design mode in an offdesign calculation.
266
+
267
+ char_warnings: boolean
268
+ Ignore warnings on default characteristics usage for this component.
269
+
270
+ printout: boolean
271
+ Include this component in the network's results printout.
272
+
273
+ Example
274
+ -------
275
+ Create a source and specify a label.
276
+
277
+ >>> from tespy.components import source
278
+ >>> so = source('a labeled source')
279
+ >>> so.component()
280
+ 'source'
281
+ >>> so.label
282
+ 'a labeled source'
283
+ """
284
+
285
+ @staticmethod
286
+ def component():
287
+ return 'source'
288
+
289
+ @staticmethod
290
+ def outlets():
291
+ return ['out1']
292
+
293
+ # %%
294
+
295
+
296
+ class subsystem_interface(component):
297
+ r"""
298
+ The subsystem interface does not change fluid properties.
299
+
300
+ Equations
301
+
302
+ **mandatory equations**
303
+
304
+ .. math:: 0 = fluid_{i,in_{j}} - fluid_{i,out_{j}} \;
305
+ \forall i \in \mathrm{fluid}, \; \forall j \in inlets/outlets
306
+
307
+ .. math:: 0 = \dot{m}_{in_{j}} - \dot{m}_{out_{j}} \;
308
+ \forall j \in inlets/outlets
309
+
310
+ .. math:: 0 = p_{in_{j}} - p_{out_{j}} \;
311
+ \forall j \in inlets/outlets
312
+
313
+ .. math:: 0 = h_{in_{j}} - h_{out_{j}} \;
314
+ \forall j \in inlets/outlets
315
+
316
+ Inlets/Outlets
317
+
318
+ - Specify number of inlets and outlets with :code:`num_inter`,
319
+ predefined value: 1.
320
+
321
+ Image
322
+
323
+ .. image:: _images/subsys_interface.svg
324
+ :scale: 100 %
325
+ :alt: alternative text
326
+ :align: center
327
+
328
+ Parameters
329
+ ----------
330
+ label : str
331
+ The label of the component.
332
+
333
+ design : list
334
+ List containing design parameters (stated as String).
335
+
336
+ offdesign : list
337
+ List containing offdesign parameters (stated as String).
338
+
339
+ design_path: str
340
+ Path to the components design case.
341
+
342
+ local_offdesign : boolean
343
+ Treat this component in offdesign mode in a design calculation.
344
+
345
+ local_design : boolean
346
+ Treat this component in design mode in an offdesign calculation.
347
+
348
+ char_warnings: boolean
349
+ Ignore warnings on default characteristics usage for this component.
350
+
351
+ printout: boolean
352
+ Include this component in the network's results printout.
353
+
354
+ num_inter : float/tespy.tools.data_containers.dc_simple
355
+ Number of interfaces for subsystem.
356
+
357
+ Note
358
+ ----
359
+ This component passes all fluid properties and mass flow from its inlet to
360
+ the outlet.
361
+
362
+ Example
363
+ -------
364
+ As connections can only connect a component with a different
365
+ component, the subsystem interface is used to connect subsystems with the
366
+ rest of your network. It is necessary to specify the number of interfaces
367
+ of the subsystem interface, if you want any number other than 1. We will
368
+ not go in depth of subsystem usage in this example. Please refer to
369
+ :ref:`this section <tespy_subsystems_label>` for more information on
370
+ building your own subsystems.
371
+
372
+ >>> from tespy.components import sink, source, subsystem_interface
373
+ >>> from tespy.connections import connection
374
+ >>> from tespy.networks import network
375
+ >>> fluids = ['H2O', 'N2']
376
+ >>> nw = network(fluids=fluids)
377
+ >>> nw.set_attr(p_unit='bar', T_unit='C', h_unit='kJ / kg', iterinfo=False)
378
+ >>> so = source('source 1')
379
+ >>> si = sink('sink 1')
380
+ >>> IF = subsystem_interface('subsystem interface', num_inter=1)
381
+ >>> IF.component()
382
+ 'subsystem interface'
383
+ >>> len(IF.inlets())
384
+ 1
385
+
386
+ Add the subsystem the interface to a minimal network containing only a
387
+ source and a sink. The interface does not change the fluid properties
388
+ in any way.
389
+
390
+ >>> inc = connection(so, 'out1', IF, 'in1')
391
+ >>> outg = connection(IF, 'out1', si, 'in1')
392
+ >>> nw.add_conns(inc, outg)
393
+ >>> inc.set_attr(fluid={'H2O': 1, 'N2': 0}, T=40, p=3, m=100)
394
+ >>> nw.solve('design')
395
+ >>> inc.m.val_SI == outg.m.val_SI
396
+ True
397
+ >>> inc.h.val_SI == outg.h.val_SI
398
+ True
399
+ """
400
+
401
+ @staticmethod
402
+ def component():
403
+ return 'subsystem interface'
404
+
405
+ @staticmethod
406
+ def attr():
407
+ return {'num_inter': dc_simple()}
408
+
409
+ def inlets(self):
410
+ if self.num_inter.is_set:
411
+ return ['in' + str(i + 1) for i in range(self.num_inter.val)]
412
+ else:
413
+ return ['in1']
414
+
415
+ def outlets(self):
416
+ if self.num_inter.is_set:
417
+ return ['out' + str(i + 1) for i in range(self.num_inter.val)]
418
+ else:
419
+ return ['out1']
420
+
421
+ def comp_init(self, nw):
422
+
423
+ component.comp_init(self, nw)
424
+
425
+ # number of mandatroy equations for
426
+ # fluid: num_inter * num_nw_fluids
427
+ # mass flow: num_inter
428
+ # pressure: num_inter
429
+ # enthalpy: num_inter
430
+ self.num_eq = (self.num_nw_fluids + 3) * self.num_i
431
+
432
+ self.jacobian = np.zeros((
433
+ self.num_eq,
434
+ 2 * self.num_i,
435
+ self.num_nw_vars))
436
+
437
+ self.residual = np.ones(self.num_eq)
438
+ stop = self.num_nw_fluids * self.num_i
439
+ self.jacobian[0:stop] = self.fluid_deriv()
440
+ start = stop
441
+ stop = start + self.num_i
442
+ self.jacobian[start:stop] = self.inout_deriv(0)
443
+ start = stop
444
+ stop = start + self.num_i
445
+ self.jacobian[start:stop] = self.inout_deriv(1)
446
+ start = stop
447
+ stop = start + self.num_i
448
+ self.jacobian[start:stop] = self.inout_deriv(2)
449
+
450
+ def equations(self):
451
+ r"""Calculate residual vector with results of equations."""
452
+ k = 0
453
+ ######################################################################
454
+ # eqations for fluids
455
+ for i in range(self.num_i):
456
+ for fluid, x in self.inl[i].fluid.val.items():
457
+ self.residual[k] = x - self.outl[i].fluid.val[fluid]
458
+ k += 1
459
+
460
+ ######################################################################
461
+ # equations for mass flow
462
+ for i in range(self.num_i):
463
+ self.residual[k] = self.inl[i].m.val_SI - self.outl[i].m.val_SI
464
+ k += 1
465
+
466
+ ######################################################################
467
+ # equations for pressure
468
+ for i in range(self.num_i):
469
+ self.residual[k] = self.inl[i].p.val_SI - self.outl[i].p.val_SI
470
+ k += 1
471
+
472
+ ######################################################################
473
+ # equations for enthalpy
474
+ for i in range(self.num_i):
475
+ self.residual[k] = self.inl[i].h.val_SI - self.outl[i].h.val_SI
476
+ k += 1
477
+
478
+ ######################################################################
479
+
480
+ def derivatives(self, vek_z):
481
+ r"""Calculate partial derivatives for given equations."""
482
+ ######################################################################
483
+ # all derivatives are static
484
+
485
+ def inout_deriv(self, pos):
486
+ r"""
487
+ Calculate partial derivatives.
488
+
489
+ Method applies for all mass flow, pressure and enthalpy equations.
490
+
491
+ Parameters
492
+ ----------
493
+ pos : int
494
+ Position of the variable in the matrix of derivatives.
495
+ mass flow: 0, pressure: 1, enthalpy: 2.
496
+
497
+ Returns
498
+ -------
499
+ deriv : list
500
+ Matrix with partial derivatives for the fluid equations.
501
+ """
502
+ deriv = np.zeros((self.num_i, 2 * self.num_i, self.num_nw_vars))
503
+ for i in range(self.num_i):
504
+ deriv[i, i, pos] = 1
505
+ for j in range(self.num_i):
506
+ deriv[j, j + self.num_i, pos] = -1
507
+ return deriv