In January 2021 we will introduce a 10 GB quota for project repositories. Higher limits for individual projects will be available on request. Please see https://doku.lrz.de/display/PUBLIC/GitLab for more information.

Commit c57a3857 authored by Marion Goedel's avatar Marion Goedel

Merge branch 'sfm_parallel' into 'master'

Sfm parallel

See merge request !140
parents 043151d2 3ed7c511
Pipeline #315222 passed with stages
in 130 minutes and 16 seconds
package org.vadere.simulator.models.sfm;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.vadere.simulator.models.ode.AbstractModelEquations;
import org.vadere.simulator.models.ode.ODEModel;
......@@ -9,7 +12,12 @@ import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.Vector2D;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.logging.Logger;
import org.vadere.util.math.MathUtil;
import org.vadere.util.parallel.AParallelWorker;
import org.vadere.util.parallel.AParallelWorker.Work;
import org.vadere.util.parallel.CountableParallelWorker;
import org.vadere.util.parallel.IAsyncComputable;
/**
* Implementation of the Social Force Model (Helbing 1995). This implementation
......@@ -24,7 +32,10 @@ import org.vadere.util.math.MathUtil;
* IGradientProvider given in the constructor.
*
*/
public class SFMEquations extends AbstractModelEquations<Pedestrian> {
public class SFMEquations extends AbstractModelEquations<Pedestrian> implements IAsyncComputable {
private static Logger logger = Logger.getLogger(SFMEquations.class);
/**
* Four dimensions: 2 for position, 2 for velocity
......@@ -41,99 +52,155 @@ public class SFMEquations extends AbstractModelEquations<Pedestrian> {
* double[], double[])
*/
@Override
public void computeDerivatives(double t, double[] y, double[] yDot) {
double[] position = new double[2];
double[] velocity = new double[2];
double[] positionDot = new double[2];
double[] velocityDot = new double[2];
double[] grad_field = new double[2];
double[] viewing_direction = new double[2];
public void computeDerivatives(final double t, double[] y, final double[] yDot) {
// update the pedestrian positions in the topography to the ones computed in the integrator
ODEModel.updateElementPositions(Pedestrian.class, t, topography, this, y);
// create workers for each pedestrian
List<AParallelWorker<Double[]>> workers = new ArrayList<AParallelWorker<Double[]>>();
// loop over all persons and compute the next step
int personCounter = 0; // used for arrays, not identical to personID!
for (Pedestrian currentPed : elements) {
// ///////////////////////////////////////
// extract data
// position
getPosition(personCounter, y, position);
// velocity
getVelocity(personCounter, y, velocity);
// ///////////////////////////////////////
// generate gradients
assert (!Double.isNaN(position[0]));
assert (!Double.isNaN(position[1]));
// get the static gradient
staticGradientProvider.gradient(t, currentPed.getNextTargetId(),
position, grad_field);
assert (!Double.isNaN(position[0]));
assert (!Double.isNaN(position[1]));
/*
* Target target = this.topography.getTarget(currentPed.getTargets()
* .get(0));
* double distance2Target = target.getShape().distance(
* new VPoint(position[0], position[1]));
* if (distance2Target < 1) {
* MathUtil.normalize(grad_field);
* MathUtil.mult(grad_field, distance2Target);
* }
*/
// compute the velocity from the static gradient.
viewing_direction[0] = -grad_field[0];
viewing_direction[1] = -grad_field[1];
double normViewingDir = MathUtil.norm2(viewing_direction);
// set to the correct length (= speed)
if (normViewingDir > 0) {
MathUtil.normalize(viewing_direction);
for (final Pedestrian pedestrian : elements) {
AParallelWorker<Double[]> w = new CountableParallelWorker<Double[]>(
personCounter, new Work<Double[]>() {
private int ID;
@Override
public Double[] call() throws Exception {
computeSinglePerson(pedestrian, getWorkerID(), t,
y, yDot);
return null;
}
@Override
public void setID(int ID) {
this.ID = ID;
}
@Override
public int getWorkerID() {
return this.ID;
}
});
personCounter++;
workers.add(w);
w.start();
}
// finish the work
for (AParallelWorker<Double[]> worker : workers) {
try {
worker.finish();
} catch (ExecutionException e) {
logger.error(e);
e.printStackTrace();
} catch (InterruptedException e) {
// Necessary in order to tell Simulation the thread has been
// interrupted.
// TODO [priority=low] [task=refactoring] Hack, other solution?
Thread.currentThread().interrupt();
break;
}
}
}
VPoint pos = new VPoint(position[0], position[1]);
Vector2D vel = new Vector2D(velocity[0], velocity[1]);
// get the static gradient for obstacles
Vector2D obstacleGradient = obstacleGradientProvider
.getObstaclePotentialGradient(pos, currentPed);
// get the dynamic gradient for pedestrians
Collection<? extends Agent> otherPedestrians = pedestrianGradientProvider
.getRelevantAgents(new VCircle(pos, 0.1), currentPed,
topography);
Vector2D pedestrianGradient = pedestrianGradientProvider
.getAgentPotentialGradient(pos, vel, currentPed,
otherPedestrians);
// get ped speed and acceleration data
double v0 = currentPed.getFreeFlowSpeed();
double acc = currentPed.getAcceleration();
// perform the computational steps that define this equation model
positionDot[0] = velocity[0]
* normalizer(v0 * 1.3, MathUtil.norm2(velocity));
positionDot[1] = velocity[1]
* normalizer(v0 * 1.3, MathUtil.norm2(velocity));
velocityDot[0] = (-grad_field[0] * v0 - velocity[0]) * acc
- obstacleGradient.x - pedestrianGradient.x;
velocityDot[1] = (-grad_field[1] * v0 - velocity[1]) * acc
- obstacleGradient.y - pedestrianGradient.y;
assert (!Double.isNaN(positionDot[0]));
assert (!Double.isNaN(positionDot[1]));
assert (!Double.isNaN(velocityDot[0]));
assert (!Double.isNaN(velocityDot[1]));
// store data
setPosition(personCounter, yDot, positionDot);
setVelocity(personCounter, yDot, velocityDot);
personCounter++;
/**
* Computes yDot for a single person given by personID. This is computed
* asynchronously by an {@link AParallelWorker}.
*
* @param currentPed
* @param personCounter
* @param t
* @param y
* @param yDot
*/
private void computeSinglePerson(Pedestrian currentPed, int personCounter, double t, double[] y, double[] yDot) {
double[] position = new double[2];
double[] velocity = new double[2];
double[] positionDot = new double[2];
double[] velocityDot = new double[2];
double[] grad_field = new double[2];
double[] viewing_direction = new double[2];
// ///////////////////////////////////////
// extract data
// position
getPosition(personCounter, y, position);
// velocity
getVelocity(personCounter, y, velocity);
// ///////////////////////////////////////
// generate gradients
assert (!Double.isNaN(position[0]));
assert (!Double.isNaN(position[1]));
// get the static gradient
staticGradientProvider.gradient(t, currentPed.getNextTargetId(),
position, grad_field);
assert (!Double.isNaN(position[0]));
assert (!Double.isNaN(position[1]));
/*
* Target target = this.topography.getTarget(currentPed.getTargets()
* .get(0));
* double distance2Target = target.getShape().distance(
* new VPoint(position[0], position[1]));
* if (distance2Target < 1) {
* MathUtil.normalize(grad_field);
* MathUtil.mult(grad_field, distance2Target);
* }
*/
// compute the velocity from the static gradient.
viewing_direction[0] = -grad_field[0];
viewing_direction[1] = -grad_field[1];
double normViewingDir = MathUtil.norm2(viewing_direction);
// set to the correct length (= speed)
if (normViewingDir > 0) {
MathUtil.normalize(viewing_direction);
}
VPoint pos = new VPoint(position[0], position[1]);
Vector2D vel = new Vector2D(velocity[0], velocity[1]);
// get the static gradient for obstacles
Vector2D obstacleGradient = obstacleGradientProvider
.getObstaclePotentialGradient(pos, currentPed);
// get the dynamic gradient for pedestrians
Collection<? extends Agent> otherPedestrians = pedestrianGradientProvider
.getRelevantAgents(new VCircle(pos, 0.1), currentPed,
topography);
Vector2D pedestrianGradient = pedestrianGradientProvider
.getAgentPotentialGradient(pos, vel, currentPed,
otherPedestrians);
// get ped speed and acceleration data
double v0 = currentPed.getFreeFlowSpeed();
double acc = currentPed.getAcceleration();
// perform the computational steps that define this equation model
positionDot[0] = velocity[0]
* normalizer(v0 * 1.3, MathUtil.norm2(velocity));
positionDot[1] = velocity[1]
* normalizer(v0 * 1.3, MathUtil.norm2(velocity));
velocityDot[0] = (-grad_field[0] * v0 - velocity[0]) * acc
- obstacleGradient.x - pedestrianGradient.x;
velocityDot[1] = (-grad_field[1] * v0 - velocity[1]) * acc
- obstacleGradient.y - pedestrianGradient.y;
assert (!Double.isNaN(positionDot[0]));
assert (!Double.isNaN(positionDot[1]));
assert (!Double.isNaN(velocityDot[0]));
assert (!Double.isNaN(velocityDot[1]));
// store data
setPosition(personCounter, yDot, positionDot);
setVelocity(personCounter, yDot, velocityDot);
}
/**
......
......@@ -6,6 +6,11 @@ import org.vadere.simulator.models.Model;
import org.vadere.simulator.models.ode.IntegratorFactory;
import org.vadere.simulator.models.ode.ODEModel;
import org.vadere.simulator.models.potential.FloorGradientProviderFactory;
import org.vadere.simulator.models.potential.PotentialFieldModel;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTarget;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTargetGrid;
import org.vadere.simulator.models.potential.fields.PotentialFieldAgent;
import org.vadere.simulator.models.potential.fields.PotentialFieldObstacle;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTargetGrid;
import org.vadere.simulator.models.potential.fields.PotentialFieldAgent;
import org.vadere.simulator.models.potential.fields.PotentialFieldObstacle;
......@@ -21,11 +26,12 @@ import org.vadere.state.scenario.Target;
import org.vadere.state.types.GradientProviderType;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VShape;
import org.vadere.util.parallel.ParallelWorkerUtil;
import java.util.*;
@ModelClass(isMainModel = true)
public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> {
public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> implements PotentialFieldModel {
private AttributesSFM attributes;
private GradientProvider floorGradient;
......@@ -38,12 +44,12 @@ public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> {
@Deprecated
public SocialForceModel(Domain domain, AttributesSFM attributes,
PotentialFieldObstacle potentialFieldObstacle,
PotentialFieldAgent potentialFieldPedestrian,
IPotentialFieldTargetGrid potentialFieldTarget,
AttributesAgent attributesPedestrian, Random random) {
PotentialFieldObstacle potentialFieldObstacle,
PotentialFieldAgent potentialFieldPedestrian,
IPotentialFieldTargetGrid potentialFieldTarget,
AttributesAgent attributesPedestrian, Random random) {
super(Pedestrian.class, domain, IntegratorFactory.createFirstOrderIntegrator(attributes
.getAttributesODEIntegrator()), new SFMEquations(),
.getAttributesODEIntegrator()), new SFMEquations(),
attributesPedestrian, random);
this.attributes = attributes;
this.targets = new TreeMap<>();
......@@ -63,7 +69,7 @@ public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> {
@Override
public void initialize(List<Attributes> modelAttributesList, Domain domain,
AttributesAgent attributesPedestrian, Random random) {
AttributesAgent attributesPedestrian, Random random) {
this.attributes = Model.findAttributes(modelAttributesList, AttributesSFM.class);
......@@ -124,6 +130,15 @@ public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> {
@Override
public void preLoop(final double state) {
super.preLoop(state);
// setup thread pool if it is not setup already
int WORKERS_COUNT = 16;// pedestrians.keySet().size();
ParallelWorkerUtil.setup(WORKERS_COUNT);
}
@Override
public void postLoop(final double simTimeInSec) {
super.postLoop(simTimeInSec);
ParallelWorkerUtil.shutdown();
}
@Override
......@@ -177,5 +192,20 @@ public class SocialForceModel extends ODEModel<Pedestrian, AttributesAgent> {
public List<Model> getSubmodels() {
return models;
}
@Override
public IPotentialFieldTarget getPotentialFieldTarget() {
return potentialFieldTarget;
}
@Override
public PotentialFieldObstacle getPotentialFieldObstacle() {
return potentialFieldObstacle;
}
@Override
public PotentialFieldAgent getPotentialFieldAgent() {
return potentialFieldPedestrian;
}
}
......@@ -10,11 +10,11 @@ import org.vadere.state.attributes.Attributes;
@ModelAttributeClass
public class AttributesPotentialSFM extends Attributes {
private double pedestrianBodyPotential = 2.72;
private double pedestrianRecognitionDistance = 0.3;
private double pedestrianBodyPotential = 2.1; // V_{\alpha \beta}^0, default from helbing-1995
private double pedestrianRecognitionDistance = 0.3; // sigma, default from helbing-1995
private double obstacleBodyPotential = 20.1;
private double obstacleRepulsionStrength = 0.25;
private double obstacleBodyPotential = 10.0; // U_{\alpha B}^0, default from helbing-1995
private double obstacleRepulsionStrength = 0.2; // R, default from helbing-1995
// Getters...
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment