package org.openpixi.pixi.distributed.movement.boundary; import org.openpixi.pixi.distributed.SharedData; import org.openpixi.pixi.distributed.SharedDataManager; import org.openpixi.pixi.physics.particles.Particle; import org.openpixi.pixi.physics.force.Force; import org.openpixi.pixi.physics.movement.boundary.*; import org.openpixi.pixi.physics.solver.Solver; import org.openpixi.pixi.physics.util.DoubleBox; import org.openpixi.pixi.physics.util.Point; import java.util.ArrayList; import java.util.List; /** * Maps the border and boundary regions to boundaries which should be applied. */ public class DistributedParticleBoundaries implements ParticleBoundaries { private BoundaryRegions boundaryRegions; private ParticleBoundary[] boundaryMap = new ParticleBoundary[BoundaryRegions.NUM_OF_REGIONS]; private BorderRegions borderRegions; private List<List<BorderGate>> borderMap = new ArrayList<List<BorderGate>>(BorderRegions.NUM_OF_REGIONS); private ParticleBoundaryType boundaryType; private DoubleBox simulationArea; public ParticleBoundaryType getType() { return boundaryType; } public DistributedParticleBoundaries( DoubleBox simulationArea, DoubleBox innerArea, ParticleBoundaryType boundaryType, SharedDataManager sharedDataManager) { this.boundaryType = boundaryType; this.simulationArea = simulationArea; boundaryRegions = new BoundaryRegions(simulationArea); borderRegions = new BorderRegions(simulationArea, innerArea); for (int i = 0; i < BorderRegions.NUM_OF_REGIONS; ++i) { borderMap.add(new ArrayList<BorderGate>()); } createBoundaryMap(boundaryType, sharedDataManager); createBorderMap(sharedDataManager); } private void createBoundaryMap( ParticleBoundaryType boundaryType, SharedDataManager sharedDataManager) { for (int region = 0; region < BoundaryRegions.NUM_OF_REGIONS; ++region) { SharedData sd = sharedDataManager.getBoundarySharedData(region); if (sd != null) { double xoffset = getXOffset(sharedDataManager.getBoundaryDirections(region)); double yoffset = getYOffset(sharedDataManager.getBoundaryDirections(region)); boundaryMap[region] = new BoundaryGate(xoffset, yoffset, sd); } else if (region == BoundaryRegions.X_CENTER + BoundaryRegions.Y_CENTER) { boundaryMap[region] = new EmptyBoundary(0, 0); } else { double xoffset = getXOffsetFromRegion(region); double yoffset = getYOffsetFromRegion(region); boundaryMap[region] = boundaryType.createBoundary(xoffset, yoffset); } } } private void createBorderMap(SharedDataManager sharedDataManager) { for (int region = 0; region < BorderRegions.NUM_OF_REGIONS; ++region) { List<SharedData> sharedDatas = sharedDataManager.getBorderSharedData(region); List<Point> directions = sharedDataManager.getBorderDirections(region); assert sharedDatas.size() == directions.size(); for (int i = 0; i < sharedDatas.size(); ++i) { double xoffset = getXOffset(directions.get(i)); double yoffset = getYOffset(directions.get(i)); borderMap.get(region).add(new BorderGate(xoffset, yoffset, sharedDatas.get(i))); } } } /* * The x and y offsets are necessary for * correct particle position translation (in case of distributed boundary) * or for correct particle reflection (in case of non-distributed boundary) * The offsets depend on the direction of the neighbor (in case of distributed boundary) * or on the region (in case of non-distributed boundary). */ private double getYOffset(Point direction) { return direction.y * simulationArea.ysize(); } private double getXOffset(Point direction) { return direction.x * simulationArea.xsize(); } private double getYOffsetFromRegion(int region) { return BoundaryRegions.getSign(region).y * simulationArea.ysize(); } private double getXOffsetFromRegion(int region) { return BoundaryRegions.getSign(region).x * simulationArea.xsize(); } public void changeType(ParticleBoundaryType boundaryType) { throw new UnsupportedOperationException( "The type of the boundary in distributed simulation can not be changed!"); } public void applyOnParticleBoundingBox( Solver solver, Force force, Particle particle, double timeStep) { throw new UnsupportedOperationException( "In distributed boundaries we can not deduce particle's position " + "based on its bounding box as it would result in errors."); } public void applyOnParticleCenter( Solver solver, Force force, Particle particle, double timeStep) { int borderRegion = borderRegions.getRegion(particle.getX(), particle.getY()); for (BorderGate bg: borderMap.get(borderRegion)) { bg.apply(solver, force, particle, timeStep); } // Boundary gates have to be called after border gates as they change the position // of the particle. int boundaryRegion = boundaryRegions.getRegion(particle.getX(), particle.getY()); boundaryMap[boundaryRegion].apply(solver, force, particle, timeStep); } }