! Migrate this organism to a different world. If this method is called, it means that this organism is to be migrated to a *different* world (ie, it shouldn't be migrated back to this world). Conditions that depend on geometry of the worlds are checked over in IsWorldBoundary(). */
| 140 | Conditions that depend on geometry of the worlds are checked over in IsWorldBoundary(). |
| 141 | */ |
| 142 | void cMultiProcessWorld::MigrateOrganism(cOrganism* org, const cPopulationCell& cell, const cMerit& merit, int lineage) { |
| 143 | assert(org!=0); |
| 144 | int dst_world=-1; |
| 145 | |
| 146 | // which world is this organism migrating to? |
| 147 | switch(GetConfig().BIRTH_METHOD.Get()) { |
| 148 | case POSITION_OFFSPRING_RANDOM: { // spatial, random in neighborhood |
| 149 | int x, y; |
| 150 | cell.GetPosition(x,y); |
| 151 | if(x == 0) { |
| 152 | // migrate left |
| 153 | dst_world = m_mpi_world.rank() - 1; |
| 154 | } else if(x == (GetConfig().WORLD_X.Get()-1)) { |
| 155 | // migrate right |
| 156 | dst_world = m_mpi_world.rank() + 1; |
| 157 | } else if(y == 0) { |
| 158 | // migrate down |
| 159 | dst_world = m_mpi_world.rank() - m_universe_dim; |
| 160 | } else if(y == (GetConfig().WORLD_Y.Get()-1)) { |
| 161 | // migrate up |
| 162 | dst_world = m_mpi_world.rank() + m_universe_dim; |
| 163 | } |
| 164 | break; |
| 165 | } |
| 166 | case POSITION_OFFSPRING_FULL_SOUP_RANDOM: { // mass action |
| 167 | // prevent a migration back to this same world, unless this is the only world |
| 168 | // we have: |
| 169 | if(m_mpi_world.size() == 1) { |
| 170 | dst_world = 0; |
| 171 | } else { |
| 172 | dst_world = GetRandom().GetInt(m_mpi_world.size()-1); |
| 173 | if (dst_world >= m_mpi_world.rank()) { |
| 174 | ++dst_world; |
| 175 | } |
| 176 | } |
| 177 | break; |
| 178 | } |
| 179 | default: { |
| 180 | GetDriver().RaiseFatalException(-1, "Avida-MP only supports BIRTH_METHODS 0 (POSITION_OFFSPRING_RANDOM) and 4 (POSITION_OFFSPRING_FULL_SOUP_RANDOM)."); |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | assert(dst_world < m_mpi_world.size()); |
| 185 | assert(dst_world >= 0); |
| 186 | |
| 187 | // the tag is set to the number of messages previously sent; this is to allow |
| 188 | // the receiver to sort messages for consistency. |
| 189 | m_reqs.push_back(m_mpi_world.isend(dst_world, m_reqs.size(), migration_message(org, cell, merit.GetDouble(), lineage))); |
| 190 | |
| 191 | // stats tracking: |
| 192 | GetStats().OutgoingMigrant(org); |
| 193 | } |
| 194 | |
| 195 | |
| 196 | /*! Returns true if an organism should be migrated to a different world. |
nothing calls this directly
no test coverage detected