physioblocks 1.0.0__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.
Files changed (93) hide show
  1. physioblocks/__init__.py +37 -0
  2. physioblocks/base/__init__.py +27 -0
  3. physioblocks/base/operators.py +176 -0
  4. physioblocks/base/registers.py +108 -0
  5. physioblocks/computing/__init__.py +47 -0
  6. physioblocks/computing/assembling.py +291 -0
  7. physioblocks/computing/models.py +811 -0
  8. physioblocks/computing/quantities.py +354 -0
  9. physioblocks/configuration/__init__.py +38 -0
  10. physioblocks/configuration/aliases.py +203 -0
  11. physioblocks/configuration/base.py +123 -0
  12. physioblocks/configuration/computing/__init__.py +27 -0
  13. physioblocks/configuration/computing/quantities.py +56 -0
  14. physioblocks/configuration/constants.py +121 -0
  15. physioblocks/configuration/description/__init__.py +33 -0
  16. physioblocks/configuration/description/blocks.py +239 -0
  17. physioblocks/configuration/description/nets.py +155 -0
  18. physioblocks/configuration/functions.py +695 -0
  19. physioblocks/configuration/simulation/__init__.py +32 -0
  20. physioblocks/configuration/simulation/simulations.py +280 -0
  21. physioblocks/description/__init__.py +34 -0
  22. physioblocks/description/blocks.py +418 -0
  23. physioblocks/description/flux.py +157 -0
  24. physioblocks/description/nets.py +746 -0
  25. physioblocks/io/__init__.py +29 -0
  26. physioblocks/io/aliases.py +73 -0
  27. physioblocks/io/configuration.py +125 -0
  28. physioblocks/launcher/__main__.py +285 -0
  29. physioblocks/launcher/configuration.py +231 -0
  30. physioblocks/launcher/configure/__main__.py +99 -0
  31. physioblocks/launcher/constants.py +105 -0
  32. physioblocks/launcher/files.py +150 -0
  33. physioblocks/launcher/series.py +165 -0
  34. physioblocks/library/__init__.py +27 -0
  35. physioblocks/library/aliases/blocks/c_block.json +5 -0
  36. physioblocks/library/aliases/blocks/rc_block.json +5 -0
  37. physioblocks/library/aliases/blocks/rcr_block.json +5 -0
  38. physioblocks/library/aliases/blocks/spherical_cavity_block.json +5 -0
  39. physioblocks/library/aliases/blocks/valve_rl_block.json +5 -0
  40. physioblocks/library/aliases/flux/heart_flux_dof_couples.jsonc +4 -0
  41. physioblocks/library/aliases/model_components/active_law_macro_huxley_two_moments.json +5 -0
  42. physioblocks/library/aliases/model_components/rheology_fiber_additive.json +5 -0
  43. physioblocks/library/aliases/model_components/spherical_dynamics.json +5 -0
  44. physioblocks/library/aliases/model_components/velocity_law_hht.json +5 -0
  45. physioblocks/library/aliases/nets/circulation_alone_net.json +31 -0
  46. physioblocks/library/aliases/nets/spherical_heart_net.json +93 -0
  47. physioblocks/library/aliases/simulations/circulation_alone_forward_simulation.jsonc +55 -0
  48. physioblocks/library/aliases/simulations/default_forward_simulation.jsonc +7 -0
  49. physioblocks/library/aliases/simulations/default_time.jsonc +8 -0
  50. physioblocks/library/aliases/simulations/newton_method_solver.json +5 -0
  51. physioblocks/library/aliases/simulations/spherical_heart_forward_simulation.jsonc +157 -0
  52. physioblocks/library/aliases/simulations/spherical_heart_with_respiration_forward_simulation.jsonc +45 -0
  53. physioblocks/library/blocks/__init__.py +27 -0
  54. physioblocks/library/blocks/capacitances.py +516 -0
  55. physioblocks/library/blocks/cavity.py +192 -0
  56. physioblocks/library/blocks/valves.py +281 -0
  57. physioblocks/library/functions/__init__.py +27 -0
  58. physioblocks/library/functions/base_operations.py +129 -0
  59. physioblocks/library/functions/first_order.py +113 -0
  60. physioblocks/library/functions/piecewise.py +271 -0
  61. physioblocks/library/functions/trigonometric.py +78 -0
  62. physioblocks/library/functions/watchers.py +113 -0
  63. physioblocks/library/model_components/__init__.py +27 -0
  64. physioblocks/library/model_components/active_law.py +345 -0
  65. physioblocks/library/model_components/dynamics.py +986 -0
  66. physioblocks/library/model_components/rheology.py +160 -0
  67. physioblocks/library/model_components/velocity_law.py +169 -0
  68. physioblocks/references/circulation_alone_sim.jsonc +24 -0
  69. physioblocks/references/spherical_heart_respiration_sim.jsonc +33 -0
  70. physioblocks/references/spherical_heart_sim.jsonc +29 -0
  71. physioblocks/registers/__init__.py +32 -0
  72. physioblocks/registers/load_function_register.py +93 -0
  73. physioblocks/registers/save_function_register.py +106 -0
  74. physioblocks/registers/type_register.py +97 -0
  75. physioblocks/simulation/__init__.py +48 -0
  76. physioblocks/simulation/constants.py +30 -0
  77. physioblocks/simulation/functions.py +71 -0
  78. physioblocks/simulation/runtime.py +484 -0
  79. physioblocks/simulation/saved_quantities.py +129 -0
  80. physioblocks/simulation/setup.py +576 -0
  81. physioblocks/simulation/solvers.py +235 -0
  82. physioblocks/simulation/state.py +340 -0
  83. physioblocks/simulation/time_manager.py +354 -0
  84. physioblocks/utils/__init__.py +27 -0
  85. physioblocks/utils/dynamic_import_utils.py +150 -0
  86. physioblocks/utils/exceptions_utils.py +115 -0
  87. physioblocks/utils/gradient_test_utils.py +337 -0
  88. physioblocks/utils/math_utils.py +109 -0
  89. physioblocks-1.0.0.dist-info/METADATA +127 -0
  90. physioblocks-1.0.0.dist-info/RECORD +93 -0
  91. physioblocks-1.0.0.dist-info/WHEEL +4 -0
  92. physioblocks-1.0.0.dist-info/licenses/licenses/GPL-3.0-only.txt +674 -0
  93. physioblocks-1.0.0.dist-info/licenses/licenses/LGPL-3.0-only.txt +165 -0
