Microscopic models : granular and social force model

Microscopic models : granular and social force model

cromosim.micro.add_people_in_box(Np, dom, xmin, xmax, ymin, ymax, rmin, rmax, rng)[source]

Adds new persons in the box [xmin,xmax]x[ymin,ymax] Be careful : overlaps can occur…

Parameters
Np: int

Number of persons

dom: Domain

contains everything for managing the domain

xmin: float

minimal abscissa of the box

xmaxfloat

maximal abscissa of the box

ymin: float

minimal ordinate of the box

ymax: float

maximal ordinate of the box

rmin: float

minimum radius for the individuals

rmax: float

maximum radius for the individuals

rng: scipy.random.RandomState

container for the Mersenne Twister pseudo-random number generator

Returns
——-
peoplenumpy array

people coordinates and radius

cromosim.micro.check_people_in_box(dom, box, p, rng)[source]

To check that people coordinates are in the given box (test 1) and in an usable space i.e. in an area accessible and not concerned by obstacles (test 2). On the other hand, one moves the individuals which do not satisfy these two tests.

Parameters
dom: Domain

contains everything for managing the domain

box: list

coordinates of the box [xmin, xmax, ymin, ymax]

p: numpy array

people coordinates x y r

rng: RandomState

scipy random state object (see scipy.random.RandomState)

Returns
p: numpy array

new people coordinates x y r

cromosim.micro.compute_contacts(dom, people, dmax)[source]

This function uses a KDTree method to find the contacts  between individuals. Moreover the contacts with the walls are also determined from the wall distance (obtained by the fast-marching method).

Parameters
dom: Domain

contains everything for managing the domain

people: numpy array

people coordinates and radius : x,y,r

dmax: float

threshold value used to consider a contact as active (dij<dmax)

Returns
contacts: numpy array

all the contacts i,j,dij,eij_x,eij_y such that dij<dmax and i<j (no duplication)

cromosim.micro.compute_desired_velocity(dom, people)[source]

This function determines people desired velocities from the desired velocity array computed by Domain thanks to a fast-marching method.

Parameters
dom: Domain

contains everything for managing the domain

people: numpy array

people coordinates and radius : x,y,r

Returns
Inumpy array

people index i

Jnumpy array

people index j

Vdnumpy array

people desired velocity

cromosim.micro.compute_forces(F, Fwall, people, contacts, U, Vd, lambda_, delta, k, eta)[source]

This function computes all the forces (isentropic interaction and friction) and sums them. The correcting pre-factor due to the vision angle is also used into the social force term.

Parameters
F: float

social trend of an individual to keep apart from another (homogeneous to a force)

Fwall: float

social trend of an individual to keep apart from a wall (homogeneous to a force)

people: numpy array

people coordinates and radius : x,y,r

contacts: numpy array

all the contacts : i,j,dij,eij_x,eij_y

U: numpy array

people velocities

Vd: numpy array

people desired velocities

lambda_: float

quantifies the directional dependence when the vision angle is considered (between [0,1], if equal to 1 the fully isotropic case is recovered)

delta: float

maintains a certain distance between neighbors

k: float

used when there is overlapping, k is a stiffness constant of individuals seen as deformable bodies

eta: float

friction coefficient

Returns
Forces: numpy array

sum of all forces for each individual

cromosim.micro.create_people_in_box(np, box, rmin, rmax, dom, rng)[source]

To create np persons in a given box. The overlaps are not treated for the moment but one checks that the individuals are located in an area where  the desired velocity is well defined (outside inaccessible areas or obstacles). If it is not the case, one changes their coordinates in consequence.

Parameters
np: integer

number of individuals to create

box: list

coordinates of the box [xmin, xmax, ymin, ymax]

rmin: float

people minimal radius

rmax: float

people maximal radius

dom: Domain

contains everything for managing the domain

rng: RandomState

scipy random state object (see scipy.random.RandomState)

Returns
p: numpy array

new people coordinates x y r

cromosim.micro.exit_box(box, sexit, people, U, arrays=[])[source]

Removes individuals outside the box according to a threshold value.

Parameters
box: numpy array

box vertice coordinates [xmin, xmax, ymin, ymax]

sexit: float

threshold value used to remove individuals close to the exit

peoplenumpy array

people coordinates and radius : x,y,r

U: numpy array

people velocities

arrays: list of numpy array

other arrays to resize similarly as people and U

Returns
people: numpy array

new people coordinates (outside individuals had been removed)

U: numpy array

new people velocities (outside individuals had been removed)

arrays: list of numpy array

new resized arrays taking into account deleted individuals

cromosim.micro.exit_door(sexit, dom, people, U, arrays=[])[source]

Removes individuals who are at a distance less than sexit to the closest door

Parameters
sexit: float

threshold value used to remove individuals close to the exit

dom: Domain

contains everything for managing the domain

people: numpy array

people coordinates and radius : x,y,r

U: numpy array

people velocities

arrays: list of numpy array

other arrays to resize similarly as people and U arrays

Returns
people: numpy array

new people positions (outside individuals had been removed)

U: numpy array

new poeple velocities (outside individuals had been removed)

arrays: list of numpy array

new array resized

cromosim.micro.exit_out_of_domain(dom, people, arrays=[], box=None)[source]

Removes individuals who are outside the domain or outside a given box

Parameters
dom: Domain

contains everything for managing the domain

people: numpy array

people coordinates and radius : x,y,r

arrays: list of numpy array

other arrays to resize similarly as people and U

box: numpy array

box coordinates [xmin,xmax,ymin,ymax] which replace the domain minimum and maximum coordinates

Returns
people: numpy array

new people array (outside individuals had been removed)

arrays: list of numpy array

new arrays resized similarly as people array

cromosim.micro.move_people(time, dt, people, U, crosslines=[])[source]

Updates the people positions according to the new velocities U. If there exists crosslines (i.e. sensors), computes also the id, time, direction and impact points for the individuals who cross the lines.

Parameters
time: float

current time

dt: float

time step

people: numpy array

people coordinates and radius : x,y,r

U: numpy array

people velocities

crosslines: list of numpy array

list of lines [[x0,y0,x1,y1], [x0,y0,x1,y1], …]

Returns
people: numpy array

new people positions after moving

io_id: list of integers

indices of people who cross the lines (sensors)

io_times: list of floats

times when people cross the lines (sensors)

io_pts: list of floats

impact points for people crossing the lines (sensors)

io_dir: list of floats

directions for people crossing the lines (sensors), i.e. entry or exit

cromosim.micro.people_initialization(N, init_people_box, dom, dt, rmin, rmax, dmin=0, seed=0, itermax=10)[source]

To initialize people array (xyr) with coordinates in several boxes and without overlaps between them.

Parameters
N: list

list of the numbers of persons to add in each box

init_people_box: list

list of the boxes [[xmin, xmax, ymin, ymax],…]

dom: Domain

contains everything for managing the domain

dt: float

time step

rmin: float

people minimal radius

rmax: float

people maximal radius

dmin: float

minimal distance allowed between individuals (0 by default)

seed: integer

seed to initialize the RandomState (0 by default means different seed at each run)

itermax: integer

maximal number of Uzawa projections (10 by default)

Returns
people: numpy array

new people coordinates x y r

people_init_box_id: numpy array

box number for each individual

rng: RandomState

scipy random state object (see scipy.random.RandomState)

cromosim.micro.periodic_bc_vertical(ymin, ymax, people, U, xmin=None, xmax=None, rng=None)[source]

Does not exactly correspond to periodic boundary conditions (in the mathematical sense): the persons having an y-coordinate y less than ymin (respectively greater than ymax) are reinjected at y+(ymax-ymin) (respectively at y-(ymax-ymin)) with (optionally) random x-coordinates (between xmin and xmax, and with velocities equal to 0.

Parameters
ymin: float

minimal ordinate of the box

ymax: float

maximal ordinate of the box

people: numpy array

people coordinates and radius : x,y,r

U: numpy array

people velocities

xmin: float

minimal abscissa of the box

xmax: float

maximal abscissa of the box

rng: RandomState

scipy random state object (see scipy.random.RandomState)

Returns
people: numpy array

new people coordinates (outside individuals had been moved)

U: numpy array

new people velocities

cromosim.micro.plot_people(ifig, dom, people, contacts, U, colors, time=-1, axis=None, plot_people=True, plot_contacts=True, plot_velocities=True, plot_paths=False, paths=None, plot_sensors=False, sensors=[], savefig=False, filename='fig.png', cmap='winter')[source]

This function draws spheres for the individuals, lines for the active contacts and arrows for the (desired or real) velocities.

Parameters
ifig: int

figure number

dom: Domain

contains everything for managing the domain

people: numpy array

people coordinates and radius : x,y,r

contacts: numpy array

all the contacts : i,j,dij,eij_x,eij_y

U: numpy array

people velocities

colors: numpy array

scalar field used to define people colors

time: float

time in seconds

axis: numpy array

matplotlib axis : [xmin, xmax, ymin, ymax]

plot_people: boolean

draws spheres for people if true

plot_paths: boolean

draws people paths if true

paths: numpy array

coordinates of the people paths

plot_sensors: boolean

draws sensor lines if true

sensors: numpy array

sensor line coordinates (see also the sensor function below)

savefig: boolean

writes the figure as a png file if true

filename: string

png filename used to write the figure

cmap: string

matplotlib colormap name

cromosim.micro.plot_sensor_data(ifig, sensor_data, time, initial_door_dist=None, axis=None, flux_timestep=1, savefig=False, filename='fig.png', cmap='winter')[source]

When a sensor line is defined this function allows to draw the repartition of the people exit times.

Parameters
ifig: int

figure number

sensor_datanumpy array

[time, direction, intersection_point[2]] for each individual

time: float

time in seconds

initial_door_dist: numpy array

people initial distance to the door

axis: numpy array

matplotlib axis : [xmin, xmax, ymin, ymax]

flux_timestep: float

timestep for the fluxes : number of persons per flux_timestep seconds

savefig: boolean

writes the figure as a png file if true

filename: string

png filename used to write the figure

cmap: string

matplotlib colormap name

cromosim.micro.projection(dt, people, contacts, Vd, dmin=0.0, nb_iter_max=100000, rho=0.1, tol=0.01, log=False, method='cvxopt')[source]

From the desired velocities Vd, this projection step consists of computing the global velocity field defined as the closest velocity to the desired one among all the feasible fields (i.e. fields which do not lead  to disks overlapping).

Parameters
dt: float

time step

people: numpy array

people coordinates and radius : x,y,r

contacts: numpy array

all the contacts : i,j,dij,eij_x,eij_y

Vd: numpy array

people desired velocities

dmin: float

minimum distance guaranteed between individuals

nb_iter_max: integer

maximum number of iterations allowed

rho: float

parameter of the Uzawa method

tol: float

tolerance wished

log: boolean

to print the final accuracy, number of iterations,…

method: string

optimization algorithm : ‘cvxopt’ (default) or ‘uzawa’ (or ‘mosek’ if installed with a license file).

Returns
B: numpy array

constraint matrix

U: numpy array

new people velocities ensuring that there is no overlap between individuals

L: numpy array

Lagrange multipliers (only when method=’uzawa’, None otherwise)

P: numpy array

pressure on each individual (only when method=’uzawa’, None otherwise)

info: integer

number of iterations needed

cromosim.micro.remove_overlaps_in_box(dom, box, p, dt, rng, dmin, itermax=10)[source]

To remove the overlaps between individuals (spheres) in the given box. Several Uzawa projections are used to give a better robustness to this process when the number of overlaps is very high e.g. during the initialization when the individuals have random positions.

Parameters
dom: Domain

contains everything for managing the domain

box: list

coordinates of the box [xmin, xmax, ymin, ymax]

p: numpy array

people coordinates x y r

dt: float

time step

rng: RandomState

scipy random state object (see scipy.random.RandomState)

dmin: float

minimal distance allowed between individuals

itermax: integer

maximal number of Uzawa projections (10 by default)

Returns
p: numpy array

new people coordinates x y r

cromosim.micro.sensor(door, xy0, xy1, t0, t1)[source]

Compute the number of entries/exits through a door as a pedestrian sensor could do

Parameters
door: numpy array

door coordinates [x0,y0,x1,y1]

t0: float

time

t1: float

time

xy0: numpy array

people coordinates at time t0

xy1: numpy array

people coordinates at time t1

Returns
id: numpy array

index of persons who go through the door

p: numpy array

coordinates of intersection points between the door and people trajectories

io: numpy array

the exit direction is the normal direction, 1 = exit, -1 = entry

times: numpy array

exit or entry times

entries: int

number of entries

exits: int

number of exits