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
00030
00031
00032
00033
00034
00035
00036 #include "MeshBasedCellPopulation.hpp"
00037 #include "TrianglesMeshWriter.hpp"
00038 #include "VtkMeshWriter.hpp"
00039 #include "CellBasedEventHandler.hpp"
00040 #include "ApoptoticCellProperty.hpp"
00041 #include "Cylindrical2dMesh.hpp"
00042 #include "NodesOnlyMesh.hpp"
00043 #include "Exception.hpp"
00044
00045
00046 #include "CellAgesWriter.hpp"
00047 #include "CellAncestorWriter.hpp"
00048 #include "CellProliferativePhasesWriter.hpp"
00049 #include "CellProliferativeTypesWriter.hpp"
00050 #include "CellVolumesWriter.hpp"
00051
00052
00053 #include "CellMutationStatesCountWriter.hpp"
00054 #include "CellPopulationElementWriter.hpp"
00055 #include "VoronoiDataWriter.hpp"
00056 #include "NodeVelocityWriter.hpp"
00057 #include "CellPopulationAreaWriter.hpp"
00058
00059 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00060 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh,
00061 std::vector<CellPtr>& rCells,
00062 const std::vector<unsigned> locationIndices,
00063 bool deleteMesh,
00064 bool validate)
00065 : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh, rCells, locationIndices),
00066 mpVoronoiTessellation(NULL),
00067 mDeleteMesh(deleteMesh),
00068 mUseAreaBasedDampingConstant(false),
00069 mAreaBasedDampingConstantParameter(0.1),
00070 mWriteVtkAsPoints(false),
00071 mOutputMeshInVtk(false),
00072 mHasVariableRestLength(false)
00073 {
00074 mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00075
00076 assert(this->mCells.size() <= this->mrMesh.GetNumNodes());
00077
00078 if (validate)
00079 {
00080 Validate();
00081 }
00082
00083
00084 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->rGetMesh().GetNodeIteratorBegin();
00085 node_iter != this->rGetMesh().GetNodeIteratorEnd();
00086 ++node_iter)
00087 {
00088 node_iter->ClearAppliedForce();
00089 }
00090 }
00091
00092 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00093 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::MeshBasedCellPopulation(MutableMesh<ELEMENT_DIM,SPACE_DIM>& rMesh)
00094 : AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>(rMesh)
00095 {
00096 mpMutableMesh = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>* >(&(this->mrMesh));
00097 mpVoronoiTessellation = NULL;
00098 mDeleteMesh = true;
00099 }
00100
00101 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00102 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::~MeshBasedCellPopulation()
00103 {
00104 delete mpVoronoiTessellation;
00105
00106 if (mDeleteMesh)
00107 {
00108 delete &this->mrMesh;
00109 }
00110 }
00111
00112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00113 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UseAreaBasedDampingConstant()
00114 {
00115 return mUseAreaBasedDampingConstant;
00116 }
00117
00118 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00119 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
00120 {
00121 assert(SPACE_DIM==2);
00122 mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
00123 }
00124
00125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00126 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddNode(Node<SPACE_DIM>* pNewNode)
00127 {
00128 return mpMutableMesh->AddNode(pNewNode);
00129 }
00130
00131 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00132 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetNode(unsigned nodeIndex, ChastePoint<SPACE_DIM>& rNewLocation)
00133 {
00134 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetNode(nodeIndex, rNewLocation, false);
00135 }
00136
00137 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00138 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(unsigned nodeIndex)
00139 {
00140 double damping_multiplier = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetDampingConstant(nodeIndex);
00141
00142
00143
00144
00145
00146
00147 if (mUseAreaBasedDampingConstant)
00148 {
00158 assert(SPACE_DIM==2);
00159
00160 double rest_length = 1.0;
00161 double d0 = mAreaBasedDampingConstantParameter;
00162
00168 double d1 = 2.0*(1.0 - d0)/(sqrt(3.0)*rest_length*rest_length);
00169
00170 double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
00171
00177 assert(area_cell < 1000);
00178
00179 damping_multiplier = d0 + area_cell*d1;
00180 }
00181
00182 return damping_multiplier;
00183 }
00184
00185 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00186 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Validate()
00187 {
00188 std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
00189
00190 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00191 {
00192 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00193 validated_node[node_index] = true;
00194 }
00195
00196 for (unsigned i=0; i<validated_node.size(); i++)
00197 {
00198 if (!validated_node[i])
00199 {
00200 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << i << " does not appear to have a cell associated with it");
00201 }
00202 }
00203 }
00204
00205 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00206 MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh()
00207 {
00208 return *mpMutableMesh;
00209 }
00210
00211 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00212 const MutableMesh<ELEMENT_DIM,SPACE_DIM>& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetMesh() const
00213 {
00214 return *mpMutableMesh;
00215 }
00216
00217 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00218 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::RemoveDeadCells()
00219 {
00220 unsigned num_removed = 0;
00221 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00222 it != this->mCells.end();
00223 )
00224 {
00225 if ((*it)->IsDead())
00226 {
00227
00228 std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove;
00229 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
00230 it1 != this->mMarkedSprings.end();
00231 ++it1)
00232 {
00233 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
00234
00235 for (unsigned i=0; i<2; i++)
00236 {
00237 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
00238
00239 if (p_cell == *it)
00240 {
00241
00242 pairs_to_remove.push_back(&r_pair);
00243 break;
00244 }
00245 }
00246 }
00247
00248
00249 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
00250 pair_it != pairs_to_remove.end();
00251 ++pair_it)
00252 {
00253 this->mMarkedSprings.erase(**pair_it);
00254 }
00255
00256
00257 num_removed++;
00258 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00259
00260
00261 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*it));
00262 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*it));
00263
00264
00265 it = this->mCells.erase(it);
00266 }
00267 else
00268 {
00269 ++it;
00270 }
00271 }
00272
00273 return num_removed;
00274 }
00275
00276 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00277 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::Update(bool hasHadBirthsOrDeaths)
00278 {
00280 bool output_node_velocities = (this-> template HasWriter<NodeVelocityWriter>());
00281
00282 std::map<unsigned, c_vector<double, SPACE_DIM> > old_node_applied_force_map;
00283 old_node_applied_force_map.clear();
00284 if (output_node_velocities)
00285 {
00286
00287
00288
00289
00290
00291 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00292 node_iter != this->mrMesh.GetNodeIteratorEnd();
00293 ++node_iter)
00294 {
00295 unsigned node_index = node_iter->GetIndex();
00296 old_node_applied_force_map[node_index] = node_iter->rGetAppliedForce();
00297 }
00298 }
00299
00300 NodeMap node_map(this->mrMesh.GetNumAllNodes());
00301
00302
00303 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).ReMesh(node_map);
00304
00305 if (!node_map.IsIdentityMap())
00306 {
00307 UpdateGhostNodesAfterReMesh(node_map);
00308
00309
00310 std::map<Cell*, unsigned> old_cell_location_map = this->mCellLocationMap;
00311
00312
00313 this->mLocationCellMap.clear();
00314 this->mCellLocationMap.clear();
00315
00316 for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
00317 {
00318 unsigned old_node_index = old_cell_location_map[(*it).get()];
00319
00320
00321 assert(!node_map.IsDeleted(old_node_index));
00322
00323 unsigned new_node_index = node_map.GetNewIndex(old_node_index);
00324 this->SetCellUsingLocationIndex(new_node_index,*it);
00325
00326 if (output_node_velocities)
00327 {
00328 this->GetNode(new_node_index)->AddAppliedForceContribution(old_node_applied_force_map[old_node_index]);
00329 }
00330 }
00331
00332 this->Validate();
00333 }
00334 else if (output_node_velocities)
00335 {
00336 for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
00337 {
00338 unsigned node_index = this->mCellLocationMap[(*it).get()];
00339 this->GetNode(node_index)->AddAppliedForceContribution(old_node_applied_force_map[node_index]);
00340 }
00341 }
00342
00343
00344 std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
00345 for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = this->mMarkedSprings.begin();
00346 spring_it != this->mMarkedSprings.end();
00347 ++spring_it)
00348 {
00349 CellPtr p_cell_1 = spring_it->first;
00350 CellPtr p_cell_2 = spring_it->second;
00351 Node<SPACE_DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
00352 Node<SPACE_DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
00353
00354 bool joined = false;
00355
00356
00357 std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
00358 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
00359 elem_iter != p_node_1->ContainingElementsEnd();
00360 ++elem_iter)
00361 {
00362 if (node2_elements.find(*elem_iter) != node2_elements.end())
00363 {
00364 joined = true;
00365 break;
00366 }
00367 }
00368
00369
00370 if (!joined)
00371 {
00372 springs_to_remove.push_back(&(*spring_it));
00373 }
00374 }
00375
00376
00377 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
00378 spring_it != springs_to_remove.end();
00379 ++spring_it)
00380 {
00381 this->mMarkedSprings.erase(**spring_it);
00382 }
00383
00384
00385 TessellateIfNeeded();
00386
00387 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetMeshHasChangedSinceLoading();
00388 }
00389
00390 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00391 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::TessellateIfNeeded()
00392 {
00393 if ((SPACE_DIM==2 || SPACE_DIM==3)&&(ELEMENT_DIM==SPACE_DIM))
00394 {
00395 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
00396 if (mUseAreaBasedDampingConstant ||
00397 this-> template HasWriter<VoronoiDataWriter>() ||
00398 this-> template HasWriter<CellPopulationAreaWriter>() ||
00399 this-> template HasWriter<CellVolumesWriter>())
00400 {
00401 CreateVoronoiTessellation();
00402 }
00403 CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
00404 }
00405 }
00406
00407 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00408 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::DivideLongSprings(double springDivisionThreshold)
00409 {
00410
00411 assert(ELEMENT_DIM==2);
00412
00413 std::vector<c_vector<unsigned, 5> > new_nodes;
00414 new_nodes = rGetMesh().SplitLongEdges(springDivisionThreshold);
00415
00416
00417 for (unsigned index=0; index<new_nodes.size(); index++)
00418 {
00419
00420 unsigned new_node_index = new_nodes[index][0];
00421 unsigned node_a_index = new_nodes[index][1];
00422 unsigned node_b_index = new_nodes[index][2];
00423
00424 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(node_a_index);
00425
00426
00427 CellPropertyCollection daughter_property_collection = p_neighbour_cell->rGetCellPropertyCollection();
00428
00429
00430 daughter_property_collection.RemoveProperty<CellId>();
00431
00432 CellPtr p_new_cell(new Cell(p_neighbour_cell->GetMutationState(),
00433 p_neighbour_cell->GetCellCycleModel()->CreateCellCycleModel(),
00434 false,
00435 daughter_property_collection));
00436
00437
00438 this->mCells.push_back(p_new_cell);
00439 this->AddCellUsingLocationIndex(new_node_index,p_new_cell);
00440
00441
00442
00443
00444 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(node_a_index, node_b_index);
00445 double old_rest_length = mSpringRestLengths[node_pair];
00446
00447 std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair);
00448 mSpringRestLengths.erase(iter);
00449
00450
00451 node_pair = this->CreateOrderedPair(node_a_index, new_node_index);
00452 mSpringRestLengths[node_pair] = 0.5*old_rest_length;
00453
00454 node_pair = this->CreateOrderedPair(node_b_index, new_node_index);
00455 mSpringRestLengths[node_pair] = 0.5*old_rest_length;
00456
00457
00458 for (unsigned pair_index=3; pair_index<5; pair_index++)
00459 {
00460 unsigned other_node_index = new_nodes[index][pair_index];
00461
00462 if (other_node_index != UNSIGNED_UNSET)
00463 {
00464 node_pair = this->CreateOrderedPair(other_node_index, new_node_index);
00465 double new_rest_length = rGetMesh().GetDistanceBetweenNodes(new_node_index, other_node_index);
00466 mSpringRestLengths[node_pair] = new_rest_length;
00467 }
00468 }
00469 }
00470 }
00471
00472 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00473 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNode(unsigned index)
00474 {
00475 return this->mrMesh.GetNode(index);
00476 }
00477
00478 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00479 unsigned MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNumNodes()
00480 {
00481 return this->mrMesh.GetNumAllNodes();
00482 }
00483
00484 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00485 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00486 {
00487 }
00488
00489 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00490 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(CellPtr pNewCell, const c_vector<double,SPACE_DIM>& rCellDivisionVector, CellPtr pParentCell)
00491 {
00492 assert(pNewCell);
00493 assert(pParentCell);
00494
00495
00496 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00497 assert(p_created_cell == pNewCell);
00498
00499
00500 std::pair<CellPtr,CellPtr> cell_pair = this->CreateCellPair(pParentCell, p_created_cell);
00501 this->MarkSpring(cell_pair);
00502
00503
00504 return p_created_cell;
00505 }
00506
00508
00510
00511 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00512 void MeshBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00513 {
00514 if (this->mOutputResultsForChasteVisualizer)
00515 {
00516 if (!this-> template HasWriter<CellPopulationElementWriter>())
00517 {
00518 this-> template AddPopulationWriter<CellPopulationElementWriter>();
00519 }
00520 }
00521
00522 AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>::OpenWritersFiles(rOutputFileHandler);
00523 }
00524
00525 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00526 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles(const std::string& rDirectory)
00527 {
00528 if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == NULL)
00529 {
00530 TessellateIfNeeded();
00531 }
00532
00533 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteResultsToFiles(rDirectory);
00534 }
00535
00536 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00537 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM> > pPopulationWriter)
00538 {
00539 pPopulationWriter->Visit(this);
00540 }
00541
00542 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00543 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<ELEMENT_DIM, SPACE_DIM> > pPopulationCountWriter)
00544 {
00545 pPopulationCountWriter->Visit(this);
00546 }
00547
00548 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00549 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > pCellWriter, CellPtr pCell)
00550 {
00551 pCellWriter->VisitCell(pCell, this);
00552 }
00553
00554 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00555 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00556 {
00557 #ifdef CHASTE_VTK
00558
00559 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00560 std::stringstream time;
00561 time << num_timesteps;
00562
00563
00564 unsigned num_cells_from_mesh = GetNumNodes();
00565 if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL))
00566 {
00567 num_cells_from_mesh = mpVoronoiTessellation->GetNumElements();
00568 }
00569
00570
00571 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00572 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00573
00574 std::vector<std::vector<double> > cell_data;
00575 for (unsigned var=0; var<num_cell_data_items; var++)
00576 {
00577 std::vector<double> cell_data_var(num_cells_from_mesh);
00578 cell_data.push_back(cell_data_var);
00579 }
00580
00581 if (mOutputMeshInVtk)
00582 {
00583
00584 VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "mesh_"+time.str(), false);
00585 mesh_writer.WriteFilesUsingMesh(rGetMesh());
00586 }
00587
00588 if (mWriteVtkAsPoints)
00589 {
00590
00591 VtkMeshWriter<SPACE_DIM, SPACE_DIM> cells_writer(rDirectory, "results_"+time.str(), false);
00592
00593
00594 unsigned num_cells = this->GetNumAllCells();
00595 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00596 cell_writer_iter != this->mCellWriters.end();
00597 ++cell_writer_iter)
00598 {
00599
00600 std::vector<double> vtk_cell_data(num_cells);
00601
00602
00603 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
00604 cell_iter != this->End();
00605 ++cell_iter)
00606 {
00607
00608 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00609
00610
00611 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
00612 }
00613
00614 cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00615 }
00616
00617
00618 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
00619 cell_iter != this->End();
00620 ++cell_iter)
00621 {
00622
00623 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
00624
00625 for (unsigned var=0; var<num_cell_data_items; var++)
00626 {
00627 cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00628 }
00629 }
00630 for (unsigned var=0; var<num_cell_data_items; var++)
00631 {
00632 cells_writer.AddPointData(cell_data_names[var], cell_data[var]);
00633 }
00634
00635
00636 {
00637 std::vector<Node<SPACE_DIM>* > nodes;
00638 for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++)
00639 {
00640 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
00641 nodes.push_back(p_node);
00642 }
00643
00644 NodesOnlyMesh<SPACE_DIM> mesh;
00645 mesh.ConstructNodesWithoutMesh(nodes, 1.5);
00646 cells_writer.WriteFilesUsingMesh(mesh);
00647 }
00648
00649 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00650 *(this->mpVtkMetaFile) << num_timesteps;
00651 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00652 *(this->mpVtkMetaFile) << num_timesteps;
00653 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00654 }
00655 else if (mpVoronoiTessellation != NULL)
00656 {
00657
00658 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "results", false);
00659 std::vector<double> cell_volumes(num_cells_from_mesh);
00660
00661
00662 unsigned num_cells = this->GetNumAllCells();
00663 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00664 cell_writer_iter != this->mCellWriters.end();
00665 ++cell_writer_iter)
00666 {
00667
00668 std::vector<double> vtk_cell_data(num_cells);
00669
00670
00671 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00672 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00673 ++elem_iter)
00674 {
00675
00676 unsigned elem_index = elem_iter->GetIndex();
00677
00678
00679 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00680 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00681
00682
00683 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00684 }
00685
00686 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00687 }
00688
00689
00690 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
00691 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
00692 ++elem_iter)
00693 {
00694
00695 unsigned elem_index = elem_iter->GetIndex();
00696
00697
00698 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00699 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00700
00701 for (unsigned var=0; var<num_cell_data_items; var++)
00702 {
00703 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00704 }
00705 }
00706
00707 for (unsigned var=0; var<cell_data.size(); var++)
00708 {
00709 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
00710 }
00711
00712 mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
00713 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00714 *(this->mpVtkMetaFile) << num_timesteps;
00715 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00716 *(this->mpVtkMetaFile) << num_timesteps;
00717 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00718 }
00719 #endif //CHASTE_VTK
00720 }
00721
00722 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00723 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfCell(CellPtr pCell)
00724 {
00725 double cell_volume = 0;
00726
00727 if (ELEMENT_DIM == SPACE_DIM)
00728 {
00729
00730 if (mpVoronoiTessellation == NULL)
00731 {
00732 CreateVoronoiTessellation();
00733 }
00734
00735
00736 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00737
00738
00739 try
00740 {
00741 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(node_index);
00742
00743
00744 cell_volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00745 }
00746 catch (Exception&)
00747 {
00748
00749 cell_volume = DBL_MAX;
00750 }
00751 }
00752 else if (SPACE_DIM==3 && ELEMENT_DIM==2)
00753 {
00754 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00755
00756 Node<SPACE_DIM>* p_node = rGetMesh().GetNode(node_index);
00757
00758 assert(p_node->rGetContainingElementIndices().size()>0);
00759
00760 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
00761 elem_iter != p_node->ContainingElementsEnd();
00762 ++elem_iter)
00763 {
00764 Element<ELEMENT_DIM,SPACE_DIM>* p_element = rGetMesh().GetElement(*elem_iter);
00765
00766 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacob;
00767 double det;
00768
00769 p_element->CalculateJacobian(jacob, det);
00770
00771 cell_volume += fabs(p_element->GetVolume(det));
00772 }
00773
00774
00775 cell_volume /= 3.0;
00776 }
00777 else
00778 {
00779
00780 NEVER_REACHED;
00781 }
00782
00783 return cell_volume;
00784 }
00785
00786 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00787 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetWriteVtkAsPoints(bool writeVtkAsPoints)
00788 {
00789 mWriteVtkAsPoints = writeVtkAsPoints;
00790 }
00791
00792 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00793 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWriteVtkAsPoints()
00794 {
00795 return mWriteVtkAsPoints;
00796 }
00797
00798 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00799 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetOutputMeshInVtk(bool outputMeshInVtk)
00800 {
00801 mOutputMeshInVtk = outputMeshInVtk;
00802 }
00803
00804 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00805 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetOutputMeshInVtk()
00806 {
00807 return mOutputMeshInVtk;
00808 }
00809
00811
00813
00814 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00815 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeA()
00816 {
00817 return mEdgeIter.GetNodeA();
00818 }
00819
00820 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00821 Node<SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetNodeB()
00822 {
00823 return mEdgeIter.GetNodeB();
00824 }
00825
00826 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00827 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellA()
00828 {
00829 assert((*this) != mrCellPopulation.SpringsEnd());
00830 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
00831 }
00832
00833 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00834 CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::GetCellB()
00835 {
00836 assert((*this) != mrCellPopulation.SpringsEnd());
00837 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
00838 }
00839
00840 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00841 bool MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator!=(const typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& rOther)
00842 {
00843 return (mEdgeIter != rOther.mEdgeIter);
00844 }
00845
00846 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00847 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::operator++()
00848 {
00849 bool edge_is_ghost = false;
00850
00851 do
00852 {
00853 ++mEdgeIter;
00854 if (*this != mrCellPopulation.SpringsEnd())
00855 {
00856 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00857 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00858
00859 edge_is_ghost = (a_is_ghost || b_is_ghost);
00860 }
00861 }
00862 while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
00863
00864 return (*this);
00865 }
00866
00867 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00868 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator::SpringIterator(
00869 MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>& rCellPopulation,
00870 typename MutableMesh<ELEMENT_DIM,SPACE_DIM>::EdgeIterator edgeIter)
00871 : mrCellPopulation(rCellPopulation),
00872 mEdgeIter(edgeIter)
00873 {
00874 if (mEdgeIter!=static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation.mrMesh))->EdgesEnd())
00875 {
00876 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
00877 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
00878
00879 if (a_is_ghost || b_is_ghost)
00880 {
00881 ++(*this);
00882 }
00883 }
00884 }
00885
00886 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00887 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsBegin()
00888 {
00889 return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesBegin());
00890 }
00891
00892 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00893 typename MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringIterator MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SpringsEnd()
00894 {
00895 return SpringIterator(*this, static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).EdgesEnd());
00896 }
00897
00901 template<>
00902 void MeshBasedCellPopulation<2>::CreateVoronoiTessellation()
00903 {
00904 delete mpVoronoiTessellation;
00905
00906
00907 bool is_mesh_periodic = false;
00908 if (dynamic_cast<Cylindrical2dMesh*>(&mrMesh))
00909 {
00910 is_mesh_periodic = true;
00911 }
00912
00913 mpVoronoiTessellation = new VertexMesh<2, 2>(static_cast<MutableMesh<2, 2> &>((this->mrMesh)), is_mesh_periodic);
00914 }
00915
00919 template<>
00920 void MeshBasedCellPopulation<2,3>::CreateVoronoiTessellation()
00921 {
00922
00923 NEVER_REACHED;
00924 }
00925
00931 template<>
00932 void MeshBasedCellPopulation<3>::CreateVoronoiTessellation()
00933 {
00934 delete mpVoronoiTessellation;
00935 mpVoronoiTessellation = new VertexMesh<3, 3>(static_cast<MutableMesh<3, 3> &>((this->mrMesh)));
00936 }
00937
00942 template<>
00943 void MeshBasedCellPopulation<1, 1>::CreateVoronoiTessellation()
00944 {
00945
00946 NEVER_REACHED;
00947 }
00948
00953 template<>
00954 void MeshBasedCellPopulation<1, 2>::CreateVoronoiTessellation()
00955 {
00956
00957 NEVER_REACHED;
00958 }
00959
00964 template<>
00965 void MeshBasedCellPopulation<1, 3>::CreateVoronoiTessellation()
00966 {
00967
00968 NEVER_REACHED;
00969 }
00970
00971 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00972 VertexMesh<ELEMENT_DIM,SPACE_DIM>* MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiTessellation()
00973 {
00974 assert(mpVoronoiTessellation!=NULL);
00975 return mpVoronoiTessellation;
00976 }
00977
00978 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00979 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVolumeOfVoronoiElement(unsigned index)
00980 {
00981 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00982 double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
00983 return volume;
00984 }
00985
00986 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00987 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetSurfaceAreaOfVoronoiElement(unsigned index)
00988 {
00989 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
00990 double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
00991 return surface_area;
00992 }
00993
00994 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00995 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetVoronoiEdgeLength(unsigned index1, unsigned index2)
00996 {
00997 unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
00998 unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
00999 try
01000 {
01001 double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
01002 return edge_length;
01003 }
01004 catch (Exception&)
01005 {
01006
01007 EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh. Have you set ghost layers correctly?");
01008 }
01009 }
01010
01011 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01012 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CheckCellPointers()
01013 {
01014 bool res = true;
01015 for (std::list<CellPtr>::iterator it=this->mCells.begin();
01016 it!=this->mCells.end();
01017 ++it)
01018 {
01019 CellPtr p_cell = *it;
01020 assert(p_cell);
01021 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01022 assert(p_model);
01023
01024
01025 unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01026 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01027 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01028 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions
01029 if (p_cell_in_cell_population != p_cell)
01030 {
01031 std::cout << " Mismatch with cell population" << std::endl << std::flush;
01032 res = false;
01033 }
01034
01035
01036 if (p_model->GetCell() != p_cell)
01037 {
01038 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
01039 res = false;
01040 }
01041 }
01042 UNUSED_OPT(res);
01043 assert(res);
01044 #undef COVERAGE_IGNORE
01045
01046 res = true;
01047 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
01048 it1 != this->mMarkedSprings.end();
01049 ++it1)
01050 {
01051 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
01052
01053 for (unsigned i=0; i<2; i++)
01054 {
01055 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
01056
01057 assert(p_cell);
01058 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
01059 assert(p_model);
01060 unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
01061 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
01062
01063 #define COVERAGE_IGNORE //Debugging code. Shouldn't fail under normal conditions
01064
01065 if (p_cell->IsDead())
01066 {
01067 std::cout << " Cell is dead" << std::endl << std::flush;
01068 res = false;
01069 }
01070
01071
01072 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
01073 if (p_cell_in_cell_population != p_cell)
01074 {
01075 std::cout << " Mismatch with cell population" << std::endl << std::flush;
01076 res = false;
01077 }
01078
01079
01080 if (p_model->GetCell() != p_cell)
01081 {
01082 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
01083 res = false;
01084 }
01085 }
01086 #undef COVERAGE_IGNORE
01087 }
01088 assert(res);
01089 }
01090
01091 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01092 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetAreaBasedDampingConstantParameter()
01093 {
01094 return mAreaBasedDampingConstantParameter;
01095 }
01096
01097 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01098 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
01099 {
01100 assert(areaBasedDampingConstantParameter >= 0.0);
01101 mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
01102 }
01103
01104 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01105 std::vector< std::pair<Node<SPACE_DIM>*, Node<SPACE_DIM>* > >& MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::rGetNodePairs()
01106 {
01107
01108 NEVER_REACHED;
01109 return mNodePairs;
01110 }
01111
01112 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01113 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
01114 {
01115 *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n";
01116 *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" << mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n";
01117 *rParamsFile << "\t\t<WriteVtkAsPoints>" << mWriteVtkAsPoints << "</WriteVtkAsPoints>\n";
01118 *rParamsFile << "\t\t<OutputMeshInVtk>" << mOutputMeshInVtk << "</OutputMeshInVtk>\n";
01119 *rParamsFile << "\t\t<HasVariableRestLength>" << mHasVariableRestLength << "</HasVariableRestLength>\n";
01120
01121
01122 AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::OutputCellPopulationParameters(rParamsFile);
01123 }
01124
01125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01126 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetWidth(const unsigned& rDimension)
01127 {
01128
01129 double width = this->mrMesh.GetWidth(rDimension);
01130 return width;
01131 }
01132
01133 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01134 std::set<unsigned> MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetNeighbouringNodeIndices(unsigned index)
01135 {
01136
01137 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
01138
01139
01140 std::set<unsigned> neighbouring_node_indices;
01141 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
01142 elem_iter != p_node->ContainingElementsEnd();
01143 ++elem_iter)
01144 {
01145
01146 Element<ELEMENT_DIM,SPACE_DIM>* p_element = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElement(*elem_iter);
01147
01148
01149 for (unsigned i=0; i<p_element->GetNumNodes(); i++)
01150 {
01151
01152 unsigned node_index = p_element->GetNodeGlobalIndex(i);
01153 if (node_index != index)
01154 {
01155 neighbouring_node_indices.insert(node_index);
01156 }
01157 }
01158 }
01159 return neighbouring_node_indices;
01160 }
01161
01162 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01163 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::CalculateRestLengths()
01164 {
01165 mSpringRestLengths.clear();
01166
01167
01168 for (SpringIterator spring_iterator = SpringsBegin();
01169 spring_iterator != SpringsEnd();
01170 ++spring_iterator)
01171 {
01172
01173 Node<SPACE_DIM>* p_nodeA = spring_iterator.GetNodeA();
01174 Node<SPACE_DIM>* p_nodeB = spring_iterator.GetNodeB();
01175
01176 unsigned nodeA_global_index = p_nodeA->GetIndex();
01177 unsigned nodeB_global_index = p_nodeB->GetIndex();
01178
01179
01180 double separation = rGetMesh().GetDistanceBetweenNodes(nodeA_global_index, nodeB_global_index);
01181
01182
01183 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(nodeA_global_index, nodeB_global_index);
01184
01185 mSpringRestLengths[node_pair] = separation;
01186 }
01187 mHasVariableRestLength = true;
01188 }
01189
01190 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01191 double MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::GetRestLength(unsigned indexA, unsigned indexB)
01192 {
01193 if (mHasVariableRestLength)
01194 {
01195 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
01196 std::map<std::pair<unsigned,unsigned>, double>::const_iterator iter = mSpringRestLengths.find(node_pair);
01197
01198 if (iter != mSpringRestLengths.end())
01199 {
01200
01201 return iter->second;
01202 }
01203 else
01204 {
01205 EXCEPTION("Tried to get a rest length of an edge that doesn't exist. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
01206 }
01207 }
01208 else
01209 {
01210 return 1.0;
01211 }
01212 }
01213
01214 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
01215 void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetRestLength(unsigned indexA, unsigned indexB, double restLength)
01216 {
01217 if (mHasVariableRestLength)
01218 {
01219 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
01220 std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair);
01221
01222 if (iter != mSpringRestLengths.end())
01223 {
01224
01225 iter->second = restLength;
01226 }
01227 else
01228 {
01229 EXCEPTION("Tried to set the rest length of an edge not in the mesh.");
01230 }
01231 }
01232 else
01233 {
01234 EXCEPTION("Tried to set a rest length in a simulation with fixed rest length. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
01235 }
01236 }
01237
01238
01239 template class MeshBasedCellPopulation<1,1>;
01240 template class MeshBasedCellPopulation<1,2>;
01241 template class MeshBasedCellPopulation<2,2>;
01242 template class MeshBasedCellPopulation<1,3>;
01243 template class MeshBasedCellPopulation<2,3>;
01244 template class MeshBasedCellPopulation<3,3>;
01245
01246
01247 #include "SerializationExportWrapperForCpp.hpp"
01248 EXPORT_TEMPLATE_CLASS_ALL_DIMS(MeshBasedCellPopulation)