This commit is contained in:
2026-08-03 00:18:00 +02:00
parent 560c6a6a62
commit 7883f3dead
13 changed files with 1460 additions and 488 deletions
+60
View File
@@ -0,0 +1,60 @@
# Pirometro a infrarossi montato all'interno della fascetta.
#
# Il sensore osserva senza contatto un punto fisso della superficie interna,
# individuato dalla coordinata assiale x e dalla posizione circonferenziale
# theta = 0, che per convenzione è la generatrice di riferimento del modello.
#
# Con una shell a una temperatura per nodo la faccia interna e quella esterna
# hanno la stessa temperatura: il valore osservato è la temperatura della
# shell nel punto, interpolata con le funzioni di forma dell'elemento che lo
# contiene. L'approssimazione regge finché la parete è termicamente sottile
# rispetto al transito della sorgente (vedi numero_fourier_spessore in
# simulate.py).
#
# Alla temperatura vera si sovrappone la catena di misura: inerzia del primo
# ordine, rumore gaussiano e quantizzazione della lettura.
import numpy as np
import elementi_shell as el
def prepara_interpolatore(mesh: dict, x_m: float, theta_rad: float) -> dict:
# Individua l'elemento che contiene il punto osservato e i pesi nodali
# con cui ricostruirvi la temperatura.
n_x = mesh["n_elementi_x"]
n_theta = mesh["n_elementi_theta"]
x_limitato = min(max(x_m, 0.0), mesh["lunghezza_m"])
i = min(n_x - 1, max(0, int(x_limitato / mesh["lato_x_m"])))
xi = 2.0 * (x_limitato - mesh["x_nodi_m"][i]) / mesh["lato_x_m"] - 1.0
arco = (theta_rad * mesh["raggio_medio_m"]) % mesh["circonferenza_m"]
j = int(arco / mesh["lato_arco_m"]) % n_theta
eta = 2.0 * (arco - mesh["arco_nodi_m"][j]) / mesh["lato_arco_m"] - 1.0
elemento = i * n_theta + j
return {
"nodi": mesh["connettivita"][elemento],
"pesi": el.funzioni_forma(xi, eta),
"x_m": x_limitato,
"theta_rad": theta_rad,
}
def temperatura_osservata_C(interpolatore: dict, T: np.ndarray) -> float:
return float(T[interpolatore["nodi"]] @ interpolatore["pesi"])
def aggiorna_inerzia_C(
T_letta_C: float, T_vera_C: float, dt_s: float, costante_tempo_s: float
) -> float:
# Risposta del primo ordine del sensore.
tau = max(costante_tempo_s, 1e-9)
return T_letta_C + (T_vera_C - T_letta_C) * dt_s / tau
def quantizza(valore: float, passo: float) -> float:
if passo <= 0.0:
return valore
return round(valore / passo) * passo