Chaste  Release::2017.1
VertexBasedCellPopulation.cpp
1 /*
2 
3 Copyright (c) 2005-2017, University of Oxford.
4 All rights reserved.
5 
6 University of Oxford means the Chancellor, Masters and Scholars of the
7 University of Oxford, having an administrative office at Wellington
8 Square, Oxford OX1 2JD, UK.
9 
10 This file is part of Chaste.
11 
12 Redistribution and use in source and binary forms, with or without
13 modification, 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 
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 OF 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 "AbstractCellBasedSimulation.hpp"
50 
51 template<unsigned DIM>
53  std::vector<CellPtr>& rCells,
54  bool deleteMesh,
55  bool validate,
56  const std::vector<unsigned> locationIndices)
57  : AbstractOffLatticeCellPopulation<DIM>(rMesh, rCells, locationIndices),
58  mDeleteMesh(deleteMesh),
59  mOutputCellRearrangementLocations(true),
60  mRestrictVertexMovement(true)
61 {
62  mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
64 
65  // If no location indices are specified, associate with elements from the mesh (assumed to be sequentially ordered).
66  std::list<CellPtr>::iterator it = this->mCells.begin();
67  for (unsigned i=0; it != this->mCells.end(); ++it, ++i)
68  {
69  unsigned index = locationIndices.empty() ? i : locationIndices[i]; // assume that the ordering matches
71  }
72 
73  // Check each element has only one cell attached
74  if (validate)
75  {
76  Validate();
77  }
78 }
79 
80 template<unsigned DIM>
83  mDeleteMesh(true),
86 {
87  mpMutableVertexMesh = static_cast<MutableVertexMesh<DIM, DIM>* >(&(this->mrMesh));
88 }
89 
90 template<unsigned DIM>
92 {
93  if (mDeleteMesh)
94  {
95  delete &this->mrMesh;
96  }
97 }
98 
99 template<unsigned DIM>
101 {
102  // Take the average of the cells containing this vertex
103  double average_damping_constant = 0.0;
104 
105  std::set<unsigned> containing_elements = GetNode(nodeIndex)->rGetContainingElementIndices();
106 
107  unsigned num_containing_elements = containing_elements.size();
108  if (num_containing_elements == 0)
109  {
110  EXCEPTION("At time " << SimulationTime::Instance()->GetTime() << ", Node " << nodeIndex << " is not contained in any elements, so GetDampingConstant() returns zero");
111  }
112 
113  double temp = 1.0/((double) num_containing_elements);
114  for (std::set<unsigned>::iterator iter = containing_elements.begin();
115  iter != containing_elements.end();
116  ++iter)
117  {
118  CellPtr p_cell = this->GetCellUsingLocationIndex(*iter);
119  bool cell_is_wild_type = p_cell->GetMutationState()->IsType<WildTypeCellMutationState>();
120 
121  if (cell_is_wild_type)
122  {
123  average_damping_constant += this->GetDampingConstantNormal()*temp;
124  }
125  else
126  {
127  average_damping_constant += this->GetDampingConstantMutant()*temp;
128  }
129  }
130 
131  return average_damping_constant;
132 }
133 
134 template<unsigned DIM>
136 {
137  return *mpMutableVertexMesh;
138 }
139 
140 template<unsigned DIM>
142 {
143  return *mpMutableVertexMesh;
144 }
145 
146 template<unsigned DIM>
148 {
149  return mpMutableVertexMesh->GetElement(elementIndex);
150 }
151 
152 template<unsigned DIM>
154 {
155  return this->mrMesh.GetNumNodes();
156 }
157 
158 template<unsigned DIM>
160 {
161  return mpMutableVertexMesh->GetCentroidOfElement(this->mCellLocationMap[pCell.get()]);
162 }
163 
164 template<unsigned DIM>
166 {
167  return this->mrMesh.GetNode(index);
168 }
169 
170 template<unsigned DIM>
172 {
173  unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
174  return this->rGetMesh().GetNeighbouringElementIndices(elem_index);
175 }
176 
177 template<unsigned DIM>
179 {
180  return mpMutableVertexMesh->AddNode(pNewNode);
181 }
182 
183 template<unsigned DIM>
184 void VertexBasedCellPopulation<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
185 {
186  mpMutableVertexMesh->SetNode(nodeIndex, rNewLocation);
187 }
188 
189 template<unsigned DIM>
191 {
193 }
194 
195 template<unsigned DIM>
197 {
199 }
200 
201 template<unsigned DIM>
202 CellPtr VertexBasedCellPopulation<DIM>::AddCell(CellPtr pNewCell, CellPtr pParentCell)
203 {
204  // Get the element associated with this cell
205  VertexElement<DIM, DIM>* p_element = GetElementCorrespondingToCell(pParentCell);
206 
207  // Get the orientation of division
208  c_vector<double, DIM> division_vector = mpVertexBasedDivisionRule->CalculateCellDivisionVector(pParentCell, *this);
209 
210  // Divide the element
211  unsigned new_element_index = mpMutableVertexMesh->DivideElementAlongGivenAxis(p_element, division_vector, true);
212 
213  // Associate the new cell with the element
214  this->mCells.push_back(pNewCell);
215 
216  // Update location cell map
217  CellPtr p_created_cell = this->mCells.back();
218  this->SetCellUsingLocationIndex(new_element_index,p_created_cell);
219  this->mCellLocationMap[p_created_cell.get()] = new_element_index;
220 
221  return p_created_cell;
222 }
223 
224 template<unsigned DIM>
226 {
227  unsigned num_removed = 0;
228 
229  for (std::list<CellPtr>::iterator it = this->mCells.begin();
230  it != this->mCells.end();
231  )
232  {
233  if ((*it)->IsDead())
234  {
235  // Count the cell as dead
236  num_removed++;
237 
238  // Remove the element from the mesh if it is not deleted yet
240  if (!(this->GetElement(this->GetLocationIndexUsingCell((*it)))->IsDeleted()))
241  {
242  // This warning relies on the fact that there is only one other possibility for
243  // vertex elements to be marked as deleted: a T2 swap
244  WARN_ONCE_ONLY("A Cell is removed without performing a T2 swap. This could leave a void in the mesh.");
246  }
247 
248  // Delete the cell
249  it = this->mCells.erase(it);
250  }
251  else
252  {
253  ++it;
254  }
255  }
256  return num_removed;
257 }
258 
259 template<unsigned DIM>
260 void VertexBasedCellPopulation<DIM>::CheckForStepSizeException(unsigned nodeIndex, c_vector<double,DIM>& rDisplacement, double dt)
261 {
262  double length = norm_2(rDisplacement);
263 
265  {
267  {
268  rDisplacement *= 0.5*mpMutableVertexMesh->GetCellRearrangementThreshold()/length;
269 
270  std::ostringstream message;
271  message << "Vertices are moving more than half the CellRearrangementThreshold. This could cause elements to become inverted ";
272  message << "so the motion has been restricted. Use a smaller timestep to avoid these warnings.";
273 
274  double suggested_step = 0.95*dt*((0.5*mpMutableVertexMesh->GetCellRearrangementThreshold())/length);
275 
276  throw StepSizeException(suggested_step, message.str(), false);
277  }
278  }
279 }
280 
281 template<unsigned DIM>
283 {
284  return GetElementCorrespondingToCell(pCell)->IsDeleted();
285 }
286 
287 template<unsigned DIM>
288 void VertexBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
289 {
291  mpMutableVertexMesh->ReMesh(element_map);
292 
293  if (!element_map.IsIdentityMap())
294  {
295  // Fix up the mappings between CellPtrs and VertexElements
297  std::map<Cell*, unsigned> old_map = this->mCellLocationMap;
298 
299  this->mCellLocationMap.clear();
300  this->mLocationCellMap.clear();
301 
302  for (std::list<CellPtr>::iterator cell_iter = this->mCells.begin();
303  cell_iter != this->mCells.end();
304  ++cell_iter)
305  {
306  // The cell vector should only ever contain living cells
307  unsigned old_elem_index = old_map[(*cell_iter).get()];
308  assert(!element_map.IsDeleted(old_elem_index));
309 
310  unsigned new_elem_index = element_map.GetNewIndex(old_elem_index);
311  this->SetCellUsingLocationIndex(new_elem_index, *cell_iter);
312  }
313 
314  // Check that each VertexElement has only one CellPtr associated with it in the updated cell population
315  Validate();
316  }
317 
318  element_map.ResetToIdentity();
319 }
320 
321 template<unsigned DIM>
323 {
324  // Check each element has only one cell attached
325  std::vector<unsigned> validated_element = std::vector<unsigned>(this->GetNumElements(), 0);
326  for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
327  cell_iter != this->End();
328  ++cell_iter)
329  {
330  unsigned elem_index = this->GetLocationIndexUsingCell(*cell_iter);
331  validated_element[elem_index]++;
332  }
333 
334  for (unsigned i=0; i<validated_element.size(); i++)
335  {
336  if (validated_element[i] == 0)
337  {
338  EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " does not appear to have a cell associated with it");
339  }
340 
341  if (validated_element[i] > 1)
342  {
343  // This should never be reached as you can only set one cell per element index
344  EXCEPTION("At time " << SimulationTime::Instance()->GetTime() <<", Element " << i << " appears to have " << validated_element[i] << " cells associated with it");
345  }
346  }
347 }
348 
349 template<unsigned DIM>
351 {
352  pPopulationWriter->Visit(this);
353 }
354 
355 template<unsigned DIM>
357 {
358  pPopulationCountWriter->Visit(this);
359 }
360 
361 template<unsigned DIM>
362 void VertexBasedCellPopulation<DIM>::AcceptCellWriter(boost::shared_ptr<AbstractCellWriter<DIM, DIM> > pCellWriter, CellPtr pCell)
363 {
364  pCellWriter->VisitCell(pCell, this);
365 }
366 
367 template<unsigned DIM>
369 {
370  // Get the vertex element index corresponding to this cell
371  unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
372 
373  // Get the element rosette rank from the vertex mesh
374  unsigned rosette_rank = mpMutableVertexMesh->GetRosetteRankOfElement(elem_index);
375 
376  return rosette_rank;
377 }
378 
379 template<unsigned DIM>
381 {
382  // Get the vertex element index corresponding to this cell
383  unsigned elem_index = this->GetLocationIndexUsingCell(pCell);
384 
385  // Get the cell's volume from the vertex mesh
386  double cell_volume = mpMutableVertexMesh->GetVolumeOfElement(elem_index);
387 
388  return cell_volume;
389 }
390 
391 template<unsigned DIM>
392 void VertexBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
393 {
394 #ifdef CHASTE_VTK
395 
396  // Create mesh writer for VTK output
397  VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
398 
399  // Iterate over any cell writers that are present
400  unsigned num_cells = this->GetNumAllCells();
401  for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
402  cell_writer_iter != this->mCellWriters.end();
403  ++cell_writer_iter)
404  {
405  // Create vector to store VTK cell data
406  std::vector<double> vtk_cell_data(num_cells);
407 
408  // Iterate over vertex elements ///\todo #2512 - replace with loop over cells
411  ++elem_iter)
412  {
413  // Get index of this element in the vertex mesh
414  unsigned elem_index = elem_iter->GetIndex();
415 
416  // Get the cell corresponding to this element
417  CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
418  assert(p_cell);
419 
420  // Populate the vector of VTK cell data
421  vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
422  }
423 
424  mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
425  }
426 
427  // When outputting any CellData, we assume that the first cell is representative of all cells
428  unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
429  std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();
430 
431  std::vector<std::vector<double> > cell_data;
432  for (unsigned var=0; var<num_cell_data_items; var++)
433  {
434  std::vector<double> cell_data_var(num_cells);
435  cell_data.push_back(cell_data_var);
436  }
437 
438  // Loop over vertex elements ///\todo #2512 - replace with loop over cells
441  ++elem_iter)
442  {
443  // Get index of this element in the vertex mesh
444  unsigned elem_index = elem_iter->GetIndex();
445 
446  // Get the cell corresponding to this element
447  CellPtr p_cell = this->GetCellUsingLocationIndex(elem_index);
448  assert(p_cell);
449 
450  for (unsigned var=0; var<num_cell_data_items; var++)
451  {
452  cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
453  }
454  }
455  for (unsigned var=0; var<num_cell_data_items; var++)
456  {
457  mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
458  }
459 
460  unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
461  std::stringstream time;
462  time << num_timesteps;
463 
464  mesh_writer.WriteVtkUsingMesh(*mpMutableVertexMesh, time.str());
465 
466  *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
467  *(this->mpVtkMetaFile) << num_timesteps;
468  *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
469  *(this->mpVtkMetaFile) << num_timesteps;
470  *(this->mpVtkMetaFile) << ".vtu\"/>\n";
471 #endif //CHASTE_VTK
472 }
473 
474 template<unsigned DIM>
476 {
478  {
479  if (!this-> template HasWriter<CellPopulationElementWriter>())
480  {
481  this-> template AddPopulationWriter<CellPopulationElementWriter>();
482  }
483  }
484 
486  {
487  if (!this-> template HasWriter<VertexT1SwapLocationsWriter>())
488  {
489  this-> template AddPopulationWriter<VertexT1SwapLocationsWriter>();
490  }
491  if (!this-> template HasWriter<VertexT2SwapLocationsWriter>())
492  {
493  this-> template AddPopulationWriter<VertexT2SwapLocationsWriter>();
494  }
495  if (!this-> template HasWriter<VertexT3SwapLocationsWriter>())
496  {
497  this-> template AddPopulationWriter<VertexT3SwapLocationsWriter>();
498  }
499  }
500 
502 }
503 
504 template<unsigned DIM>
506 {
508 }
509 
510 template<unsigned DIM>
512 {
513  mOutputCellRearrangementLocations = outputCellRearrangementLocations;
514 }
515 
516 template<unsigned DIM>
518 {
519  *rParamsFile << "\t\t<CellRearrangementThreshold>" << mpMutableVertexMesh->GetCellRearrangementThreshold() << "</CellRearrangementThreshold>\n";
520  *rParamsFile << "\t\t<T2Threshold>" << mpMutableVertexMesh->GetT2Threshold() << "</T2Threshold>\n";
521  *rParamsFile << "\t\t<CellRearrangementRatio>" << mpMutableVertexMesh->GetCellRearrangementRatio() << "</CellRearrangementRatio>\n";
522  *rParamsFile << "\t\t<OutputCellRearrangementLocations>" << mOutputCellRearrangementLocations << "</OutputCellRearrangementLocations>\n";
523 
524  // Add the division rule parameters
525  *rParamsFile << "\t\t<VertexBasedDivisionRule>\n";
526  mpVertexBasedDivisionRule->OutputCellVertexBasedDivisionRuleInfo(rParamsFile);
527  *rParamsFile << "\t\t</VertexBasedDivisionRule>\n";
528 
529  // Call method on direct parent class
531 }
532 
533 template<unsigned DIM>
534 double VertexBasedCellPopulation<DIM>::GetWidth(const unsigned& rDimension)
535 {
536  // Call GetWidth() on the mesh
537  double width = this->mrMesh.GetWidth(rDimension);
538 
539  return width;
540 }
541 
542 template<unsigned DIM>
544 {
546 }
547 
548 template<unsigned DIM>
549 boost::shared_ptr<AbstractVertexBasedDivisionRule<DIM> > VertexBasedCellPopulation<DIM>::GetVertexBasedDivisionRule()
550 {
552 }
553 
554 template<unsigned DIM>
556 {
557  mpVertexBasedDivisionRule = pVertexBasedDivisionRule;
558 }
559 
560 template<unsigned DIM>
561 std::vector< c_vector< double, DIM > > VertexBasedCellPopulation<DIM>::GetLocationsOfT2Swaps()
562 {
563  return mLocationsOfT2Swaps;
564 }
565 
566 template<unsigned DIM>
568 {
569  return mCellIdsOfT2Swaps;
570 }
571 
572 template<unsigned DIM>
573 void VertexBasedCellPopulation<DIM>::AddLocationOfT2Swap(c_vector< double, DIM> locationOfT2Swap)
574 {
575  mLocationsOfT2Swaps.push_back(locationOfT2Swap);
576 }
577 
578 template<unsigned DIM>
580 {
581  mCellIdsOfT2Swaps.push_back(idOfT2Swap);
582 }
583 
584 template<unsigned DIM>
586 {
587  mCellIdsOfT2Swaps.clear();
588  mLocationsOfT2Swaps.clear();
589 }
590 
591 template<unsigned DIM>
593 {
594  // This method only works in 2D sequential
595  assert(DIM == 2); // LCOV_EXCL_LINE - disappears at compile time.
596  assert(PetscTools::IsSequential());
597 
598  unsigned num_vertex_nodes = mpMutableVertexMesh->GetNumNodes();
599  unsigned num_vertex_elements = mpMutableVertexMesh->GetNumElements();
600 
601  std::string mesh_file_name = "mesh";
602 
603  // Get a unique temporary foldername
604  std::stringstream pid;
605  pid << getpid();
606  OutputFileHandler output_file_handler("2D_temporary_tetrahedral_mesh_" + pid.str());
607  std::string output_dir = output_file_handler.GetOutputDirectoryFullPath();
608 
609  // Compute the number of nodes in the TetrahedralMesh
610  unsigned num_tetrahedral_nodes = num_vertex_nodes + num_vertex_elements;
611 
612  // Write node file
613  out_stream p_node_file = output_file_handler.OpenOutputFile(mesh_file_name+".node");
614  (*p_node_file) << std::scientific;
615  (*p_node_file) << std::setprecision(20);
616  (*p_node_file) << num_tetrahedral_nodes << "\t2\t0\t1" << std::endl;
617 
618  // Begin by writing each node in the VertexMesh
619  for (unsigned node_index=0; node_index<num_vertex_nodes; node_index++)
620  {
621  Node<DIM>* p_node = mpMutableVertexMesh->GetNode(node_index);
622 
624  unsigned index = p_node->GetIndex();
625  const c_vector<double, DIM>& r_location = p_node->rGetLocation();
626  unsigned is_boundary_node = p_node->IsBoundaryNode() ? 1 : 0;
627 
628  (*p_node_file) << index << "\t" << r_location[0] << "\t" << r_location[1] << "\t" << is_boundary_node << std::endl;
629  }
630 
631  // Now write an additional node at each VertexElement's centroid
632  unsigned num_tetrahedral_elements = 0;
633  for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
634  {
635  unsigned index = num_vertex_nodes + vertex_elem_index;
636 
637  c_vector<double, DIM> location = mpMutableVertexMesh->GetCentroidOfElement(vertex_elem_index);
638 
639  // Any node located at a VertexElement's centroid will not be a boundary node
640  unsigned is_boundary_node = 0;
641  (*p_node_file) << index << "\t" << location[0] << "\t" << location[1] << "\t" << is_boundary_node << std::endl;
642 
643  // Also keep track of how many tetrahedral elements there will be
644  num_tetrahedral_elements += mpMutableVertexMesh->GetElement(vertex_elem_index)->GetNumNodes();
645  }
646  p_node_file->close();
647 
648  // Write element file
649  out_stream p_elem_file = output_file_handler.OpenOutputFile(mesh_file_name+".ele");
650  (*p_elem_file) << std::scientific;
651  (*p_elem_file) << num_tetrahedral_elements << "\t3\t0" << std::endl;
652 
653  std::set<std::pair<unsigned, unsigned> > tetrahedral_edges;
654 
655  unsigned tetrahedral_elem_index = 0;
656  for (unsigned vertex_elem_index=0; vertex_elem_index<num_vertex_elements; vertex_elem_index++)
657  {
658  VertexElement<DIM, DIM>* p_vertex_element = mpMutableVertexMesh->GetElement(vertex_elem_index);
659 
660  // Iterate over nodes owned by this VertexElement
661  unsigned num_nodes_in_vertex_element = p_vertex_element->GetNumNodes();
662  for (unsigned local_index=0; local_index<num_nodes_in_vertex_element; local_index++)
663  {
664  unsigned node_0_index = p_vertex_element->GetNodeGlobalIndex(local_index);
665  unsigned node_1_index = p_vertex_element->GetNodeGlobalIndex((local_index+1)%num_nodes_in_vertex_element);
666  unsigned node_2_index = num_vertex_nodes + vertex_elem_index;
667 
668  (*p_elem_file) << tetrahedral_elem_index++ << "\t" << node_0_index << "\t" << node_1_index << "\t" << node_2_index << std::endl;
669 
670  // Add edges to the set if they are not already present
671  std::pair<unsigned, unsigned> edge_0 = this->CreateOrderedPair(node_0_index, node_1_index);
672  std::pair<unsigned, unsigned> edge_1 = this->CreateOrderedPair(node_1_index, node_2_index);
673  std::pair<unsigned, unsigned> edge_2 = this->CreateOrderedPair(node_2_index, node_0_index);
674 
675  tetrahedral_edges.insert(edge_0);
676  tetrahedral_edges.insert(edge_1);
677  tetrahedral_edges.insert(edge_2);
678  }
679  }
680  p_elem_file->close();
681 
682  // Write edge file
683  out_stream p_edge_file = output_file_handler.OpenOutputFile(mesh_file_name+".edge");
684  (*p_edge_file) << std::scientific;
685  (*p_edge_file) << tetrahedral_edges.size() << "\t1" << std::endl;
686 
687  unsigned edge_index = 0;
688  for (std::set<std::pair<unsigned, unsigned> >::iterator edge_iter = tetrahedral_edges.begin();
689  edge_iter != tetrahedral_edges.end();
690  ++edge_iter)
691  {
692  std::pair<unsigned, unsigned> this_edge = *edge_iter;
693 
694  // To be a boundary edge both nodes need to be boundary nodes.
695  bool is_boundary_edge = false;
696  if (this_edge.first < mpMutableVertexMesh->GetNumNodes() &&
697  this_edge.second < mpMutableVertexMesh->GetNumNodes())
698  {
699  is_boundary_edge = (mpMutableVertexMesh->GetNode(this_edge.first)->IsBoundaryNode() &&
700  mpMutableVertexMesh->GetNode(this_edge.second)->IsBoundaryNode() );
701  }
702  unsigned is_boundary_edge_unsigned = is_boundary_edge ? 1 : 0;
703 
704  (*p_edge_file) << edge_index++ << "\t" << this_edge.first << "\t" << this_edge.second << "\t" << is_boundary_edge_unsigned << std::endl;
705  }
706  p_edge_file->close();
707 
708  // Having written the mesh to file, now construct it using TrianglesMeshReader
710 
711  // Nested scope so reader is destroyed before we remove the temporary files
712  {
713  TrianglesMeshReader<DIM, DIM> mesh_reader(output_dir + mesh_file_name);
714  p_mesh->ConstructFromMeshReader(mesh_reader);
715  }
716 
717  // Delete the temporary files
718  output_file_handler.FindFile("").Remove();
719 
720  // The original files have been deleted, it is better if the mesh object forgets about them
722 
723  return p_mesh;
724 }
725 
726 template<unsigned DIM>
728 {
729  bool non_apoptotic_cell_present = true;
730 
731  if (pdeNodeIndex < this->GetNumNodes())
732  {
733  std::set<unsigned> containing_element_indices = this->GetNode(pdeNodeIndex)->rGetContainingElementIndices();
734 
735  for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
736  iter != containing_element_indices.end();
737  iter++)
738  {
739  if (this->GetCellUsingLocationIndex(*iter)->template HasCellProperty<ApoptoticCellProperty>() )
740  {
741  non_apoptotic_cell_present = false;
742  break;
743  }
744  }
745  }
746  else
747  {
748  /*
749  * This node of the tetrahedral finite element mesh is in the centre of the element of the
750  * vertex-based cell population, so we can use an offset to compute which cell to interrogate.
751  */
752  non_apoptotic_cell_present = !(this->GetCellUsingLocationIndex(pdeNodeIndex - this->GetNumNodes())->template HasCellProperty<ApoptoticCellProperty>());
753  }
754 
755  return non_apoptotic_cell_present;
756 }
757 
758 template<unsigned DIM>
760  unsigned pdeNodeIndex,
761  std::string& rVariableName,
762  bool dirichletBoundaryConditionApplies,
763  double dirichletBoundaryValue)
764 {
765  unsigned num_nodes = this->GetNumNodes();
766  double value = 0.0;
767 
768  // Cells correspond to nodes in the centre of the vertex element; nodes on vertices have averaged values from containing cells
769 
770  if (pdeNodeIndex >= num_nodes)
771  {
772  // Offset to relate elements in vertex mesh to nodes in tetrahedral mesh
773  assert(pdeNodeIndex-num_nodes < num_nodes);
774 
775  CellPtr p_cell = this->GetCellUsingLocationIndex(pdeNodeIndex - num_nodes);
776  value = p_cell->GetCellData()->GetItem(rVariableName);
777  }
778  else
779  {
781  if (dirichletBoundaryConditionApplies)
782  {
783  // We need to impose the Dirichlet boundaries again here as not represented in cell data
784  value = dirichletBoundaryValue;
785  }
786  else
787  {
788  assert(pdeNodeIndex < num_nodes);
789  Node<DIM>* p_node = this->GetNode(pdeNodeIndex);
790 
791  // Average over data from containing elements (cells)
792  std::set<unsigned> containing_elements = p_node->rGetContainingElementIndices();
793  for (std::set<unsigned>::iterator index_iter = containing_elements.begin();
794  index_iter != containing_elements.end();
795  ++index_iter)
796  {
797  assert(*index_iter < num_nodes);
798  CellPtr p_cell = this->GetCellUsingLocationIndex(*index_iter);
799  value += p_cell->GetCellData()->GetItem(rVariableName);
800  }
801  value /= containing_elements.size();
802  }
803  }
804 
805  return value;
806 }
807 
808 template<unsigned DIM>
810 {
811  return 0.002;
812 }
813 
814 template<unsigned DIM>
816 {
817  if (bool(dynamic_cast<Cylindrical2dVertexMesh*>(&(this->mrMesh))))
818  {
819  *pVizSetupFile << "MeshWidth\t" << this->GetWidth(0) << "\n";
820  }
821 }
822 
823 template<unsigned DIM>
825 {
826  MAKE_PTR_ARGS(T2SwapCellKiller<DIM>, p_t2_swap_cell_killer, (this));
827  pSimulation->AddCellKiller(p_t2_swap_cell_killer);
828 }
829 
830 
831 template<unsigned DIM>
833 {
835 }
836 
837 template<unsigned DIM>
839 {
840  mRestrictVertexMovement = restrictMovement;
841 }
842 
843 // Explicit instantiation
844 template class VertexBasedCellPopulation<1>;
845 template class VertexBasedCellPopulation<2>;
846 template class VertexBasedCellPopulation<3>;
847 
848 // Serialization for Boost >= 1.36
void SetOutputCellRearrangementLocations(bool outputCellRearrangementLocations)
void AddCellData(std::string dataName, std::vector< double > dataPayload)
double GetCellRearrangementRatio() const
std::vector< c_vector< double, DIM > > GetLocationsOfT2Swaps()
std::vector< unsigned > mCellIdsOfT2Swaps
void AddCellKiller(boost::shared_ptr< AbstractCellKiller< SPACE_DIM > > pCellKiller)
virtual void AcceptPopulationCountWriter(boost::shared_ptr< AbstractCellPopulationCountWriter< DIM, DIM > > pPopulationCountWriter)
unsigned DivideElementAlongGivenAxis(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, c_vector< double, SPACE_DIM > axisOfDivision, bool placeOriginalElementBelow=false)
std::set< unsigned > GetNeighbouringNodeIndices(unsigned nodeIndex)
Definition: VertexMesh.cpp:707
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
Definition: Node.hpp:58
std::vector< boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > > mCellWriters
unsigned GetNodeGlobalIndex(unsigned localIndex) const
unsigned GetNumAllElements() const
Definition: VertexMesh.cpp:610
std::vector< c_vector< double, DIM > > mLocationsOfT2Swaps
virtual void SimulationSetupHook(AbstractCellBasedSimulation< DIM, DIM > *pSimulation)
bool IsBoundaryNode() const
Definition: Node.cpp:164
Node< SPACE_DIM > * GetNode(unsigned index) const
#define EXCEPTION(message)
Definition: Exception.hpp:143
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > mpVertexBasedDivisionRule
MutableVertexMesh< DIM, DIM > * mpMutableVertexMesh
double GetT2Threshold() const
static SimulationTime * Instance()
unsigned AddNode(Node< SPACE_DIM > *pNewNode)
double GetCellRearrangementThreshold() const
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
void SetVertexBasedDivisionRule(boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > pVertexBasedDivisionRule)
std::vector< unsigned > GetCellIdsOfT2Swaps()
virtual bool IsPdeNodeAssociatedWithNonApoptoticCell(unsigned pdeNodeIndex)
std::set< unsigned > & rGetContainingElementIndices()
Definition: Node.cpp:300
virtual void WriteDataToVisualizerSetupFile(out_stream &pVizSetupFile)
unsigned GetTimeStepsElapsed() const
std::set< unsigned > GetNeighbouringNodeIndices(unsigned index)
std::string GetOutputDirectoryFullPath() const
VertexElement< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
Definition: VertexMesh.cpp:622
boost::shared_ptr< AbstractVertexBasedDivisionRule< DIM > > GetVertexBasedDivisionRule()
bool IsCellAssociatedWithADeletedLocation(CellPtr pCell)
double GetDampingConstant(unsigned nodeIndex)
void SetRestrictVertexMovementBoolean(bool restrictVertexMovement)
std::set< unsigned > GetNeighbouringLocationIndices(CellPtr pCell)
unsigned GetRosetteRankOfCell(CellPtr pCell)
MutableVertexMesh< DIM, DIM > & rGetMesh()
static bool IsSequential()
Definition: PetscTools.cpp:91
std::pair< unsigned, unsigned > CreateOrderedPair(unsigned index1, unsigned index2)
VertexElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
Definition: VertexMesh.hpp:668
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
virtual void SetNode(unsigned nodeIndex, ChastePoint< SPACE_DIM > point)
std::map< unsigned, std::set< CellPtr > > mLocationCellMap
void SetCellUsingLocationIndex(unsigned index, CellPtr pCell)
virtual void AcceptPopulationWriter(boost::shared_ptr< AbstractCellPopulationWriter< DIM, DIM > > pPopulationWriter)
void Update(bool hasHadBirthsOrDeaths=true)
unsigned GetNumNodes() const
void AddLocationOfT2Swap(c_vector< double, DIM > locationOfT2Swap)
VertexBasedCellPopulation(MutableVertexMesh< DIM, DIM > &rMesh, std::vector< CellPtr > &rCells, bool deleteMesh=false, bool validate=true, const std::vector< unsigned > locationIndices=std::vector< unsigned >())
Node< DIM > * GetNode(unsigned index)
unsigned GetNumNodes() const
virtual TetrahedralMesh< DIM, DIM > * GetTetrahedralMeshForPdeModifier()
void WriteVtkUsingMesh(VertexMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::string stamp="")
virtual double GetVolumeOfElement(unsigned index)
virtual void CheckForStepSizeException(unsigned nodeIndex, c_vector< double, DIM > &rDisplacement, double dt)
void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void OutputCellPopulationParameters(out_stream &rParamsFile)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
virtual void ReMesh(VertexElementMap &rElementMap)
virtual void OpenWritersFiles(OutputFileHandler &rOutputFileHandler)
void SetMeshHasChangedSinceLoading()
void SetNode(unsigned index, ChastePoint< DIM > &rNewLocation)
const c_vector< double, SPACE_DIM > & rGetLocation() const
Definition: Node.cpp:139
void DeleteElementPriorToReMesh(unsigned index)
void AddCellIdOfT2Swap(unsigned idOfT2Swap)
double GetWidth(const unsigned &rDimension)
c_vector< double, DIM > GetLocationOfCellCentre(CellPtr pCell)
virtual c_vector< double, SPACE_DIM > GetCentroidOfElement(unsigned index)
Definition: VertexMesh.cpp:636
unsigned GetNumElements() const
unsigned AddNode(Node< DIM > *pNewNode)
std::set< unsigned > GetNeighbouringElementIndices(unsigned elementIndex)
Definition: VertexMesh.cpp:777
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual double GetCellDataItemAtPdeNode(unsigned pdeNodeIndex, std::string &rVariableName, bool dirichletBoundaryConditionApplies=false, double dirichletBoundaryValue=0.0)
unsigned GetIndex() const
Definition: Node.cpp:158
VertexElementIterator GetElementIteratorEnd()
Definition: VertexMesh.hpp:675
virtual void AddCellUsingLocationIndex(unsigned index, CellPtr pCell)
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
VertexElement< DIM, DIM > * GetElement(unsigned elementIndex)
#define MAKE_PTR_ARGS(TYPE, NAME, ARGS)
VertexElement< DIM, DIM > * GetElementCorrespondingToCell(CellPtr pCell)
unsigned GetRosetteRankOfElement(unsigned index)
Definition: VertexMesh.cpp:549