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