Il training collassava alla soluzione banale T=T_AMB perché W_BC=10 spingeva
Adam a soddisfare le Robin BC (trivialmente, con gradiente zero) sacrificando
la PDE. Fix: W_PDE=10, W_BC=1 così la PDE domina il gradiente fin dal primo
epoch. LBFGS_STEPS: 20→200 perché L-BFGS era l'unico ottimizzatore a fare
progressi reali. forward(): rimossa moltiplicazione t_norm che causava
vanishing gradient su dT/dx e d²T/dx².
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
La normalizzazione introdotta (x,t in [0,1]²) rendeva il minimo banale
net=0 (T=T_AMB ovunque) troppo accessibile, causando il collasso del training.
Soluzione: T = T_AMB + T_char * (t/T_END) * net(x_norm, t_norm).
Così T(x,0) = T_AMB per costruzione (vincolo hard) e la rete deve trovare
soluzioni non banali per t>0. La loss IC resta ma è sempre 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- config.py: aggiunge GAUSS_SIGMA = 0.02 nella sezione parametri fisici
- model.py: T_char, grad_char, pde_scale diventano costanti di modulo (_T_char,
_grad_char, _pde_scale) calcolate una sola volta all'import
- engine.py: closure L-BFGS definita una volta sola fuori dal loop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- forward(): divide (x,t) per (L, T_END) prima di passare alla rete,
così le due dimensioni hanno la stessa scala indipendentemente da T_END
- heat_pinn_loss: calcola dT_dt e dT_dx in un singolo backward pass
usando autograd.grad con lista [t_f, x_f]
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- visualizer.py: sostituisce animations/ con results/pinn/TIMESTAMP/,
nomi fissi (heatmap.html, animation.html, comparison.html) come FDM
- config.py: aggiunge sezioni architettura, sampling, Adam, L-BFGS, loss weights
- model.py: costruisce HeatPINN dinamicamente da HIDDEN_SIZE/N_HIDDEN_LAYERS;
heat_pinn_loss legge pesi W_PDE/W_IC/W_BC da config
- engine.py: tutti i parametri di training letti da config
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- model.py: aggiunge termine sorgente Gaussiana (σ=0.02) nella PDE loss
per approssimare δ(x − X_SRC); sostituisce BC Neumann a x=0 con Robin
- engine.py: clustering collocation vicino X_SRC anziché x=0;
downsample FDM su entrambi gli assi spaziale e temporale in evaluate_model()
- visualizer.py: downsample FDM su entrambi gli assi prima del plot
- app.py: aggiorna header con fisica corrente
- CLAUDE.md: aggiorna PDE, BC e note architetturali
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>