Overriding the Initial State

When executing a FLAME GPU model its common to wish to override parts of the initial environment or provide a predefined agent population.

With Code

Overriding initial states in code is more flexible than from state files, allowing dynamic control of the initial state. For example it could be used execute models as part of a genetic algorithm.

Overriding the Initial Environment

The recommended method to override the initial state of a model is by executing it using a RunPlan.

This class allows you to configure a collection of environment property overrides. It can then be passed to simulate(), to execute the model using the provided overrides.

RunPlan provides setProperty() in the same format as elsewhere in FLAME GPU, to set the overrides.

Additionally a RunPlan holds the number of simulation steps and random seed to be used for the simulation, these replace any configuration specified via command-line or by manually setting the configs so they should normally be configured using setRandomSimulationSeed() and setSteps() respectively.

// Create a RunPlan to override the initial environment
flamegpu::RunPlan plan(model);
plan.setRandomSimulationSeed(123456);
plan.setSteps(3600);
plan.setProperty<float>("speed", 12.0f);
plan.setProperty<float, 3>("origin", {5.0f, 0.0f, 5.0f});

// Create a simulation object from the model
flamegpu::CUDASimulation simulation(model);

// Configure the simulation
...

// Run the simulation using the overrides from the RunPlan
simulation.simulate(plan);

Note

The Python method RunPlan::setPropertyArray() currently requires the second argument of array length, this is inconsistent with other uses. (issue)

Alternate Technique

You can also directly override the value of environment properties, by calling setEnvironmentProperty() directly on the CUDASimulation instance. Again, these methods have the same usage as setProperty() found in RunPlan, HostEnvironment and elsewhere.

This allows finer grained control than a RunPlan, as it can be called at any time to modify the current simulation state (e.g. if stepping the model manually, you could call it between steps).

// Create a simulation object from the model
flamegpu::CUDASimulation simulation(model);

// Override some environment properties
simulation.setEnvironmentProperty<float>("speed", 12.0f);
simulation.setEnvironmentProperty<float, 3>("origin", {5.0f, 0.0f, 5.0f});

// Configure the remainder of the simulation
...

// Run the simulation using the overrides from the RunPlan
simulation.simulate(plan);

Setting Initial Agent Populations

If you are unable to generate your agent populations within an initialisation function, as detailed in Host Agent Creation, you can create an AgentVector for each agent state population and pass them to the CUDASimulation.

An AgentVector is created by passing it’s constructor an AgentDescription and optionally the initial size of the vector which will create the specified number of default initialised agents.

The interface AgentVector is modelled after C++’s std::vector, with elements of type AgentVector::Agent. However, internally data is stored in a structure-of-arrays format.

AgentVector::Agent then has the standard setVariable() and getVariable() methods found elsewhere in the library.

Once the AgentVector is ready, it can be passed to setPopulationData() on the CUDASimulation. If your are using multiple agent states, it is also necessary to specify the desired agent state as the second argument.

// Create a population of 1000 'Boid' agents
flamegpu::AgentVector population(model.Agent("Boid"), 1000);

// Manually initialise the "speed" variable in each agent
for (flamegpu::AgentVector::Agent &instance : population) {
    instance.setVariable<float>("speed", 1.0f);
}

// Specifically set the 12th agent's variable differently
population[11].setVariable<float>("speed", 0.0f);

// Set the "Boid" population in the default state with the AgentVector
simulation.setPopulationData(population);
// Set the "Boid" population in the "healthy" state with the AgentVector
// simulation.setPopulationData(population, "healthy");

From File

FLAME GPU 2 simulations can be initialised from disk using either the XML or JSON format. The XML format is compatible with the previous FLAME GPU 1 input/output files, whereas the JSON format is new to FLAME GPU 2. In both cases, the input and output file formats are the same.

Loading simulation state (agent data and environment properties) from file can be achieved via either command line specification, or explicit specification within the code for the model. (See the previous section for more information)

In most cases, the input file will be taken from command line which can be passed using -i <input file>.

Agent IDs must be unique when the file is loaded from disk, otherwise an AgentIDCollision exception will be thrown. This must be corrected in the input file, as there is no method to do so within FLAME GPU at runtime.

In most cases, components of the input file are optional and can be omitted if defaults are preferred. If agents are not assigned IDs within the input file, they will be automatically generated.

Simulation state output files produces by FLAME GPU are compatible for use as input files. However, if working with large agent populations they are likely to be prohibitively large due to their human-readable format.

File Format

Block

Description

itno

XML Only This block provides the step number in XML output files, it is included for backwards compatibility with FLAMEGPU 1. It has no use for input.

config

This block is split into sub-blocks simulation and cuda, the members of each sub-block align with Simulation::Config and CUDASimulation::Config members of the same name respectively. These values are output to log the configuration, and can optionally be used to set the configuration via input file. (See the Configuring Execution guide for details of each individual member)

stats

This block includes statistics collected by FLAME GPU 2 during execution. It has no purpose on input.

environment

This block includes members of the environment, and can be used to configure the environment via input file. Members which begin with _ are automatically created internal properties, which can be set via input file.

xagent

XML Only Each xagent block represents a single agent, and the name and state values must match an agent state within the loaded model description hierarchy. Members which begin with _ are automatically created internal variables, which can be set via input file.

agents

JSON Only Within the agents block, a sub block may exist for each agent type, and within this a sub-block for each state type. Each state then maps to an array of object, where each object consists of a single agent’s variables. Members which begin with _ are automatically created internal variables, which can be set via input file.

The below code block displays example files output from FLAME GPU 2 in both XML and JSON formats, which could be used as input files.

<states>
    <itno>100</itno>
    <config>
        <simulation>
            <input_file></input_file>
            <step_log_file></step_log_file>
            <exit_log_file></exit_log_file>
            <common_log_file></common_log_file>
            <truncate_log_files>true</truncate_log_files>
            <random_seed>1643029170</random_seed>
            <steps>1</steps>
            <verbose>false</verbose>
            <timing>false</timing>
            <console_mode>false</console_mode>
        </simulation>
        <cuda>
            <device_id>0</device_id>
            <inLayerConcurrency>true</inLayerConcurrency>
        </cuda>
    </config>
    <stats>
        <step_count>100</step_count>
    </stats>
    <environment>
        <repulse>0.05</repulse>
        <_stepCount>1</_stepCount>
    </environment>
    <xagent>
        <name>Circle</name>
        <state>default</state>
        <_auto_sort_bin_index>0</_auto_sort_bin_index>
        <_id>241</_id>
        <drift>0.0</drift>
        <x>0.8293430805206299</x>
        <y>1.5674132108688355</y>
        <z>14.034683227539063</z>
    </xagent>
    <xagent>
        <name>Circle</name>
        <state>default</state>
        <_auto_sort_bin_index>0</_auto_sort_bin_index>
        <_id>242</_id>
        <drift>0.0</drift>
        <x>23.089038848876954</x>
        <y>24.715721130371095</y>
        <z>2.3497250080108644</z>
    </xagent>
</states>