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