You are here

Discrete events

Nuclear fission - chain reaction

ModelId: 
fission4.sml
SimileVersion: 
6.6p2

This model simulates the process of nuclear fission by chain reaction, such as occurs in a fission reactor or weapon. It models a sample of a fissile material, such as plutonium, which has the property that when a nucleus is hit by a neutron it splits, releasing two more neutrons which are capable of splitting other nuclei. In a fission reactor this process is continuous, and regulated by the insertion of rods of a material that absorbs neutrons, in order to release a controllable amount of energy.

Equations: 

Model Desktop1 : 

 
Event   start : 
    start =         1 (boolean) 
    Maximum = 0
    Comments:
        Event that occurs once at start of simulation 
 
State   split id : 
    split id =         [[U235 atoms/fission,trigger_magnitude()],[reset...,0]] (real) 
    
    Comments:
        Only one atom should split at a time, so this state is the index of the last atom to split 

Submodel Hit : 

    Submodel "Hit" an association submodel between "U235 atoms" (in role "is") and "Neutrons" (in role "does").
 
Condition   cond1 : 
    cond1 =         dist<1 (cond_spec) 
    Where:
        dist = Value(s) of dist_sqd
    
    Comments:
        True if neutron and atom are less than 1 distance unit apart. This allows the time of the collision event to be set precisely since the association will already exist. 
 
Event   happens : 
    happens =         dist_sqd (boolean) 
    Where:
        dist_sqd = Value(s) of dist_sqd
    Minimum = 0.25
    Comments:
        Splitting happens if neutron gets within 0.5 distance units of atom. 
 
Variable   dist_sqd : 
    dist_sqd =         (is_x-does_x)^2+(is_y-does_y)^2 (real) 
    Where:
        is_y = Value(s) of ../U235 atoms/y from submodel "U235 atoms" in role "is"
        {every_y} = Value(s) of ../U235 atoms/y
        is_x = Value(s) of ../U235 atoms/x from submodel "U235 atoms" in role "is"
        {every_x} = Value(s) of ../U235 atoms/x
        does_x = Value(s) of ../Neutrons/x from submodel "Neutrons" in role "does"
        {every_x_0} = Value(s) of ../Neutrons/x
        does_y = Value(s) of ../Neutrons/y from submodel "Neutrons" in role "does"
        {every_y_0} = Value(s) of ../Neutrons/y
    
    Comments:
        Square of distance between neutron and atom 

Submodel U235 atoms : 

    Submodel "U235 atoms" is a population submodel.
 
Creation   cr1 : 
    cr1 =         896 (real) 
    
    Comments:
        Initial population of atoms 
 
Event   decay : 
    decay =         after(exprnd(10000),"true") (boolean) 
    
    Comments:
        Each atom will spontaneously decay after a time sampled from a random-exponential distribution if left alone 
 
Event   fission : 
    fission =         index(1) (real) 
    
    Comments:
        Caused either by spontaneous decay or splitting by a neutron. Value is index of atom. 
 
Loss   loss1 : 
    loss1 =         1 (int) 
    
    Comments:
        Atom always removed after fission occurs 
 
Variable   size : 
    size =         2 (int) 
    
    Comments:
        For lollipop display 
 
Variable   x : 
    x =         element([x],index(1)) (real) 
    Where:
        [x] = Value(s) of ../start posns/x
    
 
Variable   y : 
    y =         element([y],index(1)) (real) 
    Where:
        [y] = Value(s) of ../start posns/y
    

Submodel Neutrons : 

    Submodel "Neutrons" is a population submodel.
 
Compartment   x : 
    Initial value = element([x],split_id) (real)
    Where:
        [x] = Value(s) of ../start posns/x
        split_id = Value(s) of ../split id
    
    
    Comments:
        Starting X position, looked up from array using index of atom that just split 
 
Compartment   y : 
    Initial value = element([y],split_id) (real)
    Where:
        [y] = Value(s) of ../start posns/y
        split_id = Value(s) of ../split id
    
    
    Comments:
        Starting Y position, looked up from array using index of atom that just split 
 
Flow   flow1 : 
    flow1 =         rand_const(-0.5,0.5) (1/day) 
    
 
Flow   flow2 : 
    flow2 =         rand_const(-0.5,0.5) (1/day) 
    
 
