61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
# 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
|