NodeBasedCellPopulationWithParticles.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "NodeBasedCellPopulationWithParticles.hpp"
00037 #include "VtkMeshWriter.hpp"
00038 #include "CellAgesWriter.hpp"
00039 #include "CellAncestorWriter.hpp"
00040 #include "CellProliferativePhasesWriter.hpp"
00041 #include "CellProliferativeTypesWriter.hpp"
00042 #include "CellVolumesWriter.hpp"
00043 #include "CellMutationStatesCountWriter.hpp"
00044 
00045 template<unsigned DIM>
00046 NodeBasedCellPopulationWithParticles<DIM>::NodeBasedCellPopulationWithParticles(NodesOnlyMesh<DIM>& rMesh,
00047                                       std::vector<CellPtr>& rCells,
00048                                       const std::vector<unsigned> locationIndices,
00049                                       bool deleteMesh)
00050     : NodeBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false)
00051 {
00052     EXCEPT_IF_NOT(PetscTools::IsSequential());
00053     if (!locationIndices.empty())
00054     {
00055         // Create a set of node indices corresponding to particles
00056         std::set<unsigned> node_indices;
00057         std::set<unsigned> location_indices;
00058         std::set<unsigned> particle_indices;
00059 
00060         for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
00061              node_iter != rMesh.GetNodeIteratorEnd();
00062              ++node_iter)
00063         {
00064             node_indices.insert(node_iter->GetIndex());
00065         }
00066         for (unsigned i=0; i<locationIndices.size(); i++)
00067         {
00068             location_indices.insert(locationIndices[i]);
00069         }
00070 
00071         std::set_difference(node_indices.begin(), node_indices.end(),
00072                             location_indices.begin(), location_indices.end(),
00073                             std::inserter(particle_indices, particle_indices.begin()));
00074 
00075         // This method finishes and then calls Validate()
00076         SetParticles(particle_indices);
00077     }
00078     else
00079     {
00080         for (typename NodesOnlyMesh<DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
00081              node_iter != rMesh.GetNodeIteratorEnd();
00082              ++node_iter)
00083         {
00084             (*node_iter).SetIsParticle(false);
00085         }
00086         NodeBasedCellPopulationWithParticles::Validate();
00087     }
00088 }
00089 
00090 template<unsigned DIM>
00091 NodeBasedCellPopulationWithParticles<DIM>::NodeBasedCellPopulationWithParticles(NodesOnlyMesh<DIM>& rMesh)
00092     : NodeBasedCellPopulation<DIM>(rMesh)
00093 {
00094 }
00095 
00096 template<unsigned DIM>
00097 bool NodeBasedCellPopulationWithParticles<DIM>::IsParticle(unsigned index)
00098 {
00099     return this->GetNode(index)->IsParticle();
00100 }
00101 
00102 template<unsigned DIM>
00103 std::set<unsigned> NodeBasedCellPopulationWithParticles<DIM>::GetParticleIndices()
00104 {
00105     std::set<unsigned> particle_indices;
00106 
00107     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00108          node_iter != this->mrMesh.GetNodeIteratorEnd();
00109          ++node_iter)
00110     {
00111         if (node_iter->IsParticle())
00112         {
00113             particle_indices.insert(node_iter->GetIndex());
00114         }
00115     }
00116 
00117     return particle_indices;
00118 }
00119 
00120 template<unsigned DIM>
00121 void NodeBasedCellPopulationWithParticles<DIM>::SetParticles(const std::set<unsigned>& rParticleIndices)
00122 {
00123     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00124          node_iter != this->mrMesh.GetNodeIteratorEnd();
00125          ++node_iter)
00126     {
00127         if (rParticleIndices.find(node_iter->GetIndex()) != rParticleIndices.end())
00128         {
00129             node_iter->SetIsParticle(true);
00130         }
00131     }
00132     NodeBasedCellPopulationWithParticles::Validate();
00133 }
00134 
00135 template<unsigned DIM>
00136 void NodeBasedCellPopulationWithParticles<DIM>::UpdateParticlePositions(double dt)
00137 {
00138     // Initialise vector of forces on particles
00139     std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
00140     for (unsigned i=0; i<drdt.size(); i++)
00141     {
00142         drdt[i] = zero_vector<double>(DIM);
00143     }
00144 
00145     // Calculate forces on particles
00146     double damping_constant = this->GetDampingConstantNormal();
00147     for (unsigned i=0; i<drdt.size(); i++)
00148     {
00149         drdt[i] = this->GetNode(i)->rGetAppliedForce()/damping_constant;
00150     }
00151 
00152     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00153          node_iter != this->mrMesh.GetNodeIteratorEnd();
00154          ++node_iter)
00155     {
00156         if (node_iter->IsParticle())
00157         {
00158             ChastePoint<DIM> new_point(node_iter->rGetLocation() + dt*drdt[node_iter->GetIndex()]);
00159             node_iter->SetPoint(new_point);
00160         }
00161     }
00162 }
00163 
00164 template<unsigned DIM>
00165 void NodeBasedCellPopulationWithParticles<DIM>::UpdateParticlesAfterReMesh(NodeMap& rMap)
00166 {
00167 }
00168 
00169 template<unsigned DIM>
00170 CellPtr NodeBasedCellPopulationWithParticles<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00171 {
00172     assert(pNewCell);
00173 
00174     // Add new cell to cell population
00175     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00176     assert(p_created_cell == pNewCell);
00177 
00178     // Then set the new cell radius in the NodesOnlyMesh
00179     unsigned node_index = this->GetLocationIndexUsingCell(p_created_cell);
00180     this->GetNode(node_index)->SetRadius(0.5);
00181     this->GetNode(node_index)->SetIsParticle(false);
00182 
00183     // Return pointer to new cell
00184     return p_created_cell;
00185 }
00186 
00187 template<unsigned DIM>
00188 void NodeBasedCellPopulationWithParticles<DIM>::Validate()
00189 {
00190     std::map<unsigned, bool> validated_nodes;
00191     for (typename AbstractMesh<DIM, DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00192          node_iter != this->mrMesh.GetNodeIteratorEnd();
00193          ++node_iter)
00194     {
00195         validated_nodes[node_iter->GetIndex()] = node_iter->IsParticle();
00196     }
00197 
00198     // Look through all of the cells and record what node they are associated with.
00199     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00200     {
00201         unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
00202 
00203         // If the node attached to this cell is labelled as a particle, then throw an error
00204         if (this->GetNode(node_index)->IsParticle())
00205         {
00206             EXCEPTION("Node " << node_index << " is labelled as a particle and has a cell attached");
00207         }
00208         validated_nodes[node_index] = true;
00209     }
00210 
00211     for (std::map<unsigned, bool>::iterator map_iter = validated_nodes.begin();
00212          map_iter != validated_nodes.end();
00213          map_iter++)
00214     {
00215         if (!map_iter->second)
00216         {
00217             EXCEPTION("Node " << map_iter->first << " does not appear to be a particle or has a cell associated with it");
00218         }
00219     }
00220 }
00221 
00222 template<unsigned DIM>
00223 void NodeBasedCellPopulationWithParticles<DIM>::UpdateNodeLocations(double dt)
00224 {
00225     // First update particle positions
00226     UpdateParticlePositions(dt);
00227 
00228     // Then call the base class method
00229     AbstractCentreBasedCellPopulation<DIM>::UpdateNodeLocations(dt);
00230 }
00231 
00232 template<unsigned DIM>
00233 void NodeBasedCellPopulationWithParticles<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00234 {
00235 #ifdef CHASTE_VTK
00236     // Store the present time as a string
00237     std::stringstream time;
00238     time << SimulationTime::Instance()->GetTimeStepsElapsed();
00239 
00240     // Make sure the nodes are ordered contiguously in memory
00241     NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
00242     this->mpNodesOnlyMesh->ReMesh(map);
00243 
00244     // Store the number of cells for which to output data to VTK
00245     unsigned num_nodes = this->GetNumNodes();
00246     std::vector<double> rank(num_nodes);
00247     std::vector<double> particles(num_nodes);
00248 
00249     unsigned num_cell_data_items = 0;
00250     std::vector<std::string> cell_data_names;
00251 
00252     // We assume that the first cell is representative of all cells
00253     if (num_nodes > 0)
00254     {
00255         num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00256         cell_data_names = this->Begin()->GetCellData()->GetKeys();
00257     }
00258 
00259     std::vector<std::vector<double> > cell_data;
00260     for (unsigned var=0; var<num_cell_data_items; var++)
00261     {
00262         std::vector<double> cell_data_var(num_nodes);
00263         cell_data.push_back(cell_data_var);
00264     }
00265 
00266     // Create mesh writer for VTK output
00267     VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00268     mesh_writer.SetParallelFiles(*(this->mpNodesOnlyMesh));
00269 
00270     // Iterate over any cell writers that are present
00271     for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00272          cell_writer_iter != this->mCellWriters.end();
00273          ++cell_writer_iter)
00274     {
00275         // Create vector to store VTK cell data
00276         std::vector<double> vtk_cell_data(num_nodes);
00277 
00278         // Loop over nodes
00279         for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00280              node_iter != this->mrMesh.GetNodeIteratorEnd();
00281              ++node_iter)
00282         {
00283             unsigned node_index = node_iter->GetIndex();
00284 
00285             // If this node is a particle (not a cell), then we set the 'dummy' VTK cell data for this to be -2.0...
00286             if (this->IsParticle(node_index))
00287             {
00288                 vtk_cell_data[node_index] = -2.0;
00289             }
00290             else
00291             {
00292                 // ...otherwise we populate the vector of VTK cell data as usual
00293                 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00294                 vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00295             }
00296         }
00297 
00298         mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00299     }
00300 
00301     // Loop over cells
00302     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
00303          cell_iter != this->End();
00304          ++cell_iter)
00305     {
00306         // Get the node index corresponding to this cell
00307         unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
00308         unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);
00309 
00310         for (unsigned var=0; var<num_cell_data_items; var++)
00311         {
00312             cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
00313         }
00314 
00315         rank[node_index] = (PetscTools::GetMyRank());
00316     }
00317 
00318     mesh_writer.AddPointData("Process rank", rank);
00319 
00320     // Loop over nodes
00321     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00322          node_iter != this->mrMesh.GetNodeIteratorEnd();
00323          ++node_iter)
00324     {
00325         unsigned node_index = node_iter->GetIndex();
00326         particles[node_index] = (double) (this->IsParticle(node_index));
00327     }
00328 
00329     mesh_writer.AddPointData("Non-particles", particles);
00330 
00331     if (num_cell_data_items > 0)
00332     {
00333         for (unsigned var=0; var<cell_data.size(); var++)
00334         {
00335             mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
00336         }
00337     }
00338 
00339     mesh_writer.WriteFilesUsingMesh(*(this->mpNodesOnlyMesh));
00340 
00341     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00342     *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00343     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00344     *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00345     EXCEPT_IF_NOT(PetscTools::IsSequential());
00346     {
00347         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00348     }
00349 /*    {
00350         // Parallel vtu files  .vtu -> .pvtu
00351         *(this->mpVtkMetaFile) << ".pvtu\"/>\n";
00352     }*/
00353 #endif //CHASTE_VTK
00354 }
00355 
00356 template<unsigned DIM>
00357 void NodeBasedCellPopulationWithParticles<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00358 {
00359     // Call method on direct parent class
00360     NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00361 }
00362 
00363 // Explicit instantiation
00364 template class NodeBasedCellPopulationWithParticles<1>;
00365 template class NodeBasedCellPopulationWithParticles<2>;
00366 template class NodeBasedCellPopulationWithParticles<3>;
00367 
00368 // Serialization for Boost >= 1.36
00369 #include "SerializationExportWrapperForCpp.hpp"
00370 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulationWithParticles)

Generated by  doxygen 1.6.2