1 #include <libgeodecomp.h>
2 #include <libgeodecomp/geometry/partitions/zcurvepartition.h>
3 #include <libgeodecomp/io/mocksteerer.h>
4 #include <libgeodecomp/io/mockwriter.h>
5 #include <libgeodecomp/io/teststeerer.h>
6 #include <libgeodecomp/io/parallelmemorywriter.h>
7 #include <libgeodecomp/io/paralleltestwriter.h>
8 #include <libgeodecomp/io/testinitializer.h>
9 #include <libgeodecomp/loadbalancer/mockbalancer.h>
10 #include <libgeodecomp/misc/nonpodtestcell.h>
11 #include <libgeodecomp/misc/testcell.h>
12 #include <libgeodecomp/misc/testhelper.h>
13 #include <libgeodecomp/parallelization/hiparsimulator.h>
14 
15 #include <boost/shared_ptr.hpp>
16 #include <cxxtest/TestSuite.h>
17 #include <sstream>
18 
19 using namespace LibGeoDecomp;
20 using namespace HiParSimulator;
21 
22 namespace LibGeoDecomp {
23 namespace HiParSimulator {
24 
25 class HiParSimulatorTest : public CxxTest::TestSuite
26 {
27 public:
28     typedef GridBase<TestCell<2>, 2> GridBaseType;
29     typedef HiParSimulator<TestCell<2>, ZCurvePartition<2> > SimulatorType;
30     typedef ParallelMemoryWriter<TestCell<2> > MemoryWriterType;
31     typedef MockSteerer<TestCell<2> > MockSteererType;
32     typedef TestSteerer<2 > TestSteererType;
33 
34     static const unsigned NANO_STEPS = APITraits::SelectNanoSteps<TestCell<2> >::VALUE;
35 
setUp()36     void setUp()
37     {
38         int width = 131;
39         int height = 241;
40         dim = Coord<2>(width, height);
41         maxSteps = 101;
42         firstStep = 20;
43         firstCycle = firstStep * NANO_STEPS;
44         TestInitializer<TestCell<2> > *init = new TestInitializer<TestCell<2> >(
45             dim, maxSteps, firstStep);
46 
47         outputPeriod = 4;
48         loadBalancingPeriod = 31;
49         ghostZoneWidth = 10;
50         sim.reset(new SimulatorType(
51                     init,
52                     new MockBalancer(),
53                     loadBalancingPeriod,
54                     ghostZoneWidth));
55         mockWriter = new MockWriter();
56         memoryWriter = new MemoryWriterType(outputPeriod);
57         sim->addWriter(mockWriter);
58         sim->addWriter(memoryWriter);
59     }
60 
tearDown()61     void tearDown()
62     {
63         sim.reset();
64     }
65 
testStep()66     void testStep()
67     {
68         sim->step();
69         TS_ASSERT_EQUALS((31 - 1)       * 27, sim->timeToNextEvent());
70         TS_ASSERT_EQUALS((101 - 20 - 1) * 27, sim->timeToLastEvent());
71         sim->step();
72         sim->step();
73         sim->step();
74 
75         TS_ASSERT_EQUALS((31 - 4)       * 27, sim->timeToNextEvent());
76         TS_ASSERT_EQUALS((101 - 20 - 4) * 27, sim->timeToLastEvent());
77 
78         std::size_t rank = MPILayer().rank();
79         MockWriter::EventVec expectedEvents;
80         expectedEvents << MockWriterHelpers::MockWriterEvent(20, WRITER_INITIALIZED, rank, false)
81                        << MockWriterHelpers::MockWriterEvent(20, WRITER_INITIALIZED, rank, true);
82         for (int t = 21; t < 25; t += 1) {
83             expectedEvents << MockWriterHelpers::MockWriterEvent(t, WRITER_STEP_FINISHED, rank, false)
84                            << MockWriterHelpers::MockWriterEvent(t, WRITER_STEP_FINISHED, rank, true);
85         }
86         TS_ASSERT_EQUALS(expectedEvents, mockWriter->events());
87 
88         for (int t = 20; t < 25; t += outputPeriod) {
89             int globalNanoStep = t * NANO_STEPS;
90             MemoryWriterType::GridMap grids = memoryWriter->getGrids();
91             TS_ASSERT_TEST_GRID(
92                 MemoryWriterType::GridType,
93                 grids[t],
94                 globalNanoStep);
95             TS_ASSERT_EQUALS(dim, grids[t].getDimensions());
96         }
97     }
98 
testRun()99     void testRun()
100     {
101         sim->run();
102 
103         for (unsigned t = firstStep; t < maxSteps; t += outputPeriod) {
104             unsigned globalNanoStep = t * NANO_STEPS;
105             MemoryWriterType::GridMap grids = memoryWriter->getGrids();
106             TS_ASSERT_TEST_GRID(
107                 MemoryWriterType::GridType,
108                 grids[t],
109                 globalNanoStep);
110             TS_ASSERT_EQUALS(dim, grids[t].getDimensions());
111         }
112 
113         // check last step, too
114         unsigned t = maxSteps;
115         unsigned globalNanoStep = t * NANO_STEPS;
116         MemoryWriterType::GridMap grids = memoryWriter->getGrids();
117         TS_ASSERT_TEST_GRID(
118             MemoryWriterType::GridType,
119             grids[t],
120             globalNanoStep);
121         TS_ASSERT_EQUALS(dim, grids[t].getDimensions());
122 
123         if (MPILayer().rank() == 0) {
124             std::string expectedEvents;
125             for (int i = 0; i < 2; ++i) {
126                 expectedEvents += "balance() [7892, 7893, 7893, 7893] [1, 1, 1, 1]\n";
127             }
128 
129             TS_ASSERT_EQUALS(expectedEvents, MockBalancer::events);
130         }
131     }
132 
testSteererCallback()133     void testSteererCallback()
134     {
135         std::stringstream events;
136         sim->addSteerer(new MockSteererType(5, &events));
137         sim->run();
138         sim.reset();
139 
140         std::stringstream expected;
141         expected << "created, period = 5\n";
142         for (int i = 25; i < 101; i += 5) {
143             expected << "nextStep(" << i << ", STEERER_NEXT_STEP, " << MPILayer().rank() << ", " << "0)\n"
144                      << "nextStep(" << i << ", STEERER_NEXT_STEP, " << MPILayer().rank() << ", " << "1)\n";
145         }
146 
147         expected << "nextStep(101, STEERER_ALL_DONE, " << MPILayer().rank() << ", " << "0)\n"
148                  << "nextStep(101, STEERER_ALL_DONE, " << MPILayer().rank() << ", " << "1)\n"
149                  << "deleted\n";
150 
151         TS_ASSERT_EQUALS(events.str(), expected.str());
152     }
153 
testSteererFunctionality()154     void testSteererFunctionality()
155     {
156         sim->addSteerer(new TestSteererType(5, 25, 4711 * 27));
157         sim->run();
158 
159         const Region<2> *region = &sim->updateGroup->partitionManager->innerSet(ghostZoneWidth);
160         const GridBaseType *grid = &sim->updateGroup->grid();
161         int cycle = 101 * 27 + 4711 * 27;
162 
163         TS_ASSERT_TEST_GRID_REGION(
164             GridBaseType,
165             *grid,
166             *region,
167             cycle);
168     }
169 
testParallelWriterInvocation()170     void testParallelWriterInvocation()
171     {
172         unsigned period = 4;
173         std::vector<unsigned> expectedSteps;
174         std::vector<WriterEvent> expectedEvents;
175         expectedSteps << 20
176                       << 24
177                       << 28
178                       << 32
179                       << 36
180                       << 40
181                       << 44
182                       << 48
183                       << 52
184                       << 56
185                       << 60
186                       << 64
187                       << 68
188                       << 72
189                       << 76
190                       << 80
191                       << 84
192                       << 88
193                       << 92
194                       << 96
195                       << 100
196                       << 101;
197         expectedEvents << WRITER_INITIALIZED
198                        << WRITER_STEP_FINISHED
199                        << WRITER_STEP_FINISHED
200                        << WRITER_STEP_FINISHED
201                        << WRITER_STEP_FINISHED
202                        << WRITER_STEP_FINISHED
203                        << WRITER_STEP_FINISHED
204                        << WRITER_STEP_FINISHED
205                        << WRITER_STEP_FINISHED
206                        << WRITER_STEP_FINISHED
207                        << WRITER_STEP_FINISHED
208                        << WRITER_STEP_FINISHED
209                        << WRITER_STEP_FINISHED
210                        << WRITER_STEP_FINISHED
211                        << WRITER_STEP_FINISHED
212                        << WRITER_STEP_FINISHED
213                        << WRITER_STEP_FINISHED
214                        << WRITER_STEP_FINISHED
215                        << WRITER_STEP_FINISHED
216                        << WRITER_STEP_FINISHED
217                        << WRITER_STEP_FINISHED
218                        << WRITER_ALL_DONE;
219 
220         sim->addWriter(new ParallelTestWriter(period, expectedSteps, expectedEvents));
221         sim->run();
222     }
223 
224 
testNonPoDCell()225     void testNonPoDCell()
226     {
227 #ifdef LIBGEODECOMP_WITH_BOOST_SERIALIZATION
228 
229         ghostZoneWidth = 3;
230 
231         HiParSimulator<NonPoDTestCell, ZCurvePartition<2> > sim(
232             new NonPoDTestCell::Initializer(),
233             new MockBalancer(),
234             loadBalancingPeriod,
235             ghostZoneWidth);
236         sim.run();
237 
238 #endif
239     }
240 
241 private:
242     boost::shared_ptr<SimulatorType> sim;
243     Coord<2> dim;
244     unsigned maxSteps;
245     unsigned firstStep;
246     unsigned firstCycle;
247     unsigned outputPeriod;
248     unsigned loadBalancingPeriod;
249     unsigned ghostZoneWidth;
250     MockWriter *mockWriter;
251     MemoryWriterType *memoryWriter;
252 };
253 
254 }
255 }
256