package turtlekit.flocking; import java.util.List; import java.util.Random; import turtlekit.cuda.CudaAverageField; import turtlekit.cuda.CudaEngine; import turtlekit.kernel.Patch; import turtlekit.kernel.TKEnvironment; /** * The Environment in this flocking simulation * <p> * The environment is characterized by: * <ul> * <li>Its size</li> * </ul> * </p> * * @author Emmanuel Hermellin * * @version 0.1 * * @see turtlekit.kernel.TKEnvironment * */ public class Environment extends TKEnvironment { /** * The GPU Module */ private CudaAverageField cudaHeadingGrid; /** * The size of the environment */ private static int envDimension = 512; /** * Do you want to use CUDA ? */ private static boolean CUDA = true; /** * The array containing the heading of all the agents */ private static float headingSheet[] = new float[envDimension * envDimension]; /** * The array containing all the Patch of the Grid * @see Patch */ private Patch patchSheet[] = new Patch[envDimension * envDimension]; /** * Random number generator */ protected static Random generator = new Random(); //TODO ne peut on pas réutiliser celui des Turtles ????? /** * Return the GPU module * @return cudaHeadingGrid */ public CudaAverageField getCudaHeadingGrid() { return cudaHeadingGrid; } /** * Return the size of the environment * @return envDimension */ public static int getEnvDimension() { return envDimension; } /** * Return if CUDA is used or not * @return CUDA */ public static boolean isCUDA() { return CUDA; } /** * Activate of the Environment * @see TKEnvironment#activate() */ protected void activate(){ super.activate(); patchSheet = this.getPatchGrid(); initSpeedAndHeadingSheet(); makeTheCache(); cudaHeadingGrid = new CudaAverageField("Average",envDimension,envDimension,BirdFlockingUnify.getVision(),headingSheet); } /** * Forcing caching of the Patch * @see Environment#activate() */ protected void makeTheCache(){ for (Patch p : getPatchGrid()) { p.getNeighbors(10, true); } } /** * Initializing the array containing the heading of the agents */ protected void initSpeedAndHeadingSheet(){ for(int i = 0 ; i < envDimension * envDimension ; i++){ headingSheet[i] = -1; } } /** * Update the environment * @see TKEnvironment#update() */ @Override protected void update() { if(CUDA){ updateSpeedAndHeadingSheetV2(); cudaHeadingGrid.computeAverage(); if(isSynchronizeGPU()){ CudaEngine.cuCtxSynchronizeAll(); } } } /** * Accessing data compute by the GPU module * @see CudaAverageField */ public float getCudaHeadingValue(int xcor, int ycor){ return cudaHeadingGrid.getResult(get1DIndex(xcor, ycor)); } /** * Set data which will be compute by the GPU module * @see CudaAverageField */ public void setCudaHeadingValue(int xcor, int ycor, double heading){ cudaHeadingGrid.set(get1DIndex(xcor, ycor),((float)heading)); } /** * Update the array containing heading of the agents */ protected void updateSpeedAndHeadingSheet(){ for(int i = 0 ; i < envDimension * envDimension ; i++){ List<BirdFlockingUnify> turtleList = patchSheet[i].getTurtles(BirdFlockingUnify.class); if(turtleList.isEmpty()){ cudaHeadingGrid.set(i,-1); } else{ for(BirdFlockingUnify b : turtleList){ cudaHeadingGrid.set(i,(float)b.getHeading()); } } } } /** * Update the array containing heading of the agents (V2) */ protected void updateSpeedAndHeadingSheetV2(){ int j = envDimension * envDimension; for(int i = j - 1 ; i > 0 ; i--){ if(patchSheet[i].isEmpty()){ cudaHeadingGrid.set(i,-1); } } } }