CaBasedCellPopulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 
00029 #include <cassert>
00030 #include <algorithm>
00031 
00032 #include "CaBasedCellPopulation.hpp"
00033 #include "RandomNumberGenerator.hpp"
00034 
00035 // Needed to convert mesh in order to write nodes to VTK (visualize as glyphs)
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     // This must always be true
00052     assert(this->mCells.size() <= mrMesh.GetNumNodes());
00053 
00054     if (!locationIndices.empty())
00055     {
00056         // Create a set of node indices corresponding to empty sites
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         // This method finishes and then calls Validate()
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     // Iterate over contributions from each UpdateRule
00106     if (this->mIterateRandomlyOverUpdateRuleCollection)
00107     {
00108         // Randomly permute mUpdateRuleCollection
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         // Randomly permute cells
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                 // Get index of the node associated with cell
00133                 unsigned current_location_index = this->GetLocationIndexUsingCell(cells_vector[i]);
00134 
00135                 assert(!this->IsEmptySite(current_location_index));
00136 
00137                 // Get index of node the cell is to move to
00138                 unsigned new_location_index = (*update_iter)->GetNewLocationOfCell(current_location_index, *this, dt);
00139 
00140                 // Update the location index of the cell and free the old site
00141                 this->MoveCell(cells_vector[i], new_location_index);
00142             }
00143         }
00144         else
00145         {
00146             // Iterate over all cells and update their positions
00147             for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00148                  cell_iter != this->End();
00149                  ++cell_iter)
00150             {
00151                 // Get index of the node associated with cell
00152                 unsigned current_location_index = this->GetLocationIndexUsingCell(*cell_iter);
00153 
00154                 assert(!this->IsEmptySite(current_location_index));
00155 
00156                 // Get index of node the cell is to move to
00157                 unsigned new_location_index = (*update_iter)->GetNewLocationOfCell(current_location_index, *this, dt);
00158 
00159                 // Update the location index of the cell and free the old site
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     // Reinitialise all entries of mIsEmptySite to false
00232     mIsEmptySite = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00233 
00234     // Update mIsEmptySite
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      * In the case of a CaBasedCellPopulation, we must provided a parent cell when calling AddCell().
00274      * This is because the location of the parent cell is used as a starting point in the search
00275      * among neighbours for an empty site in which to locate the new cell. Therefore, if no parent
00276      * cell is provided, we throw the following exception.
00277      */
00278     if (pParentCell == CellPtr())
00279     {
00280         EXCEPTION("A parent cell must be provided when calling AddCell() on a CaBasedCellPopulation.");
00281     }
00282 
00284 
00285     // Add rNewCell to mCells
00286     this->mCells.push_back(pNewCell);
00287     CellPtr p_created_cell = this->mCells.back();
00288 
00289     // Temporarily provide a location index for the new cell
00290     this->mCellLocationMap[p_created_cell.get()] = UINT_MAX;
00291 
00292     // Get the location index corresponding to the parent cell
00293     unsigned parent_index = this->mCellLocationMap[pParentCell.get()];
00294 
00295     unsigned degree_upper_bound;         // Maximum degree which to explore to
00296 
00297     if (mOnlyUseNearestNeighboursForDivision)
00298     {
00299         degree_upper_bound = 1;
00300     }
00301     else
00302     {
00303         // Get the maximum neighbour degree of this location index in each direction
00304         std::vector<unsigned> maximum_degrees = GetMaximumDegreeInEachDirection(parent_index);
00305 
00306         // Find the largest maximum degree, giving an upper bound on our search for a free location index for the new cell
00307         degree_upper_bound = *(std::max_element(maximum_degrees.begin(), maximum_degrees.end()));
00308     }
00309 
00310     bool free_neighbour_was_found = false;
00311 
00312     // Loop over increasing neighbour degrees
00313     for (unsigned degree=1; degree<=degree_upper_bound; degree++)
00314     {
00315         // Get the set of nth degree neighbour indices
00316         std::set<unsigned> nth_degree_neighbours = GetNthDegreeNeighbouringNodeIndices(parent_index, degree);
00317 
00318         // Now find which (if any) of these neighbours are free (i.e. empty sites)
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         // If there are any free neighbours at this degree...
00331         if (!free_nth_degree_neighbours.empty())
00332         {
00333             // ... then choose a free neighbour at random
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             // Compute the direction from the parent cell to the chosen free nth degree neighbour
00346             int direction_index = ((int)chosen_free_neighbour_index - (int)parent_index)/(int)degree;
00347 
00348             // Move each cell between the parent cell and the chosen free nth degree neighbour
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             // This creates a free nearest neighbour of the parent cell, which we associate with the new cell
00363             MoveCell(p_created_cell, parent_index+direction_index);
00364 
00365             // Break out of the loop
00366             free_neighbour_was_found = true;
00367             break;
00368         }
00369     }
00370 
00371     // If no free neighbour was found, throw an exception
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 //#ifdef CHASTE_VTK
00385 //    std::stringstream time;
00386 //    time << SimulationTime::Instance()->GetTimeStepsElapsed();
00387 //    VtkMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results_"+time.str(), false);
00388 //
00389 //    unsigned num_nodes = GetNumNodes();
00390 //    std::vector<double> cell_types;
00391 //    std::vector<double> cell_mutation_states;
00392 //    std::vector<double> cell_labels;
00393 //    cell_types.reserve(num_nodes);
00394 //    cell_mutation_states.reserve(num_nodes);
00395 //    cell_labels.reserve(num_nodes);
00396 //
00397 //    for (unsigned node_index=0; node_index<num_nodes; node_index++)
00398 //    {
00399 //        if (node_index)
00400 //        {
00401 //            // No cell is associated with this node
00402 //            cell_types.push_back(-1.0);
00403 //            if (this->mOutputCellMutationStates)
00404 //            {
00405 //                cell_mutation_states.push_back(-1.0);
00406 //                cell_labels.push_back(-1.0);
00407 //            }
00408 //        }
00409 //        else
00410 //        {
00411 //            CellPtr p_cell = this->mLocationCellMap[node_index];
00412 //            double cell_type = p_cell->GetCellCycleModel()->GetCellProliferativeType();
00413 //            cell_types.push_back(cell_type);
00414 //
00415 //            if (this->mOutputCellMutationStates)
00416 //            {
00417 //                double cell_mutation_state = p_cell->GetMutationState()->GetColour();
00418 //                cell_mutation_states.push_back(cell_mutation_state);
00419 //
00420 //                double cell_label = 0.0;
00421 //                if (p_cell->HasCellProperty<CellLabel>())
00422 //                {
00423 //                    CellPropertyCollection collection = p_cell->rGetCellPropertyCollection().GetProperties<CellLabel>();
00424 //                    boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(collection.GetProperty());
00425 //                    cell_label = p_label->GetColour();
00426 //                }
00427 //                cell_labels.push_back(cell_label);
00428 //            }
00429 //        }
00430 //    }
00431 //
00432 //    assert(cell_types.size() == num_nodes);
00433 //
00434 //    mesh_writer.AddPointData("Cell types", cell_types);
00435 //
00436 //    if (this->mOutputCellMutationStates)
00437 //    {
00438 //        assert(cell_mutation_states.size() == num_nodes);
00439 //        mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00440 //        assert(cell_labels.size() == num_nodes);
00441 //        mesh_writer.AddPointData("Cell labels", cell_labels);
00442 //    }
00443 //
00444 //    /*
00445 //     * The current VTK writer can only write things which inherit from AbstractTetrahedralMeshWriter.
00446 //     * For now, we do an explicit conversion to NodesOnlyMesh. This can be written to VTK then visualized as glyphs.
00447 //     */
00448 //    NodesOnlyMesh<DIM> temp_mesh;
00449 //    temp_mesh.ConstructNodesWithoutMesh(mrMesh);
00450 //    mesh_writer.WriteFilesUsingMesh(temp_mesh);
00451 //
00452 //    *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00453 //    *(this->mpVtkMetaFile) << time.str();
00454 //    *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00455 //    *(this->mpVtkMetaFile) << time.str();
00456 //    *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00457 //#endif //CHASTE_VTK
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      * Create a temporary vector to store the degrees in each direction,
00470      * some of which may be zero (if the node is on the boundary). We
00471      * take care to use the same ordering as is used in the method
00472      * GetNeighbouringNodeIndicesVector(), namely N, NW, W, SW, S, SE,
00473      * E, NE.
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; // N
00483     degrees[1] = std::min(degrees_north, degrees_west); // NW
00484     degrees[2] = degrees_west; // W
00485     degrees[3] = std::min(degrees_south, degrees_west); // SW
00486     degrees[4] = degrees_south; // S
00487     degrees[5] = std::min(degrees_south, degrees_east); // SE
00488     degrees[6] = degrees_east; // E
00489     degrees[7] = std::min(degrees_north, degrees_east); // NE
00490 
00491     /*
00492      * Now use this vector to populate another vector, which stores
00493      * only the non-zero degrees (we need to do this because this
00494      * method is used alongside GetNeighbouringNodeIndicesVector()
00495      * in the method GetNthDegreeNeighbouringNodeIndices(), so should
00496      * be the same length.
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     // Loop over all directions
00522     unsigned current_node;
00523 
00524     for (unsigned i=0; i<nearest_neighbours.size(); i++)
00525     {
00526         current_node = nearest_neighbours[i];
00527 
00528         // Find the n-th degree next nearest neighbour in the current direction
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     // Get all neighbouring node indices
00544     std::set<unsigned> all_neighbours = GetNeighbouringNodeIndices(nodeIndex);
00545 
00546     // Now find which neighbours are free (i.e. empty sites)
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     // Get the neighbouring node indices as a vector
00563     std::vector<unsigned> neighbouring_node_indices_vector = GetNeighbouringNodeIndicesVector(nodeIndex);
00564 
00565     // Now populate a std::set with these node indices
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; // Getting the number of nodes along x axis of mesh
00586 
00587             /*
00588              * This stores the available neighbours using the following numbering:
00589              *
00590              * 0------x------1
00591              *
00592              */
00593 
00594             // Create a vector of possible neighbouring node indices
00595             std::vector<unsigned> neighbour_indices(2, nodeIndex);
00596             neighbour_indices[0] -= 1;
00597             neighbour_indices[1] += 1;
00598 
00599             // Work out whether this node lies on any edge of the mesh
00600             bool on_west_edge = (nodeIndex == 0);
00601             bool on_east_edge = (nodeIndex == nodes_across-1);
00602 
00603             // Create a vector of booleans for which neighbours are available
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             // Using neighbour_indices and available_neighbours, store the indices of all available neighbours to the set all_neighbours
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; // Getting the number of nodes along x axis of mesh
00622 
00623             double height = this->mrMesh.GetWidth(1);
00624             unsigned nodes_up = (unsigned)height + 1;
00625 
00626             /*
00627              * This stores the available neighbours using the following numbering:
00628              *
00629              *  1-----0-----7
00630              *  |     |     |
00631              *  |     |     |
00632              *  2-----x-----6
00633              *  |     |     |
00634              *  |     |     |
00635              *  3-----4-----5
00636              */
00637 
00638             // Create a vector of possible neighbouring node indices
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             // Work out whether this node lies on any edge of the mesh
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             // Create a vector of booleans for which neighbours are available
00656             // Use the order N, NW, W, SW, S, SE, E, NE
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             // Using neighbour_indices and available_neighbours, store the indices of all available neighbours to the set all_neighbours
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; // Getting the number of nodes along x axis of mesh
00681 
00682             double height = this->mrMesh.GetWidth(1);
00683             unsigned nodes_up = (unsigned)height + 1; // Getting the number of nodes along y axis of mesh
00684 
00685             double depth = this->mrMesh.GetWidth(2);
00686             unsigned nodes_deep = (unsigned)depth + 1; // Getting the number of nodes along z axis of mesh
00687 
00688             unsigned nodes_layer = nodes_across*nodes_up; // Number of nodes in each layer
00689 
00690             /*
00691              * This stores the available neighbours using the following numbering:
00692              *
00693              *     6------7------8           14-----15-----16            23-----24-----25
00694              *     |      |      |           |      |      |             |      |      |
00695              *     |      |      |           |      |      |             |      |      |
00696              *     3------4------5           12-----x------13            20-----21-----22
00697              *     |      |      |           |      |      |             |      |      |
00698              *     |      |      |           |      |      |             |      |      |
00699              *     0------1------2           9------10-----11            17-----18-----19
00700              *
00701              */
00702 
00703             // Create a vector of possible neighbouring node indices
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             // Work out whether this node lies on any face of the mesh
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             // Create a vector of booleans for which neighbours are available
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             // Using neighbour_indices and available_neighbours, store the indices of all available neighbours to the set all_neighbours
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             // Get the index of the node corresponding to this cell
00794             unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00795 
00796             // Set this node to be an empty site
00797             mIsEmptySite[node_index] = true;
00798             this->mCellLocationMap.erase((*cell_iter).get());
00799             this->mLocationCellMap.erase(node_index);
00800 
00801             // Erase cell and update counter
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     // Get a list of all the sites that are empty
00820     std::vector<bool> validated_node = mIsEmptySite;
00821 
00822     assert(mIsEmptySite.size() == this->GetNumNodes());
00823 
00824     // Look through all of the cells and record what node they are associated with
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         // If the node attached to this cell is labelled as an empty site, then throw an error
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     // Write time to file
00852     *(this->mpCellVolumesFile) << SimulationTime::Instance()->GetTime() << " ";
00853 
00854     // Cell volumes all one (equal-sized lattice sites)
00855     double cell_volume = 1.0;
00856 
00857     // Loop over cells
00858     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin();
00859          cell_iter!=this->End(); ++cell_iter)
00860     {
00861         // Get the index of the corresponding node in mrMesh and write to file
00862         unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00863         *(this->mpCellVolumesFile) << node_index << " ";
00864 
00865         // Get cell ID and write to file
00866         unsigned cell_index = cell_iter->GetCellId();
00867         *(this->mpCellVolumesFile) << cell_index << " ";
00868 
00869         // Get node location and write to file
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         // Write cell volume (in 3D) or area (in 2D) to file
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     // Set up cell type counter
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     // Set up cell cycle phase counter
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     // Write cell data to file
00919     for (unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
00920     {
00922 
00923         // Write cell data to file
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     // Get the current location index corresponding to this cell
00943     unsigned current_location_index = this->mCellLocationMap[pCell.get()];
00944 
00945     if (current_location_index != newLocationIndex)
00946     {
00947         // The new location index must not already correspond to a cell
00948         assert(IsEmptySite(newLocationIndex));
00949 
00950         // Update the new location index to correspond to this cell
00951         mIsEmptySite[newLocationIndex] = false;
00952         this->mLocationCellMap[newLocationIndex] = pCell;
00953 
00954         // Update this cell to correspond to the new location index
00955         this->mCellLocationMap[pCell.get()] = newLocationIndex;
00956 
00957         // If this cell is not a new cell...
00958         if (current_location_index != UINT_MAX)
00959         {
00960             // ...update the current location index to correspond to an empty site
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     // Call method on direct parent class
00982     AbstractCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00983 }
00984 
00985 template<unsigned DIM>
00986 double CaBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00987 {
00988     // Call GetWidth() on the mesh
00989     double width = mrMesh.GetWidth(rDimension);
00990 
00991     return width;
00992 }
00993 
00995 // Explicit instantiation
00997 
00998 template class CaBasedCellPopulation<1>;
00999 template class CaBasedCellPopulation<2>;
01000 template class CaBasedCellPopulation<3>;
01001 
01002 // Serialization for Boost >= 1.36
01003 #include "SerializationExportWrapperForCpp.hpp"
01004 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CaBasedCellPopulation)
Generated on Thu Dec 22 13:00:04 2011 for Chaste by  doxygen 1.6.3