How to cache simulation results¶
The SimulationCache provides content-addressed caching to avoid redundant
simulations: identical inputs return a stored result instead of re-running
EnergyPlus. For how the cache key is computed, what gets stored, and why
invalidation is automatic, see
Caching strategy.
Python only, permanently
Running a locally installed EnergyPlus and reading its results belongs to Python alone. JavaScript is not waiting on a port and will not gain a counterpart: this is a permanent boundary, so no issue tracks it, and moving the capability out of that state takes a constitutional amendment rather than a ledger edit.
Requires an EnergyPlus installation on the machine and a subprocess to drive it, then
reads the eplusout files that run leaves on disk. Neither the installation nor the
subprocess is available in a browser, which is the runtime the JavaScript library
targets. JavaScript reaches EnergyPlus by the other mechanism instead: see
browser-simulation, which is not a
workaround for this entry but a different capability.
The full entry, including the vocabulary this capability owns, is on the capability parity page.
Basic Usage¶
from idfkit.simulation import simulate, SimulationCache
cache = SimulationCache()
# First run: executes EnergyPlus
result1 = simulate(model, "weather.epw", cache=cache)
print(f"Runtime: {result1.runtime_seconds:.1f}s")
# Second run: instant cache hit
result2 = simulate(model, "weather.epw", cache=cache)
print(f"Runtime: {result2.runtime_seconds:.1f}s") # Near zero
Cache Location¶
Default locations by platform:
| Platform | Default Path |
|---|---|
| Linux | ~/.cache/idfkit/simulation/ |
| macOS | ~/Library/Caches/idfkit/simulation/ |
| Windows | %LOCALAPPDATA%\idfkit\cache\simulation\ |
Custom Location¶
Cache Operations¶
Check for Hit¶
key = cache.compute_key(model, weather, design_day=True)
if cache.contains(key):
print("Would be a cache hit")
else:
print("Would be a cache miss")
Manual Get/Put¶
# Compute key
key = cache.compute_key(model, weather)
# Check cache
cached_result = cache.get(key)
if cached_result is not None:
print("Cache hit!")
else:
# Run simulation
result = simulate(model, weather)
# Store in cache (only successful results)
cache.put(key, result)
Clear Cache¶
Batch Processing¶
Share a cache across batch simulations. The cache is thread- and process-safe
(atomic writes via a temp directory and rename), so a shared cache is safe for
concurrent simulate_batch() runs and across multiple processes:
from idfkit.simulation import simulate_batch, SimulationCache
cache = SimulationCache()
# All jobs share the same cache
batch1 = simulate_batch(jobs, cache=cache)
# Re-running unchanged jobs hits cache
batch2 = simulate_batch(jobs, cache=cache) # Instant for unchanged
Storage Considerations¶
Disk Space¶
Each cached entry is a full copy of the run directory. Monitor usage:
Cleanup¶
# Clear everything
cache.clear()
# Or manually delete specific entries
import shutil
shutil.rmtree(cache.cache_dir / "abc123...")
Disabling Caching¶
Pass cache=None (the default) to skip caching:
# No caching
result = simulate(model, weather)
# With caching
result = simulate(model, weather, cache=SimulationCache())
Best Practices¶
- Use for development — Cache during iterative testing
- Clear for production — Start fresh for final runs
- Share across batch — Pass same cache to
simulate_batch() - Monitor disk usage — Large studies can fill disk
- Custom location — Use fast SSD for better performance
See Also¶
- Caching Strategy — Design concepts
- How to run a simulation — Basic simulation guide
- How to run batch simulations — Parallel execution