NodeBasedCellPopulationWithParticles.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2014, 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 
00039 // Cell writers
00040 #include "CellAgesWriter.hpp"
00041 #include "CellAncestorWriter.hpp"
00042 #include "CellProliferativePhasesWriter.hpp"
00043 #include "CellProliferativeTypesWriter.hpp"
00044 #include "CellVolumesWriter.hpp"
00045 
00046 // Cell population writers
00047 #include "CellMutationStatesCountWriter.hpp"
00048 
00049 template<unsigned DIM>
00050 NodeBasedCellPopulationWithParticles<DIM>::NodeBasedCellPopulationWithParticles(NodesOnlyMesh<DIM>& rMesh,
00051                                       std::vector<CellPtr>& rCells,
00052                                       const std::vector<unsigned> locationIndices,
00053                                       bool deleteMesh)
00054     : NodeBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false)
00055 {
00056     if (!locationIndices.empty())
00057     {
00058         // Create a set of node indices corresponding to particles
00059         std::set<unsigned> node_indices;
00060         std::set<unsigned> location_indices;
00061         std::set<unsigned> particle_indices;
00062 
00063         for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
00064                 node_iter != rMesh.GetNodeIteratorEnd();
00065                 ++node_iter)
00066         {
00067             node_indices.insert(node_iter->GetIndex());
00068         }
00069         for (unsigned i=0; i<locationIndices.size(); i++)
00070         {
00071             location_indices.insert(locationIndices[i]);
00072         }
00073 
00074         std::set_difference(node_indices.begin(), node_indices.end(),
00075                             location_indices.begin(), location_indices.end(),
00076                             std::inserter(particle_indices, particle_indices.begin()));
00077 
00078         // This method finishes and then calls Validate()
00079         SetParticles(particle_indices);
00080     }
00081     else
00082     {
00083         for (typename NodesOnlyMesh<DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
00084                 node_iter != rMesh.GetNodeIteratorEnd();
00085                 ++node_iter)
00086         {
00087             (*node_iter).SetIsParticle(false);
00088         }
00089         NodeBasedCellPopulationWithParticles::Validate();
00090     }
00091 }
00092 
00093 template<unsigned DIM>
00094 NodeBasedCellPopulationWithParticles<DIM>::NodeBasedCellPopulationWithParticles(NodesOnlyMesh<DIM>& rMesh)
00095     : NodeBasedCellPopulation<DIM>(rMesh)
00096 {
00097 }
00098 
00099 template<unsigned DIM>
00100 bool NodeBasedCellPopulationWithParticles<DIM>::IsParticle(unsigned index)
00101 {
00102     return this->GetNode(index)->IsParticle();
00103 }
00104 
00105 template<unsigned DIM>
00106 std::set<unsigned> NodeBasedCellPopulationWithParticles<DIM>::GetParticleIndices()
00107 {
00108     std::set<unsigned> particle_indices;
00109 
00110     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00111          node_iter != this->mrMesh.GetNodeIteratorEnd();
00112          ++node_iter)
00113     {
00114         if (node_iter->IsParticle())
00115         {
00116             particle_indices.insert(node_iter->GetIndex());
00117         }
00118     }
00119 
00120     return particle_indices;
00121 }
00122 
00123 template<unsigned DIM>
00124 void NodeBasedCellPopulationWithParticles<DIM>::SetParticles(const std::set<unsigned>& rParticleIndices)
00125 {
00126     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00127          node_iter != this->mrMesh.GetNodeIteratorEnd();
00128          ++node_iter)
00129     {
00130         if (rParticleIndices.find(node_iter->GetIndex()) != rParticleIndices.end())
00131         {
00132             node_iter->SetIsParticle(true);
00133         }
00134     }
00135     NodeBasedCellPopulationWithParticles::Validate();
00136 }
00137 
00138 template<unsigned DIM>
00139 void NodeBasedCellPopulationWithParticles<DIM>::UpdateParticlePositions(double dt)
00140 {
00141     // Initialise vector of forces on particles
00142     std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
00143     for (unsigned i=0; i<drdt.size(); i++)
00144     {
00145         drdt[i] = zero_vector<double>(DIM);
00146     }
00147 
00148     // Calculate forces on particles
00149     double damping_constant = this->GetDampingConstantNormal();
00150     for (unsigned i=0; i<drdt.size(); i++)
00151     {
00152         drdt[i]=this->GetNode(i)->rGetAppliedForce()/damping_constant;
00153     }
00154 
00155     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00156          node_iter != this->mrMesh.GetNodeIteratorEnd();
00157          ++node_iter)
00158     {
00159         if (node_iter->IsParticle())
00160         {
00161             ChastePoint<DIM> new_point(node_iter->rGetLocation() + dt*drdt[node_iter->GetIndex()]);
00162             node_iter->SetPoint(new_point);
00163         }
00164     }
00165 }
00166 
00167 template<unsigned DIM>
00168 void NodeBasedCellPopulationWithParticles<DIM>::UpdateParticlesAfterReMesh(NodeMap& rMap)
00169 {
00170 }
00171 
00172 template<unsigned DIM>
00173 CellPtr NodeBasedCellPopulationWithParticles<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00174 {
00175     assert(pNewCell);
00176 
00177     // Add new cell to cell population
00178     CellPtr p_created_cell = AbstractCentreBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00179     assert(p_created_cell == pNewCell);
00180 
00181     // Then set the new cell radius in the NodesOnlyMesh
00182     unsigned node_index = this->GetLocationIndexUsingCell(p_created_cell);
00183     this->GetNode(node_index)->SetRadius(0.5);
00184     this->GetNode(node_index)->SetIsParticle(false);
00185 
00186     // Return pointer to new cell
00187     return p_created_cell;
00188 }
00189 
00190 template<unsigned DIM>
00191 void NodeBasedCellPopulationWithParticles<DIM>::Validate()
00192 {
00193     std::map<unsigned, bool> validated_nodes;
00194     for (typename AbstractMesh<DIM, DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00195             node_iter != this->mrMesh.GetNodeIteratorEnd();
00196             ++node_iter)
00197     {
00198         validated_nodes[node_iter->GetIndex()] = node_iter->IsParticle();
00199     }
00200 
00201     // Look through all of the cells and record what node they are associated with.
00202     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00203     {
00204         unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
00205 
00206         // If the node attached to this cell is labelled as a particle, then throw an error
00207         if (this->GetNode(node_index)->IsParticle())
00208         {
00209             EXCEPTION("Node " << node_index << " is labelled as a particle and has a cell attached");
00210         }
00211         validated_nodes[node_index] = true;
00212     }
00213 
00214     for (std::map<unsigned, bool>::iterator map_iter = validated_nodes.begin();
00215             map_iter != validated_nodes.end();
00216             map_iter++)
00217     {
00218         if (!map_iter->second)
00219         {
00220             EXCEPTION("Node " << map_iter->first << " does not appear to be a particle or has a cell associated with it");
00221         }
00222     }
00223 }
00224 
00225 template<unsigned DIM>
00226 void NodeBasedCellPopulationWithParticles<DIM>::UpdateNodeLocations(double dt)
00227 {
00228     // First update particle positions
00229     UpdateParticlePositions(dt);
00230     // Then call the base class method
00231     AbstractCentreBasedCellPopulation<DIM>::UpdateNodeLocations(dt);
00232 }
00233 
00234 template<unsigned DIM>
00235 void NodeBasedCellPopulationWithParticles<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00236 {
00237 #ifdef CHASTE_VTK
00238     unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00239     std::stringstream time;
00240     time << num_timesteps;
00241 
00242     VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
00243 
00244     unsigned num_cells = this->GetNumNodes();
00245     std::vector<double> particles(num_cells);
00246     std::vector<double> cell_types(num_cells);
00247     std::vector<double> cell_ancestors(num_cells);
00248     std::vector<double> cell_mutation_states(num_cells);
00249     std::vector<double> cell_ages(num_cells);
00250     std::vector<double> cell_cycle_phases(num_cells);
00251     std::vector<double> cell_radii(num_cells);
00252 
00254 
00255     // Loop over nodes
00256     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00257          node_iter != this->mrMesh.GetNodeIteratorEnd();
00258          ++node_iter)
00259     {
00260         unsigned node_index = node_iter->GetIndex();
00261         Node<DIM>* p_node = this->GetNode(node_index);
00262 
00263         if (!this->IsParticle(node_index))
00264         {
00265             CellPtr cell_iter = this->GetCellUsingLocationIndex(node_index);
00266             if (this-> template HasWriter<CellAncestorWriter>())
00267             {
00268                 double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
00269                 cell_ancestors[node_index] = ancestor_index;
00270             }
00271             if (this-> template HasWriter<CellProliferativeTypesWriter>())
00272             {
00273                 double cell_type = cell_iter->GetCellProliferativeType()->GetColour();
00274                 cell_types[node_index] = cell_type;
00275             }
00276             if (this-> template HasWriter<CellMutationStatesCountWriter>())
00277             {
00278                 double mutation_state = cell_iter->GetMutationState()->GetColour();
00279                 cell_mutation_states[node_index] = mutation_state;
00280             }
00281             if (this-> template HasWriter<CellAgesWriter>())
00282             {
00283                 double age = cell_iter->GetAge();
00284                 cell_ages[node_index] = age;
00285             }
00286             if (this-> template HasWriter<CellProliferativePhasesWriter>())
00287             {
00288                 double cycle_phase = cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase();
00289                 cell_cycle_phases[node_index] = cycle_phase;
00290             }
00291             if (this-> template HasWriter<CellVolumesWriter>())
00292             {
00293                 double cell_radius = p_node->GetRadius();
00294                 cell_radii[node_index] = cell_radius;
00295             }
00296         }
00297         else
00298         {
00299             particles[node_index] = (double)(this->IsParticle(node_index));
00300             if (this-> template HasWriter<CellAncestorWriter>())
00301             {
00302                 cell_ancestors[node_index] = -2.0;
00303             }
00304             if (this-> template HasWriter<CellProliferativeTypesWriter>())
00305             {
00306                 cell_types[node_index] = -2.0;
00307             }
00308             if (this-> template HasWriter<CellMutationStatesCountWriter>())
00309             {
00310                 cell_mutation_states[node_index] = -2.0;
00311             }
00312             if (this-> template HasWriter<CellAgesWriter>())
00313             {
00314                 cell_ages[node_index] = -2.0;
00315             }
00316             if (this-> template HasWriter<CellProliferativePhasesWriter>())
00317             {
00318                 cell_cycle_phases[node_index] = -2.0;
00319             }
00320         }
00321     }
00322 
00323     mesh_writer.AddPointData("Non-particles", particles);
00324     if (this-> template HasWriter<CellProliferativeTypesWriter>())
00325     {
00326         mesh_writer.AddPointData("Cell types", cell_types);
00327     }
00328     if (this-> template HasWriter<CellAncestorWriter>())
00329     {
00330         mesh_writer.AddPointData("Ancestors", cell_ancestors);
00331     }
00332     if (this-> template HasWriter<CellMutationStatesCountWriter>())
00333     {
00334         mesh_writer.AddPointData("Mutation states", cell_mutation_states);
00335     }
00336     if (this-> template HasWriter<CellAgesWriter>())
00337     {
00338         mesh_writer.AddPointData("Ages", cell_ages);
00339     }
00340     if (this-> template HasWriter<CellProliferativePhasesWriter>())
00341     {
00342         mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
00343     }
00344     if (this-> template HasWriter<CellVolumesWriter>())
00345     {
00346         mesh_writer.AddPointData("Cell radii", cell_radii);
00347     }
00349 
00350     mesh_writer.WriteFilesUsingMesh(static_cast<NodesOnlyMesh<DIM>& >((this->mrMesh)));
00351 
00352     *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00353     *(this->mpVtkMetaFile) << num_timesteps;
00354     *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00355     *(this->mpVtkMetaFile) << num_timesteps;
00356     *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00357 #endif //CHASTE_VTK
00358 }
00359 
00360 template<unsigned DIM>
00361 void NodeBasedCellPopulationWithParticles<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00362 {
00363     // Call method on direct parent class
00364     NodeBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00365 }
00366 
00367 // Explicit instantiation
00368 template class NodeBasedCellPopulationWithParticles<1>;
00369 template class NodeBasedCellPopulationWithParticles<2>;
00370 template class NodeBasedCellPopulationWithParticles<3>;
00371 
00372 // Serialization for Boost >= 1.36
00373 #include "SerializationExportWrapperForCpp.hpp"
00374 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedCellPopulationWithParticles)

Generated by  doxygen 1.6.2