package org.openpixi.pixi.distributed; import org.openpixi.pixi.distributed.grid.DistributedGridFactory; import org.openpixi.pixi.distributed.grid.DistributedInterpolation; import org.openpixi.pixi.distributed.ibis.IbisRegistry; import org.openpixi.pixi.distributed.ibis.WorkerToMaster; import org.openpixi.pixi.distributed.movement.boundary.DistributedParticleBoundaries; import org.openpixi.pixi.distributed.util.BooleanLock; import org.openpixi.pixi.distributed.util.IncomingProblemHandler; import org.openpixi.pixi.physics.particles.Particle; import org.openpixi.pixi.physics.Settings; import org.openpixi.pixi.physics.Simulation; import org.openpixi.pixi.physics.grid.Cell; import org.openpixi.pixi.physics.grid.Grid; import org.openpixi.pixi.physics.grid.Interpolation; import org.openpixi.pixi.physics.movement.boundary.ParticleBoundaries; import org.openpixi.pixi.physics.util.ClassCopier; import org.openpixi.pixi.physics.util.DoubleBox; import org.openpixi.pixi.physics.util.IntBox; import java.io.IOException; import java.util.List; /** * Receives the problem, calculates the problem, sends back results. */ public class Worker { private WorkerToMaster communicator; /* Local and global settings differ only in settings connected to simulation size. */ private Settings localSettings; private Settings globalSettings; /** ID of this worker. */ private int workerID; private Simulation simulation; private SharedDataManager sharedDataManager; /* Received problem */ private IntBox[] partitions; private List<Particle> particles; private Cell[][] cells; private BooleanLock recvProblemLock = new BooleanLock(); public Worker(IbisRegistry registry, Settings settings) { this.globalSettings = settings; try { communicator = new WorkerToMaster(registry, new ProblemHandler()); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } workerID = registry.convertIbisIDToWorkerID(registry.getIbis().identifier()); } public void step() { simulation.step(); } public void receiveProblem() { recvProblemLock.waitForTrue(); recvProblemLock.reset(); createSimulation(); } public void sendResults() { Cell[][] finalCells = getFinalCells(simulation.grid); // The results can come in arbitrary order; thus, // we have to send also the id of the node which is sending the result. try { communicator.sendResults( workerID, simulation.particles, finalCells); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * If the local simulation is at the edge of global simulation, * we also need to include the extra cells to the master * (because of hardwall boundaries). */ private Cell[][] getFinalCells(Grid grid) { IntBox mypart = partitions[workerID]; int xstart = 0; int ystart = 0; int xend = mypart.xsize() - 1; int yend = mypart.ysize() - 1; if (mypart.xmin() == 0) { xstart -= Grid.EXTRA_CELLS_BEFORE_GRID; } if (mypart.xmax() == globalSettings.getGridCellsX() - 1) { xend += Grid.EXTRA_CELLS_AFTER_GRID; } if (mypart.ymin() == 0) { ystart -= Grid.EXTRA_CELLS_BEFORE_GRID; } if (mypart.ymax() == globalSettings.getGridCellsY() - 1) { yend += Grid.EXTRA_CELLS_AFTER_GRID; } Cell[][] finalCells = new Cell[xend - xstart + 1][yend - ystart + 1]; for (int x = xstart; x <= xend ; ++x) { for (int y = ystart; y <= yend; ++y) { finalCells[x - xstart][y - ystart] = grid.getCell(x,y); } } return finalCells; } private void createSimulation() { createLocalSettings(); sharedDataManager = createSharedDataManager(); ParticleBoundaries particleBoundaries = createParticleBoundaries(sharedDataManager); sharedDataManager.setParticleBoundaries(particleBoundaries); Grid grid = createGrid(sharedDataManager); Interpolation interpolation = createInterpolationIterator(sharedDataManager); sharedDataManager.setGrid(grid); sharedDataManager.initializeCommunication(); this.simulation = new Simulation( localSettings, grid, particles, particleBoundaries, interpolation); } /** * Some settings (e.g. simulation width and height) pertain to the global simulation * and are incorrect for the local simulation. * Thus, we need to correct them, so that they correspond to the local simulation. */ private void createLocalSettings() { IntBox mypart = partitions[workerID]; double cellWidth = globalSettings.getCellWidth(); double cellHeight = globalSettings.getCellHeight(); localSettings = ClassCopier.copy(globalSettings); localSettings.setGridCellsX(mypart.xsize()); localSettings.setGridCellsY(mypart.ysize()); localSettings.setSimulationWidth(cellWidth * mypart.xsize()); localSettings.setSimulationHeight(cellHeight * mypart.ysize()); } private Interpolation createInterpolationIterator(SharedDataManager sharedDataManager) { DoubleBox zoneOfLocalInfluence = new DoubleBox( (Grid.INTERPOLATION_RADIUS - 1) * localSettings.getCellWidth(), localSettings.getSimulationWidth() - Grid.INTERPOLATION_RADIUS * localSettings.getCellWidth(), (Grid.INTERPOLATION_RADIUS - 1) * localSettings.getCellHeight(), localSettings.getSimulationHeight() - Grid.INTERPOLATION_RADIUS * localSettings.getCellHeight()); return new DistributedInterpolation( localSettings.getInterpolator(), sharedDataManager, zoneOfLocalInfluence, localSettings.getParticleIterator()); } private SharedDataManager createSharedDataManager() { IntBox simulationAreaInCellDimensions = new IntBox( 0, globalSettings.getGridCellsX() - 1, 0, globalSettings.getGridCellsY() - 1); return new SharedDataManager( workerID, partitions, simulationAreaInCellDimensions, localSettings.getBoundaryType(), communicator.getRegistry()); } private Grid createGrid(SharedDataManager sharedDataManager) { DistributedGridFactory gridFactory = new DistributedGridFactory( localSettings, partitions[workerID], cells, sharedDataManager); return gridFactory.create(); } private ParticleBoundaries createParticleBoundaries(SharedDataManager sharedDataManager) { DoubleBox simulationAreaInParticleDimensions = new DoubleBox( 0, localSettings.getSimulationWidth(), 0, localSettings.getSimulationHeight()); DoubleBox innerSimulationArea = new DoubleBox( 0, localSettings.getSimulationWidth() - localSettings.getCellWidth(), 0, localSettings.getSimulationHeight() - localSettings.getCellHeight()); return new DistributedParticleBoundaries( simulationAreaInParticleDimensions, innerSimulationArea, localSettings.getParticleBoundary(), sharedDataManager); } public void close() { communicator.close(); sharedDataManager.close(); } private class ProblemHandler implements IncomingProblemHandler { public void handle(IntBox[] partitions, List<Particle> particles, Cell[][] cells) { Worker.this.partitions = partitions; Worker.this.particles = particles; Worker.this.cells = cells; recvProblemLock.setToTrue(); } } }