working with several threads, one has to make sure,
that not more than one thread works with a particle
at the same time. To compute the forces for one
particle, one has to consider all particles from the
same box plus all the particles from the
neighbouring boxes. If two work with one particle at
the same time (reentrancy), this could lead to false
results. Synchronized methods would solve this
problem. However, they use locking and locking
could produce deadlocks. To synchronize the threads
and to avoid deadlocks, a specifically developed
synchronization strategy is to be used.
At a certain point in time every thread shall
determine the actual forces for all particles of some
box. To compute the forces of the particles in one
box, the thread also has to work with the particles
from the boxes in the direct neighbourhood. When
working with one box, no other thread shall work
with this box or its neighbours. If two threads are
determining the forces for two boxes, there must be
at least two boxes between these boxes.
Figure 10: Boxes used to avoid reentrancy.
Figure 10 explains the multi threading and
synchronization concept. In this figure, there are
several amounts of water. Each amount of water is
represented by a set of particles. During simulation,
an orthogonal grid of quadratic boxes is used and
each particle is assigned to one of the boxes. In
Figure 10, one can see vertical columns. Each
column represents a vertical sequence of boxes. The
width of the columns is
. At a point in time, one
thread shall compute the forces for all particles of
one column plus the forces applied from these
particles to the particles that are in the columns next
to the actual column. One has to make sure, that at
no time there are two threads working with columns
with less than two columns in between. Figure 10
shows a snapshot during computation. The grey
columns represent columns, where a thread is
currently computing the forces.
Threads are synchronized using the wait/notify
mechanism from Java to make sure, that at any time
there are at least two columns in between two active
threads. Figure 11 shows the pattern, that is used for
this synchronization. Each number represents one
column and each arrow represents a wait-notify-
relationship. The thread actually executing the
column at the starting point of the arrow has to
finish its work, unless the computation of the
column, that the arrow points to, cannot be started.
A thread at the end point of an arrow has to invoke
wait(). It is blocked unless the thread from the
starting point of the arrow sends him a notify()
signal.
Figure 11: Synchronization.
Rigid bodies are either represented by lines or by
circle segments. The algorithm shall compute all
forces, that particles apply to rigid bodies, and all
forces, that rigid bodies apply to particles.
Theoretically, one would have to consider all
combinations of rigid bodies and particles. To save
computing time, forces shall be neglected if the
distance is greater than
.
The algorithms used for computing the forces
between rigid bodies and particles use the grid of
boxes. One has to find all combinations of boxes and
rigid bodies, where the box is not more than
apart from the rigid body. More precisely: There is
at least one point inside the box, that is not more
than
apart from the rigid body. For every such
pair of rigid body and box, one has to iterate through
all particles and compute the actual distance to the
rigid body. If the distance between the particle and
the rigid body is not greater than
, then the force
between this particle and the rigid body is computed
and this force is added to the rigid body and to the
particle – with opposite signs.
But how to efficiently determine all
combinations of boxes and rigid bodies, that are not
more than
apart? There are two different
approaches, that are to be called algorithm A and
algorithm B. Algorithm A iterates through all boxes.
For every box, the algorithm determines the distance
to all rigid bodies. Algorithm B works the other way
round: It iterates through all rigid bodies. For every
rigid body, the algorithm walks along the rigid body
from the beginning point to the end point of the line
and computes the position of the boxes in the
neighbourhood of the line. For every such position,
it checks, if there is such a box with particles.
Determining the position of all box positions is easy
for lines. Beginning at the starting point of the line,
one simply has to add a small piece of the direction