Biotope and Double-Buffering
GridEnvironment is the canonical owner of PHIDS’s grid-aligned environmental state. It is where
continuous fields, diffusion behavior, wind transport, and the most explicit double-buffering
mechanics of the current engine are implemented.
This chapter documents the current implementation in src/phids/engine/core/biotope.py.
Role in the Engine
GridEnvironment provides the field side of the hybrid ECS + cellular-automata runtime. While
ECSWorld stores discrete entities, GridEnvironment stores the continuous or grid-aggregated
quantities that those entities read from and write to.
In current implementation it owns:
plant_energy_layer_plant_energy_layer_writeplant_energy_by_species_plant_energy_by_species_writesignal_layers_signal_layers_writetoxin_layers_toxin_layers_writewind_vector_xwind_vector_yflow_field
Architectural Significance
PHIDS’s design rules repeatedly refer to double-buffering. In the current codebase, that principle
is most concretely embodied in GridEnvironment.
This means GridEnvironment is not just a container for NumPy arrays. It is the subsystem that
makes the engine’s buffered environmental semantics real.
Bounded Memory Discipline
The biotope enforces several hard constraints at initialization time:
1 <= width <= GRID_W_MAX1 <= height <= GRID_H_MAX1 <= num_signals <= MAX_SUBSTANCE_TYPES1 <= num_toxins <= MAX_SUBSTANCE_TYPES
It also pre-allocates the species-specific plant-energy tensor with shape:
(MAX_FLORA_SPECIES, width, height)
This is the environmental expression of the Rule of 16. The engine does not dynamically resize these core buffers during a simulation tick.
State Layout
Aggregate plant-energy layer
plant_energy_layer is the read-visible aggregate plant-energy field consumed by later phases such
as flow-field generation.
Per-species plant-energy tensor
plant_energy_by_species stores species-specific contributions, allowing the environment to retain
species granularity while also exposing an aggregate field.
Signal and toxin layers
Signals and toxins are each stored as stacked layers of shape:
(num_signals, width, height)(num_toxins, width, height)
This allows PHIDS to represent multiple airborne signals and multiple toxin fields in a vectorized way.
Wind fields
Wind is represented as two NumPy layers:
wind_vector_xwind_vector_y
In the current implementation these are typically filled uniformly, but the abstraction also supports per-cell updates.
Flow field
flow_field is stored in the environment as a scalar guidance surface of shape (width, height).
It is written by the flow-field phase and read by the interaction phase.
Double-Buffering Mechanics
Plant-energy writes
Plant-energy writes are not applied directly to the read-visible aggregate field.
Instead:
- species-specific writes go to
_plant_energy_by_species_write, rebuild_energy_layer()aggregates those writes into_plant_energy_layer_write,- read and write buffers are swapped,
- the write buffers are refreshed from the new read-visible values.
This is one of the clearest examples of PHIDS’s buffered-state discipline.
Signal diffusion writes
Signal diffusion reads from signal_layers, writes into _signal_layers_write, and then swaps the
buffers.
Toxin diffusion writes
Toxin diffusion uses the same read/write swap pattern via toxin_layers and _toxin_layers_write.
Diffusion Model
The environment defines a precomputed Gaussian kernel through DIFFUSION_KERNEL, built by
_make_gaussian_kernel().
Current signal diffusion procedure
diffuse_signals() currently performs, for each signal layer:
- compute the mean wind vector,
- convolve the layer with
DIFFUSION_KERNELusingscipy.signal.convolve2d, - advect by integer cell shifts using
np.roll, - zero values below
SIGNAL_EPSILON, - write into the signal write buffer,
- swap read and write buffers.
Current toxin diffusion procedure
diffuse_toxins() currently mirrors the same procedure for toxin layers.
This is a significant current-state fact: in the present implementation, toxins still pass through a convolution-and-roll diffusion helper, even though higher-level design intentions may treat toxins as more localized defenses.
Subnormal Float Mitigation
After convolution and wind shifting, both signal and toxin diffusion zero out values below
SIGNAL_EPSILON.
This is not cosmetic cleanup. It is a performance invariant motivated by the cost of processing subnormal floating-point tails. In PHIDS, sparsity preservation is part of the computational model.
Wind Semantics
The environment currently supports two wind update modes:
set_uniform_wind(vx, vy)for full-field updates,update_wind_at(x, y, vx, vy)for cell-local mutation.
The live REST interface primarily exercises the uniform update pathway.
Plant-Energy API
The current plant-energy helper methods are:
set_plant_energy(x, y, species_id, value)clear_plant_energy(x, y, species_id)rebuild_energy_layer()
A notable invariant is that set_plant_energy() clamps values to >= 0.0 before storing them in
write buffers.
Serialization Role
GridEnvironment.to_dict() converts the current environment layers into list-backed structures
suitable for msgpack serialization and WebSocket transport.
This makes GridEnvironment the backbone of the replay and streaming snapshot formats.
Read/Write Boundary in Practice
The current engine does not implement a universally duplicated whole-world state. Instead, it uses field-level double-buffering for the environment combined with deterministic phase ordering.
This is the most precise description of the present runtime model:
- buffered environmental layers,
- ordered ECS mutation passes,
- synchronization at phase boundaries through rebuild/swap operations.
Evidence from Tests
The current test suite verifies key environmental properties.
Diffusion thresholding
tests/test_biotope_diffusion.py verifies that tiny signal concentrations are truncated to zero
after diffusion.
Buffer-swap and invariants
tests/test_schemas_and_invariants.py verifies that:
- invalid grid dimensions raise errors,
- plant-energy writes become visible only after
rebuild_energy_layer(), - clearing plant energy is reflected after a rebuild,
- negative energy writes are clamped to zero.
Methodological Limits of the Current Biotope
The current environment model should be described precisely:
- wind advection is represented by integer rolls of the convolved field,
- diffusion is layer-based rather than particle-based,
- toxins currently still use the diffusion helper,
- double-buffering is strongest at the field level rather than as a full read/write universe clone.
These are important characteristics of the current scientific and computational model.
Verified Current-State Evidence
src/phids/engine/core/biotope.pysrc/phids/engine/loop.pytests/test_biotope_diffusion.pytests/test_schemas_and_invariants.py
Where to Read Next
- For entity locality and cell occupancy:
ecs-and-spatial-hash.md - For the global guidance surface written into the environment:
flow-field.md - For system-level context:
index.md