davideandClaude Opus 5 97ebab844e Esporta in CSV la temperatura simulata e la lettura del sensore
Nuova azione `python main.py csv`: esporta_csv.py integra il campo FEM e scrive
output/csv/run_XXXX.csv con la temperatura vera della parete nel punto
osservato, la lettura del sensore reale e il massimo nodale istante per
istante, più un metadata.csv con una riga per analisi. La cartella è ricreata a
ogni esecuzione.

Le righe sono campionate a FEM["frequenza_campionamento_hz"],
indipendente dal passo di integrazione, e FEM["num_run"] analisi vengono
esportate di seguito: con la randomizzazione abilitata ognuna ha parametri
diversi ma riproducibili dallo stesso seed.

simula_campo_fem accetta salva_campi=False, perché all'export servono solo le
serie scalari e non i campi nodali di ogni campione, e restituisce anche la
temperatura nodale massima per campione.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 11:44:58 +02:00

Analisi Termica FEM — Fascetta, Sorgenti a Induzione Mobili, Sensore IR Fisso

Questo progetto calcola il transitorio termico di una fascetta (anello cilindrico sottile) riscaldata da un gruppo di sorgenti a induzione in movimento, osservata da un sensore a infrarossi fisso. La fascetta è discretizzata con una mesh a elementi shell quadrangolari e il campo di temperatura è risolto a elementi finiti, poi visualizzato in un'animazione 3D isometrica o esportato in CSV come serie temporale (temperatura vera della parete e lettura del sensore).

Geometria

La fascetta è un anello cilindrico definito da tre dimensioni:

  • diametro (default 70 mm) — il diametro esterno del cilindro;
  • spessore (default 0.18 mm) — lo spessore della parete;
  • lunghezza (default 100 mm) — l'estensione assiale lungo x.

Il dominio discretizzato è la superficie media del cilindro (raggio = (diametro spessore)/2). Lo spessore non è discretizzato: è un attributo degli elementi shell.

        sorgenti (induttori), in moto lungo x sulla superficie esterna
              ▼           ▼           ▼
              ┌───────────────────────────────────┐
        x = 0 │   superficie media del cilindro   │ x = lunghezza
              └───────────────────────────────────┘
                         ┆  linea di vista
                         ▲
                    sensore IR (fisso, x = 50 mm, theta = 0,
                    a 10 mm dalla parete interna)
  • x = asse del cilindro, da 0 a lunghezza.
  • theta = coordinata circonferenziale, con theta = 0 sul piano del sensore; nelle formule si usa la lunghezza d'arco s = R·theta.
  • Coordinate globali per la visualizzazione: x, y = R·sin(theta), z = R·cos(theta).

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 parete nel nodo più vicino a x = 50 mm sul piano theta = 0.

Modello fisico

L'equazione risolta è quella del calore per unità di superficie media:

rho·cp·t ∂T/∂t = k·t ∇²T + q(x, s, t)  (h_est + h_int)·(T  T_amb)

con t = spessore della parete e ∇² il laplaciano nel piano (x, s).

  1. Collasso dello spessore — la temperatura è uniforme attraverso la parete. Con spessore 0.18 mm il numero di Biot h·t/k vale ~1e-7 e il tempo di diffusione attraverso la parete t²/alpha è di pochi millisecondi, molto più rapido del transito delle sorgenti. Di conseguenza la profondità di penetrazione del riscaldamento a induzione non entra nel modello: conta solo il flusso totale assorbito per unità di superficie. La skin depth δ = √(2ρₑ/(ωμ)) è comunque calcolata dalla frequenza dell'induttore (frequenza_hz, oppure imposta con skin_depth_fissa_m) e riportata come grandezza diagnostica: per la banda stagnata a 20 kHz risulta ≈ 0.14 mm, confrontabile con lo spessore, il che conferma che la parete è quasi isoterma attraverso lo spessore.

  2. Sorgenti gaussiane in moto — ogni sorgente ha un'impronta gaussiana isotropa nel piano (x, s) di raggio sigma_punto_m. Un gruppo di numero_sorgenti sorgenti equidistanti (distanza_sorgenti_m) si muove rigidamente a velocità costante: q(x, s, t) = Σᵢ q_picco · efficienza · exp(-((x - xᵢ(t))² + (s - s₀)²) / (2σ²)). La distanza circonferenziale è valutata sull'immagine più vicina, perché la superficie è chiusa. L'offset s₀ del percorso rispetto al piano del sensore è offset_y_percorso_m.

  3. Scambi con l'ambiente — convezione sulla faccia esterna (h_esterno_W_m2K) e su quella interna (h_interno_W_m2K) su tutta la superficie, più convezione sui due bordi anulari x = 0 e x = lunghezza (h_bordi_W_m2K, su un'area pari a spessore × perimetro).

  4. Temperatura iniziale — il campo parte uniformemente alla temperatura ambiente dell'analisi (randomizzabile).

  5. Sensore reale — la lettura aggiunge alla temperatura vera della parete nel punto osservato: inerzia del primo ordine (costante_tempo_s), rumore gaussiano (rumore_std_C) e quantizzazione (quantizzazione_C), gli ultimi due applicati a ogni campionamento.

  6. Randomizzazione — con RANDOMIZZAZIONE["abilitata"] ogni analisi perturba velocità, flusso di picco, sigma dello spot, offset y del percorso, temperatura ambiente e rumore del sensore con estrazioni gaussiane/uniformi da un RNG con seed fisso (FEM["seed"]): analisi diverse dello stesso setup differiscono come differirebbero due passaggi reali, restando riproducibili.

