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 "VertexBasedCellPopulation.hpp"
00037 #include <boost/foreach.hpp>
00038 #include "VertexMeshWriter.hpp"
00039 #include "Warnings.hpp"
00040 #include "ChasteSyscalls.hpp"
00041 #include "IsNan.hpp"
00042 #include "ShortAxisVertexBasedDivisionRule.hpp"
00043
00044
00045 #include "CellAgesWriter.hpp"
00046 #include "CellAncestorWriter.hpp"
00047 #include "CellProliferativePhasesWriter.hpp"
00048 #include "CellProliferativeTypesWriter.hpp"
00049 #include "CellVolumesWriter.hpp"
00050
00051
00052 #include "CellMutationStatesCountWriter.hpp"
00053 #include "CellPopulationElementWriter.hpp"
00054 #include "VertexT1SwapLocationsWriter.hpp"
00055 #include "VertexT2SwapLocationsWriter.hpp"
00056 #include "VertexT3SwapLocationsWriter.hpp"
00057
00058 template<unsigned DIM>
00059 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh,
00060 std::vector<CellPtr>& rCells,
00061 bool deleteMesh,
00062 bool validate,
00063 const std::vector<unsigned> locationIndices)
00064 : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices),
00065 mDeleteMesh(deleteMesh),
00066 mOutputCellRearrangementLocations(true)
00067 {
00068 mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00069 mpVertexBasedDivisionRule.reset(new ShortAxisVertexBasedDivisionRule<DIM>());
00070
00071
00072 std::list<CellPtr>::iterator it = this->mCells.begin();
00073 for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
00074 {
00075 unsigned index = locationIndices.empty() ? i : locationIndices[i];
00076 AbstractCellPopulation<DIM, DIM>::AddCellUsingLocationIndex(index,*it);
00077 }
00078
00079
00080 if (validate)
00081 {
00082 Validate();
00083 }
00084 }
00085
00086 template<unsigned DIM>
00087 VertexBasedCellPopulation<DIM>::VertexBasedCellPopulation(MutableVertexMesh<DIM, DIM>& rMesh)
00088 : AbstractOffLatticeCellPopulation<DIM>(rMesh),
00089 mDeleteMesh(true),
00090 mOutputCellRearrangementLocations(true)
00091 {
00092 mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
00093 }
00094
00095 template<unsigned DIM>
00096 VertexBasedCellPopulation<DIM>::~VertexBasedCellPopulation()
00097 {
00098 if (mDeleteMesh)
00099 {
00100 delete &this->mrMesh;
00101 }
00102 }
00103
00104 template<unsigned DIM>
00105 double VertexBasedCellPopulation<DIM>::GetDampingConstant(unsigned nodeIndex)
00106 {
00107
00108 double average_damping_constant = 0.0;
00109
00110 std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
00111
00112 unsigned num_containing_elements = containing_elements.size();
00113 if (num_containing_elements == 0)
00114 {
00115 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << nodeIndex << " is not contained in any elements, so GetDampingConstant() returns zero");
00116 }
00117
00118 double temp = 1.0/((double) num_containing_elements);
00119 for (std::set<unsigned>::iterator iter = containing_elements.begin();
00120 iter != containing_elements.end();
00121 ++iter)
00122 {
00123 CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
00124 bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
00125 bool cell_is_labelled = p_cell->HasCellProperty<CellLabel>();
00126
00127 if (cell_is_wild_type && !cell_is_labelled)
00128 {
00129 average_damping_constant += this->GetDampingConstantNormal()*temp;
00130 }
00131 else
00132 {
00133 average_damping_constant += this->GetDampingConstantMutant()*temp;
00134 }
00135 }
00136
00137 return average_damping_constant;
00138 }
00139
00140 template<unsigned DIM>
00141 MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh()
00142 {
00143 return *mpMutableVertexMesh;
00144 }
00145
00146 template<unsigned DIM>
00147 const MutableVertexMesh<DIM, DIM>& VertexBasedCellPopulation<DIM>::rGetMesh() const
00148 {
00149 return *mpMutableVertexMesh;
00150 }
00151
00152 template<unsigned DIM>
00153 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElement(unsigned elementIndex)
00154 {
00155 return mpMutableVertexMesh->GetElement(elementIndex);
00156 }
00157
00158 template<unsigned DIM>
00159 unsigned VertexBasedCellPopulation<DIM>::GetNumNodes()
00160 {
00161 return this->mrMesh.GetNumNodes();
00162 }
00163
00164 template<unsigned DIM>
00165 c_vector<double, DIM> VertexBasedCellPopulation<DIM>::GetLocationOfCellCentre(CellPtr pCell)
00166 {
00167 return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
00168 }
00169
00170 template<unsigned DIM>
00171 Node<DIM>* VertexBasedCellPopulation<DIM>::GetNode(unsigned index)
00172 {
00173 return this->mrMesh.GetNode(index);
00174 }
00175
00176 template<unsigned DIM>
00177 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringLocationIndices(CellPtr pCell)
00178 {
00179 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00180 return this->rGetMesh().GetNeighbouringElementIndices(elem_index);
00181 }
00182
00183 template<unsigned DIM>
00184 unsigned VertexBasedCellPopulation<DIM>::AddNode(Node<DIM>* pNewNode)
00185 {
00186 return mpMutableVertexMesh->AddNode(pNewNode);
00187 }
00188
00189 template<unsigned DIM>
00190 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00191 {
00192 mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
00193 }
00194
00195 template<unsigned DIM>
00196 VertexElement<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetElementCorrespondingToCell(CellPtr pCell)
00197 {
00198 return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
00199 }
00200
00201 template<unsigned DIM>
00202 unsigned VertexBasedCellPopulation<DIM>::GetNumElements()
00203 {
00204 return mpMutableVertexMesh->GetNumElements();
00205 }
00206
00207 template<unsigned DIM>
00208 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell,
00209 const c_vector<double,DIM>& rCellDivisionVector,
00210 CellPtr pParentCell)
00211 {
00212
00213 VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
00214
00215
00216 unsigned new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element,
00217 rCellDivisionVector,
00218 true);
00219
00220 this->mCells.push_back(pNewCell);
00221
00222
00223 CellPtr p_created_cell = this->mCells.back();
00224 this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
00225 this->mCellLocationMap[p_created_cell.get()] = new_element_index;
00226 return p_created_cell;
00227 }
00228
00229 template<unsigned DIM>
00230 unsigned VertexBasedCellPopulation<DIM>::RemoveDeadCells()
00231 {
00232 unsigned num_removed = 0;
00233
00234 for (std::list<CellPtr>::iterator it = this->mCells.begin();
00235 it != this->mCells.end();
00236 )
00237 {
00238 if ((*it)->IsDead())
00239 {
00240
00241 num_removed++;
00242
00243
00245 if (!(this->GetElement(this->GetLocationIndexUsingCell((*it)))->IsDeleted()))
00246 {
00247
00248
00249 WARN_ONCE_ONLY("A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
00250 mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it)));
00251 }
00252
00253
00254 it = this->mCells.erase(it);
00255 }
00256 else
00257 {
00258 ++it;
00259 }
00260 }
00261 return num_removed;
00262 }
00263
00264 template<unsigned DIM>
00265 void VertexBasedCellPopulation<DIM>::UpdateNodeLocations(double dt)
00266 {
00267
00268 for (unsigned node_index=0; node_index<GetNumNodes(); node_index++)
00269 {
00270
00271 double damping_const = this->GetDampingConstant(node_index);
00272
00273
00274 c_vector<double, DIM> displacement = dt*this->GetNode(node_index)->rGetAppliedForce()/damping_const;
00275
00276
00277
00278
00279
00280
00281
00282
00283 if (norm_2(displacement) > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())
00284 {
00285 WARN_ONCE_ONLY("Vertices are moving more than half the CellRearrangementThreshold. This could cause elements to become inverted so the motion has been restricted. Use a smaller timestep to avoid these warnings.");
00286 displacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/norm_2(displacement);
00287 }
00288
00289
00290 c_vector<double, DIM> new_node_location = this->GetNode(node_index)->rGetLocation() + displacement;
00291
00292 for (unsigned i=0; i<DIM; i++)
00293 {
00294 assert(!std::isnan(new_node_location(i)));
00295 }
00296
00297
00298 ChastePoint<DIM> new_point(new_node_location);
00299
00300
00301 this->SetNode(node_index, new_point);
00302 }
00303 }
00304
00305 template<unsigned DIM>
00306 bool VertexBasedCellPopulation<DIM>::IsCellAssociatedWithADeletedLocation(CellPtr pCell)
00307 {
00308 return GetElementCorrespondingToCell(pCell)->IsDeleted();;
00309 }
00310
00311 template<unsigned DIM>
00312 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
00313 {
00314 VertexElementMap element_map(mpMutableVertexMesh->GetNumAllElements());
00315 mpMutableVertexMesh->ReMesh(element_map);
00316
00317 if (!element_map.IsIdentityMap())
00318 {
00319
00321 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
00322
00323 this->mCellLocationMap.clear();
00324 this->mLocationCellMap.clear();
00325
00326 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
00327 cell_iter != this->mCells.end();
00328 ++cell_iter)
00329 {
00330
00331 unsigned old_elem_index = old_map[(*cell_iter).get()];
00332 assert(!element_map.IsDeleted(old_elem_index));
00333
00334 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
00335 this->SetCellUsingLocationIndex(new_elem_index, *cell_iter);
00336 }
00337
00338
00339 Validate();
00340 }
00341
00342 element_map.ResetToIdentity();
00343 }
00344
00345 template<unsigned DIM>
00346 void VertexBasedCellPopulation<DIM>::Validate()
00347 {
00348
00349 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
00350 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00351 cell_iter != this->End();
00352 ++cell_iter)
00353 {
00354 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
00355 validated_element[elem_index]++;
00356 }
00357
00358 for (unsigned i=0; i<validated_element.size(); i++)
00359 {
00360 if (validated_element[i] == 0)
00361 {
00362 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " does not appear to have a cell associated with it");
00363 }
00364
00365 if (validated_element[i] > 1)
00366 {
00367
00368 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
00369 }
00370 }
00371 }
00372
00373 template<unsigned DIM>
00374 void VertexBasedCellPopulation<DIM>::AcceptPopulationWriter(boost::shared_ptr<AbstractCellPopulationWriter<DIM, DIM> > pPopulationWriter)
00375 {
00376 pPopulationWriter->Visit(this);
00377 }
00378
00379 template<unsigned DIM>
00380 void VertexBasedCellPopulation<DIM>::AcceptPopulationCountWriter(boost::shared_ptr<AbstractCellPopulationCountWriter<DIM, DIM> > pPopulationCountWriter)
00381 {
00382 pPopulationCountWriter->Visit(this);
00383 }
00384
00385 template<unsigned DIM>
00386 void VertexBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
00387 {
00388 pCellWriter->VisitCell(pCell, this);
00389 }
00390
00391 template<unsigned DIM>
00392 double VertexBasedCellPopulation<DIM>::GetVolumeOfCell(CellPtr pCell)
00393 {
00394
00395 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
00396
00397
00398 double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
00399
00400 return cell_volume;
00401 }
00402
00403 template<unsigned DIM>
00404 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00405 {
00406 #ifdef CHASTE_VTK
00407
00408
00409 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
00410
00411
00412 unsigned num_cells = this->GetNumAllCells();
00413 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00414 cell_writer_iter != this->mCellWriters.end();
00415 ++cell_writer_iter)
00416 {
00417
00418 std::vector<double> vtk_cell_data(num_cells);
00419
00420
00421 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
00422 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
00423 ++elem_iter)
00424 {
00425
00426 unsigned elem_index = elem_iter->GetIndex();
00427
00428
00429 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00430 assert(p_cell);
00431
00432
00433 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00434 }
00435
00436 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00437 }
00438
00439
00440 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00441 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
00442
00443 std::vector<std::vector<double> > cell_data;
00444 for (unsigned var=0; var<num_cell_data_items; var++)
00445 {
00446 std::vector<double> cell_data_var(num_cells);
00447 cell_data.push_back(cell_data_var);
00448 }
00449
00450
00451 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
00452 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
00453 ++elem_iter)
00454 {
00455
00456 unsigned elem_index = elem_iter->GetIndex();
00457
00458
00459 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
00460 assert(p_cell);
00461
00462 for (unsigned var=0; var<num_cell_data_items; var++)
00463 {
00464 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
00465 }
00466 }
00467 for (unsigned var=0; var<num_cell_data_items; var++)
00468 {
00469 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
00470 }
00471
00472 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00473 std::stringstream time;
00474 time << num_timesteps;
00475
00476 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
00477
00478 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00479 *(this->mpVtkMetaFile) << num_timesteps;
00480 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00481 *(this->mpVtkMetaFile) << num_timesteps;
00482 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00483 #endif //CHASTE_VTK
00484 }
00485
00486 template<unsigned DIM>
00487 void VertexBasedCellPopulation<DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00488 {
00489 if (this->mOutputResultsForChasteVisualizer)
00490 {
00491 if (!this-> template HasWriter<CellPopulationElementWriter>())
00492 {
00493 this-> template AddPopulationWriter<CellPopulationElementWriter>();
00494 }
00495 }
00496
00497 if (mOutputCellRearrangementLocations)
00498 {
00499 if (!this-> template HasWriter<VertexT1SwapLocationsWriter>())
00500 {
00501 this-> template AddPopulationWriter<VertexT1SwapLocationsWriter>();
00502 }
00503 if (!this-> template HasWriter<VertexT2SwapLocationsWriter>())
00504 {
00505 this-> template AddPopulationWriter<VertexT2SwapLocationsWriter>();
00506 }
00507 if (!this-> template HasWriter<VertexT3SwapLocationsWriter>())
00508 {
00509 this-> template AddPopulationWriter<VertexT3SwapLocationsWriter>();
00510 }
00511 }
00512
00513 AbstractCellPopulation<DIM>::OpenWritersFiles(rOutputFileHandler);
00514 }
00515
00516 template<unsigned DIM>
00517 bool VertexBasedCellPopulation<DIM>::GetOutputCellRearrangementLocations()
00518 {
00519 return mOutputCellRearrangementLocations;
00520 }
00521
00522 template<unsigned DIM>
00523 void VertexBasedCellPopulation<DIM>::SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
00524 {
00525 mOutputCellRearrangementLocations = outputCellRearrangementLocations;
00526 }
00527
00528 template<unsigned DIM>
00529 void VertexBasedCellPopulation<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00530 {
00531 *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
00532 *rParamsFile << "\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
00533 *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
00534 *rParamsFile << "\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations << "</OutputCellRearrangementLocations>\n";
00535
00536
00537 *rParamsFile << "\t\t<VertexBasedDivisionRule>\n";
00538 mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
00539 *rParamsFile << "\t\t</VertexBasedDivisionRule>\n";
00540
00541
00542 AbstractOffLatticeCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00543 }
00544
00545 template<unsigned DIM>
00546 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
00547 {
00548
00549 double width = this->mrMesh.GetWidth(rDimension);
00550
00551 return width;
00552 }
00553
00554 template<unsigned DIM>
00555 std::set<unsigned> VertexBasedCellPopulation<DIM>::GetNeighbouringNodeIndices(unsigned index)
00556 {
00557 return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
00558 }
00559
00560 template<unsigned DIM>
00561 boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > VertexBasedCellPopulation<DIM>::GetVertexBasedDivisionRule()
00562 {
00563 return mpVertexBasedDivisionRule;
00564 }
00565
00566 template<unsigned DIM>
00567 void VertexBasedCellPopulation<DIM>::SetVertexBasedDivisionRule(boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > pVertexBasedDivisionRule)
00568 {
00569 mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
00570 }
00571
00572 template<unsigned DIM>
00573 std::vector< c_vector< double, DIM > > VertexBasedCellPopulation<DIM>::GetLocationsOfT2Swaps()
00574 {
00575 return mLocationsOfT2Swaps;
00576 }
00577
00578 template<unsigned DIM>
00579 std::vector< unsigned > VertexBasedCellPopulation<DIM>::GetCellIdsOfT2Swaps()
00580 {
00581 return mCellIdsOfT2Swaps;
00582 }
00583
00584 template<unsigned DIM>
00585 void VertexBasedCellPopulation<DIM>::AddLocationOfT2Swap(c_vector< double, DIM> locationOfT2Swap)
00586 {
00587 mLocationsOfT2Swaps.push_back(locationOfT2Swap);
00588 }
00589
00590 template<unsigned DIM>
00591 void VertexBasedCellPopulation<DIM>::AddCellIdOfT2Swap(unsigned idOfT2Swap)
00592 {
00593 mCellIdsOfT2Swaps.push_back(idOfT2Swap);
00594 }
00595
00596 template<unsigned DIM>
00597 void VertexBasedCellPopulation<DIM>::ClearLocationsAndCellIdsOfT2Swaps()
00598 {
00599 mCellIdsOfT2Swaps.clear();
00600 mLocationsOfT2Swaps.clear();
00601 }
00602
00603 template<unsigned DIM>
00604 TetrahedralMesh<DIM, DIM>* VertexBasedCellPopulation<DIM>::GetTetrahedralMeshUsingVertexMesh()
00605 {
00606
00607 assert(DIM == 2);
00608 assert(PetscTools::IsSequential());
00609
00610 unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
00611 unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
00612
00613 std::string mesh_file_name = "mesh";
00614
00615
00616 std::stringstream pid;
00617 pid << getpid();
00618 OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
00619 std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
00620
00621
00622 unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
00623
00624
00625 out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
00626 (*p_node_file) << std::scientific;
00627 (*p_node_file) << std::setprecision(20);
00628 (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;
00629
00630
00631 for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
00632 {
00633 Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
00634
00636 unsigned index = p_node->GetIndex();
00637
00638 c_vector<double, DIM> location = p_node->rGetLocation();
00639
00640 unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;
00641
00642 (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
00643 }
00644
00645
00646 unsigned num_tetrahedral_elements = 0;
00647 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
00648 {
00649 unsigned index = num_vertex_nodes + vertex_elem_index;
00650
00651 c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
00652
00653
00654 unsigned is_boundary_node = 0;
00655 (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
00656
00657
00658 num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
00659 }
00660 p_node_file->close();
00661
00662
00663 out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
00664 (*p_elem_file) << std::scientific;
00665 (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;
00666
00667 std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
00668
00669 unsigned tetrahedral_elem_index = 0;
00670 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
00671 {
00672 VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);
00673
00674
00675 unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
00676 for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
00677 {
00678 unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
00679 unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
00680 unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
00681
00682 (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;
00683
00684
00685 std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
00686 std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
00687 std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
00688
00689 tetrahedral_edges.insert(edge_0);
00690 tetrahedral_edges.insert(edge_1);
00691 tetrahedral_edges.insert(edge_2);
00692 }
00693 }
00694 p_elem_file->close();
00695
00696
00697 out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
00698 (*p_edge_file) << std::scientific;
00699 (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;
00700
00701 unsigned edge_index = 0;
00702 for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
00703 edge_iter != tetrahedral_edges.end();
00704 ++edge_iter)
00705 {
00706 std::pair<unsigned, unsigned> this_edge = *edge_iter;
00707
00708
00709 bool is_boundary_edge = false;
00710 if (this_edge.first < mpMutableVertexMesh->GetNumNodes() &&
00711 this_edge.second < mpMutableVertexMesh->GetNumNodes())
00712 {
00713 is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
00714 mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
00715 }
00716 unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
00717
00718 (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
00719 }
00720 p_edge_file->close();
00721
00722
00723 TetrahedralMesh<DIM, DIM>* p_mesh = new TetrahedralMesh<DIM, DIM>;
00724
00725 {
00726 TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
00727 p_mesh->ConstructFromMeshReader(mesh_reader);
00728 }
00729
00730
00731 output_file_handler.FindFile("").Remove();
00732
00733
00734 p_mesh->SetMeshHasChangedSinceLoading();
00735
00736 return p_mesh;
00737 }
00738
00739
00740 template class VertexBasedCellPopulation<1>;
00741 template class VertexBasedCellPopulation<2>;
00742 template class VertexBasedCellPopulation<3>;
00743
00744
00745 #include "SerializationExportWrapperForCpp.hpp"
00746 EXPORT_TEMPLATE_CLASS_SAME_DIMS(VertexBasedCellPopulation)