~starkingdoms/starkingdoms

ref: 06f4e4a24e833f920faa0dfaaefea8f09e706eba starkingdoms/crates/unified/src/server/heat/radiation.rs -rw-r--r-- 1.6 KiB
06f4e4a2ghostly_zsh feat: radiation area 15 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
use crate::{attachment::PartInShip, ecs::{Part, Player, Radiator, Temperature}, prelude::*};

const STEFAN_BOLTZMANN: f32 = 5.670374419E-8;
const T_ENV: f32 = 4.0; // units: Kelvin

pub fn heat_radiation_plugin(app: &mut App) {
    app.add_systems(Update, part_radiation);
}

fn part_radiation(
    time: Res<Time>,
    parts: Query<(&mut Temperature, &Radiator, &Part)>
) {
    for (mut temperature, radiator, part) in parts {
        // time for the implicit euler method
        // e = emissivity, o = stefan-boltzmann constant, m = mass,
        // c = specific heat, A = surface area
        // k = (eoA)/(mc)
        // dT/dt = -k(T^4 - T_env^4)
        // T_env = 200.0 K
        // T_n+1 = T_n + dt*f(T_n+1)
        // T_n+1 = T_n - k*dt*((T_n+1)^4 - T_env^4)
        // g(T_n+1) = T_n+1 + k*dt*(T_n+1)^4 - T_n - k*dt*(T_env)^4
        // g'(T_n+1) = 1 + 4*k*dt*(T_n+1)^3
        // newton's method:
        // x_n+1 = x_n - g(x_n)/g'(x_n)
        // where x_n is the previous guess for T_n+1
        let initial_temp = temperature.0;
        let k = (radiator.emissivity * STEFAN_BOLTZMANN * radiator.surface_area)
            / (part.strong_config.physics.mass * part.strong_config.part.specific_heat);
        let dt = time.delta_secs();

        // initial guess
        let mut next_temp = initial_temp;
        for _ in 0..3 {
            let g = next_temp + k*dt*next_temp.powi(4) - initial_temp - k*dt*T_ENV;
            let g_prime = 1.0 + 4.0*k*dt*(next_temp).powi(3);

            next_temp = next_temp - g/g_prime;
        }
        temperature.0 = next_temp;
    }
}