wall-ctf 1.0.0__tar.gz

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,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .pytest_cache/
8
+ *.so
9
+ .DS_Store
10
+ vb/
@@ -0,0 +1,49 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite the following publications."
3
+ title: "wall-ctf (CATI) - Conduction Transfer Function Coefficients"
4
+ version: 1.0.0
5
+ date-released: 2026-04-08
6
+ authors:
7
+ - family-names: Lo Brano
8
+ given-names: Valerio
9
+ email: valerio.lobrano@unipa.it
10
+ affiliation: "Universita degli Studi di Palermo"
11
+ orcid: ""
12
+ license: CC-BY-NC-4.0
13
+ repository-code: "https://github.com/valeriolobrano/wall-ctf"
14
+ preferred-citation:
15
+ type: article
16
+ authors:
17
+ - family-names: Beccali
18
+ given-names: Giorgio
19
+ - family-names: Cellura
20
+ given-names: Maurizio
21
+ - family-names: Lo Brano
22
+ given-names: Valerio
23
+ - family-names: Orioli
24
+ given-names: Aldo
25
+ title: "Single thermal zone balance solved by Transfer Function Method"
26
+ journal: "Energy and Buildings"
27
+ volume: 37
28
+ start: 1268
29
+ end: 1277
30
+ year: 2005
31
+ doi: "10.1016/j.enbuild.2005.02.010"
32
+ references:
33
+ - type: article
34
+ authors:
35
+ - family-names: Beccali
36
+ given-names: Giorgio
37
+ - family-names: Cellura
38
+ given-names: Maurizio
39
+ - family-names: Lo Brano
40
+ given-names: Valerio
41
+ - family-names: Orioli
42
+ given-names: Aldo
43
+ title: "Is the transfer function method reliable in a European building context? A theoretical analysis and a case study in the south of Italy"
44
+ journal: "Applied Thermal Engineering"
45
+ volume: 25
46
+ start: 341
47
+ end: 357
48
+ year: 2005
49
+ doi: "10.1016/j.applthermaleng.2004.06.010"
wall_ctf-1.0.0/LICENSE ADDED
@@ -0,0 +1,43 @@
1
+ Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)
2
+
3
+ Copyright (c) 2005-2026 Valerio Lo Brano
4
+ Universita degli Studi di Palermo
5
+ Dipartimento di Ingegneria
6
+
7
+ This work is licensed under the Creative Commons
8
+ Attribution-NonCommercial 4.0 International License.
9
+
10
+ You are free to:
11
+
12
+ - Share: copy and redistribute the material in any medium or format
13
+ - Adapt: remix, transform, and build upon the material
14
+
15
+ Under the following terms:
16
+
17
+ - Attribution: You must give appropriate credit, provide a link to the
18
+ license, and indicate if changes were made. You must cite the following
19
+ publications:
20
+
21
+ [1] G. Beccali, M. Cellura, V. Lo Brano, A. Orioli,
22
+ "Single thermal zone balance solved by Transfer Function Method",
23
+ Energy and Buildings, 37 (2005) 1268-1277.
24
+ DOI: 10.1016/j.enbuild.2005.02.010
25
+
26
+ [2] G. Beccali, M. Cellura, V. Lo Brano, A. Orioli,
27
+ "Is the transfer function method reliable in a European building
28
+ context? A theoretical analysis and a case study in the south
29
+ of Italy", Applied Thermal Engineering, 25 (2005) 341-357.
30
+ DOI: 10.1016/j.applthermaleng.2004.06.010
31
+
32
+ - NonCommercial: You may not use the material for commercial purposes
33
+ without obtaining prior written permission from the copyright holder.
34
+
35
+ For commercial licensing inquiries, contact:
36
+ Valerio Lo Brano
37
+ valerio.lobrano@unipa.it
38
+ Universita degli Studi di Palermo
39
+
40
+ No additional restrictions: You may not apply legal terms or technological
41
+ measures that legally restrict others from doing anything the license permits.
42
+
43
+ Full license text: https://creativecommons.org/licenses/by-nc/4.0/legalcode
@@ -0,0 +1,459 @@
1
+ Metadata-Version: 2.4
2
+ Name: wall-ctf
3
+ Version: 1.0.0
4
+ Summary: wall-ctf (CATI) - Conduction Transfer Function (CTF) coefficients for multilayer walls using the Mitalas-Stephenson / Z-transform method
5
+ Project-URL: Homepage, https://github.com/valeriolobrano/wall-ctf
6
+ Project-URL: Documentation, https://github.com/valeriolobrano/wall-ctf#readme
7
+ Project-URL: Issues, https://github.com/valeriolobrano/wall-ctf/issues
8
+ Author-email: Valerio Lo Brano <valerio.lobrano@unipa.it>
9
+ License: CC-BY-NC-4.0
10
+ License-File: LICENSE
11
+ Keywords: ASHRAE,CTF,Mitalas,TRNSYS,Z-transform,building-simulation,conduction,heat-transfer,multilayer,thermal,transfer-function,wall
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Education
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: Other/Proprietary License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Scientific/Engineering :: Physics
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: numpy>=1.26
21
+ Provides-Extra: plot
22
+ Requires-Dist: matplotlib>=3.8; extra == 'plot'
23
+ Description-Content-Type: text/markdown
24
+
25
+ # wall-ctf (CATI) - Conduction Transfer Function Coefficients
26
+
27
+ **Version 1.0.0** | **Author:** Valerio Lo Brano, Universita degli Studi di Palermo
28
+
29
+ CATI computes the Conduction Transfer Function (CTF) coefficients for
30
+ multilayer wall assemblies using the Z-transform method. This is the same
31
+ mathematical approach used by TRNSYS, DOE-2, BLAST, TARP, and the ASHRAE
32
+ Transfer Function Method (TFM) for dynamic thermal simulation of buildings.
33
+
34
+ Given the thermophysical properties of a wall (layer thicknesses, densities,
35
+ specific heats, conductivities), CATI determines the Z-domain transfer function
36
+ coefficients that allow to compute, at each time step, the heat flux at the
37
+ internal surface as a function of the external (sol-air) temperature history
38
+ and the internal air temperature.
39
+
40
+ ![CTF vs Fourier validation](docs/ctf_vs_fourier.png)
41
+
42
+ *Comparison between the Z-transform (CTF) and Fourier (harmonic analysis)
43
+ solutions for a heavy concrete wall (plaster 2cm + concrete 25cm + plaster 2cm).
44
+ The two curves are virtually indistinguishable, with a Percentage Mean Error
45
+ of 0.15%.*
46
+
47
+ ---
48
+
49
+ ## Table of contents
50
+
51
+ - [Theoretical background](#theoretical-background)
52
+ - [Installation](#installation)
53
+ - [Quick start](#quick-start)
54
+ - [Input format](#input-format)
55
+ - [Parameters and guidelines](#parameters-and-guidelines)
56
+ - [Examples](#examples)
57
+ - [Validation](#validation)
58
+ - [How to cite](#how-to-cite)
59
+ - [License](#license)
60
+
61
+ ---
62
+
63
+ ## Theoretical background
64
+
65
+ ### The thermal transmission matrix
66
+
67
+ The non-steady-state heat transfer through a homogeneous isotropic layer can
68
+ be described in the Laplace domain by a 2x2 transmission matrix that relates
69
+ temperatures and heat fluxes on the two sides of the layer:
70
+
71
+ ```
72
+ | T_e | | a b | | T_i |
73
+ | | = | | x | |
74
+ | Q_e | | c d | | Q_i |
75
+ ```
76
+
77
+ where, for a material layer of thickness *L*, conductivity *k*,
78
+ density *rho*, specific heat *Cp*, and diffusivity *alpha = k/(rho\*Cp)*:
79
+
80
+ ```
81
+ a = d = cosh(L * sqrt(s/alpha))
82
+ b = sinh(L * sqrt(s/alpha)) / (k * sqrt(s/alpha))
83
+ c = k * sqrt(s/alpha) * sinh(L * sqrt(s/alpha))
84
+ ```
85
+
86
+ For surface resistance layers (convective + radiative films) and air gaps,
87
+ the matrix reduces to `[[1, R], [0, 1]]` where *R* is the thermal resistance.
88
+
89
+ For a multilayer wall, the overall matrix **M(s)** is the ordered product of
90
+ all individual layer matrices, from the external surface to the internal one.
91
+
92
+ ### From Laplace to Z-domain
93
+
94
+ The heat flux at the internal surface can be expressed as:
95
+
96
+ ```
97
+ Q_i(z) = [1/B(z)] * T_e(z) - [A(z)/B(z)] * T_i(z)
98
+ ```
99
+
100
+ where A and B are elements of the overall transmission matrix. The Z-transform
101
+ coefficients are obtained through:
102
+
103
+ 1. Finding the poles *s_n* (zeros of B(s) on the negative real axis)
104
+ 2. Heaviside partial-fraction expansion of the ramp response
105
+ 3. **Procedure I**: optimal selection of significant poles/residues
106
+ 4. Computation of the Z-domain denominator and numerator polynomials
107
+
108
+ The resulting recursive formula is:
109
+
110
+ ```
111
+ q_i(n*Delta) = SUM_j b_j * T_e((n-j)*Delta)
112
+ - SUM_j d_j * q_i((n-j)*Delta)
113
+ - T_i * SUM_j c_j
114
+ ```
115
+
116
+ ### Procedure I: optimal pole selection
117
+
118
+ As demonstrated in Ref. [2], for massive building walls typical of the
119
+ Mediterranean architectural heritage, a naive application of the TFM with
120
+ many poles can produce **worse** results than using fewer poles. The Percentage
121
+ Mean Error (PME) can increase from < 1% to > 1000% when using 15 poles
122
+ instead of 5.
123
+
124
+ CATI implements **Procedure I** from Ref. [2]: residues are sorted by absolute
125
+ value in descending order, and only those above a significance threshold
126
+ (|res_n| > 10^-10) are retained. This guarantees PME < 1% for all standard
127
+ wall constructions at 1-hour sampling period.
128
+
129
+ ---
130
+
131
+ ## Installation
132
+
133
+ ### With uv (recommended)
134
+
135
+ [uv](https://docs.astral.sh/uv/) is the fastest way to manage Python projects:
136
+
137
+ ```bash
138
+ # Clone the repository
139
+ git clone https://github.com/valeriolobrano/wall-ctf.git
140
+ cd wall-ctf
141
+
142
+ # Install with uv (creates virtualenv automatically)
143
+ uv sync
144
+
145
+ # Run tests
146
+ uv run pytest
147
+
148
+ # Run the CLI
149
+ uv run cati examples/heavy_wall.json
150
+
151
+ # Run with optional plotting support
152
+ uv add matplotlib
153
+ uv run python scripts/generate_figures.py
154
+ ```
155
+
156
+ ### With pip
157
+
158
+ ```bash
159
+ pip install wall-ctf
160
+ ```
161
+
162
+ Or from source:
163
+
164
+ ```bash
165
+ git clone https://github.com/valeriolobrano/wall-ctf.git
166
+ cd wall-ctf
167
+ pip install .
168
+
169
+ # With plotting support
170
+ pip install ".[plot]"
171
+ ```
172
+
173
+ ### Requirements
174
+
175
+ - Python >= 3.12
176
+ - NumPy >= 1.26
177
+ - matplotlib >= 3.8 (optional, for plotting)
178
+
179
+ ---
180
+
181
+ ## Quick start
182
+
183
+ ### Basic example: single wall
184
+
185
+ ```python
186
+ from cati import Wall, Layer, compute_ctf
187
+
188
+ # Define a wall from outside to inside:
189
+ # external surface resistance -> material layers -> internal surface resistance
190
+ # All values in SI units
191
+ wall = Wall(layers=[
192
+ Layer(name="External surface", resistance=0.04), # m2*K/W
193
+ Layer(name="Concrete", thickness=0.25, density=2400, # m, kg/m3
194
+ specific_heat=1000, conductivity=1.4), # J/(kg*K), W/(m*K)
195
+ Layer(name="Internal surface", resistance=0.13),
196
+ ])
197
+
198
+ result = compute_ctf(wall, n_roots=30, n_coefficients=20)
199
+
200
+ print(f"U-value: {result.thermal_transmittance:.3f} W/(m2*K)")
201
+ print(f"Significant poles: {result.n_poles}")
202
+ print(f"Effective coefficients: {result.n_coefficients}")
203
+ ```
204
+
205
+ ### With Fourier validation
206
+
207
+ ```python
208
+ import numpy as np
209
+
210
+ # 24-hour sol-air temperature profile (hourly, 25 values with wrap-around)
211
+ profile = np.array([
212
+ 25.0, 24.0, 23.5, 23.0, 22.5, 23.0, # 0h-5h
213
+ 24.0, 26.0, 28.0, 30.0, 32.0, 34.0, # 6h-11h
214
+ 36.0, 37.0, 37.5, 37.0, 36.0, 34.0, # 12h-17h
215
+ 32.0, 30.0, 28.0, 27.0, 26.0, 25.5, # 18h-23h
216
+ 25.0, # 24h = 0h
217
+ ])
218
+
219
+ result = compute_ctf(
220
+ wall,
221
+ n_roots=30,
222
+ n_coefficients=20,
223
+ temperature_profile=profile,
224
+ T_int=24.0, # constant internal temperature [C]
225
+ sampling_time=1.0, # sampling period [hours]
226
+ n_periods=20, # periods to exit transient
227
+ validate_fourier=True, # compare with harmonic solution
228
+ )
229
+
230
+ print(f"Fourier validation error: {result.fourier_error:.2f}%")
231
+ # Output: Fourier validation error: 0.15%
232
+ ```
233
+
234
+ ### Using the CTF coefficients in a simulation
235
+
236
+ ```python
237
+ nc = result.n_coefficients # number of effective coefficients
238
+ b = result.b_coeffs[:nc+1] # numerator for external temperature
239
+ c = result.c_coeffs[:nc+1] # numerator for internal temperature
240
+ d = result.d_coeffs[:nc+1] # denominator (common)
241
+
242
+ # Simulation loop (hourly time step)
243
+ T_int = 24.0
244
+ q = np.zeros(8760) # one year, hourly
245
+
246
+ for n in range(1, 8760):
247
+ # b * T_external (convolution)
248
+ q[n] = sum(b[j] * T_ext_hourly[max(0, n-j)] for j in range(nc+1))
249
+ # - d * q_past (recursive feedback)
250
+ q[n] -= sum(d[j] * q[max(0, n-j)] for j in range(1, nc+1))
251
+ # - c * T_internal (constant offset)
252
+ q[n] -= T_int * sum(c)
253
+ ```
254
+
255
+ ### Parallel computation for multiple walls
256
+
257
+ ```python
258
+ from cati import compute_ctf_batch
259
+
260
+ # Compute CTF for all walls of a building in parallel
261
+ walls = [wall_north, wall_south, wall_east, wall_west, roof, floor]
262
+ results = compute_ctf_batch(walls, n_roots=30, n_coefficients=20)
263
+
264
+ for wall, result in zip(walls, results):
265
+ print(f"{wall.name}: U={result.thermal_transmittance:.3f}, "
266
+ f"poles={result.n_poles}, coeffs={result.n_coefficients}")
267
+ ```
268
+
269
+ ### Command-line interface
270
+
271
+ ```bash
272
+ # Compute and print CTF coefficients as JSON
273
+ uv run cati examples/heavy_wall.json --roots 30 --coefficients 20
274
+
275
+ # Save results to file
276
+ uv run cati examples/heavy_wall.json -o results.json
277
+
278
+ # Custom parameters
279
+ uv run cati wall.json --sampling-time 2 --periods 30 --t-int 26
280
+
281
+ # Skip Fourier validation (faster)
282
+ uv run cati wall.json --no-fourier
283
+ ```
284
+
285
+ ### Loading walls from JSON
286
+
287
+ ```python
288
+ from cati import Wall
289
+
290
+ # From a JSON file
291
+ wall = Wall.from_json("examples/heavy_wall.json")
292
+
293
+ # From a Python dictionary
294
+ wall = Wall.from_dict({
295
+ "name": "My wall",
296
+ "layers": [
297
+ {"name": "Ext", "resistance": 0.04},
298
+ {"name": "Brick", "thickness": 0.12, "density": 1700,
299
+ "specific_heat": 800, "conductivity": 0.84},
300
+ {"name": "Int", "resistance": 0.13},
301
+ ]
302
+ })
303
+ ```
304
+
305
+ ---
306
+
307
+ ## Input format
308
+
309
+ ### JSON wall definition
310
+
311
+ ```json
312
+ {
313
+ "name": "Concrete wall with plaster",
314
+ "layers": [
315
+ {"name": "External surface", "thickness": 0.0, "resistance": 0.04},
316
+ {"name": "External plaster", "thickness": 0.02, "density": 1800,
317
+ "specific_heat": 1000, "conductivity": 0.9},
318
+ {"name": "Concrete block", "thickness": 0.25, "density": 2400,
319
+ "specific_heat": 1000, "conductivity": 1.4},
320
+ {"name": "Internal plaster", "thickness": 0.02, "density": 1400,
321
+ "specific_heat": 1000, "conductivity": 0.7},
322
+ {"name": "Internal surface", "thickness": 0.0, "resistance": 0.13}
323
+ ],
324
+ "temperature_profile": [25, 24, 23.5, 23, 22.5, 23, 24, 26, 28, 30,
325
+ 32, 34, 36, 37, 37.5, 37, 36, 34, 32, 30,
326
+ 28, 27, 26, 25.5]
327
+ }
328
+ ```
329
+
330
+ ### Units (SI)
331
+
332
+ | Property | Unit | Description |
333
+ |---|---|---|
334
+ | `thickness` | m | Layer thickness (0 for surface resistance or air gap) |
335
+ | `density` | kg/m^3 | Material density |
336
+ | `specific_heat` | J/(kg\*K) | Specific heat capacity |
337
+ | `conductivity` | W/(m\*K) | Thermal conductivity |
338
+ | `resistance` | m^2\*K/W | Thermal resistance (for air gaps and surface films) |
339
+
340
+ ### Wall structure rules
341
+
342
+ A wall must contain **at least 3 layers**:
343
+
344
+ 1. **First layer**: external surface resistance (combined convective and radiative exchange coefficient)
345
+ 2. **Intermediate layers**: material layers or air gaps, ordered from outside to inside
346
+ 3. **Last layer**: internal surface resistance
347
+
348
+ Typical surface resistance values (EN ISO 6946):
349
+
350
+ | Surface | Resistance [m^2\*K/W] | Notes |
351
+ |---|---|---|
352
+ | External, normal exposure | 0.04 | Wind speed > 4 m/s |
353
+ | External, sheltered | 0.06 | Wind speed 1-4 m/s |
354
+ | Internal, horizontal flow | 0.13 | Vertical walls |
355
+ | Internal, upward flow | 0.10 | Floors (heating) |
356
+ | Internal, downward flow | 0.17 | Ceilings (heating) |
357
+
358
+ ---
359
+
360
+ ## Parameters and guidelines
361
+
362
+ | Parameter | Default | Description |
363
+ |---|---|---|
364
+ | `n_roots` | 50 | Number of zeros of B(s) to find |
365
+ | `n_coefficients` | 49 | Maximum number of Z-domain coefficients |
366
+ | `sampling_time` | 1.0 | Sampling period [hours] (must divide 24) |
367
+ | `n_periods` | 10 | Number of 24h periods for transient decay |
368
+ | `n_harmonics` | 120 | Harmonics for Fourier validation |
369
+ | `T_int` | 24.0 | Constant internal air temperature [C] |
370
+ | `use_mitalas` | True | Apply Mitalas instruction (recommended) |
371
+
372
+ ### Recommendations
373
+
374
+ Based on the analysis in Ref. [2]:
375
+
376
+ 1. **Do not use too many poles.** For most walls, 20-30 roots with automatic
377
+ Procedure I selection gives optimal results. The effective number of
378
+ poles is determined automatically.
379
+
380
+ 2. **Increase the sampling period for massive walls.** For walls with total
381
+ thickness > 0.4 m (typical of historical European buildings), a sampling
382
+ period of 2 h may give better results than 1 h.
383
+
384
+ 3. **Procedure I is enabled by default.** It sorts residues by significance
385
+ and discards negligible ones, preventing the numerical problems that
386
+ affect naive implementations.
387
+
388
+ 4. **Check the Fourier validation error.** A PME below 5% indicates
389
+ reliable coefficients. If the error is high, try:
390
+ - Increasing the sampling period
391
+ - Reducing `n_roots`
392
+ - Checking wall data for unrealistic property values
393
+
394
+ ---
395
+
396
+ ## Examples
397
+
398
+ The `examples/` directory contains ready-to-use JSON wall definitions:
399
+
400
+ - **`heavy_wall.json`**: Plaster + concrete 25cm + plaster (U = 2.50 W/m^2K)
401
+ - **`insulated_wall.json`**: Insulated cavity wall with air gap (U = 0.33 W/m^2K)
402
+
403
+ Run them with:
404
+
405
+ ```bash
406
+ uv run cati examples/heavy_wall.json --roots 30 --coefficients 20
407
+ ```
408
+
409
+ ---
410
+
411
+ ## Validation
412
+
413
+ The CTF output is validated against an independent Fourier steady-state
414
+ solution (harmonic analysis using the complex thermal quadrupole). The
415
+ Percentage Mean Error (PME) is computed as in Ref. [2], Eq. (4-5):
416
+
417
+ ```
418
+ PME = (1/24) * SUM_{tau=1}^{24} |T_Z(tau) - T_F(tau)| / |T_F(tau)| * 100
419
+ ```
420
+
421
+ Typical results:
422
+
423
+ | Wall type | Thickness | U [W/m^2K] | PME |
424
+ |---|---|---|---|
425
+ | Heavy concrete + plaster | 0.29 m | 2.50 | **0.15%** |
426
+ | Brick + concrete (2 layers) | 0.27 m | ~2.5 | **< 5%** |
427
+ | Lightweight wood | 0.10 m | 1.20 | **~5%** |
428
+
429
+ ---
430
+
431
+ ## How to cite
432
+
433
+ If you use CATI in your research, please cite the following publications:
434
+
435
+ > G. Beccali, M. Cellura, V. Lo Brano, A. Orioli, *"Single thermal zone
436
+ > balance solved by Transfer Function Method"*, Energy and Buildings 37 (2005)
437
+ > 1268-1277. DOI: [10.1016/j.enbuild.2005.02.010](https://doi.org/10.1016/j.enbuild.2005.02.010)
438
+
439
+ > G. Beccali, M. Cellura, V. Lo Brano, A. Orioli, *"Is the transfer function
440
+ > method reliable in a European building context? A theoretical analysis and
441
+ > a case study in the south of Italy"*, Applied Thermal Engineering 25 (2005)
442
+ > 341-357. DOI: [10.1016/j.applthermaleng.2004.06.010](https://doi.org/10.1016/j.applthermaleng.2004.06.010)
443
+
444
+ BibTeX entries are available in the [`CITATION.cff`](CITATION.cff) file.
445
+
446
+ ---
447
+
448
+ ## License
449
+
450
+ **CC BY-NC 4.0** (Creative Commons Attribution-NonCommercial 4.0 International)
451
+
452
+ - **Free** for academic, educational, and non-commercial use with proper attribution.
453
+ - **Commercial use** requires prior written permission from the copyright holder.
454
+ - **Attribution** must include a citation of the publications listed above.
455
+ - Contact for commercial licensing: valerio.lobrano@unipa.it
456
+
457
+ Copyright (c) 2005-2026 Valerio Lo Brano, Universita degli Studi di Palermo.
458
+
459
+ See [`LICENSE`](LICENSE) for the full license text.