1 #ifndef LIBGEODECOMP_PARALLELIZATION_HIPARSIMULATOR_STEERERADAPTER_H 2 #define LIBGEODECOMP_PARALLELIZATION_HIPARSIMULATOR_STEERERADAPTER_H 3 4 #include <libgeodecomp/io/steerer.h> 5 #include <libgeodecomp/storage/patchprovider.h> 6 7 namespace LibGeoDecomp { 8 namespace HiParSimulator { 9 10 template<typename GRID_TYPE, typename CELL_TYPE> 11 class SteererAdapter : public PatchProvider<GRID_TYPE> 12 { 13 public: 14 typedef typename APITraits::SelectTopology<CELL_TYPE>::Value Topology; 15 16 static const unsigned NANO_STEPS = APITraits::SelectNanoSteps<CELL_TYPE>::VALUE; 17 static const int DIM = Topology::DIM; 18 19 using PatchProvider<GRID_TYPE>::storedNanoSteps; 20 SteererAdapter(boost::shared_ptr<Steerer<CELL_TYPE>> steerer,const std::size_t firstStep,const std::size_t lastStep,Coord<Topology::DIM> globalGridDimensions,std::size_t rank,bool lastCall)21 SteererAdapter( 22 boost::shared_ptr<Steerer<CELL_TYPE> > steerer, 23 const std::size_t firstStep, 24 const std::size_t lastStep, 25 Coord<Topology::DIM> globalGridDimensions, 26 std::size_t rank, 27 bool lastCall) : 28 steerer(steerer), 29 firstNanoStep(firstStep * NANO_STEPS), 30 lastNanoStep(lastStep * NANO_STEPS), 31 rank(rank), 32 lastCall(lastCall), 33 globalGridDimensions(globalGridDimensions) 34 { 35 std::size_t firstRegularEventStep = firstStep; 36 std::size_t period = steerer->getPeriod(); 37 std::size_t offset = firstStep % period; 38 firstRegularEventStep = firstStep + period - offset; 39 40 // fixme: make tests work with the following line enabled (ATM steerers never get the STEERER_INITIALIZED event from us if firstStep is not a multiple of period() 41 // storedNanoSteps << firstNanoStep; 42 storedNanoSteps << firstRegularEventStep * NANO_STEPS; 43 storedNanoSteps << lastNanoStep; 44 } 45 setRegion(const Region<DIM> & region)46 virtual void setRegion(const Region<DIM>& region) 47 { 48 steerer->setRegion(region); 49 } 50 51 virtual void get( 52 GRID_TYPE *destinationGrid, 53 const Region<DIM>& patchableRegion, 54 const std::size_t globalNanoStep, 55 const bool remove = true) 56 { 57 std::size_t nanoStep = globalNanoStep % NANO_STEPS; 58 if (nanoStep != 0) { 59 throw std::logic_error( 60 "SteererAdapter expects to be called only at the beginning of a time step (nanoStep == 0)"); 61 } 62 63 std::size_t step = globalNanoStep / NANO_STEPS; 64 65 SteererEvent event = STEERER_NEXT_STEP; 66 if (globalNanoStep == firstNanoStep) { 67 event = STEERER_INITIALIZED; 68 } 69 if (globalNanoStep == lastNanoStep) { 70 event = STEERER_ALL_DONE; 71 } 72 73 if ((event == STEERER_NEXT_STEP) && (step % steerer->getPeriod() != 0)) { 74 throw std::logic_error("SteererAdapter called at wrong step (got " + StringOps::itoa(step) + 75 " but expected multiple of " + StringOps::itoa(steerer->getPeriod())); 76 } 77 78 typename Steerer<CELL_TYPE>::SteererFeedback feedback; 79 80 steerer->nextStep( 81 destinationGrid, 82 patchableRegion, 83 globalGridDimensions, 84 step, 85 event, 86 rank, 87 lastCall, 88 &feedback); 89 90 if ((event != STEERER_INITIALIZED) && remove) { 91 storedNanoSteps.erase(globalNanoStep); 92 storedNanoSteps << globalNanoStep + NANO_STEPS * steerer->getPeriod(); 93 } 94 95 // fixme: apply SteererFeedback! 96 } 97 98 private: 99 boost::shared_ptr<Steerer<CELL_TYPE> > steerer; 100 std::size_t firstNanoStep; 101 std::size_t lastNanoStep; 102 std::size_t rank; 103 bool lastCall; 104 Coord<Topology::DIM> globalGridDimensions; 105 106 }; 107 108 } 109 } 110 111 #endif 112