Files
davide 4d83ac4e70 Allinea le proprietà della banda stagnata all'acciaio dolce reale
Il rivestimento di stagno è troppo sottile per influire sulle proprietà
in massa: la banda stagnata è fisicamente acciaio a basso tenore di
carbonio, quindi ne eredita conducibilità, densità, calore specifico,
resistività e permeabilità. Ricalibra il flusso di picco della sorgente
di conseguenza e documenta le fonti in README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 22:37:21 +02:00

217 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Simulatore Termico 2D — Fascetta, Sorgenti a Induzione Mobili, Sensore IR Fisso
Questo progetto genera misurazioni CSV pseudo-realistiche della temperatura di una
fascetta (anello cilindrico sottile) riscaldata da un gruppo di sorgenti a induzione
in movimento, osservata da un sensore a infrarossi fisso. Lo scopo è produrre dataset
per l'addestramento e la validazione di modelli di stima/regressione termica.
## Geometria
La fascetta è un anello cilindrico definito da tre dimensioni:
- **diametro** (default 70 mm) — il diametro del cilindro;
- **spessore** (default 0.12 mm) — lo spessore della parete;
- **lunghezza** (default 100 mm) — l'estensione assiale lungo `x`.
Il dominio simulato è la **sezione rettangolare lunghezza × spessore**. Il sistema di
coordinate ha l'origine `(0, 0)` nel vertice in alto a sinistra della sezione:
```text
sorgenti (induttori), in moto verso -x
▼ ▼ ▼
(0,0) ─────────────────────────────────────► x
│ ┌───────────────────────────────────┐ z = 0 lato ESTERNO
│ │ sezione della fascetta │ (flusso termico)
│ └───────────────────────────────────┘ z = spessore lato INTERNO
▼ ┆
z ┆ linea di vista
sensore IR (fisso, x = 50 mm,
a 10 mm dalla parete interna)
```
- **x** = direzione della lunghezza, da `0` a `lunghezza`. Le sorgenti viaggiano in
direzione `-x` sul lato esterno.
- **z** = direzione dello spessore, da `0` (lato esterno, dove arriva il flusso
termico) a `spessore` (lato interno, osservato dal sensore).
- **y** = coordinata circonferenziale (lungo la circonferenza π·diametro). Non è
risolta spazialmente: vedi sotto come viene trattata.
Il **sensore** è un pirometro a infrarossi posto all'interno della fascetta, a una
distanza configurabile dalla parete interna (default 10 mm). Essendo senza contatto,
la distanza non influenza la misura: il sensore legge la temperatura della superficie
interna nel punto `x` configurato (default 50 mm, al centro della lunghezza).
## Modello fisico
Non è una simulazione FEM elettromagnetica + termica completa: è un generatore
pratico di dataset. La catena di approssimazioni è la seguente.
1. **Sorgenti gaussiane in moto** — ogni sorgente ha un'impronta gaussiana di raggio
`sigma_punto_m`. Un gruppo di `numero_sorgenti` sorgenti equidistanti
(`distanza_sorgenti_m`) si muove rigidamente a velocità costante. Il profilo di
flusso sul lato esterno è la somma dei contributi:
`q(x, t) = Σᵢ q_picco · efficienza · exp(-((x - xᵢ(t))² + Δy²) / (2σ²))`.
L'offset circonferenziale `Δy` tra il percorso delle sorgenti e il punto osservato
dal sensore non è risolto spazialmente: entra come attenuazione gaussiana del flusso.
2. **Skin depth** — il riscaldamento a induzione è approssimato come riscaldamento
volumetrico che decade esponenzialmente con la profondità `z`:
`q_vol(x, z) = q(x) · exp(-z/δ) / (δ·(1 - exp(-spessore/δ)))`, normalizzato in modo
da conservare il flusso superficiale. La skin depth `δ = √(2ρₑ/(ωμ))` è calcolata
dalla resistività elettrica e dalla permeabilità del materiale alla frequenza di
induzione, oppure può essere imposta con `skin_depth_fissa_m`. Per la banda
stagnata a 20 kHz risulta ≈ 0.1 mm, confrontabile con lo spessore: la parete è
quasi isoterma attraverso lo spessore.
3. **Diffusione 2D del calore** — l'equazione del calore è integrata nella sezione
`(x, z)` con volumi finiti ed Eulero implicito (incondizionatamente stabile).
4. **Scambi con l'esterno** — la sezione scambia calore con l'ambiente su tutto il
contorno:
- convezione sul lato esterno (`h_esterno_W_m2K`), sul lato interno
(`h_interno_W_m2K`) e sui due bordi in x (`h_bordi_W_m2K`);
- **conduzione circonferenziale**: la sezione cede calore per conduzione lungo `y`
al resto della fascetta, assunto a temperatura ambiente. Il termine è
un'equazione di aletta ricavata sull'intero volume del cilindro: il calore
conduce lungo `y` attraverso l'intero spessore mentre le superfici esterna e
interna dell'intero cilindro perdono calore per convezione, dando
`q_y = -(h_esterno + h_interno)/spessore · (T - T_amb)` — nessun parametro di
conduzione `y` aggiuntivo da configurare.
5. **Temperatura iniziale** — il campo parte uniformemente alla temperatura ambiente
del run (che è randomizzata, quindi varia run per run).
6. **Sensore realistico** — la lettura aggiunge alla temperatura vera della superficie
interna: inerzia del primo ordine (`costante_tempo_s`), rumore gaussiano
(`rumore_std_C`) e quantizzazione (`quantizzazione_C`).
## Metodo numerico
- Griglia a volumi finiti `n_nodi_x × n_nodi_z` (default 100 × 15); le incognite sono
i centri cella.
- Eulero implicito con passo `dt_interno_s` (default 0.2 ms), più fine del periodo di
campionamento CSV.
- Tutti i termini (diffusione, convezione, conduzione circonferenziale) sono lineari e
costanti nel run: la matrice sparsa viene costruita e **fattorizzata LU una sola
volta per run** (`scipy.sparse.linalg.splu`); ogni passo temporale risolve solo i
sistemi triangolari. Un run da 30 s simulati richiede ~20 s di calcolo.
- Se in futuro si introducessero proprietà dipendenti dalla temperatura, la matrice
andrebbe ricostruita e rifattorizzata a ogni passo.
## File
```text
config.py tutti i parametri di simulazione
materials.py proprietà termofisiche ed elettriche dei materiali
simulate.py motore fisico + generazione dei CSV
plot_csv.py grafici rapidi (temperature e flusso) del primo run
plot_animazione.py animazione della sezione: campo T(x,z), sorgenti, sensore
dataset/ output generato da simulate.py (ricreato a ogni esecuzione)
```
## Installazione
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## Uso
```bash
# genera il dataset (ATTENZIONE: cancella e ricrea la cartella dataset/)
python simulate.py
# grafici statici del primo run (temperatura e flusso nel tempo)
python plot_csv.py
# animazione della sezione durante il passaggio delle sorgenti
python plot_animazione.py
```
Gli script di visualizzazione aprono finestre interattive (backend Qt); se il backend
non è interattivo (es. sessione senza display) salvano automaticamente PNG/GIF in
`dataset/`.
L'animazione riproduce esattamente la fisica di `run_0001` (stesso seed) e mostra tre
pannelli allineati: il profilo di flusso `q(x)` con le sorgenti in transito, il campo
di temperatura nella sezione con il sensore IR, e la temperatura nel punto osservato
(vera e con inerzia del sensore). Finestra temporale e cadenza dei fotogrammi si
regolano con le costanti in testa a `plot_animazione.py`.
## Configurazione
Tutto si modifica in `config.py`. I dizionari principali:
| Dizionario | Contenuto |
|------------------|---------------------------------------------------------------------------|
| `SIMULAZIONE` | numero di run, durata, campionamento CSV, passo interno, seed, cartella |
| `FASCETTA` | diametro, lunghezza, spessore, griglia, conduzione circonferenziale, materiale |
| `ARIA` | temperatura ambiente e coefficienti di convezione dei quattro lati |
| `SORGENTE` | corsa, velocità (il segno dà il verso), gruppo di sorgenti, gaussiana, flusso, frequenza |
| `SENSORE` | posizione (x e distanza dalla parete), inerzia, rumore, quantizzazione |
| `RANDOMIZZAZIONE`| entità delle perturbazioni per run |
Punti da conoscere:
- **Corsa delle sorgenti**: `x_inizio_m` è la distanza dal sensore, all'inizio della
corsa, della sorgente più avanzata (quella che lo raggiunge per prima);
`x_fine_m` è la distanza dal sensore, a fine corsa, della sorgente più arretrata
(quella che lo supera per ultima). Con `zero_dopo_fine` ogni sorgente si spegne
alla fine della propria corsa.
- **Materiale**: `FASCETTA["materiale"]` deve essere una chiave di `MATERIALI` in
`materials.py`. Per aggiungere un materiale basta una nuova voce nel dizionario
(conducibilità, densità, calore specifico, resistività elettrica, permeabilità).
- **Proprietà di `banda_stagnata`**: la banda stagnata è un nastro di acciaio a basso
tenore di carbonio (0,150,25% C) rivestito su entrambe le facce da un sottile
strato di stagno elettrolitico, dello spessore di pochi micrometri — trascurabile
rispetto allo spessore tipico della parete (es. 0,18 mm) e quindi ininfluente sulle
proprietà termiche, elettriche e magnetiche in massa. I valori in `materials.py`
sono quindi quelli dell'acciaio dolce sottostante:
[Banda stagnata: tutto quello che c'è da sapere (MUNDOLATAS)](https://mundolatas.com/it/banda-stagnata-tutto-quello-che-ce-da-sapere/),
[Bande stagnate elettrolitiche (EUROPERF)](https://www.europerf.it/it/banda-stagnata-elettrolitica.php),
[Differenza tra banda stagnata e acciaio inossidabile (Wuxi Bright Packing)](https://it.brightmetalcan.com/info/difference-between-tinplate-and-stainless-stee-48700260.html).
- **Randomizzazione**: ogni run perturba velocità, flusso di picco, sigma, offset y,
temperatura ambiente e rumore del sensore con estrazioni da un RNG a seed fisso
(`SIMULAZIONE["seed"]`): il dataset è riproducibile.
## Output
### `dataset/run_XXXX.csv` — serie temporale del run
| Colonna | Significato |
|--------------------------------|--------------------------------------------------------------------|
| `id_run` | identificativo del run |
| `tempo_s` | tempo simulato |
| `x_sorgente_m` | posizione della sorgente di riferimento del gruppo |
| `offset_y_sorgente_m` | offset circonferenziale del percorso (costante nel run) |
| `flusso_termico_sorgente_W_m2` | flusso efficace nel punto x del sensore |
| `skin_depth_m` | skin depth usata (costante nel run) |
| `T_vera_lato_sensore_C` | temperatura vera della superficie interna nel punto del sensore |
| `T_misurata_sensore_C` | lettura del sensore (inerzia + rumore + quantizzazione) |
| `T_lato_caldo_C` | temperatura della superficie esterna nello stesso punto x |
| `T_ambiente_C` | temperatura ambiente del run |
| `velocita_m_s`, `sigma_punto_m`, `flusso_picco_W_m2` | parametri randomizzati del run |
| `materiale` | chiave del materiale |
### `dataset/metadata.csv` — una riga per run
Contiene tutti i parametri effettivi del run (geometria, griglia, coefficienti di
scambio, parametri delle sorgenti e del sensore, valori randomizzati) e le temperature
di picco vera e misurata: utile come ground truth e per filtrare i run.
## Limitazioni
1. Il campo elettromagnetico non è simulato: l'accoppiamento induttivo è ridotto a
impronta gaussiana × efficienza × decadimento esponenziale in z.
2. La coordinata circonferenziale y non è risolta: offset del percorso e conduzione
verso il resto della fascetta sono modelli collassati (attenuazione gaussiana e
scambio lineare verso T ambiente).
3. Le proprietà dei materiali sono costanti con la temperatura; per gli acciai
ferromagnetici la skin depth reale varia fortemente con temperatura e campo
(punto di Curie non modellato).
4. Irraggiamento non modellato: a ~220 °C le perdite radiative non sono del tutto
trascurabili rispetto alla convezione.