! Process post-update events. This method is called after each update of the local population completes. Here we check to see if this world has received any migrants from other worlds, and if so, we inject them into the local population. Note that this is an unconditional injection -- that is, migrants are "pushed" to this world. Migrants are injected according to BIRTH_METHOD. \todo
| 272 | second mode that relaxes consistency in favor of speed. |
| 273 | */ |
| 274 | void cMultiProcessWorld::ProcessPostUpdate(cAvidaContext& ctx) { |
| 275 | namespace mpi = boost::mpi; |
| 276 | using namespace boost; |
| 277 | |
| 278 | // restart the timer for this method, and get the elapsed time for the past update: |
| 279 | m_pf[UPDATE] = m_update_timer.elapsed(); |
| 280 | m_post_update_timer.restart(); |
| 281 | |
| 282 | // wait until we're sure that this process has sent all its messages: |
| 283 | mpi::wait_all(m_reqs.begin(), m_reqs.end()); |
| 284 | m_reqs.clear(); |
| 285 | |
| 286 | // at this point, we know that *this* process has sent everything. but, we don't |
| 287 | // know if it's *received* everything. so, we're going to put in a synchronization |
| 288 | // barrier, which means that every process must reach the barrier before any are allowed |
| 289 | // to proceed. since we just finished waiting for all communication to complete, |
| 290 | // this means that all messages must have been received, too. |
| 291 | m_mpi_world.barrier(); |
| 292 | |
| 293 | // now, receive all the messages, but store them in order by source and tag: |
| 294 | typedef std::map<int,migration_message> rx_tag_t; |
| 295 | typedef std::map<int,rx_tag_t> rx_src_t; |
| 296 | rx_src_t recvd; |
| 297 | optional<mpi::status> s = m_mpi_world.iprobe(mpi::any_source,mpi::any_tag); |
| 298 | while(s.is_initialized()) { |
| 299 | migration_message msg; |
| 300 | m_mpi_world.recv(s->source(), s->tag(), msg); |
| 301 | recvd[s->source()][s->tag()] = msg; |
| 302 | // any others? |
| 303 | s = m_mpi_world.iprobe(mpi::any_source,mpi::any_tag); |
| 304 | } |
| 305 | |
| 306 | // iterate over received messages in-order, injecting genomes into our population: |
| 307 | for(rx_src_t::iterator i=recvd.begin(); i!=recvd.end(); ++i) { |
| 308 | for(rx_tag_t::iterator j=i->second.begin(); j!=i->second.end(); ++j) { |
| 309 | //std::cerr << "********** INJECTING *********** " << i->first << " " << j->first << std::endl; |
| 310 | // ok, add this migrant to the current population |
| 311 | migration_message& migrant = j->second; |
| 312 | int target_cell=-1; |
| 313 | |
| 314 | switch(GetConfig().BIRTH_METHOD.Get()) { |
| 315 | case POSITION_OFFSPRING_RANDOM: { // spatial |
| 316 | // invert the orginating cell |
| 317 | migrant._x = GetConfig().WORLD_X.Get() - migrant._x - 1; |
| 318 | migrant._y = GetConfig().WORLD_Y.Get() - migrant._y - 1; |
| 319 | target_cell = GetConfig().WORLD_Y.Get() * migrant._y + migrant._x; |
| 320 | break; |
| 321 | } |
| 322 | case POSITION_OFFSPRING_FULL_SOUP_RANDOM: { // mass action |
| 323 | target_cell = GetRandom().GetInt(GetPopulation().GetSize()); |
| 324 | break; |
| 325 | } |
| 326 | default: { |
| 327 | GetDriver().RaiseFatalException(-1, "Avida-MP only supports BIRTH_METHODS 0 (POSITION_OFFSPRING_RANDOM) and 4 (POSITION_OFFSPRING_FULL_SOUP_RANDOM)."); |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | GetPopulation().InjectGenome(target_cell, |
nothing calls this directly
no test coverage detected