Immigration   im1 : 
    im1 =         2 (real) 
    
    Comments:
        Number of new neutrons produced when an atom undergoes fission 
 
Loss   loss102 : 
    loss102 =         x<-20 or x>120 or y<-20 or y>120 (boolean) 
    Where:
        x = Value(s) of x
        y = Value(s) of y
    
    Comments:
        Neutron is removed from simulation if it is heading away from the atoms to save processing time 
 
Loss   loss2 : 
    loss2 =         1 (int) 
    
    Comments:
        Old neutron removed when it splits an atom, so new ones will have new random trajectories 
 
Variable   size : 
    size =         1 (int) 
    
    Comments:
        For lollipop display 

Submodel start posns : 

    Submodel "start posns" is a fixed_membership multi-instance submodel with dimensions [896].
    Comments:
        This is a 1-D array for calculating the positions of all the atoms, used to set them up and to set positions of new neutrons when they split 
 
Variable   x : 
    x =         3*((index(1)-1)%32)+3 (real) 
    
 
Variable   y : 
    y =         3.464*ceil(index(1)/32)+1.732*(index(1)%2) (real) 
    

Results: 

This image is a screenshot taken while executing the model in SimiLive. In some areas the atom grid is complete, while in others many atoms (green) are missing and there are large numbers of neutrons (orange).

Queueing for a group of ATM machines

ModelId: 
atm.sml
SimileVersion: 
6.6p2

This model illustrates the use of Simile to create pure event-driven models. There are no compartments or explicit references to time in the model, so the state only changes when an event occurs. This means that the setting of the "Update every:" period has no effect on the model behaviour.

Category: 
Technique
Equations: 

Model Desktop1 :

 
Event   arrival : Customer arrives
    arrival =         "true" (boolean)
    
    Comments:
        This happens after a wait from the beginning of the simulation or from the last customer arrival
 
Event   next arrival : Wait for customer arrival
    next arrival =         after(exprnd(4),"true") (boolean)
    
    Comments:
        Customers arrive ar random intervals, so time between arrivals is given by the exponential distribution. Wait starts either at start of simulation or on arrival of previous customer.
 
Event   start : Start of simulation
    start =         time() (boolean)
    Maximum = 0
    Comments:
        Provides an event at time 0, the start of the simulation.
 
State   queue : Number of customers waiting
    queue =         [[arrival,prev(0)+(if full then 1 else 0)],[reset...,0],[machine/de-queue,prev(0)-1]] (int)
    Where:
        full = Value(s) of full
    
    Comments:
        This starts at zero, increases by 1 if a customer arrives when all machines are full, and decreases by one when a customer leaves the queue
 
Variable   full : All machines are in use
    full =         all([in_use]) (boolean)
    Where:
        [in_use] = Value(s) of machine/in use
    

Submodel machine :

    Submodel "machine" is a fixed_membership multi-instance submodel with dimensions [3].
 
Event   de-queue : Customer moves from queue to machine
    de-queue =         queue>0 (boolean)
    Where:
        queue = Value(s) of ../queue
    
    Comments:
        Happens if someone finishes using a machine while people are waiting
 
Event   finish using : Customer completes transaction
    finish using =         after(gaussian_var(10,1),"true") (boolean)
    
    Comments:
        A period of time sampled from a normal distribution has elapsed since the customer started using the machine. Customer either started using machine which was idle, or came out of the queue.
 
Event   start using : Machine comes into use
    start using =         not unreached and not in_use (boolean)
    Where:
        in_use = Value(s) of in use
        unreached = Value(s) of unreached
    
    Comments:
        Happens when this is the first free machine and a customer arrives and starts using it immediately
 
State   in use : Machine is busy.
    in use =         [[finish using,queue>0],[start using,"true"],[reset...,"false"]] (boolean)
    Where:
        queue = Value(s) of ../queue
    
    Comments:
        Machine becomes busy when a customer arrives and starts using it, and remains busy until a customer finishes using it while the queue is empty.
 
Variable   unreached : New customers do not reach this machine
    unreached =         in_preceding(prev(0) or not in_use) (boolean)
    Where:
        in_use = Value(s) of in use
    
    Comments:
        There is an unused machine earlier in the group than this one. Either the last machine is itself unreached or it is not in use.

 

Results: 

This graph shows results for six consecutive runs superposed. Only the blue and brown runs show significant queueing.

Subscribe to RSS - Discrete events