00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <cassert>
00030 #include <algorithm>
00031
00032 #include "CaBasedCellPopulation.hpp"
00033 #include "RandomNumberGenerator.hpp"
00034
00035
00036 #include "VtkMeshWriter.hpp"
00037 #include "NodesOnlyMesh.hpp"
00038 #include "Exception.hpp"
00039
00040 template<unsigned DIM>
00041 CaBasedCellPopulation<DIM>::CaBasedCellPopulation(TetrahedralMesh<DIM, DIM>& rMesh,
00042 std::vector<CellPtr>& rCells,
00043 const std::vector<unsigned> locationIndices,
00044 bool deleteMesh,
00045 bool validate)
00046 : AbstractOnLatticeCellPopulation<DIM>(rCells, locationIndices),
00047 mrMesh(rMesh),
00048 mOnlyUseNearestNeighboursForDivision(false),
00049 mUseVonNeumannNeighbourhoods(false)
00050 {
00051
00052 assert(this->mCells.size() <= mrMesh.GetNumNodes());
00053
00054 if (!locationIndices.empty())
00055 {
00056
00057 std::set<unsigned> node_indices;
00058 std::set<unsigned> location_indices;
00059 std::set<unsigned> empty_site_indices;
00060
00061 for (unsigned i=0; i<this->GetNumNodes(); i++)
00062 {
00063 node_indices.insert(this->GetNode(i)->GetIndex());
00064 }
00065 for (unsigned i=0; i<locationIndices.size(); i++)
00066 {
00067 location_indices.insert(locationIndices[i]);
00068 }
00069
00070 std::set_difference(node_indices.begin(), node_indices.end(),
00071 location_indices.begin(), location_indices.end(),
00072 std::inserter(empty_site_indices, empty_site_indices.begin()));
00073
00074
00075 SetEmptySites(empty_site_indices);
00076 }
00077 else
00078 {
00079 mIsEmptySite = std::vector<bool>(this->GetNumNodes(), false);
00080 Validate();
00081 }
00082 }
00083
00084 template<unsigned DIM>
00085 CaBasedCellPopulation<DIM>::CaBasedCellPopulation(TetrahedralMesh<DIM, DIM>& rMesh)
00086 : AbstractOnLatticeCellPopulation<DIM>(),
00087 mrMesh(rMesh),
00088 mOnlyUseNearestNeighboursForDivision(false),
00089 mUseVonNeumannNeighbourhoods(false)
00090 {
00091 }
00092
00093 template<unsigned DIM>
00094 CaBasedCellPopulation<DIM>::~CaBasedCellPopulation()
00095 {
00096 if (this->mDeleteMesh)
00097 {
00098 delete &mrMesh;
00099 }
00100 }
00101
00102 template<unsigned DIM>
00103 void CaBasedCellPopulation<DIM>::UpdateCellLocations(double dt)
00104 {
00105
00106 if (this->mIterateRandomlyOverUpdateRuleCollection)
00107 {
00108
00110 std::random_shuffle(mUpdateRuleCollection.begin(), mUpdateRuleCollection.end());
00111 }
00112
00113 for (typename std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >::iterator update_iter = mUpdateRuleCollection.begin();
00114 update_iter != mUpdateRuleCollection.end();
00115 ++update_iter)
00116 {
00117
00118 if (this->mUpdateNodesInRandomOrder)
00119 {
00120 std::vector<CellPtr> cells_vector;
00121 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00122 cell_iter != this->End();
00123 ++cell_iter)
00124 {
00125 cells_vector.push_back(*cell_iter);
00126 }
00128 std::random_shuffle(cells_vector.begin(), cells_vector.end());
00129
00130 for (unsigned i=0; i<cells_vector.size(); i++)
00131 {
00132
00133 unsigned current_location_index = this->GetLocationIndexUsingCell(cells_vector[i]);
00134
00135 assert(!this->IsEmptySite(current_location_index));
00136
00137
00138 unsigned new_location_index = (*update_iter)->GetNewLocationOfCell(current_location_index, *this, dt);
00139
00140
00141 this->MoveCell(cells_vector[i], new_location_index);
00142 }
00143 }
00144 else
00145 {
00146
00147 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00148 cell_iter != this->End();
00149 ++cell_iter)
00150 {
00151
00152 unsigned current_location_index = this->GetLocationIndexUsingCell(*cell_iter);
00153
00154 assert(!this->IsEmptySite(current_location_index));
00155
00156
00157 unsigned new_location_index = (*update_iter)->GetNewLocationOfCell(current_location_index, *this, dt);
00158
00159
00160 this->MoveCell(*cell_iter, new_location_index);
00161 }
00162 }
00163 }
00164 }
00165
00166 template<unsigned DIM>
00167 void CaBasedCellPopulation<DIM>::SetOnlyUseNearestNeighboursForDivision(bool onlyUseNearestNeighboursForDivision)
00168 {
00169 mOnlyUseNearestNeighboursForDivision = onlyUseNearestNeighboursForDivision;
00170 }
00171
00172 template<unsigned DIM>
00173 bool CaBasedCellPopulation<DIM>::GetOnlyUseNearestNeighboursForDivision()
00174 {
00175 return mOnlyUseNearestNeighboursForDivision;
00176 }
00177
00178 template<unsigned DIM>
00179 void CaBasedCellPopulation<DIM>::AddUpdateRule(boost::shared_ptr<AbstractCaUpdateRule<DIM> > pUpdateRule)
00180 {
00181 mUpdateRuleCollection.push_back(pUpdateRule);
00182 }
00183
00184 template<unsigned DIM>
00185 const std::vector<boost::shared_ptr<AbstractCaUpdateRule<DIM> > >& CaBasedCellPopulation<DIM>::rGetUpdateRuleCollection() const
00186 {
00187 return mUpdateRuleCollection;
00188 }
00189
00190 template<unsigned DIM>
00191 void CaBasedCellPopulation<DIM>::SetUseVonNeumannNeighbourhoods(bool useVonNeumannNeighbourhoods)
00192 {
00193 mUseVonNeumannNeighbourhoods = useVonNeumannNeighbourhoods;
00194 }
00195
00196 template<unsigned DIM>
00197 bool CaBasedCellPopulation<DIM>::GetUseVonNeumannNeighbourhoods()
00198 {
00199 return mUseVonNeumannNeighbourhoods;
00200 }
00201
00202 template<unsigned DIM>
00203 std::vector<bool>& CaBasedCellPopulation<DIM>::rGetEmptySites()
00204 {
00205 return mIsEmptySite;
00206 }
00207
00208 template<unsigned DIM>
00209 bool CaBasedCellPopulation<DIM>::IsEmptySite(unsigned index)
00210 {
00211 return mIsEmptySite[index];
00212 }
00213
00214 template<unsigned DIM>
00215 std::set<unsigned> CaBasedCellPopulation<DIM>::GetEmptySiteIndices()
00216 {
00217 std::set<unsigned> empty_site_indices;
00218 for (unsigned i=0; i<mIsEmptySite.size(); i++)
00219 {
00220 if (mIsEmptySite[i])
00221 {
00222 empty_site_indices.insert(i);
00223 }
00224 }
00225 return empty_site_indices;
00226 }
00227
00228 template<unsigned DIM>
00229 void CaBasedCellPopulation<DIM>::SetEmptySites(const std::set<unsigned>& rEmptySiteIndices)
00230 {
00231
00232 mIsEmptySite = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00233
00234
00235 for (std::set<unsigned>::iterator iter = rEmptySiteIndices.begin();
00236 iter != rEmptySiteIndices.end();
00237 ++iter)
00238 {
00239 mIsEmptySite[*iter] = true;
00240 }
00241
00242 Validate();
00243 }
00244
00245 template<unsigned DIM>
00246 TetrahedralMesh<DIM, DIM>& CaBasedCellPopulation<DIM>::rGetMesh()
00247 {
00248 return mrMesh;
00249 }
00250
00251 template<unsigned DIM>
00252 const TetrahedralMesh<DIM, DIM>& CaBasedCellPopulation<DIM>::rGetMesh() const
00253 {
00254 return mrMesh;
00255 }
00256
00257 template<unsigned DIM>
00258 Node<DIM>* CaBasedCellPopulation<DIM>::GetNode(unsigned index)
00259 {
00260 return mrMesh.GetNode(index);
00261 }
00262
00263 template<unsigned DIM>
00264 unsigned CaBasedCellPopulation<DIM>::GetNumNodes()
00265 {
00266 return mrMesh.GetNumAllNodes();
00267 }
00268
00269 template<unsigned DIM>
00270 CellPtr CaBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00271 {
00272
00273
00274
00275
00276
00277
00278 if (pParentCell == CellPtr())
00279 {
00280 EXCEPTION("A parent cell must be provided when calling AddCell() on a CaBasedCellPopulation.");
00281 }
00282
00284
00285
00286 this->mCells.push_back(pNewCell);
00287 CellPtr p_created_cell = this->mCells.back();
00288
00289
00290 this->mCellLocationMap[p_created_cell.get()] = UINT_MAX;
00291
00292
00293 unsigned parent_index = this->mCellLocationMap[pParentCell.get()];
00294
00295 unsigned degree_upper_bound;
00296
00297 if (mOnlyUseNearestNeighboursForDivision)
00298 {
00299 degree_upper_bound = 1;
00300 }
00301 else
00302 {
00303
00304 std::vector<unsigned> maximum_degrees = GetMaximumDegreeInEachDirection(parent_index);
00305
00306
00307 degree_upper_bound = *(std::max_element(maximum_degrees.begin(), maximum_degrees.end()));
00308 }
00309
00310 bool free_neighbour_was_found = false;
00311
00312
00313 for (unsigned degree=1; degree<=degree_upper_bound; degree++)
00314 {
00315
00316 std::set<unsigned> nth_degree_neighbours = GetNthDegreeNeighbouringNodeIndices(parent_index, degree);
00317
00318
00319 std::set<unsigned> free_nth_degree_neighbours;
00320 for (std::set<unsigned>::iterator neighbour_iter = nth_degree_neighbours.begin();
00321 neighbour_iter != nth_degree_neighbours.end();
00322 ++neighbour_iter)
00323 {
00324 if (IsEmptySite(*neighbour_iter))
00325 {
00326 free_nth_degree_neighbours.insert(*neighbour_iter);
00327 }
00328 }
00329
00330
00331 if (!free_nth_degree_neighbours.empty())
00332 {
00333
00334 unsigned num_free_neighbours = free_nth_degree_neighbours.size();
00335 unsigned random_offset = RandomNumberGenerator::Instance()->randMod(num_free_neighbours);
00336
00337 std::set<unsigned>::iterator free_neighbour_iter = free_nth_degree_neighbours.begin();
00338 for (unsigned i=0; i<random_offset; i++)
00339 {
00340 free_neighbour_iter++;
00341 }
00342
00343 unsigned chosen_free_neighbour_index = *free_neighbour_iter;
00344
00345
00346 int direction_index = ((int)chosen_free_neighbour_index - (int)parent_index)/(int)degree;
00347
00348
00349 std::vector<unsigned> indices(degree);
00350 for (unsigned i=0; i<degree; i++)
00351 {
00352 indices[i] = parent_index + (i+1)*direction_index;
00353 }
00354 for (unsigned i=degree-1; i>0; i--)
00355 {
00356 CellPtr p_current_cell = this->mLocationCellMap[indices[i-1]];
00357 assert(p_current_cell);
00358
00359 MoveCell(p_current_cell, indices[i]);
00360 }
00361
00362
00363 MoveCell(p_created_cell, parent_index+direction_index);
00364
00365
00366 free_neighbour_was_found = true;
00367 break;
00368 }
00369 }
00370
00371
00372 if (!free_neighbour_was_found)
00373 {
00374 EXCEPTION("Cell can not divide as there are no free neighbours at maximum degree in any direction.");
00375 }
00376
00377 return p_created_cell;
00378 }
00379
00380 template<unsigned DIM>
00381 void CaBasedCellPopulation<DIM>::WriteVtkResultsToFile()
00382 {
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458 }
00459
00460 template<unsigned DIM>
00461 std::vector<unsigned> CaBasedCellPopulation<DIM>::GetMaximumDegreeInEachDirection(unsigned nodeIndex)
00462 {
00463 double width = this->mrMesh.GetWidth(0);
00464 unsigned nodes_across = (unsigned)width + 1;
00465 double height = this->mrMesh.GetWidth(1);
00466 unsigned nodes_up = (unsigned)height + 1;
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476 unsigned degrees_south = nodeIndex/nodes_up;
00477 unsigned degrees_north = nodes_up - degrees_south - 1;
00478 unsigned degrees_west = (nodeIndex < nodes_across) ? nodeIndex : nodeIndex%nodes_across;
00479 unsigned degrees_east = nodes_across - degrees_west - 1;
00480
00481 std::vector<unsigned> degrees(8);
00482 degrees[0] = degrees_north;
00483 degrees[1] = std::min(degrees_north, degrees_west);
00484 degrees[2] = degrees_west;
00485 degrees[3] = std::min(degrees_south, degrees_west);
00486 degrees[4] = degrees_south;
00487 degrees[5] = std::min(degrees_south, degrees_east);
00488 degrees[6] = degrees_east;
00489 degrees[7] = std::min(degrees_north, degrees_east);
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 std::vector<unsigned> non_zero_degrees_in_each_direction;
00500 for (unsigned i=0; i<8; i++)
00501 {
00502 if (degrees[i] > 0)
00503 {
00504 non_zero_degrees_in_each_direction.push_back(degrees[i]);
00505 }
00506 }
00507
00508 return non_zero_degrees_in_each_direction;
00509 }
00510
00511 template<unsigned DIM>
00512 std::set<unsigned> CaBasedCellPopulation<DIM>::GetNthDegreeNeighbouringNodeIndices(unsigned nodeIndex, unsigned degree)
00513 {
00514 std::set<unsigned> nth_degree_neighbours;
00515 std::vector<unsigned> nearest_neighbours = this->GetNeighbouringNodeIndicesVector(nodeIndex);
00516
00517 int next_neighbour;
00518
00519 std::vector<unsigned> max_degrees = GetMaximumDegreeInEachDirection(nodeIndex);
00520
00521
00522 unsigned current_node;
00523
00524 for (unsigned i=0; i<nearest_neighbours.size(); i++)
00525 {
00526 current_node = nearest_neighbours[i];
00527
00528
00529 if (degree <= max_degrees[i])
00530 {
00531 next_neighbour = (int) nodeIndex + (int) degree * ((int) current_node - (int) nodeIndex);
00532 nth_degree_neighbours.insert(next_neighbour);
00533 }
00534 }
00535 return nth_degree_neighbours;
00536 }
00537
00538 template<unsigned DIM>
00539 std::set<unsigned> CaBasedCellPopulation<DIM>::GetFreeNeighbouringNodeIndices(unsigned nodeIndex)
00540 {
00541 std::set<unsigned> free_neighbouring_nodes;
00542
00543
00544 std::set<unsigned> all_neighbours = GetNeighbouringNodeIndices(nodeIndex);
00545
00546
00547 for (std::set<unsigned>::iterator neighbour_iter = all_neighbours.begin();
00548 neighbour_iter != all_neighbours.end();
00549 ++neighbour_iter)
00550 {
00551 if (IsEmptySite(*neighbour_iter))
00552 {
00553 free_neighbouring_nodes.insert(*neighbour_iter);
00554 }
00555 }
00556 return free_neighbouring_nodes;
00557 }
00558
00559 template<unsigned DIM>
00560 std::set<unsigned> CaBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned nodeIndex)
00561 {
00562
00563 std::vector<unsigned> neighbouring_node_indices_vector = GetNeighbouringNodeIndicesVector(nodeIndex);
00564
00565
00566 std::set<unsigned> all_neighbours;
00567 for (unsigned i=0; i<neighbouring_node_indices_vector.size(); i++)
00568 {
00569 all_neighbours.insert(neighbouring_node_indices_vector[i]);
00570 }
00571
00572 return all_neighbours;
00573 }
00574
00575 template<unsigned DIM>
00576 std::vector<unsigned> CaBasedCellPopulation<DIM>::GetNeighbouringNodeIndicesVector(unsigned nodeIndex)
00577 {
00578 std::vector<unsigned> all_neighbours;
00579
00580 switch (DIM)
00581 {
00582 case 1:
00583 {
00584 double width = this->mrMesh.GetWidth(0);
00585 unsigned nodes_across = (unsigned)width + 1;
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595 std::vector<unsigned> neighbour_indices(2, nodeIndex);
00596 neighbour_indices[0] -= 1;
00597 neighbour_indices[1] += 1;
00598
00599
00600 bool on_west_edge = (nodeIndex == 0);
00601 bool on_east_edge = (nodeIndex == nodes_across-1);
00602
00603
00604 std::vector<bool> available_neighbours = std::vector<bool>(8, true);
00605 available_neighbours[0] = !on_west_edge;
00606 available_neighbours[1] = !on_east_edge;
00607
00608
00609 for (unsigned i=0; i<2; i++)
00610 {
00611 if (available_neighbours[i])
00612 {
00613 all_neighbours.push_back(neighbour_indices[i]);
00614 }
00615 }
00616 break;
00617 }
00618 case 2:
00619 {
00620 double width = this->mrMesh.GetWidth(0);
00621 unsigned nodes_across = (unsigned)width + 1;
00622
00623 double height = this->mrMesh.GetWidth(1);
00624 unsigned nodes_up = (unsigned)height + 1;
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 std::vector<unsigned> neighbour_indices(8, nodeIndex);
00640 neighbour_indices[0] += nodes_across;
00641 neighbour_indices[1] += nodes_across - 1;
00642 neighbour_indices[2] -= 1;
00643 neighbour_indices[3] -= nodes_across + 1;
00644 neighbour_indices[4] -= nodes_across;
00645 neighbour_indices[5] -= nodes_across - 1;
00646 neighbour_indices[6] += 1;
00647 neighbour_indices[7] += nodes_across + 1;
00648
00649
00650 bool on_south_edge = (nodeIndex < nodes_across);
00651 bool on_north_edge = (nodeIndex > nodes_up*(nodes_across - 1)-1);
00652 bool on_west_edge = (nodeIndex%nodes_across == 0);
00653 bool on_east_edge = (nodeIndex%nodes_across == nodes_across - 1);
00654
00655
00656
00657 std::vector<bool> available_neighbours = std::vector<bool>(8, true);
00658 available_neighbours[0] = !on_north_edge;
00659 available_neighbours[1] = !(on_north_edge || on_west_edge || mUseVonNeumannNeighbourhoods);
00660 available_neighbours[2] = !on_west_edge;
00661 available_neighbours[3] = !(on_south_edge || on_west_edge || mUseVonNeumannNeighbourhoods);
00662 available_neighbours[4] = !on_south_edge;
00663 available_neighbours[5] = !(on_south_edge || on_east_edge || mUseVonNeumannNeighbourhoods);
00664 available_neighbours[6] = !on_east_edge;
00665 available_neighbours[7] = !(on_north_edge || on_east_edge || mUseVonNeumannNeighbourhoods);
00666
00667
00668 for (unsigned i=0; i<8; i++)
00669 {
00670 if (available_neighbours[i])
00671 {
00672 all_neighbours.push_back(neighbour_indices[i]);
00673 }
00674 }
00675 break;
00676 }
00677 case 3:
00678 {
00679 double width = this->mrMesh.GetWidth(0);
00680 unsigned nodes_across = (unsigned)width + 1;
00681
00682 double height = this->mrMesh.GetWidth(1);
00683 unsigned nodes_up = (unsigned)height + 1;
00684
00685 double depth = this->mrMesh.GetWidth(2);
00686 unsigned nodes_deep = (unsigned)depth + 1;
00687
00688 unsigned nodes_layer = nodes_across*nodes_up;
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 std::vector<unsigned> neighbour_indices(26, nodeIndex);
00705 for (unsigned i=0; i<9; i++)
00706 {
00707 neighbour_indices[i] -= nodes_layer;
00708 neighbour_indices[25-i] += nodes_layer;
00709 }
00710 for (unsigned i=0; i<3; i++)
00711 {
00712 neighbour_indices[i] -= nodes_across;
00713 neighbour_indices[9+i] -= nodes_across;
00714 neighbour_indices[17+i] -= nodes_across;
00715 neighbour_indices[6+i] += nodes_across;
00716 neighbour_indices[14+i] += nodes_across;
00717 neighbour_indices[23+i] += nodes_across;
00718 }
00719 for (unsigned i=0; i<4; i++)
00720 {
00721 neighbour_indices[3*i] -= 1;
00722 neighbour_indices[25-3*i] += 1;
00723 neighbour_indices[2+3*i] += 1;
00724 neighbour_indices[23-3*i] -= 1;
00725 }
00726 neighbour_indices[12] -= 1;
00727 neighbour_indices[13] += 1;
00728
00729
00730 bool on_bottom_face = (nodeIndex < nodes_layer);
00731 bool on_top_face = (nodeIndex > (nodes_deep-1)*nodes_layer-1);
00732 bool on_south_face = (nodeIndex%nodes_layer < nodes_across);
00733 bool on_north_face = (nodeIndex%nodes_layer > nodes_across*(nodes_up-1)-1);
00734 bool on_west_face = (nodeIndex%nodes_across == 0);
00735 bool on_east_face = (nodeIndex%nodes_across == nodes_across - 1);
00736
00737
00738 std::vector<bool> available_neighbours = std::vector<bool>(26, true);
00739 available_neighbours[0] = !(on_bottom_face || on_west_face || on_south_face || mUseVonNeumannNeighbourhoods);
00740 available_neighbours[1] = !(on_bottom_face || on_south_face || mUseVonNeumannNeighbourhoods);
00741 available_neighbours[2] = !(on_bottom_face || on_east_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00742 available_neighbours[3] = !(on_bottom_face || on_west_face|| mUseVonNeumannNeighbourhoods);
00743 available_neighbours[4] = !on_bottom_face;
00744 available_neighbours[5] = !(on_bottom_face || on_east_face|| mUseVonNeumannNeighbourhoods);
00745 available_neighbours[6] = !(on_bottom_face || on_west_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00746 available_neighbours[7] = !(on_bottom_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00747 available_neighbours[8] = !(on_bottom_face || on_east_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00748 available_neighbours[9] = !(on_west_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00749 available_neighbours[10] = !on_south_face;
00750 available_neighbours[11] = !(on_east_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00751 available_neighbours[12] = !on_west_face;
00752 available_neighbours[13] = !on_east_face;
00753 available_neighbours[14] = !(on_west_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00754 available_neighbours[15] = !on_north_face;
00755 available_neighbours[16] = !(on_east_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00756 available_neighbours[17] = !(on_top_face || on_west_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00757 available_neighbours[18] = !(on_top_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00758 available_neighbours[19] = !(on_top_face || on_east_face || on_south_face|| mUseVonNeumannNeighbourhoods);
00759 available_neighbours[20] = !(on_top_face || on_west_face|| mUseVonNeumannNeighbourhoods);
00760 available_neighbours[21] = !on_top_face;
00761 available_neighbours[22] = !(on_top_face || on_east_face|| mUseVonNeumannNeighbourhoods);
00762 available_neighbours[23] = !(on_top_face || on_west_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00763 available_neighbours[24] = !(on_top_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00764 available_neighbours[25] = !(on_top_face || on_east_face || on_north_face|| mUseVonNeumannNeighbourhoods);
00765
00766
00767 for (unsigned i=0; i<26; i++)
00768 {
00769 if (available_neighbours[i])
00770 {
00771 all_neighbours.push_back(neighbour_indices[i]);
00772 }
00773 }
00774 break;
00775 }
00776 default:
00777 NEVER_REACHED;
00778 }
00779 return all_neighbours;
00780 }
00781
00782 template<unsigned DIM>
00783 unsigned CaBasedCellPopulation<DIM>::RemoveDeadCells()
00784 {
00785 unsigned num_removed = 0;
00786
00787 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00788 cell_iter != this->mCells.end();
00789 ++cell_iter)
00790 {
00791 if ((*cell_iter)->IsDead())
00792 {
00793
00794 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00795
00796
00797 mIsEmptySite[node_index] = true;
00798 this->mCellLocationMap.erase((*cell_iter).get());
00799 this->mLocationCellMap.erase(node_index);
00800
00801
00802 num_removed++;
00803 cell_iter = this->mCells.erase(cell_iter);
00804 --cell_iter;
00805 }
00806 }
00807 return num_removed;
00808 }
00809
00810 template<unsigned DIM>
00811 void CaBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00812 {
00813 Validate();
00814 }
00815
00816 template<unsigned DIM>
00817 void CaBasedCellPopulation<DIM>::Validate()
00818 {
00819
00820 std::vector<bool> validated_node = mIsEmptySite;
00821
00822 assert(mIsEmptySite.size() == this->GetNumNodes());
00823
00824
00825 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00826 cell_iter != this->End();
00827 ++cell_iter)
00828 {
00829 unsigned node_index = this->mCellLocationMap[(*cell_iter).get()];
00830
00831
00832 if (mIsEmptySite[node_index])
00833 {
00834 EXCEPTION("Node " << node_index << " is labelled as an empty site and has a cell attached");
00835 }
00836 validated_node[node_index] = true;
00837 }
00838
00839 for (unsigned i=0; i<validated_node.size(); i++)
00840 {
00841 if (!validated_node[i])
00842 {
00843 EXCEPTION("Node " << i << " does not appear to be an empty site or have a cell associated with it");
00844 }
00845 }
00846 }
00847
00848 template<unsigned DIM>
00849 void CaBasedCellPopulation<DIM>::WriteCellVolumeResultsToFile()
00850 {
00851
00852 *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00853
00854
00855 double cell_volume = 1.0;
00856
00857
00858 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin();
00859 cell_iter!=this->End(); ++cell_iter)
00860 {
00861
00862 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00863 *(this->mpCellVolumesFile) << node_index << " ";
00864
00865
00866 unsigned cell_index = cell_iter->GetCellId();
00867 *(this->mpCellVolumesFile) << cell_index << " ";
00868
00869
00870 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00871 for (unsigned i=0; i<DIM; i++)
00872 {
00873 *(this->mpCellVolumesFile) << node_location[i] << " ";
00874 }
00875
00876
00877 *(this->mpCellVolumesFile) << cell_volume << " ";
00878 }
00879 *(this->mpCellVolumesFile) << "\n";
00880 }
00881
00882 template<unsigned DIM>
00883 void CaBasedCellPopulation<DIM>::GenerateCellResults(unsigned locationIndex,
00884 std::vector<unsigned>& rCellProliferativeTypeCounter,
00885 std::vector<unsigned>& rCellCyclePhaseCounter)
00886 {
00887 if (IsEmptySite(locationIndex) == true)
00888 {
00889 *(this->mpVizCellProliferativeTypesFile) << INVISIBLE_COLOUR << " ";
00890 }
00891 else
00892 {
00893 AbstractCellPopulation<DIM>::GenerateCellResults(locationIndex,
00894 rCellProliferativeTypeCounter,
00895 rCellCyclePhaseCounter);
00896 }
00897 }
00898
00899 template<unsigned DIM>
00900 void CaBasedCellPopulation<DIM>::GenerateCellResultsAndWriteToFiles()
00901 {
00902
00903 unsigned num_cell_types = this->mCellProliferativeTypeCount.size();
00904 std::vector<unsigned> cell_type_counter(num_cell_types);
00905 for (unsigned i=0; i<num_cell_types; i++)
00906 {
00907 cell_type_counter[i] = 0;
00908 }
00909
00910
00911 unsigned num_cell_cycle_phases = this->mCellCyclePhaseCount.size();
00912 std::vector<unsigned> cell_cycle_phase_counter(num_cell_cycle_phases);
00913 for (unsigned i=0; i<num_cell_cycle_phases; i++)
00914 {
00915 cell_cycle_phase_counter[i] = 0;
00916 }
00917
00918
00919 for (unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
00920 {
00922
00923
00924 if (!(this->GetNode(node_index)->IsDeleted()))
00925 {
00926 this->GenerateCellResults(node_index, cell_type_counter, cell_cycle_phase_counter);
00927 }
00928 }
00929
00930 this->WriteCellResultsToFiles(cell_type_counter, cell_cycle_phase_counter);
00931 }
00932
00933 template<unsigned DIM>
00934 bool CaBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00935 {
00936 return false;
00937 }
00938
00939 template<unsigned DIM>
00940 void CaBasedCellPopulation<DIM>::MoveCell(CellPtr pCell, unsigned newLocationIndex)
00941 {
00942
00943 unsigned current_location_index = this->mCellLocationMap[pCell.get()];
00944
00945 if (current_location_index != newLocationIndex)
00946 {
00947
00948 assert(IsEmptySite(newLocationIndex));
00949
00950
00951 mIsEmptySite[newLocationIndex] = false;
00952 this->mLocationCellMap[newLocationIndex] = pCell;
00953
00954
00955 this->mCellLocationMap[pCell.get()] = newLocationIndex;
00956
00957
00958 if (current_location_index != UINT_MAX)
00959 {
00960
00961 this->mLocationCellMap.erase(current_location_index);
00962 mIsEmptySite[current_location_index] = true;
00963 }
00964 }
00965 }
00966
00967 template<unsigned DIM>
00968 c_vector<double, DIM> CaBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00969 {
00970 unsigned node_index = this->mCellLocationMap[pCell.get()];
00971 c_vector<double, DIM> node_location = this->GetNode(node_index)->rGetLocation();
00972 return node_location;
00973 }
00974
00975 template<unsigned DIM>
00976 void CaBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00977 {
00978 *rParamsFile << "\t\t<OnlyUseNearestNeighboursForDivision>" << mOnlyUseNearestNeighboursForDivision << "</OnlyUseNearestNeighboursForDivision>\n";
00979 *rParamsFile << "\t\t<UseVonNeumannNeighbourhoods>" << mUseVonNeumannNeighbourhoods << "</UseVonNeumannNeighbourhoods>\n";
00980
00981
00982 AbstractCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00983 }
00984
00985 template<unsigned DIM>
00986 double CaBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00987 {
00988
00989 double width = mrMesh.GetWidth(rDimension);
00990
00991 return width;
00992 }
00993
00995
00997
00998 template class CaBasedCellPopulation<1>;
00999 template class CaBasedCellPopulation<2>;
01000 template class CaBasedCellPopulation<3>;
01001
01002
01003 #include "SerializationExportWrapperForCpp.hpp"
01004 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CaBasedCellPopulation)