import numpy as np import pytest import sys, os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import config def run_solver_with(x_src): """Run solver with a temporary X_SRC override.""" original = config.X_SRC config.X_SRC = x_src try: from fdm import solver import importlib importlib.reload(solver) return solver.solve() finally: config.X_SRC = original def test_shape(): """Output deve avere forma (NX, NT).""" T, x, t = run_solver_with(0.0) assert T.shape == (config.NX, config.NT) assert len(x) == config.NX assert len(t) == config.NT def test_initial_condition(): """La prima colonna deve essere uniforme a T0.""" T, x, t = run_solver_with(0.0) np.testing.assert_allclose(T[:, 0], config.T0) def test_temperature_increases_near_source_center(): """Con x_src=0.5 e a fine simulazione, il nodo centrale deve essere più caldo di quello iniziale.""" T, x, t = run_solver_with(0.5) i_src = int(np.argmin(np.abs(x - 0.5))) assert T[i_src, -1] > config.T0 def test_temperature_increases_near_source_left(): """Con x_src=0.0 il nodo sinistro deve scaldarsi.""" T, x, t = run_solver_with(0.0) assert T[0, -1] > config.T0 def test_temperature_increases_near_source_right(): """Con x_src=L il nodo destro deve scaldarsi.""" T, x, t = run_solver_with(config.L) assert T[-1, -1] > config.T0 def test_x_src_position_affects_profile(): """Spostandosi la sorgente da 0.1 a 0.9, il massimo del profilo finale deve spostarsi verso destra.""" T_left, x, _ = run_solver_with(0.1) T_right, _, _ = run_solver_with(0.9) x_max_left = x[np.argmax(T_left[:, -1])] x_max_right = x[np.argmax(T_right[:, -1])] assert x_max_right > x_max_left def test_no_nan_or_inf(): """La soluzione non deve contenere NaN o Inf.""" for x_src in [0.0, 0.25, 0.5, 0.75, 1.0]: T, _, _ = run_solver_with(x_src) assert np.all(np.isfinite(T)), f"NaN/Inf con x_src={x_src}"