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>& ghostNodeIndices)
00103 {
00104
00105 this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00106
00107
00108 std::set<unsigned>::iterator iter = ghostNodeIndices.begin();
00109 while (iter!=ghostNodeIndices.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 = CancerParameters::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 (unsigned index = 0; index<this->GetNumNodes(); index++)
00156 {
00157 if ((!this->GetNode(index)->IsDeleted()) && this->mIsGhostNode[index])
00158 {
00159 ChastePoint<DIM> new_point(this->GetNode(index)->rGetLocation() + dt*drdt[index]);
00160 this->mrMesh.SetNode(index, new_point, false);
00161 }
00162 }
00163 }
00164
00165 template<unsigned DIM>
00166 c_vector<double, DIM> MeshBasedTissueWithGhostNodes<DIM>::CalculateForceBetweenNodes(const unsigned& rNodeAGlobalIndex, const unsigned& rNodeBGlobalIndex)
00167 {
00168 assert(rNodeAGlobalIndex!=rNodeBGlobalIndex);
00169 c_vector<double, DIM> unit_difference;
00170 c_vector<double, DIM> node_a_location = this->GetNode(rNodeAGlobalIndex)->rGetLocation();
00171 c_vector<double, DIM> node_b_location = this->GetNode(rNodeBGlobalIndex)->rGetLocation();
00172
00173
00174 unit_difference = this->mrMesh.GetVectorFromAtoB(node_a_location, node_b_location);
00175
00176 double distance_between_nodes = norm_2(unit_difference);
00177
00178 unit_difference /= distance_between_nodes;
00179
00180 double rest_length = 1.0;
00181
00182 return CancerParameters::Instance()->GetSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
00183 }
00184
00185 template<unsigned DIM>
00186 TissueCell* MeshBasedTissueWithGhostNodes<DIM>::AddCell(TissueCell& rNewCell, c_vector<double,DIM> newLocation, TissueCell* pParentCell)
00187 {
00188
00189 TissueCell* p_created_cell = MeshBasedTissue<DIM>::AddCell(rNewCell, newLocation, pParentCell);
00190
00191
00192 unsigned new_node_index = this->mCellLocationMap[p_created_cell];
00193
00194 if (this->GetNumNodes() > this->mIsGhostNode.size())
00195 {
00196 this->mIsGhostNode.resize(this->GetNumNodes());
00197 this->mIsGhostNode[new_node_index] = false;
00198 }
00199
00200
00201 return p_created_cell;
00202 }
00203
00204 template<unsigned DIM>
00205 void MeshBasedTissueWithGhostNodes<DIM>::Validate()
00206 {
00207
00208 std::vector<bool> validated_node = mIsGhostNode;
00209 assert(mIsGhostNode.size()==this->GetNumNodes());
00210
00211
00212 for (typename AbstractTissue<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00213 {
00214 unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00215
00216
00217 if (mIsGhostNode[node_index])
00218 {
00219 std::stringstream ss;
00220 ss << "Node " << node_index << " is labelled as a ghost node and has a cell attached";
00221 EXCEPTION(ss.str());
00222 }
00223 validated_node[node_index] = true;
00224 }
00225
00226 for (unsigned i=0; i<validated_node.size(); i++)
00227 {
00228 if (!validated_node[i])
00229 {
00230 std::stringstream ss;
00231 ss << "Node " << i << " does not appear to be a ghost node or have a cell associated with it";
00232 EXCEPTION(ss.str());
00233 }
00234 }
00235 }
00236
00237 template<unsigned DIM>
00238 void MeshBasedTissueWithGhostNodes<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00239 {
00240
00241 std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00242
00243
00244 mIsGhostNode.clear();
00245 mIsGhostNode.resize(this->GetNumNodes());
00246
00247
00248 for (unsigned old_index=0; old_index<rMap.Size(); old_index++)
00249 {
00250 if (!rMap.IsDeleted(old_index))
00251 {
00252 unsigned new_index = rMap.GetNewIndex(old_index);
00253 mIsGhostNode[new_index] = ghost_nodes_before_remesh[old_index];
00254 }
00255 }
00256 }
00257
00258 template<unsigned DIM>
00259 void MeshBasedTissueWithGhostNodes<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00260 {
00261
00262 UpdateGhostPositions(dt);
00263
00264
00265 AbstractCellCentreBasedTissue<DIM>::UpdateNodeLocations(rNodeForces, dt);
00266 }
00267
00268
00270
00272
00273
00274 template class MeshBasedTissueWithGhostNodes<1>;
00275 template class MeshBasedTissueWithGhostNodes<2>;
00276 template class MeshBasedTissueWithGhostNodes<3>;