package org.openpixi.pixi.distributed; import junit.framework.Assert; import junit.framework.TestCase; import org.openpixi.pixi.distributed.NeighborMap; import org.openpixi.pixi.distributed.movement.boundary.BorderRegions; import org.openpixi.pixi.distributed.partitioning.Partitioner; import org.openpixi.pixi.distributed.partitioning.SimplePartitioner; import org.openpixi.pixi.physics.GeneralBoundaryType; import org.openpixi.pixi.physics.movement.boundary.BoundaryRegions; import org.openpixi.pixi.physics.util.IntBox; import org.openpixi.pixi.physics.util.Point; /** * Tests the creation of neighbors under hardwall and periodic boundaries. * There are two kinds of tests: * * 1) GENERIC TESTS - Test the neighbor maps of all partitions for: * - Correct number of potential neighbors at the region in question. * Corner border regions have 3 potential neighbors * while edge border regions or boundary regions have only 1 potential neighbor. * - Valid neighbor id range or dummy NO_NEIGHBOR id. * E.g. periodic corner border regions have always 3 valid neighbors * while the hardwall corner border regions might have 0,1 or 3 valid neighbors. * (Do not verify the specific neighbor values) * * 2) SPECIFIC TESTS - Test the specific neighbor values for a given region * (verify whether region r really has a neighbor n). * Furthermore, also verifies the direction of the neighbor. * The result of the specific test is dependent on the partitioning! * It expects the following partitioning: * 0 2 * 1 3 * 4 6 * 5 7 */ public class NeighborMapTest extends TestCase { // Constants for generic tests - feel free to change them. private static final int NUM_CELLS_X_GEN = 64; private static final int NUM_CELLS_Y_GEN = 128; private static final int NUM_PARTITIONS_GEN = 32; // Constants for specific tests - can not be changed! private static final int NUM_CELLS_X_SPC = 32; private static final int NUM_CELLS_Y_SPC = 32; private static final int NUM_PARTITIONS_SPC = 8; public void testPeriodicMapsGeneric() { // Create partitions Partitioner partitioner = new SimplePartitioner(); IntBox[] partitions = partitioner.partition(NUM_CELLS_X_GEN, NUM_CELLS_Y_GEN, NUM_PARTITIONS_GEN); IntBox globalSimulation = new IntBox(0, NUM_CELLS_X_GEN - 1, 0, NUM_CELLS_Y_GEN - 1); // Go through each partition and test its neighbor map for (int i = 0; i < partitions.length; ++i) { NeighborMap neighborMap = new NeighborMap( i, partitions, globalSimulation, GeneralBoundaryType.Periodic); testSinglePeriodicMap(i, neighborMap, partitions.length); } } public void testHardwallMapsGeneric() { // Create partitions Partitioner partitioner = new SimplePartitioner(); IntBox[] partitions = partitioner.partition(NUM_CELLS_X_GEN, NUM_CELLS_Y_GEN, NUM_PARTITIONS_GEN); IntBox globalSimulation = new IntBox(0, NUM_CELLS_X_GEN - 1, 0, NUM_CELLS_Y_GEN - 1); // Go through each partition and test its neighbor map for (int i = 0; i < partitions.length; ++i) { NeighborMap neighborMap = new NeighborMap( i, partitions, globalSimulation, GeneralBoundaryType.Hardwall); testSingleHardwallBoundaryMap(i, partitions, globalSimulation, neighborMap); testSingleHardwallBorderMap(i, partitions, globalSimulation, neighborMap); } } public void testPeriodicMapSpecific() { // Create partitions Partitioner partitioner = new SimplePartitioner(); IntBox[] partitions = partitioner.partition(NUM_CELLS_X_SPC, NUM_CELLS_Y_SPC, NUM_PARTITIONS_SPC); IntBox globalSimulation = new IntBox(0, NUM_CELLS_X_SPC - 1, 0, NUM_CELLS_Y_SPC - 1); int myPartID = 0; NeighborMap neighborMap = new NeighborMap( myPartID, partitions, globalSimulation, GeneralBoundaryType.Periodic); // Test boundary corner regions int region = BoundaryRegions.X_MIN + BoundaryRegions.Y_MIN; int neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(7, neighbor); Point direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(-1, -1), direction); region = BoundaryRegions.X_MAX + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(3, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(1, 1), direction); region = BoundaryRegions.X_MIN + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(3, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(-1, 1), direction); // Test boundary edge regions region = BoundaryRegions.X_MIN + BoundaryRegions.Y_CENTER; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(2, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(-1, 0), direction); region = BoundaryRegions.X_MAX + BoundaryRegions.Y_CENTER; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(2, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(1, 0), direction); region = BoundaryRegions.X_CENTER + BoundaryRegions.Y_MIN; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(5, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(0, -1), direction); // Test border corner regions region = BorderRegions.X_BORDER_MIN + BorderRegions.Y_BORDER_MIN; int[] neighbors = neighborMap.getBorderNeighbors(region); int on1 = assertContains(neighbors, 2); int on2 = assertContains(neighbors, 5); int on3 = assertContains(neighbors, 7); Point[] directions = neighborMap.getBorderNeighborsDirections(region); int od1 = assertContainsPoint(directions, new Point(-1, 0)); int od2 = assertContainsPoint(directions, new Point(0, -1)); int od3 = assertContainsPoint(directions, new Point(-1, -1)); // Test order Assert.assertEquals(on1, od1); Assert.assertEquals(on2, od2); Assert.assertEquals(on3, od3); region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_BORDER_MAX; neighbors = neighborMap.getBorderNeighbors(region); on1 = assertContains(neighbors, 1); on2 = assertContains(neighbors, 2); on3 = assertContains(neighbors, 3); directions = neighborMap.getBorderNeighborsDirections(region); od1 = assertContainsPoint(directions, new Point(0, 1)); od2 = assertContainsPoint(directions, new Point(1, 0)); od3 = assertContainsPoint(directions, new Point(1, 1)); // Test order Assert.assertEquals(on1, od1); Assert.assertEquals(on2, od2); Assert.assertEquals(on3, od3); // Test border edge regions region = BorderRegions.X_CENTER + BorderRegions.Y_BORDER_MIN; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, 5); directions = neighborMap.getBorderNeighborsDirections(region); assertContainsPoint(directions, new Point(0, -1)); region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_CENTER; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, 2); directions = neighborMap.getBorderNeighborsDirections(region); assertContainsPoint(directions, new Point(1, 0)); } public void testHardwallMapSpecific() { // Create partitions Partitioner partitioner = new SimplePartitioner(); IntBox[] partitions = partitioner.partition(NUM_CELLS_X_SPC, NUM_CELLS_Y_SPC, NUM_PARTITIONS_SPC); IntBox globalSimulation = new IntBox(0, NUM_CELLS_X_SPC - 1, 0, NUM_CELLS_Y_SPC - 1); int myPartID = 0; NeighborMap neighborMap = new NeighborMap( myPartID, partitions, globalSimulation, GeneralBoundaryType.Hardwall); // Test boundary corner regions int region = BoundaryRegions.X_MIN + BoundaryRegions.Y_MIN; int neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(NeighborMap.NO_NEIGHBOR, neighbor); Point direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertNull(direction); region = BoundaryRegions.X_MAX + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(3, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(1, 1), direction); region = BoundaryRegions.X_MIN + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(1, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(0, 1), direction); // Test boundary edge regions region = BoundaryRegions.X_MIN + BoundaryRegions.Y_CENTER; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(NeighborMap.NO_NEIGHBOR, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertNull(direction); region = BoundaryRegions.X_MAX + BoundaryRegions.Y_CENTER; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(2, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(1, 0), direction); region = BoundaryRegions.X_CENTER + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); Assert.assertEquals(1, neighbor); direction = neighborMap.getBoundaryNeighborsDirections(region); Assert.assertEquals(new Point(0, 1), direction); // Test border corner regions region = BorderRegions.X_BORDER_MIN + BorderRegions.Y_BORDER_MAX; int[] neighbors = neighborMap.getBorderNeighbors(region); int on1 = assertContains(neighbors, 1); assertContains(neighbors, NeighborMap.NO_NEIGHBOR); Point[] directions = neighborMap.getBorderNeighborsDirections(region); int od1 = assertContainsPoint(directions, new Point(0, 1)); // Test order Assert.assertEquals(on1, od1); region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_BORDER_MAX; neighbors = neighborMap.getBorderNeighbors(region); on1 = assertContains(neighbors, 1); int on2 = assertContains(neighbors, 2); int on3 = assertContains(neighbors, 3); directions = neighborMap.getBorderNeighborsDirections(region); od1 = assertContainsPoint(directions, new Point(0, 1)); int od2 = assertContainsPoint(directions, new Point(1, 0)); int od3 = assertContainsPoint(directions, new Point(1, 1)); // Test order Assert.assertEquals(on1, od1); Assert.assertEquals(on2, od2); Assert.assertEquals(on3, od3); // Test border outside corner regions region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_BOUNDARY_MIN; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, 2); directions = neighborMap.getBorderNeighborsDirections(region); assertContainsPoint(directions, new Point(1, 0)); region = BorderRegions.X_BOUNDARY_MAX + BorderRegions.Y_BORDER_MIN; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, NeighborMap.NO_NEIGHBOR); directions = neighborMap.getBorderNeighborsDirections(region); Assert.assertEquals(1, directions.length); Assert.assertNull(directions[0]); // Test border edge regions region = BorderRegions.X_CENTER + BorderRegions.Y_BORDER_MAX; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, 1); directions = neighborMap.getBorderNeighborsDirections(region); assertContainsPoint(directions, new Point(0, 1)); region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_CENTER; neighbors = neighborMap.getBorderNeighbors(region); assertContains(neighbors, 2); directions = neighborMap.getBorderNeighborsDirections(region); assertContainsPoint(directions, new Point(1, 0)); } /** * Tests whether the expected neighbor is in the list. * Returns the order of the expected neighbor. */ private int assertContains(int[] neighbors, int expected) { for (int i = 0; i < neighbors.length; ++i) { if (neighbors[i] == expected) { return i; } } Assert.fail("Missing neighbor: " + expected + "!"); return -1; } /** * Tests whether the expected point is in the list. * Returns the order of the expected point. */ private int assertContainsPoint(Point[] directions, Point expected) { for (int i = 0; i < directions.length; ++i) { if (directions[i] == null) { continue; } if (directions[i].equals(expected)) { return i; } } Assert.fail("Missing direction: " + expected + "!"); return -1; } private void testSinglePeriodicMap(int workerID, NeighborMap neighborMap, int numOfWorkers) { // Boundary regions test for (int region = 0; region < BoundaryRegions.NUM_OF_REGIONS; ++region) { if (region == BoundaryRegions.X_CENTER + BoundaryRegions.Y_CENTER) { continue; } int neighbor = neighborMap.getBoundaryNeighbor(region); String identification = identificationString( GeneralBoundaryType.Periodic, workerID, region, "org/openpixi/pixi/distributed/movement/boundary"); testForAnyNeighbor( neighbor, numOfWorkers, identification); } // Border regions test for (int region: BorderRegions.EDGE_REGIONS) { int[] neighbors = neighborMap.getBorderNeighbors(region); String identification = identificationString( GeneralBoundaryType.Periodic, workerID, region, "border-edge"); testPotentialNeighborsCount(1, neighbors.length, identification); testForAnyNeighbor(neighbors[0], numOfWorkers, identification); } for (int region: BorderRegions.CORNER_REGIONS) { int[] neighbors = neighborMap.getBorderNeighbors(region); String identification = identificationString( GeneralBoundaryType.Periodic, workerID, region, "border-corner"); testPotentialNeighborsCount(3, neighbors.length, identification); for (int neighbor: neighbors) { testForAnyNeighbor(neighbor, numOfWorkers, identification); } } for (int region: BorderRegions.OUTSIDE_CORNER_REGIONS) { int[] neighbors = neighborMap.getBorderNeighbors(region); String identification = identificationString( GeneralBoundaryType.Periodic, workerID, region, "border-outside-corner"); testPotentialNeighborsCount(1, neighbors.length, identification); for (int neighbor: neighbors) { testForNoNeighbor(neighbor, identification); } } } /** * Does not test all the regions. * Tests only one corner and one edge region. */ private void testSingleHardwallBoundaryMap( int myPartID, IntBox[] partitions, IntBox globalSimulation, NeighborMap neighborMap) { IntBox myPart = partitions[myPartID]; // Test upper-left corner int region = BoundaryRegions.X_MIN + BoundaryRegions.Y_MIN; int neighbor = neighborMap.getBoundaryNeighbor(region); String identification = identificationString( GeneralBoundaryType.Hardwall, myPartID, region, "boundary-corner"); if (myPart.xmin() != globalSimulation.xmin() || myPart.ymin() != globalSimulation.ymin()) { // If the region is not a simulation corner it must have one neighbor testForAnyNeighbor(neighbor, partitions.length, identification); } else { // At the global simulation corner there should be no neighbor testForNoNeighbor(neighbor, identification); } // Test bottom edge region = BoundaryRegions.X_CENTER + BoundaryRegions.Y_MAX; neighbor = neighborMap.getBoundaryNeighbor(region); identification = identificationString( GeneralBoundaryType.Hardwall, myPartID, region, "boundary-edge"); if (myPart.ymax() != globalSimulation.ymax()) { // If the region is not at the bottom of global simulation // then it must have one neighbor testForAnyNeighbor(neighbor, partitions.length, identification); } else { testForNoNeighbor(neighbor, identification); } } /** * Does not test all the regions. * Tests only one corner, one outside corner and one edge region. */ private void testSingleHardwallBorderMap( int myPartID, IntBox[] partitions, IntBox globalSimulation, NeighborMap neighborMap) { IntBox myPart = partitions[myPartID]; // Test bottom-right corner int region = BorderRegions.X_BORDER_MAX + BorderRegions.Y_BORDER_MAX; int[] neighbors = neighborMap.getBorderNeighbors(region); String identification = identificationString( GeneralBoundaryType.Hardwall, myPartID, region, "border-corner"); testPotentialNeighborsCount(3, neighbors.length, identification); if (myPart.xmax() == globalSimulation.xmax() && myPart.ymax() == globalSimulation.ymax()) { // If the region is at global simulation corner it can not have any neighbors for (int neighbor: neighbors) { testForNoNeighbor(neighbor, identification); } } else if (myPart.xmax() == globalSimulation.xmax() || myPart.ymax() == globalSimulation.ymax()) { // If the region is not at global simulation corner but at its edge // it must have exactly one neighbor testForSingleNeighbor(neighbors, partitions.length, identification); } else { // If the region is inside the global simulation it must have exactly 3 neighbors for (int neighbor: neighbors) { testForAnyNeighbor(neighbor, partitions.length, identification); } } // Test right-top outside corner region = BorderRegions.X_BOUNDARY_MAX + BorderRegions.Y_BORDER_MIN; neighbors = neighborMap.getBorderNeighbors(region); identification = identificationString( GeneralBoundaryType.Hardwall, myPartID, region, "border-outside-corner"); testPotentialNeighborsCount(1, neighbors.length, identification); if (myPart.xmax() == globalSimulation.xmax() && myPart.ymin() != globalSimulation.ymin()) { testForAnyNeighbor(neighbors[0], partitions.length, identification); } else { testForNoNeighbor(neighbors[0], identification); } // Test left edge region = BorderRegions.X_BORDER_MIN + BorderRegions.Y_CENTER; neighbors = neighborMap.getBorderNeighbors(region); identification = identificationString( GeneralBoundaryType.Hardwall, myPartID, region, "border-edge"); testPotentialNeighborsCount(1, neighbors.length, identification); if (myPart.xmin() != globalSimulation.xmin()) { testForAnyNeighbor(neighbors[0], partitions.length, identification); } else { testForNoNeighbor(neighbors[0], identification); } } private void testPotentialNeighborsCount(int expected, int actual, String identification) { if (actual < expected) { myFail(identification, "Too few potential neighbors!"); } else if (actual > expected) { myFail(identification, "Too many potential neighbors!"); } } private void testForSingleNeighbor(int[] neighbors, int numOfWorkers, String identification) { int realNeighbor = NeighborMap.NO_NEIGHBOR; for (int neighbor: neighbors) { if (neighbor != NeighborMap.NO_NEIGHBOR) { if (realNeighbor != NeighborMap.NO_NEIGHBOR) { myFail(identification, "Two valid neighbors!"); } realNeighbor = neighbor; } } testForAnyNeighbor(realNeighbor, numOfWorkers, identification); } private void testForNoNeighbor(int neighbor, String identification) { if (neighbor != NeighborMap.NO_NEIGHBOR) { myFail(identification, "Found neighbor!"); } } private void testForAnyNeighbor(int neighbor, int numOfWorkers, String identification) { if (neighbor == NeighborMap.NO_NEIGHBOR) { myFail(identification, "No neighbor detected!"); } else if (neighbor < 0) { myFail(identification, "Negative neighbor id!"); } else if (neighbor >= numOfWorkers) { myFail(identification, "Neighbor ID too large!"); } } /** * Identifies the tested partition, region and boundary. */ private String identificationString( GeneralBoundaryType boundaryType, int workerID, int regionID, String regionType) { return "Boundary: " + boundaryType + ", Partition: " + workerID + ", Region ID: " + regionID + ", Region type: " + regionType; } private void myFail(String identification, String msg) { Assert.fail(identification + "\n" + msg); } }