Skip to content

Temperature Computation

Real Ant Engineer edited this page Nov 3, 2025 · 10 revisions

🌡️ Temperature Computation System

This page explains how temperature computation is handled in the mod. The simulation is based on a finite-difference heat diffusion model.


📦 Section-Level Simulation

Temperature is only computed for sections (16×16×16 blocks) within a 16-block radius around BlockEntity instances implementing IHaveTemperature.

Each active section contains three data layers (more detail here):

  • TemperatureDataLayer — stores local and default temperatures.
  • ConductionDataLayer — stores thermal conductivity (how fast heat diffuses).
  • ResilienceDataLayer — stores the “return-to-default” rate (how fast it stabilizes to equilibrium).

These layers are retrieved using:

TemperatureDataLayer temperatureData = data.getTemperature(packedSection);
ConductionDataLayer conductionData = data.getConduction(packedSection);
ResilienceDataLayer resilienceData = data.getResilience(packedSection);

If any of the three are missing, the section is skipped for that tick.


🧮 Finite Difference Scheme

The simulation uses a finite-difference method to approximate heat diffusion between neighboring blocks. For each block in the section:

  1. Compute self temperature Tself and conduction Cself.
  2. For each of the six directions (+X, -X, +Y, -Y, +Z, -Z), compute:
    • Neighbor temperature Tn.
    • Neighbor conduction Cn.
    • Thermal flux contribution:
    flux += (Tn - Tself) * (Cn * Cself) / (Cn + Cself);
  3. If a neighbor is outside the section, cross-section access is used to get the flux.

🔥 Temperature Update Formula

After computing the total flux and resilience, the new temperature is calculated as:

newTemp = selfTemp + (
    ((defaultTemp - selfTemp) * resilience * 100)  // Relaxation toward default
  + totalFlux * (1 - resilience)                   // Net conduction
) * DT / CAPACITY;

Where:

  • resilience → Pulls the block temperature back toward its equilibrium/default temperature.
  • conduction → Controls how fast temperature equalizes between neighbors.
  • DT → Time step (1/20 of a second).
  • CAPACITY → Thermal capacity (very important for numerical stability, default 3e4f).

The resulting temperature is then clamped to the valid range:

Mth.clamp(newTemp, TemperatureDataLayer.MIN_TEMPERATURE, TemperatureDataLayer.MAX_TEMPERATURE);

♻️ Dirty Section Tracking

If a block’s temperature changes significantly (ΔT > 1e−3), the section is marked as dirty and all its boundary neighbors are also flagged for updates otherwise, the section is marked as clean (no change this tick) and will not be ticked next time.


🌍 Dynamic Temperature Sources

Blocks implementing IHaveTemperature (e.g. FuelAssembly, HeatExchanger) have an internal heat production or removal mechanism. They are exceptions to the dirty system and cause their section to always remain dirty (ticked every update).

if (data.dynamicContains(pos)) {
    IHaveTemperature be = data.getDynamic(pos);
    be.addTemperature(newTemp - selfTemp);
}

🧊 Notes

  • Cross-section flux continuity ensures seamless diffusion across chunk boundaries.
  • The numerical scheme is stable for reasonable conductivity and resilience values.
  • Stability depends heavily on the choice of DT and CAPACITY — lowering capacity can cause oscillations.

Implemented in TemperatureTicker and data layers under com.rae.crowns.content.fields.temperature.

Clone this wiki locally