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