Irraggiamento non modellato e proprietà dei materiali costanti con la temperatura: a ~210 °C le perdite radiative non sono del tutto trascurabili rispetto alla convezione, e per gli acciai ferromagnetici la skin depth reale varia fortemente con temperatura e campo (punto di Curie non modellato).

Metodo numerico

  • Mesh (mesh.py): griglia strutturata n_elementi_x × n_elementi_circonferenza di quadrilateri a 4 nodi (default 40 × 48), chiusa lungo la circonferenza senza nodi duplicati sulla cucitura.
  • Elementi: shell bilineari a 4 nodi. Tutti gli elementi sono rettangoli identici dx × ds, quindi le matrici di elemento (massa e rigidezza) sono calcolate una volta sola e assemblate in forma vettorizzata. La matrice di massa di superficie è riusata per capacità termica, convezione sulle facce e carico della sorgente; la convezione sui bordi anulari usa una matrice di massa 1D sull'anello di nodi.
  • Integrazione temporale: Eulero implicito con passo FEM["dt_s"] (default 1 ms). Tutti i termini sono lineari e costanti, quindi la matrice di sistema è assemblata e fattorizzata LU una sola volta (scipy.sparse.linalg.splu) in prepara_stato_fem; ogni passo assembla solo il termine noto e risolve i sistemi triangolari.
  • Flusso nodale: l'impronta gaussiana isotropa è separabile, q(x, s) = q_x(x) · q_s(s), e il fattore circonferenziale è costante nel tempo (precalcolato). A ogni passo si valuta quindi solo il fattore assiale sui n_x + 1 nodi distinti in x, espanso con un prodotto esterno.
  • Se in futuro si introducessero proprietà dipendenti dalla temperatura, la matrice andrebbe ricostruita e rifattorizzata a ogni passo.

File

main.py                 punto di ingresso da riga di comando
config.py               tutti i parametri (geometria, mesh, FEM, aria, sorgente, sensore)
materials.py            proprietà termofisiche ed elettriche dei materiali
mesh.py                 generazione della mesh a elementi shell
fem.py                  solutore termico transitorio a elementi finiti
plot_mesh.py            disegno della sola mesh
plot_animazione_fem.py  animazione 3D del campo di temperatura
esporta_csv.py          export CSV della serie temporale
output/                 immagini e GIF salvate quando il backend non è interattivo
output/csv/             CSV esportati (ricreata a ogni esecuzione)

Installazione

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Uso

python main.py          # elenco delle azioni disponibili
python main.py mesh     # disegna la sola mesh a elementi shell
python main.py fem      # integra il campo FEM e lo anima in 3D
python main.py csv      # esporta la serie temporale in output/csv/

Ogni modulo resta eseguibile anche direttamente (python plot_mesh.py, python plot_animazione_fem.py, python esporta_csv.py).

Gli script aprono finestre interattive (backend Qt); se il backend non è interattivo (es. sessione senza display) salvano automaticamente PNG/GIF in output/.

L'animazione FEM mostra due pannelli: la fascetta in vista isometrica con il campo di temperatura dipinto sugli elementi shell e i marker delle sorgenti in transito, e la storia della temperatura nel punto osservato dal sensore (valore nodale vero e lettura del sensore reale). Finestra temporale iniziale e cadenza dei fotogrammi si regolano con le costanti in testa a plot_animazione_fem.py; la durata simulata è FEM["durata_s"].

Output CSV

python main.py csv cancella e ricrea output/csv/, poi esporta FEM["num_run"] analisi (una per file run_XXXX.csv) più un metadata.csv con una riga per analisi. Le righe sono campionate a FEM["frequenza_campionamento_hz"], indipendente dal passo di integrazione.

output/csv/run_XXXX.csv — serie temporale

Colonna Significato
id_run identificativo dell'analisi
tempo_s tempo simulato
x_sorgente_m posizione della sorgente di riferimento del gruppo
T_vera_sensore_C temperatura vera della parete nel punto osservato (valore nodale FEM)
T_misurata_sensore_C lettura del sensore (inerzia + rumore + quantizzazione)
T_massima_fascetta_C temperatura nodale massima su tutta la fascetta in quell'istante
T_ambiente_C temperatura ambiente dell'analisi
offset_y_sorgente_m, velocita_m_s, sigma_punto_m, flusso_picco_W_m2 parametri effettivi dell'analisi (variano se la randomizzazione è attiva)
skin_depth_m skin depth diagnostica
materiale chiave del materiale

output/csv/metadata.csv — una riga per analisi

Tutti i parametri effettivi (geometria, mesh, coefficienti di scambio, sorgenti, sensore) e i valori di picco: T_vera_max_sensore_C, T_misurata_max_sensore_C, T_massima_fascetta_C.

Configurazione

Tutto si modifica in config.py. I dizionari principali:

Dizionario Contenuto
FASCETTA diametro, lunghezza, spessore, materiale
MESH numero di elementi shell lungo x e lungo la circonferenza
FEM passo temporale, durata, seed, campionamento CSV, numero di analisi
ARIA temperatura ambiente e coefficienti di convezione (facce e bordi)
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 analisi
USCITA cartella per immagini e animazioni salvate

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à termica, densità, calore specifico, resistività elettrica, permeabilità relativa).
  • 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), Bande stagnate elettrolitiche (EUROPERF), Differenza tra banda stagnata e acciaio inossidabile (Wuxi Bright Packing).
S
Description
No description provided
Readme
258 KiB
Languages
Python 100%