# 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,15–0,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.