Chaste Commit::6e4f5fe395bca70eb7641cf6e0e87f450383ca5a
VertexBasedCellPopulation.cpp
1/*
2
3Copyright (c) 2005-2026, University of Oxford.
4All rights reserved.
5
6University of Oxford means the Chancellor, Masters and Scholars of the
7University of Oxford, having an administrative office at Wellington
8Square, Oxford OX1 2JD, UK.
9
10This file is part of Chaste.
11
12Redistribution and use in source and binary forms, with or without
13modification, are permitted provided that the following conditions are met:
14 * Redistributions of source code must retain the above copyright notice,
15 this list of conditions and the following disclaimer.
16 * Redistributions in binary form must reproduce the above copyright notice,
17 this list of conditions and the following disclaimer in the documentation
18 and/or other materials provided with the distribution.
19 * Neither the name of the University of Oxford nor the names of its
20 contributors may be used to endorse or promote products derived from this
21 software without specific prior written permission.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*/
35
36#include "VertexBasedCellPopulation.hpp"
37#include "Warnings.hpp"
38#include "ShortAxisVertexBasedDivisionRule.hpp"
39#include "StepSizeException.hpp"
40#include "WildTypeCellMutationState.hpp"
41#include "Cylindrical2dVertexMesh.hpp"
42#include "SmartPointers.hpp"
43#include "T2SwapCellKiller.hpp"
44#include "ApoptoticCellProperty.hpp"
45#include "CellPopulationElementWriter.hpp"
46#include "VertexT1SwapLocationsWriter.hpp"
47#include "VertexT2SwapLocationsWriter.hpp"
48#include "VertexT3SwapLocationsWriter.hpp"
49#include "VertexIntersectionSwapLocationsWriter.hpp"
50#include "AbstractCellBasedSimulation.hpp"
51
52template<unsigned DIM>
54 std::vector<CellPtr>& rCells,
55 bool deleteMesh,
56 bool validate,
57 const std::vector<unsigned> locationIndices)
58 : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices),
59 mDeleteMesh(deleteMesh),
60 mOutputCellRearrangementLocations(true),
61 mRestrictVertexMovement(true)
62{
65
66 // If no location indices are specified, associate with elements from the mesh (assumed to be sequentially ordered).
67 std::list<CellPtr>::iterator it = this->mCells.begin();
68 for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
69 {
70 unsigned index = locationIndices.empty() ? i : locationIndices[i]; // assume that the ordering matches
72 }
73
74 // Check each element has only one cell attached
75 if (validate)
76 {
77 Validate();
78 }
79
80 // If cells contain an SRN model, then we need to track mesh operations
81 // and update SRNs accordingly. Here we assume the first cell is a representative of other cells
82 if ((*this->mCells.begin())->HasSrnModel())
83 {
84 mPopulationSrn.SetVertexCellPopulation(this);
86 }
87}
88
89template<unsigned DIM>
93 mDeleteMesh(true),
94 mOutputCellRearrangementLocations(true),
95 mRestrictVertexMovement(true),
96 mPopulationSrn(rPopSrn)
97{
99 mPopulationSrn.SetVertexCellPopulation(this);
100}
101
102template<unsigned DIM>
104{
105 if (mDeleteMesh)
106 {
107 delete &this->mrMesh;
108 }
109}
110
111template<unsigned DIM>
113{
114 // Take the average of the cells containing this vertex
115 double average_damping_constant = 0.0;
116
117 std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
118
119 unsigned num_containing_elements = containing_elements.size();
120 if (num_containing_elements == 0)
121 {
122 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << nodeIndex << " is not contained in any elements, so GetDampingConstant() returns zero");
123 }
124
125 double temp = 1.0/((double) num_containing_elements);
126 for (std::set<unsigned>::iterator iter = containing_elements.begin();
127 iter != containing_elements.end();
128 ++iter)
129 {
130 CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
131 bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
132
133 if (cell_is_wild_type)
134 {
135 average_damping_constant += this->GetDampingConstantNormal()*temp;
136 }
137 else
138 {
139 average_damping_constant += this->GetDampingConstantMutant()*temp;
140 }
141 }
142
143 return average_damping_constant;
144}
145
146template<unsigned DIM>
148{
149 return *mpMutableVertexMesh;
150}
151
152template<unsigned DIM>
154{
155 return *mpMutableVertexMesh;
156}
157
158template<unsigned DIM>
160{
161 return mpMutableVertexMesh->GetElement(elementIndex);
162}
163
164template<unsigned DIM>
166{
167 return this->mrMesh.GetNumNodes();
168}
169
170template<unsigned DIM>
172{
173 return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
174}
175
176template<unsigned DIM>
178{
179 return this->mrMesh.GetNode(index);
180}
181
182template<unsigned DIM>
184{
185 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
186 return this->rGetMesh().GetNeighbouringElementIndices(elem_index);
187}
188
189template<unsigned DIM>
190std::set<std::pair<unsigned, unsigned>>
192{
193 std::set<std::pair<unsigned, unsigned>> neighbours;
194 auto cellLocationIndex = this->GetLocationIndexUsingCell(pCell);
195 auto p_element = this->GetElement(cellLocationIndex);
196 auto global_edge_index = p_element->GetEdgeGlobalIndex(edgeLocalIndex);
197 auto neighbour_element_indices = p_element->GetNeighbouringElementAtEdgeIndex(edgeLocalIndex);
198
199 // Normally there is only one neighbouring element
200 for (auto neighbour_element_index : neighbour_element_indices)
201 {
202 auto p_neighbour_element = this->GetElement(neighbour_element_index);
203
204 // Iterate over neighbouring element indices
205 for (unsigned elem_index = 0; elem_index < p_neighbour_element->GetNumEdges(); elem_index++)
206 {
207 // If the neighbours edge matches EdgeLocalIndex
208 if (p_neighbour_element->GetEdge(elem_index)->GetIndex() == global_edge_index)
209 {
210 neighbours.insert(std::pair<unsigned, unsigned>(neighbour_element_index, elem_index));
211 }
212 }
213 }
214
215 return neighbours;
216}
217
218template<unsigned DIM>
220{
221 return mpMutableVertexMesh->AddNode(pNewNode);
222}
223
224template<unsigned DIM>
225void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
226{
227 mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
228}
229
230template<unsigned DIM>
232{
233 return mpMutableVertexMesh->GetElement(this->GetLocationIndexUsingCell(pCell));
234}
235
236template<unsigned DIM>
238{
239 return mpMutableVertexMesh->GetNumElements();
240}
241
242template<unsigned DIM>
243CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, CellPtr pParentCell)
244{
245 // Get the element associated with this cell
246 VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
247
248 // Get the orientation of division
249 c_vector<double, DIM> division_vector = mpVertexBasedDivisionRule->CalculateCellDivisionVector(pParentCell, *this);
250
251 // Divide the element
252 unsigned new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element, division_vector, true);
253
254 // Associate the new cell with the element
255 this->mCells.push_back(pNewCell);
256
257 // Update location cell map
258 CellPtr p_created_cell = this->mCells.back();
259 this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
260 this->mCellLocationMap[p_created_cell.get()] = new_element_index;
261
262 return p_created_cell;
263}
264
265template<unsigned DIM>
267{
268 unsigned num_removed = 0;
269
270 for (std::list<CellPtr>::iterator it = this->mCells.begin();
271 it != this->mCells.end();
272 )
273 {
274 if ((*it)->IsDead())
275 {
276 // Count the cell as dead
277 num_removed++;
278
279 // Remove the element from the mesh if it is not deleted yet
281 if (!(this->GetElement(this->GetLocationIndexUsingCell((*it)))->IsDeleted()))
282 {
283 // This warning relies on the fact that there is only one other possibility for
284 // vertex elements to be marked as deleted: a T2 swap
285 WARN_ONCE_ONLY("A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
286 mpMutableVertexMesh->DeleteElementPriorToReMesh(this->GetLocationIndexUsingCell((*it)));
287 }
288
289 // Delete the cell
290 it = this->mCells.erase(it);
291 }
292 else
293 {
294 ++it;
295 }
296 }
297 return num_removed;
298}
299
300template<unsigned DIM>
301void VertexBasedCellPopulation<DIM>::CheckForStepSizeException(unsigned nodeIndex, c_vector<double,DIM>& rDisplacement, double dt)
302{
303 double length = norm_2(rDisplacement);
304
305 /* There are two reasons to adjust movement in a vertex model:
306 * - either the movement is large enough to cause a T2 swap,
307 * - or the movement is too large (i.e. larger than AbsoluteMovementThreshold).
308 *
309 * In the first case we want to restrict movement but not throw an exception, just a warning.
310 * In the second case we want to throw an exception which can be used by the adaptive timestepper.
311 * This is handled in the parent class, which checks for movement above the AbsoluteMovementThreshold
312 * and throws an exception. In this class we check for movement above half the CellRearrangementThreshold
313 * and restrict movement if this is the case, but only throw an exception if movement is above the
314 * AbsoluteMovementThreshold.
315 */
316
317 // Check for movement above the AbsoluteMovementThreshold first, and throw an exception if exceeded
319
320 if (mRestrictVertexMovement)
321 {
322 if (length > 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())
323 {
324 // restrict the movement
325 rDisplacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/length;
326
327 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.");
328 }
329 }
330}
331
332template<unsigned DIM>
334{
335 return GetElementCorrespondingToCell(pCell)->IsDeleted();
336}
337
338template<unsigned DIM>
339void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
340{
341 VertexElementMap element_map(mpMutableVertexMesh->GetNumAllElements());
342 mpMutableVertexMesh->ReMesh(element_map);
343
344 if (!element_map.IsIdentityMap())
345 {
346 // Fix up the mappings between CellPtrs and VertexElements
348 std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
349
350 this->mCellLocationMap.clear();
351 this->mLocationCellMap.clear();
352
353 for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
354 cell_iter != this->mCells.end();
355 ++cell_iter)
356 {
357 // The cell vector should only ever contain living cells
358 unsigned old_elem_index = old_map[(*cell_iter).get()];
359 assert(!element_map.IsDeleted(old_elem_index));
360
361 unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
362 this->SetCellUsingLocationIndex(new_elem_index, *cell_iter);
363 }
364
365 // Check that each VertexElement has only one CellPtr associated with it in the updated cell population
366 Validate();
367 }
368
369 if (this->GetNumAllCells()>0)
370 {
371 //First cell is representative of other cells
372 bool EdgeModelOrNot = (*this->mCells.begin())->GetSrnModel()->HasEdgeModel();
373
374 if (EdgeModelOrNot)
375 {
376 // Note that SRN initialisation in daughter cell is handled through Cell::Divide() method
377 mPopulationSrn.UpdateSrnAfterBirthOrDeath(element_map);
378 }
379 }
380
381 element_map.ResetToIdentity();
382}
383
384template<unsigned DIM>
386{
387 // Check each element has only one cell attached
388 std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
389 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
390 cell_iter != this->End();
391 ++cell_iter)
392 {
393 unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
394 validated_element[elem_index]++;
395 }
396
397 for (unsigned i=0; i<validated_element.size(); i++)
398 {
399 if (validated_element[i] == 0)
400 {
401 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " does not appear to have a cell associated with it");
402 }
403
404 if (validated_element[i] > 1)
405 {
406 // This should never be reached as you can only set one cell per element index
407 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
408 }
409 }
410}
411
412template<unsigned DIM>
414{
415 pPopulationWriter->Visit(this);
416}
417
418template<unsigned DIM>
420{
421 pPopulationCountWriter->Visit(this);
422}
423
424template<unsigned DIM>
426{
427 pPopulationEventWriter->Visit(this);
428}
429
430template<unsigned DIM>
431void VertexBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
432{
433 pCellWriter->VisitCell(pCell, this);
434}
435
436template<unsigned DIM>
438{
439 // Get the vertex element index corresponding to this cell
440 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
441
442 // Get the element rosette rank from the vertex mesh
443 unsigned rosette_rank = mpMutableVertexMesh->GetRosetteRankOfElement(elem_index);
444
445 return rosette_rank;
446}
447
448template<unsigned DIM>
450{
451 // Get the vertex element index corresponding to this cell
452 unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
453
454 // Get the cell's volume from the vertex mesh
455 double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
456
457 return cell_volume;
458}
459
460template<unsigned DIM>
462{
463 unsigned num_cells = this->GetNumAllCells();
464 if (num_cells>0)
465 {
466 auto cells = this->rGetCells();
467 boost::shared_ptr<CellEdgeData> p_cell_edge_data = (*cells.begin())->GetCellEdgeData();
468 //If edge SRNs are specified, then write vtk results into a mesh where quantities
469 //associated with each edge are taken into account. We assume that the first cell is
470 //representative of all cells.
471 //Edge VTKs are also written if cells contain CellEdgeData
472
473 //If cells contain edge data
474 if (p_cell_edge_data->GetNumItems() != 0&&mWriteEdgeVtkResults)
475 {
476 this->WriteCellEdgeVtkResultsToFile(rDirectory);
477 return;
478 }
479
480 //If cells don't contain edge data, output CellData only
481 if (p_cell_edge_data->GetNumItems() == 0&&mWriteCellVtkResults)
482 {
483 this->WriteCellVtkResultsToFile(rDirectory);
484 }
485 }
486}
487
488template<unsigned DIM>
490{
491#ifdef CHASTE_VTK
492
493 // Create mesh writer for VTK output
494 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
495
496 // We avoid writing out CellData if the population is empty (i.e. no cells).
497 unsigned num_cells = this->GetNumAllCells();
498
499 if (num_cells > 0)
500 {
501 // Iterate over any cell writers that are present
502 for (auto cell_writer_iter = this->mCellWriters.begin();
503 cell_writer_iter != this->mCellWriters.end();
504 ++cell_writer_iter)
505 {
506 // Create vector to store VTK cell data
507 std::vector<double> vtk_cell_data(num_cells);
508
509 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
510 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
511 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
512 ++elem_iter)
513 {
514 // Get index of this element in the vertex mesh
515 unsigned elem_index = elem_iter->GetIndex();
516
517 // Get the cell corresponding to this element
518 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
519 assert(p_cell);
520
521 // Populate the vector of VTK cell data
522 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
523 }
524
525 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
526 }
527
528 // When outputting any CellData, we assume that the first cell is representative of all cells
529 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
530 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
531
532 std::vector<std::vector<double> > cell_data;
533 for (unsigned var=0; var<num_cell_data_items; var++)
534 {
535 std::vector<double> cell_data_var(num_cells);
536 cell_data.push_back(cell_data_var);
537 }
538
539 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
540 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
541 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
542 ++elem_iter)
543 {
544 // Get index of this element in the vertex mesh
545 unsigned elem_index = elem_iter->GetIndex();
546
547 // Get the cell corresponding to this element
548 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
549 assert(p_cell);
550
551 for (unsigned var=0; var<num_cell_data_items; var++)
552 {
553 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
554 }
555 }
556 for (unsigned var=0; var<num_cell_data_items; var++)
557 {
558 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
559 }
560 }
561
562 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
563 std::stringstream time;
564 time << num_timesteps;
565
566 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
567
568 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
569 *(this->mpVtkMetaFile) << num_timesteps;
570 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
571 *(this->mpVtkMetaFile) << num_timesteps;
572 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
573
574#endif //CHASTE_VTK
575}
576
577template<unsigned DIM>
579{
580#ifdef CHASTE_VTK
581 //Writes cell only data
582 {
583 // Create mesh writer for VTK output
584 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "cell_results", false);
585
586 // Iterate over any cell writers that are present
587 unsigned num_cells = this->GetNumAllCells();
588 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
589 cell_writer_iter != this->mCellWriters.end();
590 ++cell_writer_iter)
591 {
592 // Create vector to store VTK cell data
593 std::vector<double> vtk_cell_data(num_cells);
594
595 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
596 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
597 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
598 ++elem_iter)
599 {
600 // Get index of this element in the vertex mesh
601 unsigned elem_index = elem_iter->GetIndex();
602
603 // Get the cell corresponding to this element
604 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
605 assert(p_cell);
606
607 // Populate the vector of VTK cell data
608 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
609 }
610
611 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
612 }
613
614 // When outputting any CellData, we assume that the first cell is representative of all cells
615 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
616 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
617
618 std::vector<std::vector<double> > cell_data;
619 for (unsigned var=0; var<num_cell_data_items; var++)
620 {
621 std::vector<double> cell_data_var(num_cells);
622 cell_data.push_back(cell_data_var);
623 }
624
625 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
626 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
627 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
628 ++elem_iter)
629 {
630 // Get index of this element in the vertex mesh
631 unsigned elem_index = elem_iter->GetIndex();
632
633 // Get the cell corresponding to this element
634 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
635 assert(p_cell);
636
637 for (unsigned var=0; var<num_cell_data_items; var++)
638 {
639 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
640 }
641 }
642 for (unsigned var=0; var<num_cell_data_items; var++)
643 {
644 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
645 }
646
647 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
648 std::stringstream time;
649 time << num_timesteps;
650
651 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
652
653 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
654 *(this->mpVtkMetaFile) << num_timesteps;
655 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"cell_results_";
656 *(this->mpVtkMetaFile) << num_timesteps;
657 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
658 }
659 // Create mesh writer for VTK output
660 TrapezoidEdgeVertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
661 unsigned num_edges = 0;
662
663 // Here elements are synonymous with cells
664 const unsigned num_cells = this->GetNumElements();
665 //Similarly as in TrapEdgeVerteMeshWriter, but instead of nodes
666 //we fill edge arrays
667 //The first value MUST be zero
668 std::vector<unsigned> cell_offset_dist(num_cells);
669 //The order of stored data is illustrated below:
670 // [_____|_][____|_]
671 // ^^^^ ^
672 // edge cell interior
673 for (unsigned i=1; i<num_cells; ++i)
674 {
675 cell_offset_dist[i] = cell_offset_dist[i-1]+this->GetElement(i-1)->GetNumEdges()+1;
676 num_edges += this->GetElement(i)->GetNumEdges();
677 }
678 // Total number of edges
679 num_edges += this->GetElement(0)->GetNumEdges();
680
681 // Iterate over any cell writers that are present
682 // The data that is written below is associated with the entire cell
683 // E.g. the cell age. Thus, edges also share the same characteristic
684 for (auto cell_writer : this->mCellWriters)
685 {
686 // Create vector to store VTK cell data
687 std::vector<double> vtk_cell_data(num_edges+num_cells);
688
689 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
690 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
691 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
692 ++elem_iter)
693 {
694 // Get index of this element in the vertex mesh
695 unsigned elem_index = elem_iter->GetIndex();
696
697 // Get the cell corresponding to this element
698 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
699 assert(p_cell);
700
701 // Write the same property in all the edges
702 unsigned elem_num_edges = elem_iter->GetNumEdges();
703
704 // Edge data
705 for (unsigned e = 0; e < elem_num_edges; ++e)
706 {
707 // Populate the vector of VTK cell data
708 vtk_cell_data[cell_offset_dist[elem_index]+e] = cell_writer->GetCellDataForVtkOutput(p_cell, this);
709 }
710 // Internal cell data
711 vtk_cell_data[cell_offset_dist[elem_index]+elem_num_edges] = cell_writer->GetCellDataForVtkOutput(p_cell, this);
712 }
713 mesh_writer.AddCellData(cell_writer->GetVtkCellDataName(), vtk_cell_data);
714 }
715 // When outputting CellData and CellEdgeData, we assume that the first cell
716 // and its edges are representative of the population
717
718 // Get cell/edge data names
719 const unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
720 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
721
722 const unsigned num_edge_data_items = this->Begin()->GetCellEdgeData()->GetNumItems();
723 std::vector<std::string> edge_data_names = this->Begin()->GetCellEdgeData()->GetKeys();
724
725 // Total number of data items. Each data item (edge+interior) has its own value
726 const unsigned num_data_items = num_edge_data_items + num_cell_data_items;
727 std::vector<std::string> data_names(num_data_items);
728 for (unsigned var=0; var<num_edge_data_items; ++var)
729 {
730 data_names[var] = edge_data_names[var];
731 }
732 for (unsigned var=num_edge_data_items; var<num_data_items; ++var)
733 {
734 data_names[var] = cell_data_names[var-num_edge_data_items];
735 }
736 std::vector<std::vector<double> > data_values(num_data_items,
737 std::vector<double>(num_edges + num_cells));
738
739 // Writing CellEdgeData values to the edges of the cells
740 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
741 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
742 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
743 ++elem_iter)
744 {
745 const unsigned elem_index = elem_iter->GetIndex();
746 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
747 assert(p_cell);
748
749 // Edge data for interior data is set to zero.
750 unsigned elem_num_edges = elem_iter->GetNumEdges();
751 for (unsigned var = 0; var < num_edge_data_items; ++var)
752 {
753 // Write the same property in all the edges
754 for (unsigned e = 0; e < elem_num_edges; ++e)
755 {
756 data_values[var][cell_offset_dist[elem_index]+e] = p_cell->GetCellEdgeData()->GetItem(data_names[var])[e];
757 }
758 // Cell interior is set to zero
759 data_values[var][cell_offset_dist[elem_index]+elem_num_edges] = 0.0;
760 }
761 }
762
763 // Writing CellData values to the interior of the cells
764 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
765 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
766 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
767 ++elem_iter)
768 {
769 // Get index of this element in the vertex mesh
770 unsigned elem_index = elem_iter->GetIndex();
771 unsigned elem_num_edges = elem_iter->GetNumEdges();
772
773 // Get the cell corresponding to this element
774 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
775 assert(p_cell);
776
777 for (unsigned var = num_edge_data_items; var<num_data_items; ++var)
778 {
779 // Data in the edges are set to 0
780 for (unsigned e = 0; e < elem_num_edges; ++e)
781 {
782 data_values[var][cell_offset_dist[elem_index]+e] = 0.0;
783 }
784 // Filling cell interior data
785 data_values[var][cell_offset_dist[elem_index]+elem_num_edges] = p_cell->GetCellData()->GetItem(data_names[var]);
786 }
787 }
788
789 for (unsigned var=0; var<num_data_items; var++)
790 {
791 mesh_writer.AddCellData(data_names[var], data_values[var]);
792 }
793
794 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
795 std::stringstream time;
796 time << num_timesteps;
797
798 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
799
800 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
801 *(this->mpVtkMetaFile) << num_timesteps;
802 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
803 *(this->mpVtkMetaFile) << num_timesteps;
804 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
805#endif //CHASTE_VTK
806}
807
808template<unsigned DIM>
810{
811 if (this->mOutputResultsForChasteVisualizer)
812 {
813 if (!this-> template HasWriter<CellPopulationElementWriter>())
814 {
815 this-> template AddPopulationWriter<CellPopulationElementWriter>();
816 }
817 }
818
819 if (mOutputCellRearrangementLocations)
820 {
821 if (!this-> template HasWriter<VertexT1SwapLocationsWriter>())
822 {
823 this-> template AddPopulationWriter<VertexT1SwapLocationsWriter>();
824 }
825 if (!this-> template HasWriter<VertexT2SwapLocationsWriter>())
826 {
827 this-> template AddPopulationWriter<VertexT2SwapLocationsWriter>();
828 }
829 if (!this-> template HasWriter<VertexT3SwapLocationsWriter>())
830 {
831 this-> template AddPopulationWriter<VertexT3SwapLocationsWriter>();
832 }
833 if (!this-> template HasWriter<VertexIntersectionSwapLocationsWriter>())
834 {
835 this-> template AddPopulationWriter<VertexIntersectionSwapLocationsWriter>();
836 }
837 }
838
840}
841
842template<unsigned DIM>
844{
845 return mOutputCellRearrangementLocations;
846}
847
848template<unsigned DIM>
850{
851 mOutputCellRearrangementLocations = outputCellRearrangementLocations;
852}
853
854template<unsigned DIM>
856{
857 *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
858 *rParamsFile << "\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
859 *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
860 *rParamsFile << "\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations << "</OutputCellRearrangementLocations>\n";
861
862 // Add the division rule parameters
863 *rParamsFile << "\t\t<VertexBasedDivisionRule>\n";
864 mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
865 *rParamsFile << "\t\t</VertexBasedDivisionRule>\n";
866
867 // Call method on direct parent class
869}
870
871template<unsigned DIM>
872double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
873{
874 // Call GetWidth() on the mesh
875 double width = this->mrMesh.GetWidth(rDimension);
876
877 return width;
878}
879
880template<unsigned DIM>
882{
883 return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
884}
885
886template<unsigned DIM>
887boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > VertexBasedCellPopulation<DIM>::GetVertexBasedDivisionRule()
888{
889 return mpVertexBasedDivisionRule;
890}
891
892template<unsigned DIM>
894{
895 mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
896}
897
898template<unsigned DIM>
900{
901 // This method only works in 2D sequential
902 if (DIM != 2)
903 {
904 EXCEPTION("This function is only valid in 2D"); // LCOV_EXCL_LINE
905 }
906 assert(PetscTools::IsSequential());
907
908 unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
909 unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
910
911 std::string mesh_file_name = "mesh";
912
913 // Get a unique temporary foldername
914 std::stringstream pid;
915 pid << getpid();
916 OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
917 std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
918
919 // Compute the number of nodes in the TetrahedralMesh
920 unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
921
922 // Write node file
923 out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
924 (*p_node_file) << std::scientific;
925 (*p_node_file) << std::setprecision(20);
926 (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;
927
928 // Begin by writing each node in the VertexMesh
929 for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
930 {
931 Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
932
934 unsigned index = p_node->GetIndex();
935 const c_vector<double, DIM>& r_location = p_node->rGetLocation();
936 unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;
937
938 (*p_node_file) << index << "\t" << r_location[0] << "\t" << r_location[1] << "\t" << is_boundary_node << std::endl;
939 }
940
941 // Now write an additional node at each VertexElement's centroid
942 unsigned num_tetrahedral_elements = 0;
943 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
944 {
945 unsigned index = num_vertex_nodes + vertex_elem_index;
946
947 c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
948
949 // Any node located at a VertexElement's centroid will not be a boundary node
950 unsigned is_boundary_node = 0;
951 (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
952
953 // Also keep track of how many tetrahedral elements there will be
954 num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
955 }
956 p_node_file->close();
957
958 // Write element file
959 out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
960 (*p_elem_file) << std::scientific;
961 (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;
962
963 std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
964
965 unsigned tetrahedral_elem_index = 0;
966 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
967 {
968 VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);
969
970 // Iterate over nodes owned by this VertexElement
971 unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
972 for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
973 {
974 unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
975 unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
976 unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
977
978 (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;
979
980 // Add edges to the set if they are not already present
981 std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
982 std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
983 std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
984
985 tetrahedral_edges.insert(edge_0);
986 tetrahedral_edges.insert(edge_1);
987 tetrahedral_edges.insert(edge_2);
988 }
989 }
990 p_elem_file->close();
991
992 // Write edge file
993 out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
994 (*p_edge_file) << std::scientific;
995 (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;
996
997 unsigned edge_index = 0;
998 for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
999 edge_iter != tetrahedral_edges.end();
1000 ++edge_iter)
1001 {
1002 std::pair<unsigned, unsigned> this_edge = *edge_iter;
1003
1004 // To be a boundary edge both nodes need to be boundary nodes.
1005 bool is_boundary_edge = false;
1006 if (this_edge.first < mpMutableVertexMesh->GetNumNodes() &&
1007 this_edge.second < mpMutableVertexMesh->GetNumNodes())
1008 {
1009 is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
1010 mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
1011 }
1012 unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
1013
1014 (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
1015 }
1016 p_edge_file->close();
1017
1018 // Having written the mesh to file, now construct it using TrianglesMeshReader
1020
1021 // Nested scope so reader is destroyed before we remove the temporary files
1022 {
1023 TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
1024 p_mesh->ConstructFromMeshReader(mesh_reader);
1025 }
1026
1027 // Delete the temporary files
1028 output_file_handler.FindFile("").Remove();
1029
1030 // The original files have been deleted, it is better if the mesh object forgets about them
1032
1033 return p_mesh;
1034}
1035
1036template<unsigned DIM>
1037std::vector< c_vector< double, DIM > > VertexBasedCellPopulation<DIM>::GetLocationsOfT2Swaps()
1038{
1039 return mLocationsOfT2Swaps;
1040}
1041
1042template<unsigned DIM>
1044{
1045 return mCellIdsOfT2Swaps;
1046}
1047
1048template<unsigned DIM>
1049void VertexBasedCellPopulation<DIM>::AddLocationOfT2Swap(c_vector< double, DIM> locationOfT2Swap)
1050{
1051 mLocationsOfT2Swaps.push_back(locationOfT2Swap);
1052}
1053
1054template<unsigned DIM>
1056{
1057 mCellIdsOfT2Swaps.push_back(idOfT2Swap);
1058}
1059
1060template<unsigned DIM>
1062{
1063 mCellIdsOfT2Swaps.clear();
1064 mLocationsOfT2Swaps.clear();
1065}
1066
1067template<unsigned DIM>
1069{
1070 bool non_apoptotic_cell_present = true;
1071
1072 if (pdeNodeIndex < this->GetNumNodes())
1073 {
1074 std::set<unsigned> containing_element_indices = this->GetNode(pdeNodeIndex)->rGetContainingElementIndices();
1075
1076 for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
1077 iter != containing_element_indices.end();
1078 iter++)
1079 {
1080 if (this->GetCellUsingLocationIndex(*iter)->template HasCellProperty<ApoptoticCellProperty>() )
1081 {
1082 non_apoptotic_cell_present = false;
1083 break;
1084 }
1085 }
1086 }
1087 else
1088 {
1089 /*
1090 * This node of the tetrahedral finite element mesh is in the centre of the element of the
1091 * vertex-based cell population, so we can use an offset to compute which cell to interrogate.
1092 */
1093 non_apoptotic_cell_present = !(this->GetCellUsingLocationIndex(pdeNodeIndex - this->GetNumNodes())->template HasCellProperty<ApoptoticCellProperty>());
1094 }
1095
1096 return non_apoptotic_cell_present;
1097}
1098
1099template<unsigned DIM>
1101 unsigned pdeNodeIndex,
1102 std::string& rVariableName,
1103 bool dirichletBoundaryConditionApplies,
1104 double dirichletBoundaryValue)
1105{
1106 unsigned num_nodes = this->GetNumNodes();
1107 double value = 0.0;
1108
1109 // Cells correspond to nodes in the centre of the vertex element; nodes on vertices have averaged values from containing cells
1110
1111 if (pdeNodeIndex >= num_nodes)
1112 {
1113 // Offset to relate elements in vertex mesh to nodes in tetrahedral mesh
1114 assert(pdeNodeIndex-num_nodes < num_nodes);
1115
1116 CellPtr p_cell = this->GetCellUsingLocationIndex(pdeNodeIndex - num_nodes);
1117 value = p_cell->GetCellData()->GetItem(rVariableName);
1118 }
1119 else
1120 {
1122 if (dirichletBoundaryConditionApplies)
1123 {
1124 // We need to impose the Dirichlet boundaries again here as not represented in cell data
1125 value = dirichletBoundaryValue;
1126 }
1127 else
1128 {
1129 assert(pdeNodeIndex < num_nodes);
1130 Node<DIM>* p_node = this->GetNode(pdeNodeIndex);
1131
1132 // Average over data from containing elements (cells)
1133 std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
1134 for (std::set<unsigned>::iterator index_iter = containing_elements.begin();
1135 index_iter != containing_elements.end();
1136 ++index_iter)
1137 {
1138 assert(*index_iter < num_nodes);
1139 CellPtr p_cell = this->GetCellUsingLocationIndex(*index_iter);
1140 value += p_cell->GetCellData()->GetItem(rVariableName);
1141 }
1142 value /= containing_elements.size();
1143 }
1144 }
1145
1146 return value;
1147}
1148
1149template<unsigned DIM>
1151{
1152 return 0.002;
1153}
1154
1155template<unsigned DIM>
1157{
1158 if (bool(dynamic_cast<Cylindrical2dVertexMesh*>(&(this->mrMesh))))
1159 {
1160 *pVizSetupFile << "MeshWidth\t" << this->GetWidth(0) << "\n";
1161 }
1162}
1163
1164template<unsigned DIM>
1166{
1167 MAKE_PTR_ARGS(T2SwapCellKiller<DIM>, p_t2_swap_cell_killer, (this));
1168 pSimulation->AddCellKiller(p_t2_swap_cell_killer);
1169}
1170
1171
1172template<unsigned DIM>
1174{
1175 return mRestrictVertexMovement;
1176}
1177
1178template<unsigned DIM>
1180{
1181 mRestrictVertexMovement = restrictMovement;
1182}
1183
1184template<unsigned DIM>
1189
1190template<unsigned DIM>
1195
1196template<unsigned DIM>
1198{
1199 mWriteCellVtkResults = new_val;
1200}
1201
1202template<unsigned DIM>
1204{
1205 mWriteEdgeVtkResults = new_val;
1206}
1207
1208// Explicit instantiation
1209template class VertexBasedCellPopulation<1>;
1210template class VertexBasedCellPopulation<2>;
1211template class VertexBasedCellPopulation<3>;
1212
1213// Serialization for Boost >= 1.36
#define EXCEPTION(message)
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
void AddCellKiller(boost::shared_ptr< AbstractCellKiller< SPACE_DIM > > pCellKiller)
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
unsigned GetNumNodes() const
unsigned GetNodeGlobalIndex(unsigned localIndex) const
void SetMeshHasChangedSinceLoading()
virtual void CheckForStepSizeException(unsigned nodeIndex, c_vector< double, SPACE_DIM > &rDisplacement, double dt)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
void Remove() const
void SetMeshOperationTracking(const bool track)
Definition Node.hpp:59
std::set< unsigned > & rGetContainingElementIndices()
Definition Node.cpp:300
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition Node.cpp:139
bool IsBoundaryNode() const
Definition Node.cpp:164
unsigned GetIndex() const
Definition Node.cpp:158
std::string GetOutputDirectoryFullPath() const
FileFinder FindFile(std::string leafName) const
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
static bool IsSequential()
static SimulationTime * Instance()
unsigned GetTimeStepsElapsed() const
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, const std::string &stamp="")
void AddCellData(std::string dataName, std::vector< double > dataPayload)
double GetDampingConstant(unsigned nodeIndex)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
void OutputCellPopulationParameters(out_stream &rParamsFile)
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
virtual void WriteCellVtkResultsToFile(const std::string &rDirectory)
void SetWriteCellVtkResults(const bool new_val)
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > GetVertexBasedDivisionRule()
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
virtual void AcceptPopulationEventWriter(boost::shared_ptr< AbstractCellPopulationEventWriter< DIM, DIM > > pPopulationEventWriter)
VertexElement< DIM, DIM > * GetElementCorrespondingToCell(CellPtr pCell)
virtual void SimulationSetupHook(AbstractCellBasedSimulation< DIM, DIM > *pSimulation)
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
unsigned AddNode(Node< DIM > *pNewNode)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
VertexBasedCellPopulation(MutableVertexMesh< DIM, DIM > &rMesh, std::vector< CellPtr > &rCells, bool deleteMesh=false, bool validate=true, const std::vector< unsigned > locationIndices=std::vector< unsigned >())
unsigned GetRosetteRankOfCell(CellPtr pCell)
VertexElement< DIM, DIM > * GetElement(unsigned elementIndex)
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
void AddLocationOfT2Swap(c_vector< double, DIM > locationOfT2Swap)
void SetWriteEdgeVtkResults(const bool new_val)
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
VertexBasedPopulationSrn< DIM > & rGetVertexBasedPopulationSrn()
void SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
MutableVertexMesh< DIM, DIM > & rGetMesh()
void SetVertexBasedDivisionRule(boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > pVertexBasedDivisionRule)
MutableVertexMesh< DIM, DIM > * mpMutableVertexMesh
VertexBasedPopulationSrn< DIM > mPopulationSrn
virtual void WriteCellEdgeVtkResultsToFile(const std::string &rDirectory)
std::set< std::pair< unsigned, unsigned > > GetNeighbouringEdgeIndices(CellPtr pCell, unsigned edgeLocalIndex)
virtual void CheckForStepSizeException(unsigned nodeIndex, c_vector< double, DIM > &rDisplacement, double dt)
std::vector< c_vector< double, DIM > > GetLocationsOfT2Swaps()
void AddCellIdOfT2Swap(unsigned idOfT2Swap)
virtual double GetCellDataItemAtPdeNode(unsigned pdeNodeIndex, std::string &rVariableName, bool dirichletBoundaryConditionApplies=false, double dirichletBoundaryValue=0.0)
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
void Update(bool hasHadBirthsOrDeaths=true)
void SetRestrictVertexMovementBoolean(bool restrictVertexMovement)
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > mpVertexBasedDivisionRule
std::vector< unsigned > GetCellIdsOfT2Swaps()
void SetNode(unsigned index, ChastePoint< DIM > &rNewLocation)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
double GetWidth(const unsigned &rDimension)
Node< DIM > * GetNode(unsigned index)
unsigned GetNewIndex(unsigned oldIndex) const
bool IsDeleted(unsigned index)
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
void AddCellData(std::string dataName, std::vector< double > dataPayload)