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 #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
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
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
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
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
00212 std::vector<Node<DIM>*> old_nodes;
00213 old_nodes.reserve(mNodes.size());
00214
00215
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
00225 delete mNodes[i];
00226 }
00227 }
00228
00229 std::map<unsigned,CellPtr> old_map = this->mLocationCellMap;
00230 mNodes.clear();
00231
00232
00233 this->mLocationCellMap.clear();
00234 this->mCellLocationMap.clear();
00235
00236
00237 for (unsigned i=0; i<old_nodes.size(); i++)
00238 {
00239
00240 CellPtr p_live_cell = old_map[old_nodes[i]->GetIndex()];
00241
00242
00243 mNodes.push_back(old_nodes[i]);
00244 mNodes[i]->SetIndex(i);
00245
00246
00247 this->mLocationCellMap[i] = p_live_cell;
00248 this->mCellLocationMap[p_live_cell.get()] = i;
00249 }
00250
00251
00252 Clear();
00253
00254 Validate();
00255 }
00256
00257 if (mpBoxCollection!=NULL)
00258 {
00259 delete mpBoxCollection;
00260 }
00261
00262 FindMaxAndMin();
00263
00264
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
00281
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
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
00357
00358
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
00380 FindMaxAndMin();
00381
00382
00383 double width = mMaxSpatialPositions(rDimension) - mMinSpatialPositions(rDimension);
00384
00385 return width;
00386 }
00387
00389
00391
00392 template class NodeBasedCellPopulation<1>;
00393 template class NodeBasedCellPopulation<2>;
00394 template class NodeBasedCellPopulation<3>;
00395
00396
00397 #include "SerializationExportWrapperForCpp.hpp"
00398 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulation)