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 "MeshBasedTissueWithGhostNodes.hpp"
00029
00030
00031 template<unsigned DIM>
00032 MeshBasedTissueWithGhostNodes<DIM>::MeshBasedTissueWithGhostNodes(
00033 MutableMesh<DIM, DIM>& rMesh,
00034 const std::vector<TissueCell>& rCells,
00035 const std::vector<unsigned> locationIndices,
00036 bool deleteMesh)
00037 : MeshBasedTissue<DIM>(rMesh, rCells, locationIndices, deleteMesh, false)
00038 {
00039 if (!locationIndices.empty())
00040 {
00041
00042 std::set<unsigned> node_indices;
00043 std::set<unsigned> location_indices;
00044 std::set<unsigned> ghost_node_indices;
00045
00046 for (unsigned i=0; i<this->GetNumNodes(); i++)
00047 {
00048 node_indices.insert(this->GetNode(i)->GetIndex());
00049 }
00050 for (unsigned i=0; i<locationIndices.size(); i++)
00051 {
00052 location_indices.insert(locationIndices[i]);
00053 }
00054
00055 std::set_difference(node_indices.begin(), node_indices.end(),
00056 location_indices.begin(), location_indices.end(),
00057 std::inserter(ghost_node_indices, ghost_node_indices.begin()));
00058
00059
00060 SetGhostNodes(ghost_node_indices);
00061 }
00062 else
00063 {
00064 this->mIsGhostNode = std::vector<bool>(this->GetNumNodes(), false);
00065 Validate();
00066 }
00067 }
00068
00069 template<unsigned DIM>
00070 MeshBasedTissueWithGhostNodes<DIM>::MeshBasedTissueWithGhostNodes(MutableMesh<DIM, DIM>& rMesh)
00071 : MeshBasedTissue<DIM>(rMesh)
00072 {
00073 }
00074
00075 template<unsigned DIM>
00076 std::vector<bool>& MeshBasedTissueWithGhostNodes<DIM>::rGetGhostNodes()
00077 {
00078 return this->mIsGhostNode;
00079 }
00080
00081 template<unsigned DIM>
00082 bool MeshBasedTissueWithGhostNodes<DIM>::IsGhostNode(unsigned index)
00083 {
00084 return this->mIsGhostNode[index];
00085 }
00086
00087 template<unsigned DIM>
00088 std::set<unsigned> MeshBasedTissueWithGhostNodes<DIM>::GetGhostNodeIndices()
00089 {
00090 std::set<unsigned> ghost_node_indices;
00091 for (unsigned i=0; i<this->mIsGhostNode.size(); i++)
00092 {
00093 if (this->mIsGhostNode[i])
00094 {
00095 ghost_node_indices.insert(i);
00096 }
00097 }
00098 return ghost_node_indices;
00099 }
00100
00101 template<unsigned DIM>
00102 void MeshBasedTissueWithGhostNodes<DIM>::SetGhostNodes(const std::set<unsigned>& rGhostNodeIndices)
00103 {
00104
00105 this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00106
00107
00108 std::set<unsigned>::iterator iter = rGhostNodeIndices.begin();
00109 while (iter!=rGhostNodeIndices.end())
00110 {
00111 this->mIsGhostNode[*iter] = true;
00112 iter++;
00113 }
00114
00115 Validate();
00116 }
00117
00118 template<unsigned DIM>
00119 void MeshBasedTissueWithGhostNodes<DIM>::UpdateGhostPositions(double dt)
00120 {
00121
00122 std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
00123 for (unsigned i=0; i<drdt.size(); i++)
00124 {
00125 drdt[i] = zero_vector<double>(DIM);
00126 }
00127
00128
00129 for (typename MutableMesh<DIM, DIM>::EdgeIterator edge_iterator=this->mrMesh.EdgesBegin();
00130 edge_iterator!=this->mrMesh.EdgesEnd();
00131 ++edge_iterator)
00132 {
00133 unsigned nodeA_global_index = edge_iterator.GetNodeA()->GetIndex();
00134 unsigned nodeB_global_index = edge_iterator.GetNodeB()->GetIndex();
00135
00136 c_vector<double, DIM> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index);
00137
00138 double damping_constant = TissueConfig::Instance()->GetDampingConstantNormal();
00139
00140 if (!this->mIsGhostNode[nodeA_global_index])
00141 {
00142 drdt[nodeB_global_index] -= force / damping_constant;
00143 }
00144 else
00145 {
00146 drdt[nodeA_global_index] += force / damping_constant;
00147
00148 if (this->mIsGhostNode[nodeB_global_index])
00149 {
00150 drdt[nodeB_global_index] -= force / damping_constant;
00151 }
00152 }
00153 }
00154
00155 for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00156 node_iter != this->mrMesh.GetNodeIteratorEnd();
00157 ++node_iter)
00158 {
00159 unsigned node_index = node_iter->GetIndex();
00160 if (this->mIsGhostNode[node_index])
00161 {
00162 ChastePoint<DIM> new_point(node_iter->rGetLocation() + dt*drdt[node_index]);
00163 this->mrMesh.SetNode(node_index, new_point, false);
00164 }
00165 }
00166 }
00167
00168 template<unsigned DIM>
00169 c_vector<double, DIM> MeshBasedTissueWithGhostNodes<DIM>::CalculateForceBetweenNodes(const unsigned& rNodeAGlobalIndex, const unsigned& rNodeBGlobalIndex)
00170 {
00171 assert(rNodeAGlobalIndex!=rNodeBGlobalIndex);
00172 c_vector<double, DIM> unit_difference;
00173 c_vector<double, DIM> node_a_location = this->GetNode(rNodeAGlobalIndex)->rGetLocation();
00174 c_vector<double, DIM> node_b_location = this->GetNode(rNodeBGlobalIndex)->rGetLocation();
00175
00176
00177 unit_difference = this->mrMesh.GetVectorFromAtoB(node_a_location, node_b_location);
00178
00179 double distance_between_nodes = norm_2(unit_difference);
00180
00181 unit_difference /= distance_between_nodes;
00182
00183 double rest_length = 1.0;
00184
00185 return TissueConfig::Instance()->GetSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
00186 }
00187
00188 template<unsigned DIM>
00189 TissueCell* MeshBasedTissueWithGhostNodes<DIM>::AddCell(TissueCell& rNewCell, c_vector<double,DIM> newLocation, TissueCell* pParentCell)
00190 {
00191
00192 TissueCell *p_created_cell = MeshBasedTissue<DIM>::AddCell(rNewCell, newLocation, pParentCell);
00193
00194
00195 unsigned new_node_index = this->mCellLocationMap[p_created_cell];
00196
00197 if (this->GetNumNodes() > this->mIsGhostNode.size())
00198 {
00199 this->mIsGhostNode.resize(this->GetNumNodes());
00200 this->mIsGhostNode[new_node_index] = false;
00201 }
00202
00203
00204 return p_created_cell;
00205 }
00206
00207 template<unsigned DIM>
00208 void MeshBasedTissueWithGhostNodes<DIM>::Validate()
00209 {
00210
00211 std::vector<bool> validated_node = mIsGhostNode;
00212 assert(mIsGhostNode.size()==this->GetNumNodes());
00213
00214
00215 for (typename AbstractTissue<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00216 {
00217 unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00218
00219
00220 if (mIsGhostNode[node_index])
00221 {
00222 std::stringstream ss;
00223 ss << "Node " << node_index << " is labelled as a ghost node and has a cell attached";
00224 EXCEPTION(ss.str());
00225 }
00226 validated_node[node_index] = true;
00227 }
00228
00229 for (unsigned i=0; i<validated_node.size(); i++)
00230 {
00231 if (!validated_node[i])
00232 {
00233 std::stringstream ss;
00234 ss << "Node " << i << " does not appear to be a ghost node or have a cell associated with it";
00235 EXCEPTION(ss.str());
00236 }
00237 }
00238 }
00239
00240 template<unsigned DIM>
00241 void MeshBasedTissueWithGhostNodes<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 MeshBasedTissueWithGhostNodes<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00263 {
00264
00265 UpdateGhostPositions(dt);
00266
00267
00268 AbstractCellCentreBasedTissue<DIM>::UpdateNodeLocations(rNodeForces, dt);
00269 }
00270
00271 template<unsigned DIM>
00272 void MeshBasedTissueWithGhostNodes<DIM>::GenerateCellResultsAndWriteToFiles(std::vector<unsigned>& rCellTypeCounter,
00273 std::vector<unsigned>& rCellMutationStateCounter,
00274 std::vector<unsigned>& rCellCyclePhaseCounter)
00275 {
00276 for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00277 node_iter != this->mrMesh.GetNodeIteratorEnd();
00278 ++node_iter)
00279 {
00280 this->GenerateCellResults(node_iter->GetIndex(),
00281 rCellTypeCounter,
00282 rCellMutationStateCounter,
00283 rCellCyclePhaseCounter);
00284 }
00285
00286 this->WriteCellResultsToFiles(rCellTypeCounter,
00287 rCellMutationStateCounter,
00288 rCellCyclePhaseCounter);
00289 }
00290
00292
00294
00295
00296 template class MeshBasedTissueWithGhostNodes<1>;
00297 template class MeshBasedTissueWithGhostNodes<2>;
00298 template class MeshBasedTissueWithGhostNodes<3>;