Each World has its corresponding Simulator.
In [1]:
    
from ecell4.core import *
from ecell4.gillespie import GillespieWorld as world_type, GillespieSimulator as simulator_type
# from ecell4.ode import ODEWorld as world_type, ODESimulator as simulator_type
# from ecell4.lattice import LatticeWorld as world_type, LatticeSimulator as simulator_type
# from ecell4.meso import MesoscopicWorld as world_type, MesoscopicSimulator as simulator_type
# from ecell4.bd import BDWorld as world_type, BDSimulator as simulator_type
# from ecell4.egfrd import EGFRDWorld as world_type, EGFRDSimulator as simulator_type
    
Simulator needs a Model and World at the instantiation.
In [2]:
    
m = NetworkModel()
m.add_species_attribute(Species("A", "0.0025", "1"))
m.add_reaction_rule(create_degradation_reaction_rule(Species("A"), 0.693 / 1))
w = world_type(Real3(1, 1, 1))
w.bind_to(m)
w.add_molecules(Species("A"), 60)
sim = simulator_type(m, w)
sim.set_dt(0.01) #XXX: Optional
    
A Simulator has getters for a simulation time, a step interval, and the next-event time. In principle, a Simulator returns the World's time as its simulation time, and does a sum of the current time and a step interval as the next-event time.
In [3]:
    
print(sim.num_steps())
print(sim.t(), w.t())
print(sim.next_time(), sim.t() + sim.dt())
    
    
A Simulator can return the connected model and world. They are not copies, but the shared objects.
In [4]:
    
print(sim.model(), sim.world())
    
    
If you change a World after connecting it to a Simulator, you have to call initialize() manually before step(). The call will update the internal state of the Simulator.
In [5]:
    
sim.world().add_molecules(Species("A"), 60) # w.add_molecules(Species("A"), 60)
sim.initialize()
    
In [6]:
    
# w.save('test.h5')
    
Simulator has two types of step functions. First, with no argument, step() increments the time until next_time().
In [7]:
    
print("%.3e %.3e" % (sim.t(), sim.next_time()))
sim.step()
print("%.3e %.3e" % (sim.t(), sim.next_time()))
    
    
With an argument upto, if upto is later than next_time(), step(upto) increments the time upto the next_time() and returns True. Otherwise, it increments the time for upto and returns False. (If the current time t() is less than upto, it does nothing and returns False.)
In [8]:
    
print("%.3e %.3e" % (sim.t(), sim.next_time()))
print(sim.step(0.1))
print("%.3e %.3e" % (sim.t(), sim.next_time()))
    
    
For a discrete-step simulation, the main loop should be written like:
In [9]:
    
# w.load('test.h5')
sim.initialize()
    
In [10]:
    
next_time, dt = 0.0, 1e-2
for _ in range(5):
    while sim.step(next_time): pass
    next_time += dt
    print("%.3e %.3e %d %g" % (sim.t(), sim.dt(), sim.num_steps(), w.num_molecules(Species("A"))))
    
    
In [ ]: