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