Chaste Commit::29c3c4ab2bee00ddd311a035a1e522c03cbe928a
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 // Create mesh writer for VTK output
492 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
493
494 // We avoid writing out CellData if the population is empty (i.e. no cells).
495 unsigned num_cells = this->GetNumAllCells();
496
497 if (num_cells > 0)
498 {
499 // Iterate over any cell writers that are present
500 for (auto cell_writer_iter = this->mCellWriters.begin();
501 cell_writer_iter != this->mCellWriters.end();
502 ++cell_writer_iter)
503 {
504 // Create vector to store VTK cell data
505 std::vector<double> vtk_cell_data(num_cells);
506
507 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
508 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
509 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
510 ++elem_iter)
511 {
512 // Get index of this element in the vertex mesh
513 unsigned elem_index = elem_iter->GetIndex();
514
515 // Get the cell corresponding to this element
516 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
517 assert(p_cell);
518
519 // Populate the vector of VTK cell data
520 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
521 }
522
523 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
524 }
525
526 // When outputting any CellData, we assume that the first cell is representative of all cells
527 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
528 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
529
530 std::vector<std::vector<double> > cell_data;
531 for (unsigned var=0; var<num_cell_data_items; var++)
532 {
533 std::vector<double> cell_data_var(num_cells);
534 cell_data.push_back(cell_data_var);
535 }
536
537 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
538 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
539 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
540 ++elem_iter)
541 {
542 // Get index of this element in the vertex mesh
543 unsigned elem_index = elem_iter->GetIndex();
544
545 // Get the cell corresponding to this element
546 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
547 assert(p_cell);
548
549 for (unsigned var=0; var<num_cell_data_items; var++)
550 {
551 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
552 }
553 }
554 for (unsigned var=0; var<num_cell_data_items; var++)
555 {
556 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
557 }
558 }
559
560 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
561 std::stringstream time;
562 time << num_timesteps;
563
564 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
565
566 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
567 *(this->mpVtkMetaFile) << num_timesteps;
568 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
569 *(this->mpVtkMetaFile) << num_timesteps;
570 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
571}
572
573template<unsigned DIM>
575{
576 //Writes cell only data
577 {
578 // Create mesh writer for VTK output
579 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "cell_results", false);
580
581 // Iterate over any cell writers that are present
582 unsigned num_cells = this->GetNumAllCells();
583 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
584 cell_writer_iter != this->mCellWriters.end();
585 ++cell_writer_iter)
586 {
587 // Create vector to store VTK cell data
588 std::vector<double> vtk_cell_data(num_cells);
589
590 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
591 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
592 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
593 ++elem_iter)
594 {
595 // Get index of this element in the vertex mesh
596 unsigned elem_index = elem_iter->GetIndex();
597
598 // Get the cell corresponding to this element
599 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
600 assert(p_cell);
601
602 // Populate the vector of VTK cell data
603 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
604 }
605
606 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
607 }
608
609 // When outputting any CellData, we assume that the first cell is representative of all cells
610 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
611 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
612
613 std::vector<std::vector<double> > cell_data;
614 for (unsigned var=0; var<num_cell_data_items; var++)
615 {
616 std::vector<double> cell_data_var(num_cells);
617 cell_data.push_back(cell_data_var);
618 }
619
620 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
621 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
622 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
623 ++elem_iter)
624 {
625 // Get index of this element in the vertex mesh
626 unsigned elem_index = elem_iter->GetIndex();
627
628 // Get the cell corresponding to this element
629 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
630 assert(p_cell);
631
632 for (unsigned var=0; var<num_cell_data_items; var++)
633 {
634 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
635 }
636 }
637 for (unsigned var=0; var<num_cell_data_items; var++)
638 {
639 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
640 }
641
642 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
643 std::stringstream time;
644 time << num_timesteps;
645
646 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
647
648 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
649 *(this->mpVtkMetaFile) << num_timesteps;
650 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"cell_results_";
651 *(this->mpVtkMetaFile) << num_timesteps;
652 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
653 }
654 // Create mesh writer for VTK output
655 TrapezoidEdgeVertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
656 unsigned num_edges = 0;
657
658 // Here elements are synonymous with cells
659 const unsigned num_cells = this->GetNumElements();
660 //Similarly as in TrapEdgeVerteMeshWriter, but instead of nodes
661 //we fill edge arrays
662 //The first value MUST be zero
663 std::vector<unsigned> cell_offset_dist(num_cells);
664 //The order of stored data is illustrated below:
665 // [_____|_][____|_]
666 // ^^^^ ^
667 // edge cell interior
668 for (unsigned i=1; i<num_cells; ++i)
669 {
670 cell_offset_dist[i] = cell_offset_dist[i-1]+this->GetElement(i-1)->GetNumEdges()+1;
671 num_edges += this->GetElement(i)->GetNumEdges();
672 }
673 // Total number of edges
674 num_edges += this->GetElement(0)->GetNumEdges();
675
676 // Iterate over any cell writers that are present
677 // The data that is written below is associated with the entire cell
678 // E.g. the cell age. Thus, edges also share the same characteristic
679 for (auto cell_writer : this->mCellWriters)
680 {
681 // Create vector to store VTK cell data
682 std::vector<double> vtk_cell_data(num_edges+num_cells);
683
684 // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
685 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
686 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
687 ++elem_iter)
688 {
689 // Get index of this element in the vertex mesh
690 unsigned elem_index = elem_iter->GetIndex();
691
692 // Get the cell corresponding to this element
693 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
694 assert(p_cell);
695
696 // Write the same property in all the edges
697 unsigned elem_num_edges = elem_iter->GetNumEdges();
698
699 // Edge data
700 for (unsigned e = 0; e < elem_num_edges; ++e)
701 {
702 // Populate the vector of VTK cell data
703 vtk_cell_data[cell_offset_dist[elem_index]+e] = cell_writer->GetCellDataForVtkOutput(p_cell, this);
704 }
705 // Internal cell data
706 vtk_cell_data[cell_offset_dist[elem_index]+elem_num_edges] = cell_writer->GetCellDataForVtkOutput(p_cell, this);
707 }
708 mesh_writer.AddCellData(cell_writer->GetVtkCellDataName(), vtk_cell_data);
709 }
710 // When outputting CellData and CellEdgeData, we assume that the first cell
711 // and its edges are representative of the population
712
713 // Get cell/edge data names
714 const unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
715 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
716
717 const unsigned num_edge_data_items = this->Begin()->GetCellEdgeData()->GetNumItems();
718 std::vector<std::string> edge_data_names = this->Begin()->GetCellEdgeData()->GetKeys();
719
720 // Total number of data items. Each data item (edge+interior) has its own value
721 const unsigned num_data_items = num_edge_data_items + num_cell_data_items;
722 std::vector<std::string> data_names(num_data_items);
723 for (unsigned var=0; var<num_edge_data_items; ++var)
724 {
725 data_names[var] = edge_data_names[var];
726 }
727 for (unsigned var=num_edge_data_items; var<num_data_items; ++var)
728 {
729 data_names[var] = cell_data_names[var-num_edge_data_items];
730 }
731 std::vector<std::vector<double> > data_values(num_data_items,
732 std::vector<double>(num_edges + num_cells));
733
734 // Writing CellEdgeData values to the edges of the cells
735 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
736 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
737 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
738 ++elem_iter)
739 {
740 const unsigned elem_index = elem_iter->GetIndex();
741 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
742 assert(p_cell);
743
744 // Edge data for interior data is set to zero.
745 unsigned elem_num_edges = elem_iter->GetNumEdges();
746 for (unsigned var = 0; var < num_edge_data_items; ++var)
747 {
748 // Write the same property in all the edges
749 for (unsigned e = 0; e < elem_num_edges; ++e)
750 {
751 data_values[var][cell_offset_dist[elem_index]+e] = p_cell->GetCellEdgeData()->GetItem(data_names[var])[e];
752 }
753 // Cell interior is set to zero
754 data_values[var][cell_offset_dist[elem_index]+elem_num_edges] = 0.0;
755 }
756 }
757
758 // Writing CellData values to the interior of the cells
759 // Loop over vertex elements ///\todo #2512 - replace with loop over cells
760 for (auto elem_iter = mpMutableVertexMesh->GetElementIteratorBegin();
761 elem_iter != mpMutableVertexMesh->GetElementIteratorEnd();
762 ++elem_iter)
763 {
764 // Get index of this element in the vertex mesh
765 unsigned elem_index = elem_iter->GetIndex();
766 unsigned elem_num_edges = elem_iter->GetNumEdges();
767
768 // Get the cell corresponding to this element
769 CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
770 assert(p_cell);
771
772 for (unsigned var = num_edge_data_items; var<num_data_items; ++var)
773 {
774 // Data in the edges are set to 0
775 for (unsigned e = 0; e < elem_num_edges; ++e)
776 {
777 data_values[var][cell_offset_dist[elem_index]+e] = 0.0;
778 }
779 // Filling cell interior data
780 data_values[var][cell_offset_dist[elem_index]+elem_num_edges] = p_cell->GetCellData()->GetItem(data_names[var]);
781 }
782 }
783
784 for (unsigned var=0; var<num_data_items; var++)
785 {
786 mesh_writer.AddCellData(data_names[var], data_values[var]);
787 }
788
789 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
790 std::stringstream time;
791 time << num_timesteps;
792
793 mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
794
795 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
796 *(this->mpVtkMetaFile) << num_timesteps;
797 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
798 *(this->mpVtkMetaFile) << num_timesteps;
799 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
800}
801
802template<unsigned DIM>
804{
805 if (this->mOutputResultsForChasteVisualizer)
806 {
807 if (!this-> template HasWriter<CellPopulationElementWriter>())
808 {
809 this-> template AddPopulationWriter<CellPopulationElementWriter>();
810 }
811 }
812
813 if (mOutputCellRearrangementLocations)
814 {
815 if (!this-> template HasWriter<VertexT1SwapLocationsWriter>())
816 {
817 this-> template AddPopulationWriter<VertexT1SwapLocationsWriter>();
818 }
819 if (!this-> template HasWriter<VertexT2SwapLocationsWriter>())
820 {
821 this-> template AddPopulationWriter<VertexT2SwapLocationsWriter>();
822 }
823 if (!this-> template HasWriter<VertexT3SwapLocationsWriter>())
824 {
825 this-> template AddPopulationWriter<VertexT3SwapLocationsWriter>();
826 }
827 if (!this-> template HasWriter<VertexIntersectionSwapLocationsWriter>())
828 {
829 this-> template AddPopulationWriter<VertexIntersectionSwapLocationsWriter>();
830 }
831 }
832
834}
835
836template<unsigned DIM>
838{
839 return mOutputCellRearrangementLocations;
840}
841
842template<unsigned DIM>
844{
845 mOutputCellRearrangementLocations = outputCellRearrangementLocations;
846}
847
848template<unsigned DIM>
850{
851 *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
852 *rParamsFile << "\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
853 *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
854 *rParamsFile << "\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations << "</OutputCellRearrangementLocations>\n";
855
856 // Add the division rule parameters
857 *rParamsFile << "\t\t<VertexBasedDivisionRule>\n";
858 mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
859 *rParamsFile << "\t\t</VertexBasedDivisionRule>\n";
860
861 // Call method on direct parent class
863}
864
865template<unsigned DIM>
866double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
867{
868 // Call GetWidth() on the mesh
869 double width = this->mrMesh.GetWidth(rDimension);
870
871 return width;
872}
873
874template<unsigned DIM>
876{
877 return mpMutableVertexMesh->GetNeighbouringNodeIndices(index);
878}
879
880template<unsigned DIM>
881boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > VertexBasedCellPopulation<DIM>::GetVertexBasedDivisionRule()
882{
883 return mpVertexBasedDivisionRule;
884}
885
886template<unsigned DIM>
888{
889 mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
890}
891
892template<unsigned DIM>
894{
895 // This method only works in 2D sequential
896 if (DIM != 2)
897 {
898 EXCEPTION("This function is only valid in 2D"); // LCOV_EXCL_LINE
899 }
900 assert(PetscTools::IsSequential());
901
902 unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
903 unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
904
905 std::string mesh_file_name = "mesh";
906
907 // Get a unique temporary foldername
908 std::stringstream pid;
909 pid << getpid();
910 OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
911 std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
912
913 // Compute the number of nodes in the TetrahedralMesh
914 unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
915
916 // Write node file
917 out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
918 (*p_node_file) << std::scientific;
919 (*p_node_file) << std::setprecision(20);
920 (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;
921
922 // Begin by writing each node in the VertexMesh
923 for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
924 {
925 Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
926
928 unsigned index = p_node->GetIndex();
929 const c_vector<double, DIM>& r_location = p_node->rGetLocation();
930 unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;
931
932 (*p_node_file) << index << "\t" << r_location[0] << "\t" << r_location[1] << "\t" << is_boundary_node << std::endl;
933 }
934
935 // Now write an additional node at each VertexElement's centroid
936 unsigned num_tetrahedral_elements = 0;
937 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
938 {
939 unsigned index = num_vertex_nodes + vertex_elem_index;
940
941 c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
942
943 // Any node located at a VertexElement's centroid will not be a boundary node
944 unsigned is_boundary_node = 0;
945 (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
946
947 // Also keep track of how many tetrahedral elements there will be
948 num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
949 }
950 p_node_file->close();
951
952 // Write element file
953 out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
954 (*p_elem_file) << std::scientific;
955 (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;
956
957 std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
958
959 unsigned tetrahedral_elem_index = 0;
960 for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
961 {
962 VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);
963
964 // Iterate over nodes owned by this VertexElement
965 unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
966 for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
967 {
968 unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
969 unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
970 unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
971
972 (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;
973
974 // Add edges to the set if they are not already present
975 std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
976 std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
977 std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
978
979 tetrahedral_edges.insert(edge_0);
980 tetrahedral_edges.insert(edge_1);
981 tetrahedral_edges.insert(edge_2);
982 }
983 }
984 p_elem_file->close();
985
986 // Write edge file
987 out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
988 (*p_edge_file) << std::scientific;
989 (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;
990
991 unsigned edge_index = 0;
992 for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
993 edge_iter != tetrahedral_edges.end();
994 ++edge_iter)
995 {
996 std::pair<unsigned, unsigned> this_edge = *edge_iter;
997
998 // To be a boundary edge both nodes need to be boundary nodes.
999 bool is_boundary_edge = false;
1000 if (this_edge.first < mpMutableVertexMesh->GetNumNodes() &&
1001 this_edge.second < mpMutableVertexMesh->GetNumNodes())
1002 {
1003 is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
1004 mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
1005 }
1006 unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
1007
1008 (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
1009 }
1010 p_edge_file->close();
1011
1012 // Having written the mesh to file, now construct it using TrianglesMeshReader
1014
1015 // Nested scope so reader is destroyed before we remove the temporary files
1016 {
1017 TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
1018 p_mesh->ConstructFromMeshReader(mesh_reader);
1019 }
1020
1021 // Delete the temporary files
1022 output_file_handler.FindFile("").Remove();
1023
1024 // The original files have been deleted, it is better if the mesh object forgets about them
1026
1027 return p_mesh;
1028}
1029
1030template<unsigned DIM>
1031std::vector< c_vector< double, DIM > > VertexBasedCellPopulation<DIM>::GetLocationsOfT2Swaps()
1032{
1033 return mLocationsOfT2Swaps;
1034}
1035
1036template<unsigned DIM>
1038{
1039 return mCellIdsOfT2Swaps;
1040}
1041
1042template<unsigned DIM>
1043void VertexBasedCellPopulation<DIM>::AddLocationOfT2Swap(c_vector< double, DIM> locationOfT2Swap)
1044{
1045 mLocationsOfT2Swaps.push_back(locationOfT2Swap);
1046}
1047
1048template<unsigned DIM>
1050{
1051 mCellIdsOfT2Swaps.push_back(idOfT2Swap);
1052}
1053
1054template<unsigned DIM>
1056{
1057 mCellIdsOfT2Swaps.clear();
1058 mLocationsOfT2Swaps.clear();
1059}
1060
1061template<unsigned DIM>
1063{
1064 bool non_apoptotic_cell_present = true;
1065
1066 if (pdeNodeIndex < this->GetNumNodes())
1067 {
1068 std::set<unsigned> containing_element_indices = this->GetNode(pdeNodeIndex)->rGetContainingElementIndices();
1069
1070 for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
1071 iter != containing_element_indices.end();
1072 iter++)
1073 {
1074 if (this->GetCellUsingLocationIndex(*iter)->template HasCellProperty<ApoptoticCellProperty>() )
1075 {
1076 non_apoptotic_cell_present = false;
1077 break;
1078 }
1079 }
1080 }
1081 else
1082 {
1083 /*
1084 * This node of the tetrahedral finite element mesh is in the centre of the element of the
1085 * vertex-based cell population, so we can use an offset to compute which cell to interrogate.
1086 */
1087 non_apoptotic_cell_present = !(this->GetCellUsingLocationIndex(pdeNodeIndex - this->GetNumNodes())->template HasCellProperty<ApoptoticCellProperty>());
1088 }
1089
1090 return non_apoptotic_cell_present;
1091}
1092
1093template<unsigned DIM>
1095 unsigned pdeNodeIndex,
1096 std::string& rVariableName,
1097 bool dirichletBoundaryConditionApplies,
1098 double dirichletBoundaryValue)
1099{
1100 unsigned num_nodes = this->GetNumNodes();
1101 double value = 0.0;
1102
1103 // Cells correspond to nodes in the centre of the vertex element; nodes on vertices have averaged values from containing cells
1104
1105 if (pdeNodeIndex >= num_nodes)
1106 {
1107 // Offset to relate elements in vertex mesh to nodes in tetrahedral mesh
1108 assert(pdeNodeIndex-num_nodes < num_nodes);
1109
1110 CellPtr p_cell = this->GetCellUsingLocationIndex(pdeNodeIndex - num_nodes);
1111 value = p_cell->GetCellData()->GetItem(rVariableName);
1112 }
1113 else
1114 {
1116 if (dirichletBoundaryConditionApplies)
1117 {
1118 // We need to impose the Dirichlet boundaries again here as not represented in cell data
1119 value = dirichletBoundaryValue;
1120 }
1121 else
1122 {
1123 assert(pdeNodeIndex < num_nodes);
1124 Node<DIM>* p_node = this->GetNode(pdeNodeIndex);
1125
1126 // Average over data from containing elements (cells)
1127 std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
1128 for (std::set<unsigned>::iterator index_iter = containing_elements.begin();
1129 index_iter != containing_elements.end();
1130 ++index_iter)
1131 {
1132 assert(*index_iter < num_nodes);
1133 CellPtr p_cell = this->GetCellUsingLocationIndex(*index_iter);
1134 value += p_cell->GetCellData()->GetItem(rVariableName);
1135 }
1136 value /= containing_elements.size();
1137 }
1138 }
1139
1140 return value;
1141}
1142
1143template<unsigned DIM>
1145{
1146 return 0.002;
1147}
1148
1149template<unsigned DIM>
1151{
1152 if (bool(dynamic_cast<Cylindrical2dVertexMesh*>(&(this->mrMesh))))
1153 {
1154 *pVizSetupFile << "MeshWidth\t" << this->GetWidth(0) << "\n";
1155 }
1156}
1157
1158template<unsigned DIM>
1160{
1161 MAKE_PTR_ARGS(T2SwapCellKiller<DIM>, p_t2_swap_cell_killer, (this));
1162 pSimulation->AddCellKiller(p_t2_swap_cell_killer);
1163}
1164
1165
1166template<unsigned DIM>
1168{
1169 return mRestrictVertexMovement;
1170}
1171
1172template<unsigned DIM>
1174{
1175 mRestrictVertexMovement = restrictMovement;
1176}
1177
1178template<unsigned DIM>
1183
1184template<unsigned DIM>
1189
1190template<unsigned DIM>
1192{
1193 mWriteCellVtkResults = new_val;
1194}
1195
1196template<unsigned DIM>
1198{
1199 mWriteEdgeVtkResults = new_val;
1200}
1201
1202// Explicit instantiation
1203template class VertexBasedCellPopulation<1>;
1204template class VertexBasedCellPopulation<2>;
1205template class VertexBasedCellPopulation<3>;
1206
1207// 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)