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
+14 -3
View File
@@ -66,8 +66,12 @@ ARIA = {
} }
SORGENTE = { SORGENTE = {
# La sorgente parte da x = x_inizio_m e si muove verso x_fine_m. # Distanza dal sensore, all'inizio della corsa, della sorgente del
"x_inizio_m": -1.0, # gruppo più vicina al sensore (quella che lo raggiunge per prima).
"x_inizio_m": 1.0,
# Distanza dal sensore, alla fine della corsa, della sorgente del
# gruppo più lontana dal sensore (quella che lo supera per ultima).
"x_fine_m": 5.0, "x_fine_m": 5.0,
# Coordinata laterale fissa della proiezione del sensore sul lato caldo. # Coordinata laterale fissa della proiezione del sensore sul lato caldo.
@@ -81,11 +85,18 @@ SORGENTE = {
# Velocità della sorgente lungo x. # Velocità della sorgente lungo x.
"velocita_m_s": 2.0, "velocita_m_s": 2.0,
# Numero di sorgenti equidistanti che si muovono insieme come un gruppo
# rigido (stessa velocità, sigma, flusso ed efficienza).
"numero_sorgenti": 3,
# Distanza lungo x tra sorgenti consecutive del gruppo.
"distanza_sorgenti_m": 0.5,
# Raggio del punto gaussiano. Valore più alto = impronta termica più larga. # Raggio del punto gaussiano. Valore più alto = impronta termica più larga.
"sigma_punto_m": 0.012, "sigma_punto_m": 0.012,
# Flusso termico incidente massimo prima della correzione per efficienza. # Flusso termico incidente massimo prima della correzione per efficienza.
"flusso_termico_picco_W_m2": 16500000.0, "flusso_termico_picco_W_m2": 5500000.0,
# Frazione del flusso incidente che diventa effettivamente calore nella piastra. # Frazione del flusso incidente che diventa effettivamente calore nella piastra.
"efficienza_riscaldamento": 0.35, "efficienza_riscaldamento": 0.35,
+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)) 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: 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: def _intervallo_attivo(inizio: float, fine: float, v: float, 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"]
if v >= 0: if v >= 0:
return inizio <= x_m <= fine return inizio <= x_m <= fine
return fine <= x_m <= inizio return fine <= x_m <= inizio
def flusso_termico_incidente_W_m2(sorgente: dict, t_s: float) -> tuple[float, float]: 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 # Il movimento è rappresentato con un'impronta gaussiana centrata su
# sorgente in moto. Il modello 1D vede solo il flusso lungo la linea # ciascuna sorgente in moto. Più sorgenti equidistanti si muovono insieme
# che passa per il sensore fisso. # come un gruppo rigido: condividono velocità, sigma e flusso di picco, e
x = x_sorgente_al_tempo(sorgente, t_s) # 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): numero_sorgenti = sorgente.get("numero_sorgenti", 1)
return x, 0.0 distanza = sorgente.get("distanza_sorgenti_m", 0.0)
v = sorgente["velocita_m_s"]
dx = x - sorgente["x_sensore_m"] zero_dopo_fine = sorgente.get("zero_dopo_fine", True)
dy = sorgente["offset_y_percorso_m"] dy = sorgente["offset_y_percorso_m"]
sigma = sorgente["sigma_punto_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 = ( if zero_dopo_fine:
sorgente["flusso_termico_picco_W_m2"] inizio_i = x_rif_iniziale + i * distanza
* sorgente["efficienza_riscaldamento"] fine_i = x_rif_finale + i * distanza
* gaussiana if not _intervallo_attivo(inizio_i, fine_i, v, x_i):
) continue
return x, q
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( 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"], "x_sensore_m": sorgente["x_sensore_m"],
"offset_y_percorso_m": sorgente["offset_y_percorso_m"], "offset_y_percorso_m": sorgente["offset_y_percorso_m"],
"velocita_m_s": sorgente["velocita_m_s"], "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"], "sigma_punto_m": sorgente["sigma_punto_m"],
"flusso_termico_picco_W_m2": sorgente["flusso_termico_picco_W_m2"], "flusso_termico_picco_W_m2": sorgente["flusso_termico_picco_W_m2"],
"efficienza_riscaldamento": sorgente["efficienza_riscaldamento"], "efficienza_riscaldamento": sorgente["efficienza_riscaldamento"],