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
+39
View File
@@ -0,0 +1,39 @@
# Integrazione temporale implicita del sistema semidiscreto della shell.
#
# Dopo l'assemblaggio il problema è
#
# C * dT/dt + K * T = f(t) con K = K_cond + K_conv
#
# Con Eulero implicito:
#
# (C/dt + K) * T^(n+1) = (C/dt) * T^n + f^(n+1)
#
# La matrice A = C/dt + K dipende solo da mesh, materiale, passo temporale e
# condizioni convettive: nessuno di questi cambia durante un run, quindi si
# fattorizza LU una volta sola e a ogni passo si risolvono solo i sistemi
# triangolari. Se in futuro si introducessero proprietà dipendenti dalla
# temperatura, A andrebbe ricostruita e rifattorizzata a ogni passo.
import scipy.sparse as sp
from scipy.sparse.linalg import splu
def costruisci_solutore(C, K, dt_s: float) -> dict:
# A è simmetrica e definita positiva: capacità, conduzione e convezione
# lo sono tutte. L'ordinamento MMD sul grafo di A + A^T sfrutta la
# simmetria e riduce il riempimento della fattorizzazione rispetto al
# COLAMD di default, pensato per matrici non simmetriche.
A = (C / dt_s + K).tocsc()
return {
"lu": splu(A, permc_spec="MMD_AT_PLUS_A"),
"C_su_dt": (C / dt_s).tocsr(),
"dt_s": dt_s,
}
def passo_implicito(solutore: dict, T, f_costante, f_sorgente):
# Avanza il campo di un passo dt. f_costante raccoglie i termini noti
# indipendenti dal tempo (convezione verso l'ambiente su facce e bordi),
# f_sorgente il carico della sorgente all'istante di arrivo.
rhs = solutore["C_su_dt"] @ T + f_costante + f_sorgente
return solutore["lu"].solve(rhs)