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 "CellLocationWriter.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.Size(); 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 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateNodeLocations(double dt)
00284 {
00285
00286 UpdateGhostPositions(dt);
00287
00288
00289 AbstractCentreBasedCellPopulation<DIM,DIM>::UpdateNodeLocations(dt);
00290 }
00291
00292
00293 template<unsigned DIM>
00294 void MeshBasedCellPopulationWithGhostNodes<DIM>::OpenWritersFiles(const std::string& rDirectory)
00295 {
00296 if (this->mOutputResultsForChasteVisualizer)
00297 {
00298 if (!this-> template HasWriter<CellLocationWriter>())
00299 {
00300 this-> template AddCellWriter<CellLocationWriter>();
00301 }
00302 }
00303
00304 MeshBasedCellPopulation<DIM, DIM>::OpenWritersFiles(rDirectory);
00305 }
00306
00307 template<unsigned DIM>
00308 void MeshBasedCellPopulationWithGhostNodes<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00309 {
00310 #ifdef CHASTE_VTK
00311 if (this->mpVoronoiTessellation != NULL)
00312 {
00313 unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00314 std::stringstream time;
00315 time << num_timesteps;
00316
00317
00318 VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
00319
00320
00321 unsigned num_vtk_cells = this->mpVoronoiTessellation->GetNumElements();
00322 for (typename std::set<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00323 cell_writer_iter != this->mCellWriters.end();
00324 ++cell_writer_iter)
00325 {
00326
00327 std::vector<double> vtk_cell_data(num_vtk_cells);
00328
00329
00330 for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00331 elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00332 ++elem_iter)
00333 {
00334
00335 unsigned elem_index = elem_iter->GetIndex();
00336 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00337
00338
00339 if (this->IsGhostNode(node_index))
00340 {
00341
00342 vtk_cell_data[elem_index] = -1.0;
00343 }
00344 else
00345 {
00346
00347 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00348
00349
00350 vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00351 }
00352 }
00353
00354 mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00355 }
00356
00357
00359 std::vector<double> ghosts(num_vtk_cells);
00360 for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00361 elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00362 ++elem_iter)
00363 {
00364 unsigned elem_index = elem_iter->GetIndex();
00365 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00366 ghosts[elem_index] = (double) (this->IsGhostNode(node_index));
00367 }
00368 mesh_writer.AddCellData("Non-ghosts", ghosts);
00369
00371
00372 mesh_writer.WriteVtkUsingMesh(*(this->mpVoronoiTessellation), time.str());
00373 *(this->mpVtkMetaFile) << " <DataSet timestep=\"";
00374 *(this->mpVtkMetaFile) << num_timesteps;
00375 *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00376 *(this->mpVtkMetaFile) << num_timesteps;
00377 *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00378 }
00379 #endif //CHASTE_VTK
00380 }
00381
00382 template<unsigned DIM>
00383 void MeshBasedCellPopulationWithGhostNodes<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00384 {
00385 *rParamsFile << "\t\t<GhostSpringStiffness>" << mGhostSpringStiffness << "</GhostSpringStiffness>\n";
00386
00387
00388 MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00389 }
00390
00391
00392 template class MeshBasedCellPopulationWithGhostNodes<1>;
00393 template class MeshBasedCellPopulationWithGhostNodes<2>;
00394 template class MeshBasedCellPopulationWithGhostNodes<3>;
00395
00396
00397 #include "SerializationExportWrapperForCpp.hpp"
00398 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulationWithGhostNodes)