Microscopic models : granular and social force model¶

cromosim.micro.
check_people_in_box
(dom, box, xyrv, dest_names, rng, verbose=True)[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]
 xyrv: numpy array
people coordinates, radius and velocity coefficient:
x,y,r,v
 dest_names: numpy array
people destination names
 rng: RandomState
scipy random state object (see scipy.random.RandomState)
 verbose: boolean
logs for debug
 Returns
 xyrv: numpy array
new people coordinates
x y r

cromosim.micro.
compute_contacts
(dom, xyrv, 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 fastmarching method).
 Parameters
 dom: Domain
contains everything for managing the domain
 xyrv: numpy array
people coordinates, radius and velocity coefficient:
x,y,r,v
 dmax: float
threshold value used to consider a contact as active i.e.
dij<dmax
 Returns
 contacts: numpy array
all the contacts
i,j,dij,eij_x,eij_y
such thatdij<dmax
andi<j
(no duplication)

cromosim.micro.
compute_forces
(F, Fwall, xyrv, contacts, U, Vd, lambda_, delta, k, eta)[source]¶ This function computes all the forces (isentropic interaction and friction) and sums them. The correcting prefactor 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)
 xyrv: numpy array
people coordinates, radius and velocity coefficient:
x,y,r,v
 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
(nn, box, dest_name, radius_distribution, velocity_distribution, dom, rng, verbose=True)[source]¶ To create nn 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
 nn: integer
number of individuals to create
 box: list
coordinates of the box
[xmin, xmax, ymin, ymax]
 dest_name: string
destination name for all individuals in this group
 radius_distribution: list
distribution with its parameters
 velocity_distribution: list
distribution with its parameters
 dom: Domain
contains everything for managing the domain
 rng: RandomState
scipy random state object (see
scipy.random.RandomState
) verbose: boolean
logs for debug
 Returns
 p: numpy array
new people coordinates, radius and velocity coefficient
x y r v
 dest_names: numpy array
people destination names

cromosim.micro.
find_duplicate_people
(all_people, domains)[source]¶ This function determines people who have to be duplicated due to their presence in transit boxes (in Destination object)
 Parameters
 all_people: dict
 Has one dictionary
"people"
by domain which has at least: "xyrv"
: people coordinates and radius"destinations"
: destination for each individual
 Has one dictionary
 domains: dict
Contains all the Domain objets
 Returns
 virtual_people: dict
all duplicated people

cromosim.micro.
move_people
(time, dt, people, sensors)[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: dict
dictionary containing everything related to individuals (
"xyrv"
,"U"
,…) sensors: dict
dictionary containing everything related to sensors (
"line"
,…)
 Returns
 people: dict
dictionary updated with new people positions after moving
 sensors: dict
 dictionary enriched by:
"id"
: people id who cross the sensor lines"times"
: times when people cross the sensor lines"xy"
: impact points for people crossing the sensor lines"dir"
: directions for people crossing the sensor lines (entry or exit)

cromosim.micro.
people_initialization
(dom, groups, dt, dmin_people=0, dmin_walls=0, seed=0, itermax=10, projection_method='cvxopt', verbose=True)[source]¶ To initialize people.
 Parameters
 dom: Domain
contains everything for managing the domain
 groups: dict
 contains all groups related to this domain. A group contains:
"nb"
: number of persons"radius_distribution"
:["uniform",min,max]
or["normal",mean,std_dev]
"velocity_distribution"
:["uniform",min,max]
or["normal",mean,std_dev]
"box"
:[xmin,xmax,ymin,ymax]
"destination"
: initial destination
 dt: float
time step
 dmin_people: float
minimal distance allowed between individuals (0 by default)
 dmin_walls: float
minimal distance allowed between an individual and a wall
 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)
 projection_method: string
optimizer name for the projection step:
"cvxopt"
,"uzawa"
or"mosek"
 verbose: boolean
logs for debug
 Returns
 people: dict
 people dictionary which contains:
"xyrv"
: coordinates, radius and velocity coefficient for each individual"destinations"
: destination for each individual"gpid"
: group id
 rng: RandomState
scipy random state object (see
scipy.random.RandomState
)

cromosim.micro.
people_update_destination
(all_people, domains, thld, box=None)[source]¶ This function updates people destinations and domains
 Parameters
 all_people: dict
 Has one dictionary
"people"
by domain which has at least: "xyrv"
: people coordinates and radius"destinations"
: destination for each individual
 Has one dictionary
 domains: dict
Contains all the Domain objets
 thld: float
threshold value used to decide if an individual has reached its destination
 box: numpy array
box used to remove people outside
 Returns
 all_people: dict
all people in all domains updated

cromosim.micro.
plot_people
(ifig, dom, people, contacts, colors, time= 1, axis=None, virtual_people=None, plot_people=True, plot_contacts=True, plot_velocities=False, plot_desired_velocities=False, plot_paths=False, plot_sensors=False, sensors=[], savefig=False, filename='fig.png', dpi=150, 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: dict
contains everything concerning people:
x, y, r, v, U,...
 contacts: numpy array
all the contacts:
i, j, dij, eij_x, eij_y
 colors: numpy array
scalar field used to define people colors
 time: float
time in seconds
 virtual_people: dict
contains everything concerning virtual people:
x, y, r,...
 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
 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
 dpi: integer
number of pixel per inch for the saved figure
 cmap: string
matplotlib colormap name

cromosim.micro.
plot_sensors
(ifig, sensors, time, flux_timestep=1, savefig=False, filename='fig.png', dpi=150, cmap='winter')[source]¶ This function traces, for each sensor, a graph with the passage times of the individuals crossing the counting line, as well as the incoming and outgoing flows.
 Parameters
 ifig: int
figure number
 sensors: dict
contains for each sensor, the date, position and direction of an individual who cut the counting line
 time: float
time in seconds
 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
 dpi: integer
number of pixel per inch for the saved figure
 cmap: string
matplotlib colormap name

cromosim.micro.
projection
(dt, xyrv, contacts, Vd, dmin_people=0, dmin_walls=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
 xyrv: numpy array
people coordinates, radius and velocity coefficient:
x,y,r,v
 contacts: numpy array
all the contacts:
i,j,dij,eij_x,eij_y
 Vd: numpy array
people desired velocities
 dmin_people: float
minimum distance guaranteed between individuals
 dmin_walls: float
minimum distance guaranteed between an individual and a wall
 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
 info: integer
number of iterations needed
 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)

cromosim.micro.
remove_overlaps_in_box
(dom, box, xyrv, dest_names, dt, rng, projection_method='cvxopt', dmin_people=0, dmin_walls=0, itermax=10, verbose=True)[source]¶ To remove the overlaps between individuals (spheres) in the given box. Several 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]
 xyrv: numpy array
people coordinates
x y
, radiusr
and velocity coefficientv
 dest_names: numpy array
people destination names
 dt: float
time step
 rng: RandomState
scipy random state object (see
scipy.random.RandomState
) dmin_people: float
minimal distance allowed between individuals
 dmin_walls: float
minimal distance allowed between an individual and a wall
 itermax: integer
maximal number of Uzawa projections (10 by default)
 verbose: boolean
logs for debug
 Returns
 xyrv: numpy array
new people coordinates
x y
, same radiusr
and velocity coefficientv

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