00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "MeshBasedCellPopulationWithGhostNodes.hpp"
00029
00030
00031 template<unsigned DIM>
00032 MeshBasedCellPopulationWithGhostNodes<DIM>::MeshBasedCellPopulationWithGhostNodes(
00033 MutableMesh<DIM, DIM>& rMesh,
00034 std::vector<CellPtr>& rCells,
00035 const std::vector<unsigned> locationIndices,
00036 bool deleteMesh,
00037 double ghostSpringStiffness)
00038 : MeshBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false),
00039 mGhostSpringStiffness(ghostSpringStiffness)
00040 {
00041 if (!locationIndices.empty())
00042 {
00043
00044 std::set<unsigned> node_indices;
00045 std::set<unsigned> location_indices;
00046 std::set<unsigned> ghost_node_indices;
00047
00048 for (unsigned i=0; i<this->GetNumNodes(); i++)
00049 {
00050 node_indices.insert(this->GetNode(i)->GetIndex());
00051 }
00052 for (unsigned i=0; i<locationIndices.size(); i++)
00053 {
00054 location_indices.insert(locationIndices[i]);
00055 }
00056
00057 std::set_difference(node_indices.begin(), node_indices.end(),
00058 location_indices.begin(), location_indices.end(),
00059 std::inserter(ghost_node_indices, ghost_node_indices.begin()));
00060
00061
00062 SetGhostNodes(ghost_node_indices);
00063 }
00064 else
00065 {
00066 this->mIsGhostNode = std::vector<bool>(this->GetNumNodes(), false);
00067 Validate();
00068 }
00069 }
00070
00071 template<unsigned DIM>
00072 MeshBasedCellPopulationWithGhostNodes<DIM>::MeshBasedCellPopulationWithGhostNodes(MutableMesh<DIM, DIM>& rMesh,
00073 double ghostSpringStiffness)
00074 : MeshBasedCellPopulation<DIM>(rMesh),
00075 mGhostSpringStiffness(ghostSpringStiffness)
00076 {
00077 }
00078
00079 template<unsigned DIM>
00080 std::vector<bool>& MeshBasedCellPopulationWithGhostNodes<DIM>::rGetGhostNodes()
00081 {
00082 return this->mIsGhostNode;
00083 }
00084
00085 template<unsigned DIM>
00086 bool MeshBasedCellPopulationWithGhostNodes<DIM>::IsGhostNode(unsigned index)
00087 {
00088 return this->mIsGhostNode[index];
00089 }
00090
00091 template<unsigned DIM>
00092 std::set<unsigned> MeshBasedCellPopulationWithGhostNodes<DIM>::GetGhostNodeIndices()
00093 {
00094 std::set<unsigned> ghost_node_indices;
00095 for (unsigned i=0; i<this->mIsGhostNode.size(); i++)
00096 {
00097 if (this->mIsGhostNode[i])
00098 {
00099 ghost_node_indices.insert(i);
00100 }
00101 }
00102 return ghost_node_indices;
00103 }
00104
00105 template<unsigned DIM>
00106 void MeshBasedCellPopulationWithGhostNodes<DIM>::SetGhostNodes(const std::set<unsigned>& rGhostNodeIndices)
00107 {
00108
00109 this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00110
00111
00112 for (std::set<unsigned>::iterator iter=rGhostNodeIndices.begin(); iter!=rGhostNodeIndices.end(); ++iter)
00113 {
00114 this->mIsGhostNode[*iter] = true;
00115 }
00116
00117 Validate();
00118 }
00119
00120 template<unsigned DIM>
00121 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateGhostPositions(double dt)
00122 {
00123
00124 std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
00125 for (unsigned i=0; i<drdt.size(); i++)
00126 {
00127 drdt[i] = zero_vector<double>(DIM);
00128 }
00129
00130
00131 for (typename MutableMesh<DIM, DIM>::EdgeIterator edge_iterator = this->mrMesh.EdgesBegin();
00132 edge_iterator != this->mrMesh.EdgesEnd();
00133 ++edge_iterator)
00134 {
00135 unsigned nodeA_global_index = edge_iterator.GetNodeA()->GetIndex();
00136 unsigned nodeB_global_index = edge_iterator.GetNodeB()->GetIndex();
00137
00138 c_vector<double, DIM> force = CalculateForceBetweenGhostNodes(nodeA_global_index, nodeB_global_index);
00139
00140 double damping_constant = this->GetDampingConstantNormal();
00141
00142 if (!this->mIsGhostNode[nodeA_global_index])
00143 {
00144 drdt[nodeB_global_index] -= force / damping_constant;
00145 }
00146 else
00147 {
00148 drdt[nodeA_global_index] += force / damping_constant;
00149
00150 if (this->mIsGhostNode[nodeB_global_index])
00151 {
00152 drdt[nodeB_global_index] -= force / damping_constant;
00153 }
00154 }
00155 }
00156
00157 for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00158 node_iter != this->mrMesh.GetNodeIteratorEnd();
00159 ++node_iter)
00160 {
00161 unsigned node_index = node_iter->GetIndex();
00162 if (this->mIsGhostNode[node_index])
00163 {
00164 ChastePoint<DIM> new_point(node_iter->rGetLocation() + dt*drdt[node_index]);
00165 this->mrMesh.SetNode(node_index, new_point, false);
00166 }
00167 }
00168 }
00169
00170 template<unsigned DIM>
00171 c_vector<double, DIM> MeshBasedCellPopulationWithGhostNodes<DIM>::CalculateForceBetweenGhostNodes(const unsigned& rNodeAGlobalIndex, const unsigned& rNodeBGlobalIndex)
00172 {
00173 assert(rNodeAGlobalIndex != rNodeBGlobalIndex);
00174 c_vector<double, DIM> unit_difference;
00175 c_vector<double, DIM> node_a_location = this->GetNode(rNodeAGlobalIndex)->rGetLocation();
00176 c_vector<double, DIM> node_b_location = this->GetNode(rNodeBGlobalIndex)->rGetLocation();
00177
00178
00179 unit_difference = this->mrMesh.GetVectorFromAtoB(node_a_location, node_b_location);
00180
00181 double distance_between_nodes = norm_2(unit_difference);
00182
00183 unit_difference /= distance_between_nodes;
00184
00185 double rest_length = 1.0;
00186
00187 return mGhostSpringStiffness * unit_difference * (distance_between_nodes - rest_length);
00188 }
00189
00190 template<unsigned DIM>
00191 CellPtr MeshBasedCellPopulationWithGhostNodes<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00192 {
00193
00194 CellPtr p_created_cell = MeshBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00195 assert(p_created_cell == pNewCell);
00196
00197
00198 unsigned new_node_index = this->mCellLocationMap[p_created_cell.get()];
00199
00200 if (this->GetNumNodes() > this->mIsGhostNode.size())
00201 {
00202 this->mIsGhostNode.resize(this->GetNumNodes());
00203 this->mIsGhostNode[new_node_index] = false;
00204 }
00205
00206
00207 return p_created_cell;
00208 }
00209
00210 template<unsigned DIM>
00211 void MeshBasedCellPopulationWithGhostNodes<DIM>::Validate()
00212 {
00213
00214 std::vector<bool> validated_node = mIsGhostNode;
00215 assert(mIsGhostNode.size()==this->GetNumNodes());
00216
00217
00218 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00219 {
00220 unsigned node_index = this->mCellLocationMap[(*cell_iter).get()];
00221
00222
00223 if (mIsGhostNode[node_index])
00224 {
00225 std::stringstream ss;
00226 ss << "Node " << node_index << " is labelled as a ghost node and has a cell attached";
00227 EXCEPTION(ss.str());
00228 }
00229 validated_node[node_index] = true;
00230 }
00231
00232 for (unsigned i=0; i<validated_node.size(); i++)
00233 {
00234 if (!validated_node[i])
00235 {
00236 std::stringstream ss;
00237 ss << "Node " << i << " does not appear to be a ghost node or have a cell associated with it";
00238 EXCEPTION(ss.str());
00239 }
00240 }
00241 }
00242
00243 template<unsigned DIM>
00244 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00245 {
00246
00247 std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00248
00249
00250 mIsGhostNode.clear();
00251 mIsGhostNode.resize(this->GetNumNodes());
00252
00253
00254 for (unsigned old_index=0; old_index<rMap.Size(); old_index++)
00255 {
00256 if (!rMap.IsDeleted(old_index))
00257 {
00258 unsigned new_index = rMap.GetNewIndex(old_index);
00259 mIsGhostNode[new_index] = ghost_nodes_before_remesh[old_index];
00260 }
00261 }
00262 }
00263
00264 template<unsigned DIM>
00265 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00266 {
00267
00268 UpdateGhostPositions(dt);
00269
00270
00271 AbstractCentreBasedCellPopulation<DIM>::UpdateNodeLocations(rNodeForces, dt);
00272 }
00273
00274 template<unsigned DIM>
00275 void MeshBasedCellPopulationWithGhostNodes<DIM>::WriteVtkResultsToFile()
00276 {
00277 #ifdef CHASTE_VTK
00278 VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00279 std::stringstream time;
00280 time << SimulationTime::Instance()->GetTimeStepsElapsed();
00281
00282 unsigned num_elements = this->mpVoronoiTessellation->GetNumElements();
00283 std::vector<double> ghosts(num_elements);
00284 std::vector<double> cell_types(num_elements);
00285 std::vector<double> cell_ancestors(num_elements);
00286 std::vector<double> cell_mutation_states(num_elements);
00287 std::vector<double> cell_ages(num_elements);
00288 std::vector<double> cell_cycle_phases(num_elements);
00289 std::vector<double> cell_volumes(num_elements);
00290
00291
00292 for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00293 elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00294 ++elem_iter)
00295 {
00296
00297 unsigned elem_index = elem_iter->GetIndex();
00298
00299 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00300
00301 ghosts[elem_index] = (double)(this->IsGhostNode(node_index));
00302
00303 if (!this->IsGhostNode(node_index))
00304 {
00305
00306 CellPtr p_cell = this->mLocationCellMap[node_index];
00307
00308 if (this->mOutputCellAncestors)
00309 {
00310 double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00311 cell_ancestors[elem_index] = ancestor_index;
00312 }
00313 if (this->mOutputCellProliferativeTypes)
00314 {
00315 double cell_type = p_cell->GetCellCycleModel()->GetCellProliferativeType();
00316 cell_types[elem_index] = cell_type;
00317 }
00318 if (this->mOutputCellMutationStates)
00319 {
00320 double mutation_state = p_cell->GetMutationState()->GetColour();
00321 cell_mutation_states[elem_index] = mutation_state;
00322 }
00323 if (this->mOutputCellAges)
00324 {
00325 double age = p_cell->GetAge();
00326 cell_ages[elem_index] = age;
00327 }
00328 if (this->mOutputCellCyclePhases)
00329 {
00330 double cycle_phase = p_cell->GetCellCycleModel()->GetCurrentCellCyclePhase();
00331 cell_cycle_phases[elem_index] = cycle_phase;
00332 }
00333 if (this->mOutputCellVolumes)
00334 {
00335 double cell_volume = this->mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00336 cell_volumes[elem_index] = cell_volume;
00337 }
00338 }
00339 else
00340 {
00341 if (this->mOutputCellAncestors)
00342 {
00343 cell_ancestors[elem_index] = -1.0;
00344 }
00345 if (this->mOutputCellProliferativeTypes)
00346 {
00347 cell_types[elem_index] = -1.0;
00348 }
00349 if (this->mOutputCellMutationStates)
00350 {
00351 cell_mutation_states[elem_index] = -1.0;
00352 }
00353 if (this->mOutputCellAges)
00354 {
00355 cell_ages[elem_index] = -1.0;
00356 }
00357 if (this->mOutputCellCyclePhases)
00358 {
00359 cell_cycle_phases[elem_index] = -1.0;
00360 }
00361 if (this->mOutputCellVolumes)
00362 {
00363 cell_volumes[elem_index] = -1.0;
00364 }
00365 }
00366 }
00367
00368 mesh_writer.AddCellData("Non-ghosts", ghosts);
00369 if (this->mOutputCellProliferativeTypes)
00370 {
00371 mesh_writer.AddCellData("Cell types", cell_types);
00372 }
00373 if (this->mOutputCellAncestors)
00374 {
00375 mesh_writer.AddCellData("Ancestors", cell_ancestors);
00376 }
00377 if (this->mOutputCellMutationStates)
00378 {
00379 mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00380 }
00381 if (this->mOutputCellAges)
00382 {
00383 mesh_writer.AddCellData("Ages", cell_ages);
00384 }
00385 if (this->mOutputCellCyclePhases)
00386 {
00387 mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00388 }
00389 if (this->mOutputCellVolumes)
00390 {
00391 mesh_writer.AddCellData("Cell volumes", cell_volumes);
00392 }
00393
00394 mesh_writer.WriteVtkUsingMesh(*(this->mpVoronoiTessellation), time.str());
00395 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00396 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00397 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00398 *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00399 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00400 #endif //CHASTE_VTK
00401 }
00402
00403 template<unsigned DIM>
00404 void MeshBasedCellPopulationWithGhostNodes<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00405 {
00406 *rParamsFile << "\t\t<GhostSpringStiffness>"<< mGhostSpringStiffness << "</GhostSpringStiffness> \n" ;
00407
00408
00409 MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00410
00411 }
00412
00414
00416
00417
00418 template class MeshBasedCellPopulationWithGhostNodes<1>;
00419 template class MeshBasedCellPopulationWithGhostNodes<2>;
00420 template class MeshBasedCellPopulationWithGhostNodes<3>;
00421
00422
00423
00424 #include "SerializationExportWrapperForCpp.hpp"
00425 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulationWithGhostNodes)