NodeBasedCellPopulation.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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 #include "NodeBasedCellPopulation.hpp"
00029 
00030 template<unsigned DIM>
00031 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const std::vector<Node<DIM>* > nodes,
00032                                       std::vector<CellPtr>& rCells,
00033                                       const std::vector<unsigned> locationIndices,
00034                                       bool deleteNodes)
00035     : AbstractCentreBasedCellPopulation<DIM>(rCells, locationIndices),
00036       mNodes(nodes.begin(), nodes.end()),
00037       mAddedNodes(true),
00038       mpBoxCollection(NULL),
00039       mDeleteNodes(deleteNodes),
00040       mMechanicsCutOffLength(DBL_MAX)
00041 {
00042     Validate();
00043 }
00044 
00045 // archiving constructor
00046 template<unsigned DIM>
00047 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const std::vector<Node<DIM>* > nodes, double mechanicsCutOffLength, bool deleteNodes)
00048     : AbstractCentreBasedCellPopulation<DIM>(),
00049       mNodes(nodes.begin(), nodes.end()),
00050       mAddedNodes(true),
00051       mpBoxCollection(NULL),
00052       mDeleteNodes(deleteNodes),
00053       mMechanicsCutOffLength(mechanicsCutOffLength)
00054 {
00055     // No Validate() because the cells are not associated with the cell population yet in archiving
00056 }
00057 
00058 template<unsigned DIM>
00059 NodeBasedCellPopulation<DIM>::NodeBasedCellPopulation(const AbstractMesh<DIM,DIM>& rMesh,
00060                                       std::vector<CellPtr>& rCells)
00061     : AbstractCentreBasedCellPopulation<DIM>(rCells),
00062       mAddedNodes(false),
00063       mpBoxCollection(NULL),
00064       mDeleteNodes(true),
00065       mMechanicsCutOffLength(DBL_MAX)
00066 {
00067     unsigned num_nodes = rMesh.GetNumNodes();
00068 
00069     mNodes.reserve(num_nodes);
00070     // Copy the actual node objects from mesh to this (mesh-less) cell population.
00071     for (unsigned i=0; i<num_nodes; i++)
00072     {
00073         Node<DIM>* p_node = new Node<DIM>(*(rMesh.GetNode(i)));
00074         mNodes.push_back(p_node);
00075     }
00076     mAddedNodes = true;
00077     Validate();
00078 }
00079 
00080 template<unsigned DIM>
00081 NodeBasedCellPopulation<DIM>::~NodeBasedCellPopulation()
00082 {
00083     Clear();
00084 
00085     // Free node memory
00086     if (mDeleteNodes)
00087     {
00088         for (unsigned i=0; i<mNodes.size(); i++)
00089         {
00090             delete mNodes[i];
00091         }
00092     }
00093 }
00094 
00095 template<unsigned DIM>
00096 void NodeBasedCellPopulation<DIM>::Clear()
00097 {
00098     delete mpBoxCollection;
00099     mpBoxCollection = NULL;
00100     mNodePairs.clear();
00101     mDeletedNodeIndices.clear();
00102     mAddedNodes = false;
00103 }
00104 
00105 template<unsigned DIM>
00106 void NodeBasedCellPopulation<DIM>::Validate()
00107 {
00108     std::vector<bool> validated_node(GetNumNodes());
00109     for (unsigned i=0; i<validated_node.size(); i++)
00110     {
00111         validated_node[i] = false;
00112     }
00113 
00114     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00115     {
00116         unsigned node_index = this->mCellLocationMap[(*cell_iter).get()];
00117         validated_node[node_index] = true;
00118     }
00119 
00120     for (unsigned i=0; i<validated_node.size(); i++)
00121     {
00122         if (!validated_node[i])
00123         {
00124             std::stringstream ss;
00125             ss << "Node " << i << " does not appear to have a cell associated with it";
00126             EXCEPTION(ss.str());
00127         }
00128     }
00129 }
00130 
00131 template<unsigned DIM>
00132 std::vector<Node<DIM>* >& NodeBasedCellPopulation<DIM>::rGetNodes()
00133 {
00134     return mNodes;
00135 }
00136 
00137 template<unsigned DIM>
00138 const std::vector<Node<DIM>* >& NodeBasedCellPopulation<DIM>::rGetNodes() const
00139 {
00140     return mNodes;
00141 }
00142 
00143 template<unsigned DIM>
00144 void NodeBasedCellPopulation<DIM>::SplitUpIntoBoxes(double cutOffLength, c_vector<double, 2*DIM> domainSize)
00145 {
00146     mpBoxCollection = new BoxCollection<DIM>(cutOffLength, domainSize);
00147     mpBoxCollection->SetupLocalBoxesHalfOnly();
00148 
00149     for (unsigned i=0; i<mNodes.size(); i++)
00150     {
00151         unsigned box_index = mpBoxCollection->CalculateContainingBox(mNodes[i]);
00152         mpBoxCollection->rGetBox(box_index).AddNode(mNodes[i]);
00153     }
00154 }
00155 
00156 template<unsigned DIM>
00157 void NodeBasedCellPopulation<DIM>::FindMaxAndMin()
00158 {
00159     c_vector<double, DIM> min_posn;
00160     c_vector<double, DIM> max_posn;
00161     for (unsigned i=0; i<DIM; i++)
00162     {
00163         min_posn(i) = DBL_MAX;
00164         max_posn(i) = -DBL_MAX;
00165     }
00166 
00167     for (unsigned i=0; i<mNodes.size(); i++)
00168     {
00169         c_vector<double, DIM> posn = this->GetNode(i)->rGetLocation();
00170 
00171         for (unsigned j=0; j<DIM; j++)
00172         {
00173             if (posn(j) > max_posn(j))
00174             {
00175                 max_posn(j) = posn(j);
00176             }
00177             if (posn(j) < min_posn(j))
00178             {
00179                 min_posn(j) = posn(j);
00180             }
00181         }
00182     }
00183 
00184     for (unsigned i=0; i<DIM; i++)
00185     {
00186         assert(min_posn(i) != DBL_MAX);
00187         mMinSpatialPositions(i) = min_posn(i);
00188 
00189         assert(max_posn(i) != -DBL_MAX);
00190         mMaxSpatialPositions(i) = max_posn(i);
00191     }
00192 }
00193 
00194 template<unsigned DIM>
00195 Node<DIM>* NodeBasedCellPopulation<DIM>::GetNode(unsigned index)
00196 {
00197     return mNodes[index];
00198 }
00199 
00200 template<unsigned DIM>
00201 void NodeBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00202 {
00203     mNodes[nodeIndex]->SetPoint(rNewLocation);
00204 }
00205 
00206 template<unsigned DIM>
00207 void NodeBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00208 {
00209     if (hasHadBirthsOrDeaths)
00210     {
00211         // Create and reserve space for a temporary vector
00212         std::vector<Node<DIM>*> old_nodes;
00213         old_nodes.reserve(mNodes.size());
00214 
00215         // Store all non-deleted nodes in the temporary vector
00216         for (unsigned i=0; i<mNodes.size(); i++)
00217         {
00218             if (!mNodes[i]->IsDeleted())
00219             {
00220                 old_nodes.push_back(mNodes[i]);
00221             }
00222             else
00223             {
00224                 // Free node memory
00225                 delete mNodes[i];
00226             }
00227         }
00228 
00229         std::map<unsigned,CellPtr> old_map = this->mLocationCellMap;
00230         mNodes.clear();
00231 
00232         // Clear maps
00233         this->mLocationCellMap.clear();
00234         this->mCellLocationMap.clear();
00235 
00236         // Update mNodes to new indices which go from 0 to NumNodes-1
00237         for (unsigned i=0; i<old_nodes.size(); i++)
00238         {
00239             // Get the living cell associated with the old node
00240             CellPtr p_live_cell = old_map[old_nodes[i]->GetIndex()];
00241 
00242             // Set the node up
00243             mNodes.push_back(old_nodes[i]);
00244             mNodes[i]->SetIndex(i);
00245 
00246             // Set the maps up
00247             this->mLocationCellMap[i] = p_live_cell;
00248             this->mCellLocationMap[p_live_cell.get()] = i;
00249         }
00250 
00251         // Remove current dead indices data
00252         Clear();
00253 
00254         Validate();
00255     }
00256 
00257     if (mpBoxCollection!=NULL)
00258     {
00259         delete mpBoxCollection;
00260     }
00261 
00262     FindMaxAndMin();
00263 
00264     // Something here to set up the domain size (max and min of each node position dimension)
00265     c_vector<double, 2*DIM> domain_size;
00266 
00267     for (unsigned i=0; i<DIM; i++)
00268     {
00269         domain_size(2*i) = mMinSpatialPositions(i);
00270         domain_size(2*i+1) = mMaxSpatialPositions(i);
00271     }
00272 
00273     if (mMechanicsCutOffLength == DBL_MAX)
00274     {
00275         std::string error =  std::string("NodeBasedCellPopulation cannot create boxes if the cut-off length has not been set - ")
00276                            + std::string("Call SetMechanicsCutOffLength on the CellPopulation ensuring it is larger than GetCutOffLength() on the force law");
00277         EXCEPTION(error);
00278     }
00279 
00280     // Add this parameter and suggest that mechanics systems set it.
00281     // Allocates memory for mpBoxCollection and does the splitting and putting nodes into boxes
00282     SplitUpIntoBoxes(mMechanicsCutOffLength, domain_size);
00283 
00284     mpBoxCollection->CalculateNodePairs(mNodes, mNodePairs);
00285 }
00286 
00287 template<unsigned DIM>
00288 unsigned NodeBasedCellPopulation<DIM>::RemoveDeadCells()
00289 {
00290     unsigned num_removed = 0;
00291 
00292     for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00293          cell_iter != this->mCells.end();
00294          ++cell_iter)
00295     {
00296         if ((*cell_iter)->IsDead())
00297         {
00298             // Remove the node
00299             num_removed++;
00300             this->GetNodeCorrespondingToCell(*cell_iter)->MarkAsDeleted();
00301             mDeletedNodeIndices.push_back(this->mCellLocationMap[(*cell_iter).get()]);
00302             cell_iter = this->mCells.erase(cell_iter);
00303             --cell_iter;
00304         }
00305     }
00306     return num_removed;
00307 }
00308 
00309 template<unsigned DIM>
00310 unsigned NodeBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00311 {
00312     if (mDeletedNodeIndices.empty())
00313     {
00314         pNewNode->SetIndex(mNodes.size());
00315         mNodes.push_back(pNewNode);
00316     }
00317     else
00318     {
00319         unsigned index = mDeletedNodeIndices.back();
00320         pNewNode->SetIndex(index);
00321         mDeletedNodeIndices.pop_back();
00322         delete mNodes[index];
00323         mNodes[index] = pNewNode;
00324     }
00325     mAddedNodes = true;
00326     return pNewNode->GetIndex();
00327 }
00328 
00329 template<unsigned DIM>
00330 unsigned NodeBasedCellPopulation<DIM>::GetNumNodes()
00331 {
00332     return mNodes.size() - mDeletedNodeIndices.size();
00333 }
00334 
00335 template<unsigned DIM>
00336 BoxCollection<DIM>* NodeBasedCellPopulation<DIM>::GetBoxCollection()
00337 {
00338     return mpBoxCollection;
00339 }
00340 
00341 template<unsigned DIM>
00342 std::set< std::pair<Node<DIM>*, Node<DIM>* > >& NodeBasedCellPopulation<DIM>::rGetNodePairs()
00343 {
00344     if (mNodePairs.empty())
00345     {
00346         EXCEPTION("No node pairs set up, rGetNodePairs probably called before Update");
00347     }
00348     return mNodePairs;
00349 }
00350 
00351 template<unsigned DIM>
00352 void NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00353 {
00354     *rParamsFile << "\t\t<MechanicsCutOffLength>"<< mMechanicsCutOffLength << "</MechanicsCutOffLength>\n";
00355 
00356     // Currently no specific parameters to output all come from parent classes
00357 
00358     // Call direct parent class method
00359     AbstractCentreBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00360 
00361 }
00362 
00363 template<unsigned DIM>
00364 void NodeBasedCellPopulation<DIM>::SetMechanicsCutOffLength(double mechanicsCutOffLength)
00365 {
00366     assert(mechanicsCutOffLength > 0.0);
00367     mMechanicsCutOffLength = mechanicsCutOffLength;
00368 }
00369 
00370 template<unsigned DIM>
00371 double NodeBasedCellPopulation<DIM>::GetMechanicsCutOffLength()
00372 {
00373     return mMechanicsCutOffLength;
00374 }
00375 
00376 template<unsigned DIM>
00377 double NodeBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00378 {
00379     // Update the member variables mMinSpatialPositions and mMaxSpatialPositions
00380     FindMaxAndMin();
00381 
00382     // Compute the maximum distance between any nodes in this dimension
00383     double width = mMaxSpatialPositions(rDimension) - mMinSpatialPositions(rDimension);
00384 
00385     return width;
00386 }
00387 
00389 // Explicit instantiation
00391 
00392 template class NodeBasedCellPopulation<1>;
00393 template class NodeBasedCellPopulation<2>;
00394 template class NodeBasedCellPopulation<3>;
00395 
00396 // Serialization for Boost >= 1.36
00397 #include "SerializationExportWrapperForCpp.hpp"
00398 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5