temp
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
||||
# Sorgenti a induzione in movimento sulla superficie esterna della fascetta.
|
||||
#
|
||||
# Il gruppo è formato da più sorgenti equidistanti che traslano insieme lungo
|
||||
# x con la stessa velocità. Tutte percorrono la stessa generatrice, cioè la
|
||||
# stessa posizione circonferenziale, definita dall'offset rispetto al punto
|
||||
# osservato dal sensore.
|
||||
#
|
||||
# Il flusso termico incidente su un punto della superficie è
|
||||
#
|
||||
# q''(x, arco, t) = q_picco * somma_i exp(-((x - x_i(t))^2) / (2 sigma^2))
|
||||
# * exp(-(delta_arco^2) / (2 sigma^2))
|
||||
#
|
||||
# dove delta_arco è la distanza circonferenziale minima tra il punto e il
|
||||
# percorso delle sorgenti, misurata lungo la circonferenza e riavvolta su
|
||||
# 2*pi*R: passare da un lato o dall'altro della fascetta è equivalente.
|
||||
#
|
||||
# Il flusso è quindi il prodotto di un fattore che dipende solo da x e varia
|
||||
# nel tempo e di un fattore che dipende solo dall'arco ed è costante: questa
|
||||
# separazione è sfruttata dall'assemblaggio del vettore sorgente.
|
||||
|
||||
import math
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
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, x_sensore_m: float) -> float:
|
||||
# Posizione a t=0 della sorgente di indice 0. Le sorgenti i sono a
|
||||
# x_i = riferimento + i * distanza, quindi per v >= 0 l'indice 0 è la
|
||||
# più arretrata nel verso di marcia, per v < 0 è la più avanzata.
|
||||
# x_inizio_m è la distanza dal sensore della sorgente più avanzata
|
||||
# (quella che lo raggiunge per prima).
|
||||
spread = _spread_sorgenti_m(sorgente)
|
||||
x_inizio = sorgente["x_inizio_m"]
|
||||
if sorgente["velocita_m_s"] >= 0:
|
||||
return (x_sensore_m - x_inizio) - spread
|
||||
return x_sensore_m + x_inizio
|
||||
|
||||
|
||||
def x_riferimento_finale_m(sorgente: dict, x_sensore_m: float) -> float:
|
||||
# Posizione di fine corsa della sorgente di indice 0. x_fine_m è la
|
||||
# distanza dal sensore della sorgente più arretrata nel verso di marcia
|
||||
# (quella che lo supera per ultima).
|
||||
spread = _spread_sorgenti_m(sorgente)
|
||||
x_fine = sorgente["x_fine_m"]
|
||||
if sorgente["velocita_m_s"] >= 0:
|
||||
return x_sensore_m + x_fine
|
||||
return (x_sensore_m - x_fine) - spread
|
||||
|
||||
|
||||
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 theta_percorso_rad(sorgente: dict, raggio_medio_m: float) -> float:
|
||||
# Posizione circonferenziale del percorso delle sorgenti, ricavata
|
||||
# dall'offset in arco rispetto al sensore, che sta per convenzione a
|
||||
# theta = 0.
|
||||
return sorgente["offset_y_percorso_m"] / raggio_medio_m
|
||||
|
||||
|
||||
def fattore_circonferenziale(
|
||||
sorgente: dict, raggio_medio_m: float, arco_m: np.ndarray
|
||||
) -> np.ndarray:
|
||||
# Attenuazione gaussiana del flusso in funzione della distanza
|
||||
# circonferenziale dal percorso delle sorgenti. La distanza è riavvolta
|
||||
# sulla circonferenza, così la sorgente scalda anche i punti raggiunti
|
||||
# "dall'altra parte" della fascetta.
|
||||
circonferenza = 2.0 * math.pi * raggio_medio_m
|
||||
delta = arco_m - sorgente["offset_y_percorso_m"]
|
||||
delta = (delta + circonferenza / 2.0) % circonferenza - circonferenza / 2.0
|
||||
sigma = sorgente["sigma_punto_m"]
|
||||
return np.exp(-0.5 * (delta * delta) / (sigma * sigma))
|
||||
|
||||
|
||||
def profilo_flusso_x_W_m2(
|
||||
sorgente: dict, x_sensore_m: float, t_s: float, x_m: np.ndarray
|
||||
) -> tuple[float, np.ndarray]:
|
||||
# Restituisce la posizione della sorgente di riferimento e il fattore
|
||||
# assiale del flusso efficace [W/m²], somma dei contributi di tutte le
|
||||
# sorgenti attive valutata nei punti x richiesti.
|
||||
x_rif_iniziale = x_riferimento_iniziale_m(sorgente, x_sensore_m)
|
||||
x_rif_finale = x_riferimento_finale_m(sorgente, x_sensore_m)
|
||||
x_riferimento = x_rif_iniziale + sorgente["velocita_m_s"] * t_s
|
||||
|
||||
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)
|
||||
sigma = sorgente["sigma_punto_m"]
|
||||
|
||||
q_picco = (
|
||||
sorgente["flusso_termico_picco_W_m2"] * sorgente["efficienza_riscaldamento"]
|
||||
)
|
||||
|
||||
q_x = np.zeros_like(x_m)
|
||||
for i in range(numero_sorgenti):
|
||||
x_i = x_riferimento + i * distanza
|
||||
|
||||
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_m - x_i
|
||||
q_x += q_picco * np.exp(-0.5 * (dx * dx) / (sigma * sigma))
|
||||
|
||||
return x_riferimento, q_x
|
||||
|
||||
|
||||
def posizioni_sorgenti_m(sorgente: dict, x_riferimento_m: float) -> np.ndarray:
|
||||
# Posizioni lungo x di tutte le sorgenti del gruppo a partire da quella
|
||||
# di riferimento.
|
||||
numero_sorgenti = sorgente.get("numero_sorgenti", 1)
|
||||
distanza = sorgente.get("distanza_sorgenti_m", 0.0)
|
||||
return x_riferimento_m + np.arange(numero_sorgenti) * distanza
|
||||
Reference in New Issue
Block a user