Chaste Commit::f841a6fa79bd6f7a205054452b95ddf6d10aae23
MeshBasedCellPopulation.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 "MeshBasedCellPopulation.hpp"
37#include "VtkMeshWriter.hpp"
38#include "CellBasedEventHandler.hpp"
39#include "Cylindrical2dMesh.hpp"
40#include "Cylindrical2dVertexMesh.hpp"
41#include "Toroidal2dMesh.hpp"
42#include "Toroidal2dVertexMesh.hpp"
43#include "CellId.hpp"
44#include "CellVolumesWriter.hpp"
45#include "CellPopulationElementWriter.hpp"
46#include "VoronoiDataWriter.hpp"
47#include "NodeVelocityWriter.hpp"
48#include "CellPopulationAreaWriter.hpp"
49
50template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
52 std::vector<CellPtr>& rCells,
53 const std::vector<unsigned> locationIndices,
54 bool deleteMesh,
55 bool validate)
56 : AbstractCentreBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>(rMesh, rCells, locationIndices),
57 mpVoronoiTessellation(nullptr),
58 mDeleteMesh(deleteMesh),
59 mUseAreaBasedDampingConstant(false),
60 mAreaBasedDampingConstantParameter(0.1),
61 mWriteVtkAsPoints(false),
62 mBoundVoronoiTessellation(false),
63 mScaleBoundByEdgeLength(false),
64 mBoundedVoroniTesselationLengthCutoff(DBL_MAX),
65 mOffsetNewBoundaryNodes(false),
66 mHasVariableRestLength(false)
67{
69
70 assert(this->mCells.size() <= this->mrMesh.GetNumNodes());
71
72 if (validate)
73 {
74 Validate();
75 }
76
78
79 // Initialise the applied force at each node to zero
80 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->rGetMesh().GetNodeIteratorBegin();
81 node_iter != this->rGetMesh().GetNodeIteratorEnd();
82 ++node_iter)
83 {
84 node_iter->ClearAppliedForce();
85 }
86}
87
88template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
97
98template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
100{
101 delete mpVoronoiTessellation;
102
103 if (mDeleteMesh)
104 {
105 delete &this->mrMesh;
106 }
107}
108
109template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
111{
112 return mUseAreaBasedDampingConstant;
113}
114
115template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
117 [[maybe_unused]] bool useAreaBasedDampingConstant) // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9
118{
119 if constexpr (SPACE_DIM == 2)
120 {
121 mUseAreaBasedDampingConstant = useAreaBasedDampingConstant;
122 }
123 else
124 {
126 }
127}
128
129template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
131{
132 return mpMutableMesh->AddNode(pNewNode);
133}
134
135template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
137{
138 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).SetNode(nodeIndex, rNewLocation, false);
139}
140
141template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
143{
145
146 /*
147 * The next code block computes the area-dependent damping constant as given by equation
148 * (5) in the following reference: van Leeuwen et al. 2009. An integrative computational model
149 * for intestinal tissue renewal. Cell Prolif. 42(5):617-636. doi:10.1111/j.1365-2184.2009.00627.x
150 */
151 if (mUseAreaBasedDampingConstant)
152 {
161 if constexpr (SPACE_DIM == 2)
162 {
163 double rest_length = 1.0;
164 double d0 = mAreaBasedDampingConstantParameter;
165
171 double d1 = 2.0*(1.0 - d0)/(sqrt(3.0)*rest_length*rest_length);
172
173 double area_cell = GetVolumeOfVoronoiElement(nodeIndex);
174
180 assert(area_cell < 1000);
181
182 damping_multiplier = d0 + area_cell*d1;
183 }
184 else
185 {
187 }
188 }
189
190 return damping_multiplier;
191}
192
193template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
195{
196 std::vector<bool> validated_node = std::vector<bool>(this->GetNumNodes(), false);
197
198 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
199 {
200 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
201 validated_node[node_index] = true;
202 }
203
204 for (unsigned i=0; i<validated_node.size(); i++)
205 {
206 if (!validated_node[i])
207 {
208 EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << i << " does not appear to have a cell associated with it");
209 }
210 }
212
213template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
215{
216 return *mpMutableMesh;
217}
218
219template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
224
225template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
227{
228 return mpMutableMesh;
229}
230
231template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
233{
234 unsigned num_removed = 0;
235 for (std::list<CellPtr>::iterator it = this->mCells.begin();
236 it != this->mCells.end();
237 )
239 if ((*it)->IsDead())
240 {
241 // Check if this cell is in a marked spring
242 std::vector<const std::pair<CellPtr,CellPtr>*> pairs_to_remove; // Pairs that must be purged
243 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
244 it1 != this->mMarkedSprings.end();
245 ++it1)
246 {
247 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
249 for (unsigned i=0; i<2; i++)
250 {
251 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
252
253 if (p_cell == *it)
254 {
255 // Remember to purge this spring
256 pairs_to_remove.push_back(&r_pair);
257 break;
258 }
259 }
260 }
261
262 // Purge any marked springs that contained this cell
263 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator pair_it = pairs_to_remove.begin();
264 pair_it != pairs_to_remove.end();
265 ++pair_it)
266 {
267 this->mMarkedSprings.erase(**pair_it);
268 }
269
270 // Remove the node from the mesh
271 num_removed++;
272 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).DeleteNodePriorToReMesh(this->GetLocationIndexUsingCell((*it)));
274 // Update mappings between cells and location indices
275 unsigned location_index_of_removed_node = this->GetLocationIndexUsingCell((*it));
276 this->RemoveCellUsingLocationIndex(location_index_of_removed_node, (*it));
277
278 // Update vector of cells
279 it = this->mCells.erase(it);
280 }
281 else
282 {
283 ++it;
284 }
285 }
286
287 return num_removed;
288}
289
290template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
292{
293 this->mNodePairs.clear();
294 for (SpringIterator spring_it = SpringsBegin(); spring_it != SpringsEnd(); ++spring_it)
295 {
296 this->mNodePairs.emplace_back(spring_it.GetNodeA(), spring_it.GetNodeB());
297 }
298}
299
300template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
302{
304 bool output_node_velocities = (this-> template HasWriter<NodeVelocityWriter>());
305
316 std::map<unsigned, double> old_node_radius_map;
317 old_node_radius_map.clear();
318 if (this->mrMesh.GetNodeIteratorBegin()->HasNodeAttributes())
319 {
320 if (this->mrMesh.GetNodeIteratorBegin()->GetRadius() > 0.0)
321 {
322 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
323 node_iter != this->mrMesh.GetNodeIteratorEnd();
324 ++node_iter)
325 {
326 unsigned node_index = node_iter->GetIndex();
327 old_node_radius_map[node_index] = node_iter->GetRadius();
328 }
329 }
330 }
332 std::map<unsigned, c_vector<double, SPACE_DIM> > old_node_applied_force_map;
333 old_node_applied_force_map.clear();
334 if (output_node_velocities)
335 {
336 /*
337 * If outputting node velocities, we must keep a record of the applied force at each
338 * node, since this will be cleared during the remeshing process. We then restore
339 * these attributes to the nodes after calling ReMesh().
340 */
341 for (typename AbstractMesh<ELEMENT_DIM, SPACE_DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
342 node_iter != this->mrMesh.GetNodeIteratorEnd();
343 ++node_iter)
344 {
345 unsigned node_index = node_iter->GetIndex();
346 old_node_applied_force_map[node_index] = node_iter->rGetAppliedForce();
347 }
348 }
350 NodeMap node_map(this->mrMesh.GetNumAllNodes());
351
352 // We must use a static_cast to call ReMesh() as this method is not defined in parent mesh classes
353 static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).ReMesh(node_map);
354
355 if (!node_map.IsIdentityMap())
356 {
357 UpdateGhostNodesAfterReMesh(node_map);
358
359 // Update the mappings between cells and location indices
360 std::map<Cell*, unsigned> old_cell_location_map = this->mCellLocationMap;
361
362 // Remove any dead pointers from the maps (needed to avoid archiving errors)
363 this->mLocationCellMap.clear();
364 this->mCellLocationMap.clear();
365
366 for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
367 {
368 unsigned old_node_index = old_cell_location_map[(*it).get()];
369
370 // This shouldn't ever happen, as the cell vector only contains living cells
371 assert(!node_map.IsDeleted(old_node_index));
372
373 unsigned new_node_index = node_map.GetNewIndex(old_node_index);
374 this->SetCellUsingLocationIndex(new_node_index,*it);
375
376 if (old_node_radius_map[old_node_index] > 0.0)
377 {
378 this->GetNode(new_node_index)->SetRadius(old_node_radius_map[old_node_index]);
379 }
380 if (output_node_velocities)
381 {
382 this->GetNode(new_node_index)->AddAppliedForceContribution(old_node_applied_force_map[old_node_index]);
383 }
384 }
385
386 this->Validate();
388 else
389 {
390 if (old_node_radius_map[this->mCellLocationMap[(*(this->mCells.begin())).get()]] > 0.0)
391 {
392 for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
393 {
394 unsigned node_index = this->mCellLocationMap[(*it).get()];
395 this->GetNode(node_index)->SetRadius(old_node_radius_map[node_index]);
396 }
397 }
398 if (output_node_velocities)
399 {
400 for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it)
401 {
402 unsigned node_index = this->mCellLocationMap[(*it).get()];
403 this->GetNode(node_index)->AddAppliedForceContribution(old_node_applied_force_map[node_index]);
404 }
406 }
407
408 // Purge any marked springs that are no longer springs
409 std::vector<const std::pair<CellPtr,CellPtr>*> springs_to_remove;
410 for (std::set<std::pair<CellPtr,CellPtr> >::iterator spring_it = this->mMarkedSprings.begin();
411 spring_it != this->mMarkedSprings.end();
412 ++spring_it)
413 {
414 CellPtr p_cell_1 = spring_it->first;
415 CellPtr p_cell_2 = spring_it->second;
416 Node<SPACE_DIM>* p_node_1 = this->GetNodeCorrespondingToCell(p_cell_1);
417 Node<SPACE_DIM>* p_node_2 = this->GetNodeCorrespondingToCell(p_cell_2);
418
419 bool joined = false;
420
421 // For each element containing node1, if it also contains node2 then the cells are joined
422 std::set<unsigned> node2_elements = p_node_2->rGetContainingElementIndices();
423 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node_1->ContainingElementsBegin();
424 elem_iter != p_node_1->ContainingElementsEnd();
425 ++elem_iter)
426 {
427 if (node2_elements.find(*elem_iter) != node2_elements.end())
428 {
429 joined = true;
430 break;
432 }
433
434 // If no longer joined, remove this spring from the set
435 if (!joined)
436 {
437 springs_to_remove.push_back(&(*spring_it));
438 }
439 }
440
441 // Remove any springs necessary
442 for (std::vector<const std::pair<CellPtr,CellPtr>* >::iterator spring_it = springs_to_remove.begin();
443 spring_it != springs_to_remove.end();
444 ++spring_it)
445 {
446 this->mMarkedSprings.erase(**spring_it);
447 }
448
449 // Update node pairs. Note, this must happen after remeshing.
450 UpdateNodePairs();
451
452 // Tessellate if needed
453 TessellateIfNeeded();
454
456}
457
458template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
460{
461 if ((SPACE_DIM==2 || SPACE_DIM==3)&&(ELEMENT_DIM==SPACE_DIM))
462 {
463 CellBasedEventHandler::BeginEvent(CellBasedEventHandler::TESSELLATION);
464 if (mUseAreaBasedDampingConstant ||
465 this-> template HasWriter<VoronoiDataWriter>() ||
466 this-> template HasWriter<CellPopulationAreaWriter>() ||
467 this-> template HasWriter<CellVolumesWriter>())
468 {
469 CreateVoronoiTessellation();
470 }
471 CellBasedEventHandler::EndEvent(CellBasedEventHandler::TESSELLATION);
472 }
473}
474
475template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
476void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::DivideLongSprings([[maybe_unused]] double springDivisionThreshold) // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9
477{
478 // Only implemented for 2D elements
479 if constexpr (ELEMENT_DIM == 2)
480 {
481 std::vector<c_vector<unsigned, 5> > new_nodes;
482 new_nodes = rGetMesh().SplitLongEdges(springDivisionThreshold);
484 // Add new cells onto new nodes
485 for (unsigned index=0; index<new_nodes.size(); index++)
486 {
487 // Copy the cell attached to one of the neighbouring nodes onto the new node
488 unsigned new_node_index = new_nodes[index][0];
489 unsigned node_a_index = new_nodes[index][1];
490 unsigned node_b_index = new_nodes[index][2];
491
492 CellPtr p_neighbour_cell = this->GetCellUsingLocationIndex(node_a_index);
494 // Create copy of cell property collection to modify for daughter cell
495 CellPropertyCollection daughter_property_collection = p_neighbour_cell->rGetCellPropertyCollection();
496
497 // Remove the CellId from the daughter cell a new one will be assigned in the constructor
498 daughter_property_collection.RemoveProperty<CellId>();
499
500 CellPtr p_new_cell(new Cell(p_neighbour_cell->GetMutationState(),
501 p_neighbour_cell->GetCellCycleModel()->CreateCellCycleModel(),
502 p_neighbour_cell->GetSrnModel()->CreateSrnModel(),
503 false,
504 daughter_property_collection));
505
506 // Add new cell to cell population
507 this->mCells.push_back(p_new_cell);
508 this->AddCellUsingLocationIndex(new_node_index,p_new_cell);
509
510 // Update rest lengths
511
512 // Remove old node pair // note node_a_index < node_b_index
513 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(node_a_index, node_b_index);
514 double old_rest_length = mSpringRestLengths[node_pair];
516 std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair);
517 mSpringRestLengths.erase(iter);
518
519 // Add new pairs
520 node_pair = this->CreateOrderedPair(node_a_index, new_node_index);
521 mSpringRestLengths[node_pair] = 0.5*old_rest_length;
522
523 node_pair = this->CreateOrderedPair(node_b_index, new_node_index);
524 mSpringRestLengths[node_pair] = 0.5*old_rest_length;
525
526 // If necessary add other new spring rest lengths
527 for (unsigned pair_index=3; pair_index<5; pair_index++)
528 {
529 unsigned other_node_index = new_nodes[index][pair_index];
530
531 if (other_node_index != UNSIGNED_UNSET)
533 node_pair = this->CreateOrderedPair(other_node_index, new_node_index);
534 double new_rest_length = rGetMesh().GetDistanceBetweenNodes(new_node_index, other_node_index);
535 mSpringRestLengths[node_pair] = new_rest_length;
536 }
538 }
539 }
540 else
541 {
543 }
544}
545
546template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
548{
549 return this->mrMesh.GetNode(index);
550}
551
552template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
555 return this->mrMesh.GetNumAllNodes();
556}
557
558template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
562
563template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
564CellPtr MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(CellPtr pNewCell, CellPtr pParentCell)
565{
566 assert(pNewCell);
567 assert(pParentCell);
569 // Add new cell to population
570 CellPtr p_created_cell = AbstractCentreBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::AddCell(pNewCell, pParentCell);
571 assert(p_created_cell == pNewCell);
572
573 // Mark spring between parent cell and new cell
574 std::pair<CellPtr,CellPtr> cell_pair = this->CreateCellPair(pParentCell, p_created_cell);
575 this->MarkSpring(cell_pair);
576
577 // Return pointer to new cell
578 return p_created_cell;
579}
582// Output methods //
584
585template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
587{
588 if (this->mOutputResultsForChasteVisualizer)
589 {
590 if (!this-> template HasWriter<CellPopulationElementWriter>())
591 {
592 this-> template AddPopulationWriter<CellPopulationElementWriter>();
593 }
594 }
595
598
599template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
601{
602 if (SimulationTime::Instance()->GetTimeStepsElapsed() == 0 && this->mpVoronoiTessellation == nullptr)
603 {
604 TessellateIfNeeded(); // Update isn't run on time-step zero
605 }
606
608}
610template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
612{
613 pPopulationWriter->Visit(this);
614}
615
616template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
618{
619 pPopulationCountWriter->Visit(this);
620}
622template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
624{
625 pPopulationEventWriter->Visit(this);
626}
627
628template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
630{
631 pCellWriter->VisitCell(pCell, this);
632}
633
634template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
636{
637#ifdef CHASTE_VTK
638 // Store the present time as a string
639 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
640 std::stringstream time;
641 time << num_timesteps;
643 // Store the number of cells for which to output data to VTK
644 unsigned num_cells_from_mesh = GetNumNodes();
645
646 // When outputting any CellData, we assume that the first cell is representative of all cells
647 unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
648 std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
649
650 std::vector<std::vector<double> > cell_data;
651 for (unsigned var=0; var<num_cell_data_items; var++)
652 {
653 std::vector<double> cell_data_var(num_cells_from_mesh);
654 cell_data.push_back(cell_data_var);
655 }
656
657 if (mWriteVtkAsPoints)
658 {
659 // Create mesh writer for VTK output
660 VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> cells_writer(rDirectory, "mesh_results_"+time.str(), false);
661
662 // Iterate over any cell writers that are present
663 unsigned num_cells = this->GetNumAllCells();
664 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
665 cell_writer_iter != this->mCellWriters.end();
666 ++cell_writer_iter)
667 {
668 // Create vector to store VTK cell data
669 std::vector<double> vtk_cell_data(num_cells);
670
671 // Loop over cells
672 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
673 cell_iter != this->End();
674 ++cell_iter)
675 {
676 // Get the node index corresponding to this cell
677 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
678
679 // Populate the vector of VTK cell data
680 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
681 }
682
683 cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
684 }
685
686 // Loop over cells
687 for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
688 cell_iter != this->End();
689 ++cell_iter)
690 {
691 // Get the node index corresponding to this cell
692 unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
693
694 for (unsigned var=0; var<num_cell_data_items; var++)
695 {
696 cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
697 }
698 }
699 for (unsigned var=0; var<num_cell_data_items; var++)
700 {
701 cells_writer.AddPointData(cell_data_names[var], cell_data[var]);
702 }
703
704 // Write data using the mesh
705 cells_writer.WriteFilesUsingMesh(rGetMesh());
706 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
707 *(this->mpVtkMetaFile) << num_timesteps;
708 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"mesh_results_";
709 *(this->mpVtkMetaFile) << num_timesteps;
710 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
711 }
712 if (mpVoronoiTessellation != nullptr)
713 {
714 // Create mesh writer for VTK output
715 VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "voronoi_results", false);
716 std::vector<double> cell_volumes(num_cells_from_mesh);
717
718 // Iterate over any cell writers that are present
719 unsigned num_cells = this->GetNumAllCells();
720 for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
721 cell_writer_iter != this->mCellWriters.end();
722 ++cell_writer_iter)
723 {
724 // Create vector to store VTK cell data
725 std::vector<double> vtk_cell_data(num_cells);
726
727 // Loop over elements of mpVoronoiTessellation
728 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
729 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
730 ++elem_iter)
731 {
732 // Get index of this element in mpVoronoiTessellation
733 unsigned elem_index = elem_iter->GetIndex();
734
735 // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
736 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
737 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
738
739 // Populate the vector of VTK cell data
740 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
741 }
742
743 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
744 }
745
746 // Loop over elements of mpVoronoiTessellation
747 for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
748 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
749 ++elem_iter)
750 {
751 // Get index of this element in mpVoronoiTessellation
752 unsigned elem_index = elem_iter->GetIndex();
753
754 // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
755 unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
756 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
757
758 for (unsigned var=0; var<num_cell_data_items; var++)
759 {
760 cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
761 }
762 }
763
764 for (unsigned var=0; var<cell_data.size(); var++)
765 {
766 mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
767 }
768
769 mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
770 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
771 *(this->mpVtkMetaFile) << num_timesteps;
772 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"voronoi_results_";
773 *(this->mpVtkMetaFile) << num_timesteps;
774 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
775 }
776#endif //CHASTE_VTK
777}
778
779template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
781{
782 double cell_volume = 0;
783
784 if (ELEMENT_DIM == SPACE_DIM)
785 {
786 // Ensure that the Voronoi tessellation exists
787 if (mpVoronoiTessellation == nullptr)
788 {
789 CreateVoronoiTessellation();
790 }
791
792 // Get the node index corresponding to this cell
793 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
794
795 // Try to get the element index of the Voronoi tessellation corresponding to this node index
796 try
797 {
798 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(node_index);
799
800 // Get the cell's volume from the Voronoi tessellation
801 cell_volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
802 }
803 catch (Exception&)
804 {
805 // If it doesn't exist this must be a boundary cell, so return infinite volume
806 cell_volume = DBL_MAX;
807 }
808 }
809 else if (SPACE_DIM==3 && ELEMENT_DIM==2)
810 {
811 unsigned node_index = this->GetLocationIndexUsingCell(pCell);
812
813 Node<SPACE_DIM>* p_node = rGetMesh().GetNode(node_index);
814
815 assert(!(p_node->rGetContainingElementIndices().empty()));
816
818 elem_iter != p_node->ContainingElementsEnd();
819 ++elem_iter)
820 {
821 Element<ELEMENT_DIM,SPACE_DIM>* p_element = rGetMesh().GetElement(*elem_iter);
822
823 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacob;
824 double det;
825
826 p_element->CalculateJacobian(jacob, det);
827
828 cell_volume += fabs(p_element->GetVolume(det));
829 }
830
831 // This calculation adds a third of each element to the total area
832 cell_volume /= 3.0;
833 }
834 else
835 {
836 // Not implemented for other dimensions
838 }
839
840 return cell_volume;
841}
842
843template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
845{
846 mWriteVtkAsPoints = writeVtkAsPoints;
847}
848
849template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
851{
852 return mWriteVtkAsPoints;
853}
854
855template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
857{
858 mBoundVoronoiTessellation = boundVoronoiTessellation;
859}
860
861template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
863{
864 return mBoundVoronoiTessellation;
865}
866
867template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
869{
870 mScaleBoundByEdgeLength = scaleBoundByEdgeLength;
871}
872
873template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
875{
876 return mScaleBoundByEdgeLength;
877}
878
879template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
881{
882 assert(boundedVoroniTesselationLengthCutoff>0);
883 mBoundedVoroniTesselationLengthCutoff = boundedVoroniTesselationLengthCutoff;
884}
885
886template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
888{
889 return mBoundedVoroniTesselationLengthCutoff;
890}
891
892template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
894{
895 mOffsetNewBoundaryNodes = offsetNewBoundaryNodes;
896}
897
898template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
900{
901 return mOffsetNewBoundaryNodes;
902}
903
904
905
906template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
908{
909 if (bool(dynamic_cast<Cylindrical2dMesh*>(&(this->mrMesh))))
910 {
911 *pVizSetupFile << "MeshWidth\t" << this->GetWidth(0) << "\n";
912 }
913 if (bool(dynamic_cast<Toroidal2dMesh*>(&(this->mrMesh))))
914 {
915 *pVizSetupFile << "MeshWidth\t" << this->GetWidth(0) << "\n";
916 *pVizSetupFile << "MeshHeight\t" << this->GetWidth(1) << "\n";
917 }
918}
919
920template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
922{
923 if constexpr (ELEMENT_DIM == 1)
924 {
925 // The VoronoiTessellation class is only defined in 2D or 3D
927 }
928 else if constexpr (ELEMENT_DIM == 2 && SPACE_DIM == 2)
929 {
930 delete mpVoronoiTessellation;
931
932 // Check if the mesh associated with this cell population is periodic
933 bool is_mesh_periodic = false;
934 if (dynamic_cast<Cylindrical2dMesh*>(&(this->mrMesh)))
935 {
936 if(mScaleBoundByEdgeLength || mBoundedVoroniTesselationLengthCutoff<DBL_MAX || mOffsetNewBoundaryNodes)
937 {
938 // Not implemented for Cylindrical meshes yet see Issue 305
940 }
941 is_mesh_periodic = true;
942 mpVoronoiTessellation = new Cylindrical2dVertexMesh(static_cast<Cylindrical2dMesh&>(this->mrMesh), mBoundVoronoiTessellation);
943 }
944 else if (dynamic_cast<Toroidal2dMesh*>(&(this->mrMesh)))
945 {
946 if(mScaleBoundByEdgeLength || mBoundedVoroniTesselationLengthCutoff<DBL_MAX || mOffsetNewBoundaryNodes)
947 {
948 // Not implemented for Toroidal meshes yet see Issue 305
950 }
951 is_mesh_periodic = true;
952 mpVoronoiTessellation = new Toroidal2dVertexMesh(static_cast<Toroidal2dMesh&>(this->mrMesh), mBoundVoronoiTessellation);
953 }
954 else
955 {
956 mpVoronoiTessellation = new VertexMesh<2, 2>(static_cast<MutableMesh<2, 2>&>((this->mrMesh)), is_mesh_periodic, mBoundVoronoiTessellation, mScaleBoundByEdgeLength, mBoundedVoroniTesselationLengthCutoff, mOffsetNewBoundaryNodes);
957 }
958 }
959 else if constexpr (ELEMENT_DIM == 3)
960 {
961 // The cylindrical mesh is only defined in 2D, hence there is
962 // a separate definition for this method in 3D, which doesn't have the capability
963 // of dealing with periodic boundaries in 3D. This is \todo #1374.
964 delete mpVoronoiTessellation;
965 mpVoronoiTessellation = new VertexMesh<3, 3>(static_cast<MutableMesh<3, 3>&>(this->mrMesh));
966 }
967 else // ELEMENT_DIM == 2 && SPACE_DIM != 2
968 {
970 }
971}
972
974// Spring iterator class //
976
977template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
982
983template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
988
989template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
991{
992 assert((*this) != mrCellPopulation.SpringsEnd());
993 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeA()->GetIndex());
994}
995
996template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
998{
999 assert((*this) != mrCellPopulation.SpringsEnd());
1000 return mrCellPopulation.GetCellUsingLocationIndex(mEdgeIter.GetNodeB()->GetIndex());
1001}
1002
1003template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1008
1009template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1011{
1012 bool edge_is_ghost = false;
1013
1014 do
1015 {
1016 ++mEdgeIter;
1017 if (*this != mrCellPopulation.SpringsEnd())
1018 {
1019 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
1020 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
1021
1022 edge_is_ghost = (a_is_ghost || b_is_ghost);
1023 }
1024 }
1025 while (*this!=mrCellPopulation.SpringsEnd() && edge_is_ghost);
1026
1027 return (*this);
1028}
1029
1030template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1034 : mrCellPopulation(rCellPopulation),
1035 mEdgeIter(edgeIter)
1036{
1037 if (mEdgeIter!=static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>*>(&(this->mrCellPopulation.mrMesh))->EdgesEnd())
1038 {
1039 bool a_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeA()->GetIndex());
1040 bool b_is_ghost = mrCellPopulation.IsGhostNode(mEdgeIter.GetNodeB()->GetIndex());
1041
1042 if (a_is_ghost || b_is_ghost)
1043 {
1044 ++(*this);
1045 }
1046 }
1047}
1048
1049template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1054
1055template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1060
1061template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1067
1068template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1070{
1071 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
1072 double volume = mpVoronoiTessellation->GetVolumeOfElement(element_index);
1073 return volume;
1074}
1075
1076template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1078{
1079 unsigned element_index = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index);
1080 double surface_area = mpVoronoiTessellation->GetSurfaceAreaOfElement(element_index);
1081 return surface_area;
1082}
1083
1084template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1086{
1087 unsigned element_index1 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index1);
1088 unsigned element_index2 = mpVoronoiTessellation->GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(index2);
1089 try
1090 {
1091 double edge_length = mpVoronoiTessellation->GetEdgeLength(element_index1, element_index2);
1092 return edge_length;
1093 }
1094 catch (Exception&)
1095 {
1096 // The edge was between two (potentially infinite) cells on the boundary of the mesh
1097 EXCEPTION("Spring iterator tried to calculate interaction between degenerate cells on the boundary of the mesh. Have you set ghost layers correctly?");
1098 }
1099}
1100
1101template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1103{
1104 bool res = true;
1105 for (std::list<CellPtr>::iterator it=this->mCells.begin();
1106 it!=this->mCells.end();
1107 ++it)
1108 {
1109 CellPtr p_cell = *it;
1110 assert(p_cell);
1111 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
1112 assert(p_model);
1113
1114 // Check cell exists in cell population
1115 unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
1116 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
1117 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
1118// LCOV_EXCL_START //Debugging code. Shouldn't fail under normal conditions
1119 if (p_cell_in_cell_population != p_cell)
1120 {
1121 std::cout << " Mismatch with cell population" << std::endl << std::flush;
1122 res = false;
1123 }
1124
1125 // Check model links back to cell
1126 if (p_model->GetCell() != p_cell)
1127 {
1128 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
1129 res = false;
1130 }
1131 }
1132 UNUSED_OPT(res);
1133 assert(res);
1134// LCOV_EXCL_STOP
1135
1136 res = true;
1137 for (std::set<std::pair<CellPtr,CellPtr> >::iterator it1 = this->mMarkedSprings.begin();
1138 it1 != this->mMarkedSprings.end();
1139 ++it1)
1140 {
1141 const std::pair<CellPtr,CellPtr>& r_pair = *it1;
1142
1143 for (unsigned i=0; i<2; i++)
1144 {
1145 CellPtr p_cell = (i==0 ? r_pair.first : r_pair.second);
1146
1147 assert(p_cell);
1148 AbstractCellCycleModel* p_model = p_cell->GetCellCycleModel();
1149 assert(p_model);
1150 unsigned node_index = this->GetLocationIndexUsingCell(p_cell);
1151 std::cout << "Cell at node " << node_index << " addr " << p_cell << std::endl << std::flush;
1152
1153// LCOV_EXCL_START //Debugging code. Shouldn't fail under normal conditions
1154 // Check cell is alive
1155 if (p_cell->IsDead())
1156 {
1157 std::cout << " Cell is dead" << std::endl << std::flush;
1158 res = false;
1159 }
1160
1161 // Check cell exists in cell population
1162 CellPtr p_cell_in_cell_population = this->GetCellUsingLocationIndex(node_index);
1163 if (p_cell_in_cell_population != p_cell)
1164 {
1165 std::cout << " Mismatch with cell population" << std::endl << std::flush;
1166 res = false;
1167 }
1168
1169 // Check model links back to cell
1170 if (p_model->GetCell() != p_cell)
1171 {
1172 std::cout << " Mismatch with cycle model" << std::endl << std::flush;
1173 res = false;
1174 }
1175 }
1176// LCOV_EXCL_STOP
1177 }
1178 assert(res);
1179}
1180
1181template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1186
1187template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1189{
1190 assert(areaBasedDampingConstantParameter >= 0.0);
1191 mAreaBasedDampingConstantParameter = areaBasedDampingConstantParameter;
1192}
1193
1194template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1196{
1197 *rParamsFile << "\t\t<UseAreaBasedDampingConstant>" << mUseAreaBasedDampingConstant << "</UseAreaBasedDampingConstant>\n";
1198 *rParamsFile << "\t\t<AreaBasedDampingConstantParameter>" << mAreaBasedDampingConstantParameter << "</AreaBasedDampingConstantParameter>\n";
1199 *rParamsFile << "\t\t<WriteVtkAsPoints>" << mWriteVtkAsPoints << "</WriteVtkAsPoints>\n";
1200 *rParamsFile << "\t\t<BoundVoronoiTessellation>" << mBoundVoronoiTessellation << "</BoundVoronoiTessellation>\n";
1201 *rParamsFile << "\t\t<HasVariableRestLength>" << mHasVariableRestLength << "</HasVariableRestLength>\n";
1202
1203 // Call method on direct parent class
1205}
1206
1207template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1209{
1210 // Call GetWidth() on the mesh
1211 double width = this->mrMesh.GetWidth(rDimension);
1212 return width;
1213}
1214
1215template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1217{
1218 // Get pointer to this node
1219 Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
1220
1221 // Loop over containing elements
1222 std::set<unsigned> neighbouring_node_indices;
1223 for (typename Node<SPACE_DIM>::ContainingElementIterator elem_iter = p_node->ContainingElementsBegin();
1224 elem_iter != p_node->ContainingElementsEnd();
1225 ++elem_iter)
1226 {
1227 // Get pointer to this containing element
1228 Element<ELEMENT_DIM,SPACE_DIM>* p_element = static_cast<MutableMesh<ELEMENT_DIM,SPACE_DIM>&>((this->mrMesh)).GetElement(*elem_iter);
1229
1230 // Loop over nodes contained in this element
1231 for (unsigned i=0; i<p_element->GetNumNodes(); i++)
1232 {
1233 // Get index of this node and add its index to the set if not the original node
1234 unsigned node_index = p_element->GetNodeGlobalIndex(i);
1235 if (node_index != index)
1236 {
1237 neighbouring_node_indices.insert(node_index);
1238 }
1239 }
1240 }
1241 return neighbouring_node_indices;
1242}
1243
1244template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1246{
1247 mSpringRestLengths.clear();
1248
1249 // Iterate over all springs and add calculate separation of adjacent node pairs
1250 for (SpringIterator spring_iterator = SpringsBegin();
1251 spring_iterator != SpringsEnd();
1252 ++spring_iterator)
1253 {
1254 // Note that nodeA_global_index is always less than nodeB_global_index
1255 Node<SPACE_DIM>* p_nodeA = spring_iterator.GetNodeA();
1256 Node<SPACE_DIM>* p_nodeB = spring_iterator.GetNodeB();
1257
1258 unsigned nodeA_global_index = p_nodeA->GetIndex();
1259 unsigned nodeB_global_index = p_nodeB->GetIndex();
1260
1261 // Calculate the distance between nodes
1262 double separation = rGetMesh().GetDistanceBetweenNodes(nodeA_global_index, nodeB_global_index);
1263
1264 // Order node indices
1265 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(nodeA_global_index, nodeB_global_index);
1266
1267 mSpringRestLengths[node_pair] = separation;
1268 }
1270}
1271
1272template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1274{
1276 {
1277 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
1278 std::map<std::pair<unsigned,unsigned>, double>::const_iterator iter = mSpringRestLengths.find(node_pair);
1279
1280 if (iter != mSpringRestLengths.end())
1281 {
1282 // Return the stored rest length
1283 return iter->second;
1284 }
1285 else
1286 {
1287 EXCEPTION("Tried to get a rest length of an edge that doesn't exist. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
1288 }
1289 }
1290 else
1291 {
1292 return 1.0;
1293 }
1294}
1295
1296template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
1297void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::SetRestLength(unsigned indexA, unsigned indexB, double restLength)
1298{
1300 {
1301 std::pair<unsigned,unsigned> node_pair = this->CreateOrderedPair(indexA, indexB);
1302 std::map<std::pair<unsigned,unsigned>, double>::iterator iter = mSpringRestLengths.find(node_pair);
1303
1304 if (iter != mSpringRestLengths.end())
1305 {
1306 // modify the stored rest length
1307 iter->second = restLength;
1308 }
1309 else
1310 {
1311 EXCEPTION("Tried to set the rest length of an edge not in the mesh.");
1312 }
1313 }
1314 else
1315 {
1316 EXCEPTION("Tried to set a rest length in a simulation with fixed rest length. You can only use variable rest lengths if SetUpdateCellPopulationRule is set on the simulation.");
1317 }
1318}
1319
1320// Explicit instantiation
1321template class MeshBasedCellPopulation<1,1>;
1322template class MeshBasedCellPopulation<1,2>;
1323template class MeshBasedCellPopulation<2,2>;
1324template class MeshBasedCellPopulation<1,3>;
1325template class MeshBasedCellPopulation<2,3>;
1326template class MeshBasedCellPopulation<3,3>;
1327
1328// Serialization for Boost >= 1.36
#define EXCEPTION(message)
#define UNUSED_OPT(var)
#define NEVER_REACHED
const unsigned UNSIGNED_UNSET
Definition Exception.hpp:53
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
unsigned GetLocationIndexUsingCell(CellPtr pCell)
virtual void WriteResultsToFiles(const std::string &rDirectory)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
std::set< std::pair< CellPtr, CellPtr > > mMarkedSprings
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual double GetDampingConstant(unsigned nodeIndex)
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
unsigned GetNumNodes() const
unsigned GetNodeGlobalIndex(unsigned localIndex) const
void SetMeshHasChangedSinceLoading()
double GetVolume(double determinant) const
void CalculateJacobian(c_matrix< double, SPACE_DIM, ELEMENT_DIM > &rJacobian, double &rJacobianDeterminant)
Element< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
Definition Cell.hpp:92
MutableMesh< ELEMENT_DIM, SPACE_DIM >::EdgeIterator mEdgeIter
MeshBasedCellPopulation< ELEMENT_DIM, SPACE_DIM > & mrCellPopulation
bool operator!=(const typename MeshBasedCellPopulation< ELEMENT_DIM, SPACE_DIM >::SpringIterator &rOther)
SpringIterator(MeshBasedCellPopulation< ELEMENT_DIM, SPACE_DIM > &rCellPopulation, typename MutableMesh< ELEMENT_DIM, SPACE_DIM >::EdgeIterator edgeIter)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
std::map< std::pair< unsigned, unsigned >, double > mSpringRestLengths
void SetBoundedVoroniTesselationLengthCutoff(double boundedVoroniTesselationLengthCutoff)
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void WriteResultsToFiles(const std::string &rDirectory)
virtual void Update(bool hasHadBirthsOrDeaths=true)
double GetVoronoiEdgeLength(unsigned index1, unsigned index2)
void SetScaleBoundByEdgeLength(bool scaleBoundByEdgeLength)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< ELEMENT_DIM, SPACE_DIM > > pPopulationWriter)
double GetDampingConstant(unsigned nodeIndex)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > pCellWriter, CellPtr pCell)
void SetWriteVtkAsPoints(bool writeVtkAsPoints)
double GetWidth(const unsigned &rDimension)
MeshBasedCellPopulation(MutableMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices={}, bool deleteMesh=false, bool validate=true)
void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > &rNewLocation)
virtual void AcceptPopulationEventWriter(boost::shared_ptr< AbstractCellPopulationEventWriter< ELEMENT_DIM, SPACE_DIM > > pPopulationEventWriter)
void SetAreaBasedDampingConstant(bool useAreaBasedDampingConstant)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual TetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * GetTetrahedralMeshForPdeModifier()
VertexMesh< ELEMENT_DIM, SPACE_DIM > * mpVoronoiTessellation
virtual CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell)
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
double GetSurfaceAreaOfVoronoiElement(unsigned index)
void SetOffsetNewBoundaryNodes(bool offsetNewBoundaryNodes)
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
Node< SPACE_DIM > * GetNode(unsigned index)
virtual void UpdateGhostNodesAfterReMesh(NodeMap &rMap)
void SetBoundVoronoiTessellation(bool boundVoronoiTessellation)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< ELEMENT_DIM, SPACE_DIM > > pPopulationCountWriter)
double GetVolumeOfVoronoiElement(unsigned index)
void SetRestLength(unsigned indexA, unsigned indexB, double restLength)
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
VertexMesh< ELEMENT_DIM, SPACE_DIM > * GetVoronoiTessellation()
MutableMesh< ELEMENT_DIM, SPACE_DIM > * mpMutableMesh
void SetAreaBasedDampingConstantParameter(double areaBasedDampingConstantParameter)
void DivideLongSprings(double springDivisionThreshold)
double GetRestLength(unsigned indexA, unsigned indexB)
double GetVolumeOfCell(CellPtr pCell)
MutableMesh< ELEMENT_DIM, SPACE_DIM > & rGetMesh()
virtual void ReMesh(NodeMap &map)
void DeleteNodePriorToReMesh(unsigned index)
virtual void SetNode(unsigned index, ChastePoint< SPACE_DIM > point, bool concreteMove=true)
Definition Node.hpp:59
ContainingElementIterator ContainingElementsEnd() const
Definition Node.hpp:493
std::set< unsigned > & rGetContainingElementIndices()
Definition Node.cpp:300
ContainingElementIterator ContainingElementsBegin() const
Definition Node.hpp:485
unsigned GetIndex() const
Definition Node.cpp:158
static SimulationTime * Instance()
unsigned GetTimeStepsElapsed() const
EdgeIterator EdgesEnd()