Aggiunge gruppo di sorgenti multiple rigide lungo x

Sostituisce la singola sorgente con un gruppo di N sorgenti equidistanti
che si muovono insieme, sommando i contributi di flusso sul sensore.
This commit is contained in:
2026-07-05 14:25:57 +02:00
parent e636dfaad8
commit b40ee49528
2 changed files with 81 additions and 28 deletions
+67 -25
View File
@@ -27,46 +27,86 @@ def calcola_skin_depth_m(materiale: dict, frequenza_hz: float) -> float:
return math.sqrt(2.0 * rho_e / (omega * mu))
def _spread_sorgenti_m(sorgente: dict) -> float:
# Distanza lungo x tra la prima e l'ultima sorgente del gruppo.
numero_sorgenti = sorgente.get("numero_sorgenti", 1)
distanza = sorgente.get("distanza_sorgenti_m", 0.0)
return (numero_sorgenti - 1) * distanza
def _x_riferimento_iniziale_m(sorgente: dict) -> float:
# Posizione a t=0 della sorgente di indice 0 (quella più arretrata nel
# verso di marcia). x_inizio_m è la distanza dal sensore della sorgente
# più avanzata (che quindi lo raggiunge per prima).
spread = _spread_sorgenti_m(sorgente)
x_sensore = sorgente["x_sensore_m"]
x_inizio = sorgente["x_inizio_m"]
if sorgente["velocita_m_s"] >= 0:
return (x_sensore - x_inizio) - spread
return (x_sensore + x_inizio) + spread
def _x_riferimento_finale_m(sorgente: dict) -> float:
# Posizione di fine corsa della sorgente di indice 0. x_fine_m è la
# distanza dal sensore della sorgente più arretrata (che quindi lo
# supera per ultima).
x_sensore = sorgente["x_sensore_m"]
x_fine = sorgente["x_fine_m"]
if sorgente["velocita_m_s"] >= 0:
return x_sensore + x_fine
return x_sensore - x_fine
def x_sorgente_al_tempo(sorgente: dict, t_s: float) -> float:
return sorgente["x_inizio_m"] + sorgente["velocita_m_s"] * t_s
return _x_riferimento_iniziale_m(sorgente) + sorgente["velocita_m_s"] * t_s
def sorgente_attiva(sorgente: dict, x_m: float) -> bool:
if not sorgente.get("zero_dopo_fine", True):
return True
inizio = sorgente["x_inizio_m"]
fine = sorgente["x_fine_m"]
v = sorgente["velocita_m_s"]
def _intervallo_attivo(inizio: float, fine: float, v: float, x_m: float) -> bool:
if v >= 0:
return inizio <= x_m <= fine
return fine <= x_m <= inizio
def flusso_termico_incidente_W_m2(sorgente: dict, t_s: float) -> tuple[float, float]:
# Restituisce x_sorgente_m e flusso_termico_efficace_W_m2.
# Restituisce x_sorgente_m (posizione della sorgente di riferimento) e
# flusso_termico_efficace_W_m2 (somma dei contributi di tutte le sorgenti).
#
# Il movimento è rappresentato con un'impronta gaussiana centrata sulla
# sorgente in moto. Il modello 1D vede solo il flusso lungo la linea
# che passa per il sensore fisso.
x = x_sorgente_al_tempo(sorgente, t_s)
# Il movimento è rappresentato con un'impronta gaussiana centrata su
# ciascuna sorgente in moto. Più sorgenti equidistanti si muovono insieme
# come un gruppo rigido: condividono velocità, sigma e flusso di picco, e
# sono sfalsate lungo x di un multiplo di "distanza_sorgenti_m". Il
# modello 1D vede solo il flusso lungo la linea che passa per il sensore
# fisso, sommando il contributo di tutte le sorgenti attive.
x_rif_iniziale = _x_riferimento_iniziale_m(sorgente)
x_rif_finale = _x_riferimento_finale_m(sorgente)
x_riferimento = x_rif_iniziale + sorgente["velocita_m_s"] * t_s
if not sorgente_attiva(sorgente, x):
return x, 0.0
dx = x - sorgente["x_sensore_m"]
numero_sorgenti = sorgente.get("numero_sorgenti", 1)
distanza = sorgente.get("distanza_sorgenti_m", 0.0)
v = sorgente["velocita_m_s"]
zero_dopo_fine = sorgente.get("zero_dopo_fine", True)
dy = sorgente["offset_y_percorso_m"]
sigma = sorgente["sigma_punto_m"]
gaussiana = math.exp(-0.5 * (dx * dx + dy * dy) / (sigma * sigma))
q_totale = 0.0
for i in range(numero_sorgenti):
x_i = x_riferimento + i * distanza
q = (
sorgente["flusso_termico_picco_W_m2"]
* sorgente["efficienza_riscaldamento"]
* gaussiana
)
return x, q
if zero_dopo_fine:
inizio_i = x_rif_iniziale + i * distanza
fine_i = x_rif_finale + i * distanza
if not _intervallo_attivo(inizio_i, fine_i, v, x_i):
continue
dx = x_i - sorgente["x_sensore_m"]
gaussiana = math.exp(-0.5 * (dx * dx + dy * dy) / (sigma * sigma))
q_totale += (
sorgente["flusso_termico_picco_W_m2"]
* sorgente["efficienza_riscaldamento"]
* gaussiana
)
return x_riferimento, q_totale
def riscaldamento_volumetrico_W_m3(
@@ -315,6 +355,8 @@ def simula_singolo(cfg_run: dict, output_csv: Path, rng: random.Random) -> dict:
"x_sensore_m": sorgente["x_sensore_m"],
"offset_y_percorso_m": sorgente["offset_y_percorso_m"],
"velocita_m_s": sorgente["velocita_m_s"],
"numero_sorgenti": sorgente.get("numero_sorgenti", 1),
"distanza_sorgenti_m": sorgente.get("distanza_sorgenti_m", 0.0),
"sigma_punto_m": sorgente["sigma_punto_m"],
"flusso_termico_picco_W_m2": sorgente["flusso_termico_picco_W_m2"],
"efficienza_riscaldamento": sorgente["efficienza_riscaldamento"],