MeshBasedTissueWithGhostNodes.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2009
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
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) // do not call the base class Validate()
00038 {
00039     if (!locationIndices.empty())
00040     {
00041         // Create a set of node indices corresponding to ghost nodes
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         // This method finishes and then calls Validate()
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     // Reinitialise all entries of mIsGhostNode to false
00105     this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00106 
00107     // Update mIsGhostNode
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     // Initialise vector of forces on ghost nodes
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     // Calculate forces on ghost nodes
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     // There is reason not to subtract one position from the other (cylindrical meshes)
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     // Add new cell to tissue
00189     TissueCell* p_created_cell = MeshBasedTissue<DIM>::AddCell(rNewCell, newLocation, pParentCell);
00190 
00191     // Update size of mIsGhostNode if necessary
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     // Return pointer to new cell
00201     return p_created_cell;
00202 }
00203 
00204 template<unsigned DIM>
00205 void MeshBasedTissueWithGhostNodes<DIM>::Validate()
00206 {
00207     // Get a list of all the nodes that are ghosts
00208     std::vector<bool> validated_node = mIsGhostNode;
00209     assert(mIsGhostNode.size()==this->GetNumNodes());
00210 
00211     // Look through all of the cells and record what node they are associated with.
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         // If the node attached to this cell is labelled as a ghost node, then throw an error
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     // Copy mIsGhostNode to a temporary vector
00241     std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00242 
00243     // Reinitialise mIsGhostNode
00244     mIsGhostNode.clear();
00245     mIsGhostNode.resize(this->GetNumNodes());
00246 
00247     // Update mIsGhostNode using the node map
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     // First update ghost positions first because they do not affect the real cells
00262     UpdateGhostPositions(dt);
00263 
00264     // Then call the base class method
00265     AbstractCellCentreBasedTissue<DIM>::UpdateNodeLocations(rNodeForces, dt);
00266 }
00267 
00268 
00270 // Explicit instantiation
00272 
00273 
00274 template class MeshBasedTissueWithGhostNodes<1>;
00275 template class MeshBasedTissueWithGhostNodes<2>;
00276 template class MeshBasedTissueWithGhostNodes<3>;

Generated on Wed Mar 18 12:51:50 2009 for Chaste by  doxygen 1.5.5