@@ -0,0 +1,27 @@
1
+ # SPDX-FileCopyrightText: Copyright INRIA
2
+ #
3
+ # SPDX-License-Identifier: LGPL-3.0-only
4
+ #
5
+ # Copyright INRIA
6
+ #
7
+ # This file is part of PhysioBlocks, a library mostly developed by the
8
+ # [Ananke project-team](https://team.inria.fr/ananke) at INRIA.
9
+ #
10
+ # Authors:
11
+ # - Colin Drieu
12
+ # - Dominique Chapelle
13
+ # - François Kimmig
14
+ # - Philippe Moireau
15
+ #
16
+ # PhysioBlocks is free software: you can redistribute it and/or modify it under the
17
+ # terms of the GNU Lesser General Public License as published by the Free Software
18
+ # Foundation, version 3 of the License.
19
+ #
20
+ # PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
+ # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
23
+ #
24
+ # You should have received a copy of the GNU Lesser General Public License along with
25
+ # PhysioBlocks. If not, see <https://www.gnu.org/licenses/>.
26
+
27
+ """Module defining the available base blocks"""
@@ -0,0 +1,516 @@
1
+ # SPDX-FileCopyrightText: Copyright INRIA
2
+ #
3
+ # SPDX-License-Identifier: LGPL-3.0-only
4
+ #
5
+ # Copyright INRIA
6
+ #
7
+ # This file is part of PhysioBlocks, a library mostly developed by the
8
+ # [Ananke project-team](https://team.inria.fr/ananke) at INRIA.
9
+ #
10
+ # Authors:
11
+ # - Colin Drieu
12
+ # - Dominique Chapelle
13
+ # - François Kimmig
14
+ # - Philippe Moireau
15
+ #
16
+ # PhysioBlocks is free software: you can redistribute it and/or modify it under the
17
+ # terms of the GNU Lesser General Public License as published by the Free Software
18
+ # Foundation, version 3 of the License.
19
+ #
20
+ # PhysioBlocks is distributed in the hope that it will be useful, but WITHOUT ANY
21
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
22
+ # PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
23
+ #
24
+ # You should have received a copy of the GNU Lesser General Public License along with
25
+ # PhysioBlocks. If not, see <https://www.gnu.org/licenses/>.
26
+
27
+ """Module describing capacitance blocks"""
28
+
29
+ from dataclasses import dataclass
30
+ from typing import Any
31
+
32
+ import numpy as np
33
+
34
+ from physioblocks.computing import Block, Expression, Quantity, diff, mid_point
35
+ from physioblocks.registers import register_type
36
+ from physioblocks.simulation import Time
37
+
38
+ # C BLOCK Definition
39
+
40
+
41
+ # Constant for the c block type id
42
+ C_BLOCK_TYPE_ID = "c_block"
43
+
44
+ # Constant for the c block dof id
45
+ C_BLOCK_PRESSURE_DOF_ID = "pressure"
46
+
47
+
48
+ @register_type(C_BLOCK_TYPE_ID)
49
+ @dataclass
50
+ class CBlock(Block):
51
+ r"""
52
+ C Block quantities and flux definitions
53
+
54
+ .. tikz:: C Block scheme
55
+
56
+ \draw (0,1) to[short, -*, i=$Q$] (0,3) node[right]{$P$}
57
+ (0,1) to[C=$C$] (0,0) node[ground]{};
58
+
59
+ **Node 1:**
60
+
61
+ :math:`Q = - C\dot{P}`
62
+
63
+ **Discretisation:**
64
+
65
+ .. math::
66
+
67
+ Q^{n + \frac{1}{2}} = - C\ \frac{P^{n + 1} - P^{n}}{\Delta t^n}
68
+
69
+ """
70
+
71
+ pressure: Quantity[np.float64]
72
+ """Pressure quantity"""
73
+
74
+ capacitance: Quantity[np.float64]
75
+ """Block capacitance quantity"""
76
+
77
+ time: Time
78
+ """Simulation time"""
79
+
80
+ def flux(self) -> Any:
81
+ """
82
+ Compute the flux at local node 1
83
+
84
+ :return: the flux
85
+ :rtype: np.float64
86
+ """
87
+ return -self.capacitance.current * diff(self.pressure) * self.time.inv_dt
88
+
89
+ def dflux_dpressure(self) -> Any:
90
+ """
91
+ Compute the flux at local node 1 partial derivative for pressure
92
+
93
+ :return: the flux derivative
94
+ :rtype: np.float64
95
+ """
96
+ return -self.capacitance.current * self.time.inv_dt
97
+
98
+
99
+ _c_block_flux_expression = Expression(
100
+ 1, CBlock.flux, {C_BLOCK_PRESSURE_DOF_ID: CBlock.dflux_dpressure}
101
+ )
102
+ CBlock.declares_flux_expression(1, C_BLOCK_PRESSURE_DOF_ID, _c_block_flux_expression)
103
+
104
+
105
+ # RC BLOCK Definition
106
+
107
+ # Constant for the rc block type id
108
+ RC_BLOCK_TYPE_ID = "rc_block"
109
+
110
+ # Constant for the pressure in local id
111
+ RC_BLOCK_PRESSURE_1_DOF_ID = "pressure_1"
112
+
113
+ # Constant for the pressure out local id
114
+ RC_BLOCK_PRESSURE_2_DOF_ID = "pressure_2"
115
+
116
+
117
+ @register_type(RC_BLOCK_TYPE_ID)
118
+ @dataclass
119
+ class RCBlock(Block):
120
+ r"""
121
+ RC Block quantities and fluxes definitions
122
+
123
+ .. tikz:: RC Block scheme
124
+
125
+ \draw (0,3) node[below]{$P_{1}$} to[short, *-] (1,3);
126
+ \draw (2, 3) to[short, i=$Q_{1}$] (1, 3);
127
+ \draw (2, 3) to[R=$R$] (4,3);
128
+ \draw (4,3) to[C=$C$] (4,0) node[ground]{};
129
+ \draw (4,3) to[short, -*, i=$Q_{2}$] (6,3) node[below]{$P_{2}$};
130
+
131
+ **Node 1:**
132
+
133
+ :math:`Q_1 = \frac{P_2 - P_1}{R}`
134
+
135
+ **Node 2:**
136
+
137
+ :math:`Q_2 = \frac{P_1 - P_2}{R} - C\dot{P_2}`
138
+
139
+ **Discretisation:**
140
+
141
+ .. math::
142
+
143
+ Q_1^{n + \frac{1}{2}} = \frac{P_2^{n + \frac{1}{2}} - P_1^{n + \frac{1}{2}}}{R}
144
+
145
+ .. math::
146
+
147
+ Q_2^{n + \frac{1}{2}} = \frac{P_1^{n + \frac{1}{2}} - P_2^{n + \frac{1}{2}}}{R}
148
+ - C\ \frac{P_2^{n + 1} - P_2^{n}}{\Delta t^n}
149
+
150
+ """
151
+
152
+ pressure_1: Quantity[np.float64]
153
+ """Pressure at local node 1 of the block"""
154
+
155
+ pressure_2: Quantity[np.float64]
156
+ """Pressure at local node 2 of the block"""
157
+
158
+ resistance: Quantity[np.float64]
159
+ """Resistance value of the block"""
160
+
161
+ capacitance: Quantity[np.float64]
162
+ """Capacitor value of the block"""
163
+
164
+ time: Time
165
+ """The simulation time"""
166
+
167
+ def flux_1(self) -> Any:
168
+ """
169
+ Computes the outlet flux at local node 1.
170
+
171
+ :return: the flux value for current block values
172
+ :rtype: np.float64
173
+ """
174
+ pressure_1 = mid_point(self.pressure_1)
175
+ pressure_2 = mid_point(self.pressure_2)
176
+ return (pressure_2 - pressure_1) / self.resistance.current
177
+
178
+ def dflux_1_dpressure_1(self) -> Any:
179
+ """
180
+ Computes the outlet flux at node 1 derivative for pressure_1.
181
+
182
+ :return: the flux derivative for pressure_1
183
+ :rtype: np.float64
184
+ """
185
+ return -0.5 / self.resistance.current
186
+
187
+ def dflux_1_dpressure_2(self) -> Any:
188
+ """
189
+ Computes the outlet flux at node 1 derivative for pressure_2.
190
+
191
+ :return: the flux derivative for pressure_2
192
+ :rtype: np.float64
193
+ """
194
+ return 0.5 / self.resistance.current
195
+
196
+ def flux_2(self) -> Any:
197
+ """
198
+ Computes the outlet flux at node 2.
199
+
200
+ :return: the flux value for current block values
201
+ :rtype: np.float64
202
+ """
203
+ pressure_1 = mid_point(self.pressure_1)
204
+ pressure_2 = mid_point(self.pressure_2)
205
+ dpressure_2 = diff(self.pressure_2)
206
+ return (
207
+ (pressure_1 - pressure_2) / self.resistance.current
208
+ - self.capacitance.current * self.time.inv_dt * dpressure_2
209
+ )
210
+
211
+ def dflux_2_dpressure_1(self) -> Any:
212
+ """
213
+ Computes the outlet flux at node 2 derivative for pressure_1.
214
+
215
+ :return: the flux derivative for pressure_1
216
+ :rtype: np.float64
217
+ """
218
+ return 0.5 / self.resistance.current
219
+
220
+ def dflux_2_dpressure_2(self) -> Any:
221
+ """
222
+ Computes the outlet flux at node 2 derivative for pressure_2.
223
+
224
+ :return: the flux derivative for pressure_2
225
+ :rtype: np.float64
226
+ """
227
+ return (
228
+ -0.5 / self.resistance.current - self.capacitance.current * self.time.inv_dt
229
+ )
230
+
231
+
232
+ # Define the flux expression going in the input node for rc_block
233
+ _rc_block_flux_1_expr = Expression(
234
+ 1,
235
+ RCBlock.flux_1,
236
+ {
237
+ RC_BLOCK_PRESSURE_1_DOF_ID: RCBlock.dflux_1_dpressure_1,
238
+ RC_BLOCK_PRESSURE_2_DOF_ID: RCBlock.dflux_1_dpressure_2,
239
+ },
240
+ )
241
+
242
+ # Define the flux expression going in the output node for rc_block
243
+ _rc_block_flux_2_expr = Expression(
244
+ 1,
245
+ RCBlock.flux_2,
246
+ {
247
+ RC_BLOCK_PRESSURE_1_DOF_ID: RCBlock.dflux_2_dpressure_1,
248
+ RC_BLOCK_PRESSURE_2_DOF_ID: RCBlock.dflux_2_dpressure_2,
249
+ },
250
+ )
251
+
252
+ RCBlock.declares_flux_expression(1, RC_BLOCK_PRESSURE_1_DOF_ID, _rc_block_flux_1_expr)
253
+ RCBlock.declares_flux_expression(2, RC_BLOCK_PRESSURE_2_DOF_ID, _rc_block_flux_2_expr)
254
+
255
+ # RCR BLOCK Definition
256
+
257
+ # Constant for the rcr block type id
258
+ RCR_BLOCK_TYPE_ID = "rcr_block"
259
+
260
+ # Constant for the rcr block volume saved quantity
261
+ RCR_BLOCK_VOLUME_OUTPUT_ID = "volume_stored"
262
+
263
+ # Constant for the rcr block pressure at the mid point
264
+ RCR_BLOCK_PRESSURE_MID_ID = "pressure_mid"
265
+
266
+ # Constant for the rcr block pressure at local node 1
267
+ RCR_BLOCK_PRESSURE_1_ID = "pressure_1"
268
+
269
+ # Constant for the rcr block pressure at local node 2
270
+ RCR_BLOCK_PRESSURE_2_ID = "pressure_2"
271
+
272
+
273
+ @register_type(RCR_BLOCK_TYPE_ID)
274
+ @dataclass
275
+ class RCRBlock(Block):
276
+ r"""
277
+ RCR Block quantities and flux definitions
278
+
279
+ .. tikz::
280
+
281
+ \draw (-5,3) node[above]{$P_1$} to[short, *-] (-4,3);
282
+ \draw (-3, 3) to[short, i=$Q_1$] (-4,3);
283
+ \draw (-3, 3) to [R=$R_1$] (0, 3);
284
+ \draw (0, 3) node[above]{$P_{mid}$} to [short, *-, R=$R_2$] (3, 3);
285
+ \draw (3, 3) to[short, i=$Q_2$] (4, 3);
286
+ \draw (4,3) to[short, -*] (5,3) node[above]{$P_2$};
287
+ \draw (0,3) to[C=$C$] (0,0) node[ground]{};
288
+
289
+ **Node 1:**
290
+
291
+ :math:`Q_1 = \frac{P_{mid} - P_1}{R_1}`
292
+
293
+ **Node 2:**
294
+
295
+ :math:`Q_2 = \frac{P_{mid} - P_2}{R_2}`
296
+
297
+ **Internal equation:**
298
+
299
+ .. math::
300
+
301
+ \frac{P_1 - P_{mid}}{R_1} + \frac{P_2 - P_{mid}}{R_2} - C\dot{P}_{mid} = 0
302
+
303
+ **Discretisation:**
304
+
305
+ .. math::
306
+
307
+ Q_1^{n + \frac{1}{2}} = \frac{P_{mid}^{n + \frac{1}{2}}
308
+ - P_1^{n + \frac{1}{2}}}{R_1}
309
+
310
+ .. math::
311
+
312
+ Q_2^{n + \frac{1}{2}} = \frac{P_{mid}^{n + \frac{1}{2}}
313
+ - P_2^{n + \frac{1}{2}}}{R_2}
314
+
315
+ .. math::
316
+
317
+ \frac{P_1^{n + \frac{1}{2}} - P_{mid}^{n + \frac{1}{2}}}{R_1}
318
+ + \frac{P_2^{n + \frac{1}{2}} - P_{mid}^{n + \frac{1}{2}}}{R_2}
319
+ - C\ \frac{P_{mid}^{n + 1} - P_{mid}^{n}}{\Delta t^n} = 0
320
+
321
+ """
322
+
323
+ pressure_1: Quantity[np.float64]
324
+ """Pressure at the input of the block"""
325
+
326
+ pressure_2: Quantity[np.float64]
327
+ """Pressure at the output of the block"""
328
+
329
+ pressure_mid: Quantity[np.float64]
330
+ """Pressure at the output of the block"""
331
+
332
+ resistance_1: Quantity[np.float64]
333
+ """Resistance in value of the block"""
334
+
335
+ capacitance: Quantity[np.float64]
336
+ """Capacitor value of the block"""
337
+
338
+ resistance_2: Quantity[np.float64]
339
+ """Resistance out value of the block"""
340
+
341
+ time: Time
342
+ """The simulation time"""
343
+
344
+ def flux_1(self) -> Any:
345
+ """
346
+ Computes the outlet flux at node 1.
347
+
348
+ :return: the flux value
349
+ :rtype: np.float64
350
+ """
351
+
352
+ pressure_1_discr = mid_point(self.pressure_1)
353
+ pressure_mid_discr = mid_point(self.pressure_mid)
354
+
355
+ return (pressure_mid_discr - pressure_1_discr) / self.resistance_1.current
356
+
357
+ def dflux_1_dp_1(self) -> Any:
358
+ """
359
+ Computes the outlet flux at node 1 derivative for pressure_1.
360
+
361
+ :return: flux derivative for pressure_1
362
+ :rtype: np.float64
363
+ """
364
+
365
+ return -0.5 / self.resistance_1.current
366
+
367
+ def dflux_1_dp_mid(self) -> Any:
368
+ """
369
+ Computes the outlet flux at node 1 derivative for pressure_mid.
370
+
371
+ :return: flux derivative for pressure_2
372
+ :rtype: np.float64
373
+ """
374
+
375
+ return 0.5 / self.resistance_1.current
376
+
377
+ def flux_2(self) -> Any:
378
+ """
379
+ Computes the flux at node 2.
380
+
381
+ :return: the flux value
382
+ :rtype: np.float64
383
+ """
384
+ pressure_2_discr = mid_point(self.pressure_2)
385
+ pressure_mid_discr = mid_point(self.pressure_mid)
386
+
387
+ return (pressure_mid_discr - pressure_2_discr) / self.resistance_2.current
388
+
389
+ def dflux_2_dp_mid(self) -> Any:
390
+ """
391
+ Computes the outlet flux at node 2 derivative for pressure_mid.
392
+
393
+ :return: flux derivative for pressure_mid
394
+ :rtype: np.float64
395
+ """
396
+
397
+ return 0.5 / self.resistance_2.current
398
+
399
+ def dflux_2_dp_2(self) -> Any:
400
+ """
401
+ Computes the outlet flux at node 2 derivative for pressure_2.
402
+
403
+ :return: flux derivative for pressure_2
404
+ :rtype: np.float64
405
+ """
406
+
407
+ return -0.5 / self.resistance_2.current
408
+
409
+ def pressure_mid_residual(self) -> Any:
410
+ """
411
+ Compute the residual representing dynamics of the mid node pressure.
412
+
413
+ :return: the residual value
414
+ :rtype: np.float64
415
+ """
416
+
417
+ p_1_discr = mid_point(self.pressure_1)
418
+ p_mid_discr = mid_point(self.pressure_mid)
419
+ p_2_discr = mid_point(self.pressure_2)
420
+
421
+ return (
422
+ +(p_1_discr - p_mid_discr) / self.resistance_1.current
423
+ + (p_2_discr - p_mid_discr) / self.resistance_2.current
424
+ - self.capacitance.current * self.time.inv_dt * diff(self.pressure_mid)
425
+ )
426
+
427
+ def pressure_mid_residual_dp_1(self) -> Any:
428
+ """
429
+ Compute the residual derivative for pressure_1
430
+
431
+ :return: the residual derivative for pressure_1
432
+ :rtype: np.float64
433
+ """
434
+
435
+ return 0.5 / self.resistance_1.current
436
+
437
+ def pressure_mid_residual_dp_2(self) -> Any:
438
+ """
439
+ Compute the residual derivative for pressure_2
440
+
441
+ :return: the residual derivative for pressure_2
442
+ :rtype: np.float64
443
+ """
444
+
445
+ return 0.5 / self.resistance_2.current
446
+
447
+ def pressure_mid_residual_dp_mid(self) -> Any:
448
+ """
449
+ Compute the residual derivative for pressure_mid
450
+
451
+ :return: the residual derivative for pressure_mid
452
+ :rtype: np.float64
453
+ """
454
+
455
+ return (
456
+ -self.capacitance.current * self.time.inv_dt
457
+ - 0.5 / self.resistance_1.current
458
+ - 0.5 / self.resistance_2.current
459
+ )
460
+
461
+ def compute_volume_stored(self) -> Any:
462
+ """
463
+ Computes volume stored in the capacitance.
464
+
465
+ :return: volume stored in the capacitance
466
+ :rtype: np.float64
467
+ """
468
+
469
+ return self.capacitance.current * self.pressure_mid.current
470
+
471
+
472
+ # Define the flux expression going in node 1 for rcr block
473
+ _rcr_block_flux_1_expr = Expression(
474
+ 1,
475
+ RCRBlock.flux_1,
476
+ {
477
+ RCR_BLOCK_PRESSURE_1_ID: RCRBlock.dflux_1_dp_1,
478
+ RCR_BLOCK_PRESSURE_MID_ID: RCRBlock.dflux_1_dp_mid,
479
+ },
480
+ )
481
+
482
+
483
+ # Define the flux expression going in node 2 for rcr block
484
+ _rcr_block_flux_2_expr = Expression(
485
+ 1,
486
+ RCRBlock.flux_2,
487
+ {
488
+ RCR_BLOCK_PRESSURE_MID_ID: RCRBlock.dflux_2_dp_mid,
489
+ RCR_BLOCK_PRESSURE_2_ID: RCRBlock.dflux_2_dp_2,
490
+ },
491
+ )
492
+
493
+ # Define the residual expression giving the pressure at the mid node
494
+ _rcr_block_pressure_mid_residual_expr = Expression(
495
+ 1,
496
+ RCRBlock.pressure_mid_residual,
497
+ {
498
+ RCR_BLOCK_PRESSURE_1_ID: RCRBlock.pressure_mid_residual_dp_1,
499
+ RCR_BLOCK_PRESSURE_MID_ID: RCRBlock.pressure_mid_residual_dp_mid,
500
+ RCR_BLOCK_PRESSURE_2_ID: RCRBlock.pressure_mid_residual_dp_2,
501
+ },
502
+ )
503
+
504
+ # Derfine the stored volume saved quantity expression.
505
+ _rcr_volume_stored_expr = Expression(1, RCRBlock.compute_volume_stored)
506
+
507
+
508
+ RCRBlock.declares_internal_expression(
509
+ RCR_BLOCK_PRESSURE_MID_ID, _rcr_block_pressure_mid_residual_expr
510
+ )
511
+
512
+ RCRBlock.declares_flux_expression(1, RCR_BLOCK_PRESSURE_1_ID, _rcr_block_flux_1_expr)
513
+ RCRBlock.declares_flux_expression(2, RCR_BLOCK_PRESSURE_2_ID, _rcr_block_flux_2_expr)
514
+ RCRBlock.declares_saved_quantity_expression(
515
+ RCR_BLOCK_VOLUME_OUTPUT_ID, _rcr_volume_stored_expr
516
+ )