bb492c37a6
La lastra diventa una fascetta cilindrica (diametro, lunghezza, spessore) di cui si simula la sezione rettangolare lunghezza x spessore, con origine nel vertice in alto a sinistra: x = lunghezza, z = spessore, y = coordinata circonferenziale non risolta (offset collassato in attenuazione gaussiana). - Le sorgenti si muovono in direzione -x e producono un profilo di flusso q(x) su tutto il lato esterno; corretto il posizionamento del gruppo per velocita' negative - Sensore a infrarossi con coordinata x e distanza dalla parete interna, misura la superficie interna senza contatto - Volumi finiti 2D con Eulero implicito: matrice sparsa fattorizzata LU una volta per run (scipy.sparse.linalg.splu), a ogni passo solo i sistemi triangolari - Convezione sui lati esterno/interno, bordi adiabatici in x - Schema CSV invariato; metadata con geometria e griglia 2D Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
69 lines
5.2 KiB
Markdown
69 lines
5.2 KiB
Markdown
# 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:
|
||
|
||
```bash
|
||
# Creare e attivare il venv (prima volta)
|
||
python -m venv .venv
|
||
source .venv/bin/activate
|
||
|
||
# Installare le dipendenze
|
||
pip install -r requirements.txt
|
||
|
||
# Generare il dataset (scrive dataset/run_XXXX.csv + dataset/metadata.csv)
|
||
python simulate.py
|
||
|
||
# Visualizzare il primo run
|
||
python plot_csv.py
|
||
```
|
||
|
||
Attivare sempre il venv (`source .venv/bin/activate`) prima di eseguire qualsiasi comando Python.
|
||
|
||
Non sono configurati test o linter.
|
||
|
||
## Architettura
|
||
|
||
Generatore di dataset per misurazioni termiche pseudo-realistiche di una fascetta (anello cilindrico sottile) riscaldata da sorgenti a induzione in movimento.
|
||
|
||
**Geometria:** la fascetta ha diametro, spessore e lunghezza configurabili. Il dominio simulato è la sezione rettangolare lunghezza × spessore, con origine (0, 0) nel vertice in alto a sinistra: x = lunghezza (le sorgenti si muovono in direzione -x sul lato esterno), z = spessore (0 = lato esterno, spessore = lato interno). La coordinata circonferenziale y non è risolta: l'offset y delle sorgenti è collassato in un'attenuazione gaussiana del flusso. Il sensore è un pirometro a infrarossi dentro la fascetta che misura la superficie interna in un punto x fisso.
|
||
|
||
**Flusso dei dati:**
|
||
|
||
1. `config.py` — tutti i parametri configurabili (dizionari SIMULAZIONE, FASCETTA, ARIA, SORGENTE, SENSORE, RANDOMIZZAZIONE)
|
||
2. `materials.py` — dizionario MATERIALI con proprietà termofisiche ed elettriche per materiale
|
||
3. `simulate.py` — motore principale: genera N run randomizzati, scrive i CSV, scrive `metadata.csv`
|
||
4. `plot_csv.py` — visualizzazione autonoma per un singolo run
|
||
|
||
**Pipeline fisica dentro `simula_singolo()` in [simulate.py](simulate.py):**
|
||
|
||
- La skin depth è calcolata dalla resistività elettrica del materiale e dalla frequenza di induzione (`calcola_skin_depth_m`)
|
||
- Le sorgenti gaussiane in movimento producono un profilo di flusso termico superficiale q(x) sul lato esterno, variabile nel tempo (`profilo_flusso_incidente_W_m2`)
|
||
- Quel flusso è ridistribuito volumetricamente attraverso lo spessore con decadimento esponenziale in z (`profilo_deposizione_z_1_m`): q_vol(x, z) = q(x) · p(z)
|
||
- Uno schema 2D a volumi finiti con Eulero implicito integra l'equazione del calore su `n_nodi_x × n_nodi_z` celle: la matrice sparsa è fattorizzata LU una volta per run (`costruisci_solutore_implicito_2d`, che restituisce l'oggetto `splu`), poi ad ogni passo si risolve solo il sistema triangolare
|
||
- Le condizioni al contorno sono incorporate nella matrice: convezione sui lati esterno (z = 0) e interno (z = spessore), bordi adiabatici a x = 0 e x = lunghezza
|
||
- L'output del sensore aggiunge inerzia del primo ordine, rumore gaussiano e quantizzazione
|
||
|
||
**Randomizzazione per run** (`configurazione_randomizzata`): ogni run perturba velocità, flusso di picco, sigma del punto, offset y, temperatura ambiente e rumore del sensore con estrazioni gaussiane/uniformi da un RNG con seed fisso, garantendo riproducibilità.
|
||
|
||
**Schema di output** (`dataset/run_XXXX.csv`): serie temporale con colonne `id_run, tempo_s, x_sorgente_m, offset_y_sorgente_m, flusso_termico_sorgente_W_m2, skin_depth_m, T_vera_lato_sensore_C, T_misurata_sensore_C, T_lato_caldo_C, T_ambiente_C, velocita_m_s, sigma_punto_m, flusso_picco_W_m2, materiale`. `metadata.csv` ha una riga per run con tutti i parametri e le temperature di picco.
|
||
|
||
## Convenzioni su `config.py`
|
||
|
||
Ogni parametro in [config.py](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 è 2D nella sezione (x = lunghezza, z = spessore). La coordinata circonferenziale y non è risolta spazialmente — l'offset y del percorso delle sorgenti è collassato in un'attenuazione gaussiana del flusso; il diametro è registrato solo come geometria del setup.
|
||
- 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 per run (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.
|
||
- `simulate.py` cancella e ricrea l'intera cartella di output ad ogni esecuzione (`shutil.rmtree`).
|
||
- Aggiungere un nuovo materiale richiede solo una nuova voce nel dizionario `MATERIALI` in [materials.py](materials.py); la chiave del materiale va poi impostata in `FASCETTA["materiale"]` in [config.py](config.py).
|