Files
simulatore-induttori/CLAUDE.md
T
davideandClaude Opus 5 1631d6c94e Rimuove il modello ai volumi finiti lasciando la sola analisi FEM
Il progetto conteneva due discretizzazioni indipendenti della stessa fisica:
i volumi finiti sulla sezione x-z di simulate.py (con generazione del dataset
CSV e le sue animazioni 2D/3D) e gli elementi finiti sulla mesh shell di
fem.py. Resta solo il secondo, che risolve la circonferenza invece di
collassarla in un'attenuazione gaussiana.

Eliminati simulate.py, plot_csv.py, plot_animazione.py e plot_animazione_3d.py.
Il FEM dipendeva da simulate.py per la cinematica del gruppo di sorgenti e per
la configurazione del run, quindi fem.py assorbe _x_riferimento_iniziale_m,
_x_riferimento_finale_m, _intervallo_attivo e configurazione_randomizzata; la
lettura del sensore (inerzia, rumore, quantizzazione) è ora applicata dentro
simula_campo_fem e la skin depth resta calcolata dalla frequenza dell'induttore
come sola grandezza diagnostica, dato che nel modello shell lo spessore è
collassato.

config.py perde i parametri che servivano solo ai volumi finiti (griglia
n_nodi_x/n_nodi_z, campionamento e cartella del dataset, numero di processi) e
guadagna FEM["durata_s"], FEM["seed"] e USCITA["cartella"]: le immagini e le
animazioni vanno in output/ invece che in dataset/.

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

6.0 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Lingua

L'utente comunica in italiano. Tutto il codice, i commenti, la documentazione e i messaggi di commit devono essere scritti in italiano.

Comandi

Usare sempre il virtual environment:

# Creare e attivare il venv (prima volta)
python -m venv .venv
source .venv/bin/activate

# Installare le dipendenze
pip install -r requirements.txt

# Punto di ingresso unico: `python main.py` elenca le azioni disponibili
python main.py mesh      # disegna la sola mesh a elementi shell
python main.py fem       # animazione 3D del campo FEM sulla mesh shell

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

Attivare sempre il venv (source .venv/bin/activate) prima di eseguire qualsiasi comando Python.

Non sono configurati test o linter.

Architettura

Analisi termica transitoria a elementi finiti di una fascetta (anello cilindrico sottile) riscaldata da sorgenti a induzione in movimento.

Geometria: la fascetta ha diametro, spessore e lunghezza configurabili. Il dominio discretizzato è la superficie media del cilindro: x = asse (le sorgenti si muovono lungo x sulla superficie esterna), theta = coordinata circonferenziale con theta = 0 sul piano del sensore, s = R·theta la lunghezza d'arco. Lo spessore non è discretizzato. Il sensore è un pirometro a infrarossi dentro la fascetta che misura la parete in un punto x fisso sul piano theta = 0.

Flusso dei dati:

  1. main.py — dispatcher da riga di comando che seleziona l'azione (mesh, fem)
  2. config.py — tutti i parametri configurabili (dizionari FASCETTA, MESH, FEM, ARIA, SORGENTE, SENSORE, RANDOMIZZAZIONE, USCITA)
  3. materials.py — dizionario MATERIALI con proprietà termofisiche ed elettriche per materiale
  4. mesh.py — mesh a elementi shell quadrangolari della superficie media del cilindro, visualizzata da plot_mesh.py
  5. fem.py — solutore termico transitorio a elementi finiti sulla mesh shell, animato da plot_animazione_fem.py

Mesh shell (mesh.py): griglia strutturata n_elementi_x × n_elementi_circonferenza di quadrilateri a 4 nodi sulla superficie media (raggio = (diametro spessore)/2); lo spessore non è discretizzato, è un attributo della shell. La mesh è chiusa lungo la circonferenza (nessun nodo duplicato sulla cucitura) e usa coordinate globali x = asse, y = R·sin(theta), z = R·cos(theta), con theta = 0 sul piano del sensore.

Pipeline FEM dentro fem.py: equazione risolta 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 convezione h_bordi sui due bordi anulari (area = spessore × perimetro). Il collasso in spessore è lecito perché Biot ≈ 1e-7 e il tempo di diffusione nella parete è di pochi ms: la profondità di penetrazione del riscaldamento non entra nel modello, conta solo il flusso assorbito. La skin depth è comunque calcolata dalla frequenza dell'induttore (calcola_skin_depth_m) e riportata in stato["skin_depth_m"] come sola diagnostica. L'impronta della sorgente è una gaussiana isotropa in (x, s) con distanza circonferenziale valutata sull'immagine più vicina (superficie chiusa). Gli elementi sono bilineari a 4 nodi e tutti identici (rettangoli dx × ds), quindi le matrici di elemento (MASSA_RIF, RIGIDEZZA_X, RIGIDEZZA_S) sono calcolate una volta e assemblate in forma vettorizzata; la matrice di massa di superficie è riusata per capacità, convezione e carico della sorgente. Eulero implicito con matrice costante fattorizzata LU una volta per analisi (prepara_stato_fem), poi passo_implicito_fem assembla solo il termine noto. In fem.py stanno anche la cinematica del gruppo di sorgenti (_x_riferimento_iniziale_m, _x_riferimento_finale_m, _intervallo_attivo) e la lettura della configurazione (configurazione_randomizzata).

Sensore e randomizzazione: il campo nodale è la temperatura vera della parete; simula_campo_fem restituisce anche T_lette, la lettura del sensore degradata da inerzia del primo ordine (a ogni passo dt), rumore gaussiano e quantizzazione (a ogni campionamento di frame). configurazione_randomizzata perturba velocità, flusso di picco, sigma dello spot, offset y, temperatura ambiente e rumore del sensore con un RNG con seed FEM["seed"], così due analisi restano riproducibili ma diverse; con RANDOMIZZAZIONE["abilitata"] = False restituisce i valori nominali di config.py.

Convenzioni su config.py

Ogni parametro in config.py ha un commento che spiega solo cos'è (il suo significato fisico/funzionale), mai perché è impostato a un valore specifico. Quando si modifica un parametro per ottenere un certo comportamento (es. una velocità diversa, un range di temperatura target), va cambiato solo il valore: non aggiungere commenti che giustificano o motivano quel valore, perché diventano obsoleti/fuorvianti alla prossima modifica.

Vincoli progettuali chiave

  • Il modello è una shell: la circonferenza è risolta, lo spessore è collassato (temperatura uniforme nella parete). Non introdurre effetti attraverso lo spessore (skin depth, gradiente radiale) senza prima discretizzarlo.
  • Le posizioni di inizio/fine corsa delle sorgenti (x_inizio_m, x_fine_m) sono distanze dal punto x del sensore lungo il verso di marcia; il segno di velocita_m_s determina il verso (negativo = -x).
  • La matrice implicita è costruita e fattorizzata una volta sola (proprietà del materiale costanti, nessun coefficiente dipendente dalla temperatura). Se si aggiungono proprietà dipendenti dalla temperatura, la matrice deve essere ricostruita e rifattorizzata ad ogni passo temporale.
  • Le visualizzazioni salvano in USCITA["cartella"] solo quando il backend matplotlib non è interattivo; altrimenti aprono una finestra.
  • Aggiungere un nuovo materiale richiede solo una nuova voce nel dizionario MATERIALI in materials.py; la chiave del materiale va poi impostata in FASCETTA["materiale"] in config.py.