Chaste  Release::2017.1
NodeBasedCellPopulationWithParticles.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 "NodeBasedCellPopulationWithParticles.hpp"
37 #include "VtkMeshWriter.hpp"
38 #include "CellAgesWriter.hpp"
39 #include "CellAncestorWriter.hpp"
40 #include "CellProliferativePhasesWriter.hpp"
41 #include "CellProliferativeTypesWriter.hpp"
42 #include "CellVolumesWriter.hpp"
43 #include "CellMutationStatesCountWriter.hpp"
44 
45 template<unsigned DIM>
47  std::vector<CellPtr>& rCells,
48  const std::vector<unsigned> locationIndices,
49  bool deleteMesh)
50  : NodeBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false)
51 {
53  if (!locationIndices.empty())
54  {
55  // Create a set of node indices corresponding to particles
56  std::set<unsigned> node_indices;
57  std::set<unsigned> location_indices;
58  std::set<unsigned> particle_indices;
59 
60  for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
61  node_iter != rMesh.GetNodeIteratorEnd();
62  ++node_iter)
63  {
64  node_indices.insert(node_iter->GetIndex());
65  }
66  for (unsigned i=0; i<locationIndices.size(); i++)
67  {
68  location_indices.insert(locationIndices[i]);
69  }
70 
71  std::set_difference(node_indices.begin(), node_indices.end(),
72  location_indices.begin(), location_indices.end(),
73  std::inserter(particle_indices, particle_indices.begin()));
74 
75  // This method finishes and then calls Validate()
76  SetParticles(particle_indices);
77  }
78  else
79  {
80  for (typename NodesOnlyMesh<DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
81  node_iter != rMesh.GetNodeIteratorEnd();
82  ++node_iter)
83  {
84  (*node_iter).SetIsParticle(false);
85  }
87  }
88 }
89 
90 template<unsigned DIM>
92  : NodeBasedCellPopulation<DIM>(rMesh)
93 {
94 }
95 
96 template<unsigned DIM>
98 {
99  return this->GetNode(index)->IsParticle();
100 }
101 
102 template<unsigned DIM>
104 {
105  std::set<unsigned> particle_indices;
106 
107  for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
108  node_iter != this->mrMesh.GetNodeIteratorEnd();
109  ++node_iter)
110  {
111  if (node_iter->IsParticle())
112  {
113  particle_indices.insert(node_iter->GetIndex());
114  }
115  }
116 
117  return particle_indices;
118 }
119 
120 template<unsigned DIM>
121 void NodeBasedCellPopulationWithParticles<DIM>::SetParticles(const std::set<unsigned>& rParticleIndices)
122 {
123  for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
124  node_iter != this->mrMesh.GetNodeIteratorEnd();
125  ++node_iter)
126  {
127  if (rParticleIndices.find(node_iter->GetIndex()) != rParticleIndices.end())
128  {
129  node_iter->SetIsParticle(true);
130  }
131  }
133 }
134 
135 template<unsigned DIM>
137 {
138 }
139 
140 template<unsigned DIM>
141 CellPtr NodeBasedCellPopulationWithParticles<DIM>::AddCell(CellPtr pNewCell, CellPtr pParentCell)
142 {
143  assert(pNewCell);
144 
145  // Add new cell to population
146  CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, pParentCell);
147  assert(p_created_cell == pNewCell);
148 
149  // Then set the new cell radius in the NodesOnlyMesh
150  unsigned node_index = this->GetLocationIndexUsingCell(p_created_cell);
151  this->GetNode(node_index)->SetRadius(0.5);
152  this->GetNode(node_index)->SetIsParticle(false);
153 
154  // Return pointer to new cell
155  return p_created_cell;
156 }
157 
158 template<unsigned DIM>
160 {
161  std::map<unsigned, bool> validated_nodes;
162  for (typename AbstractMesh<DIM, DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
163  node_iter != this->mrMesh.GetNodeIteratorEnd();
164  ++node_iter)
165  {
166  validated_nodes[node_iter->GetIndex()] = node_iter->IsParticle();
167  }
168 
169  // Look through all of the cells and record what node they are associated with.
170  for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
171  {
172  unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
173 
174  // If the node attached to this cell is labelled as a particle, then throw an error
175  if (this->GetNode(node_index)->IsParticle())
176  {
177  EXCEPTION("Node " << node_index << " is labelled as a particle and has a cell attached");
178  }
179  validated_nodes[node_index] = true;
180  }
181 
182  for (std::map<unsigned, bool>::iterator map_iter = validated_nodes.begin();
183  map_iter != validated_nodes.end();
184  map_iter++)
185  {
186  if (!map_iter->second)
187  {
188  EXCEPTION("Node " << map_iter->first << " does not appear to be a particle or has a cell associated with it");
189  }
190  }
191 }
192 
193 template<unsigned DIM>
195 {
196  for (typename AbstractMesh<DIM, DIM>::NodeIterator node_iter = this->rGetMesh().GetNodeIteratorBegin();
197  node_iter != this->rGetMesh().GetNodeIteratorEnd();
198  ++node_iter)
199  {
200  // If it isn't a particle then there might be cell writers attached
201  if (! this->IsParticle(node_iter->GetIndex()))
202  {
203  for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
204  cell_writer_iter != this->mCellWriters.end();
205  ++cell_writer_iter)
206  {
207  CellPtr cell_from_node = this->GetCellUsingLocationIndex(node_iter->GetIndex());
208  this->AcceptCellWriter(*cell_writer_iter, cell_from_node);
209  }
210  }
211  }
212 }
213 
214 template<unsigned DIM>
216 {
217 #ifdef CHASTE_VTK
218  // Store the present time as a string
219  std::stringstream time;
221 
222  // Make sure the nodes are ordered contiguously in memory
223  NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
224  this->mpNodesOnlyMesh->ReMesh(map);
225 
226  // Store the number of cells for which to output data to VTK
227  unsigned num_nodes = this->GetNumNodes();
228  std::vector<double> rank(num_nodes);
229  std::vector<double> particles(num_nodes);
230 
231  unsigned num_cell_data_items = 0;
232  std::vector<std::string> cell_data_names;
233 
234  // We assume that the first cell is representative of all cells
235  if (num_nodes > 0)
236  {
237  num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
238  cell_data_names = this->Begin()->GetCellData()->GetKeys();
239  }
240 
241  std::vector<std::vector<double> > cell_data;
242  for (unsigned var=0; var<num_cell_data_items; var++)
243  {
244  std::vector<double> cell_data_var(num_nodes);
245  cell_data.push_back(cell_data_var);
246  }
247 
248  // Create mesh writer for VTK output
249  VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
250  mesh_writer.SetParallelFiles(*(this->mpNodesOnlyMesh));
251 
252  // Iterate over any cell writers that are present
253  for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
254  cell_writer_iter != this->mCellWriters.end();
255  ++cell_writer_iter)
256  {
257  // Create vector to store VTK cell data
258  std::vector<double> vtk_cell_data(num_nodes);
259 
260  // Loop over nodes
261  for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
262  node_iter != this->mrMesh.GetNodeIteratorEnd();
263  ++node_iter)
264  {
265  unsigned node_index = node_iter->GetIndex();
266 
267  // If this node is a particle (not a cell), then we set the 'dummy' VTK cell data for this to be -2.0...
268  if (this->IsParticle(node_index))
269  {
270  vtk_cell_data[node_index] = -2.0;
271  }
272  else
273  {
274  // ...otherwise we populate the vector of VTK cell data as usual
275  CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
276  vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
277  }
278  }
279 
280  mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
281  }
282 
283  // Loop over cells
284  for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
285  cell_iter != this->End();
286  ++cell_iter)
287  {
288  // Get the node index corresponding to this cell
289  unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
290  unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
291 
292  for (unsigned var=0; var<num_cell_data_items; var++)
293  {
294  cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
295  }
296 
297  rank[node_index] = (PetscTools::GetMyRank());
298  }
299 
300  mesh_writer.AddPointData("Process rank", rank);
301 
302  // Loop over nodes
303  for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
304  node_iter != this->mrMesh.GetNodeIteratorEnd();
305  ++node_iter)
306  {
307  unsigned node_index = node_iter->GetIndex();
308  particles[node_index] = (double) (this->IsParticle(node_index));
309  }
310 
311  mesh_writer.AddPointData("Non-particles", particles);
312 
313  if (num_cell_data_items > 0)
314  {
315  for (unsigned var=0; var<cell_data.size(); var++)
316  {
317  mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
318  }
319  }
320 
321  mesh_writer.WriteFilesUsingMesh(*(this->mpNodesOnlyMesh));
322 
323  *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
325  *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
328  {
329  *(this->mpVtkMetaFile) << ".vtu\"/>\n";
330  }
331 /* {
332  // Parallel vtu files .vtu -> .pvtu
333  *(this->mpVtkMetaFile) << ".pvtu\"/>\n";
334  }*/
335 #endif //CHASTE_VTK
336 }
337 
338 template<unsigned DIM>
340 {
341  // Call method on direct parent class
343 }
344 
345 // Explicit instantiation
349 
350 // Serialization for Boost >= 1.36
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell)
void OutputCellPopulationParameters(out_stream &rParamsFile)
NodesOnlyMesh< DIM > & rGetMesh()
virtual unsigned GetMaximumNodeIndex()
unsigned GetLocationIndexUsingCell(CellPtr pCell)
NodeBasedCellPopulationWithParticles(NodesOnlyMesh< DIM > &rMesh, std::vector< CellPtr > &rCells, const std::vector< unsigned > locationIndices=std::vector< unsigned >(), bool deleteMesh=false)
std::vector< boost::shared_ptr< AbstractCellWriter< ELEMENT_DIM, SPACE_DIM > > > mCellWriters
#define EXCEPTION(message)
Definition: Exception.hpp:143
Node< DIM > * GetNode(unsigned index)
static SimulationTime * Instance()
void SetParallelFiles(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
NodeIterator GetNodeIteratorEnd()
unsigned GetTimeStepsElapsed() const
void ReMesh(NodeMap &rMap)
static bool IsSequential()
Definition: PetscTools.cpp:91
#define EXPORT_TEMPLATE_CLASS_SAME_DIMS(CLASS)
unsigned SolveNodeMapping(unsigned index) const
CellPtr AddCell(CellPtr pNewCell, CellPtr pParentCell=CellPtr())
#define EXCEPT_IF_NOT(test)
Definition: Exception.hpp:158
NodeIterator GetNodeIteratorBegin(bool skipDeletedNodes=true)
virtual void AcceptCellWriter(boost::shared_ptr< AbstractCellWriter< DIM, DIM > > pCellWriter, CellPtr pCell)
virtual void WriteVtkResultsToFile(const std::string &rDirectory)
virtual CellPtr GetCellUsingLocationIndex(unsigned index)
NodesOnlyMesh< DIM > * mpNodesOnlyMesh
static unsigned GetMyRank()
Definition: PetscTools.cpp:114
AbstractMesh< ELEMENT_DIM, SPACE_DIM > & mrMesh
void SetParticles(const std::set< unsigned > &rParticleIndices)