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>& rGhostNodeIndices)
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 = 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     // 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 = 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     // There is reason not to subtract one position from the other (cylindrical meshes)
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     // Add new cell to tissue
00192     TissueCell *p_created_cell = MeshBasedTissue<DIM>::AddCell(rNewCell, newLocation, pParentCell);
00193 
00194     // Update size of mIsGhostNode if necessary
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     // Return pointer to new cell
00204     return p_created_cell;
00205 }
00206 
00207 template<unsigned DIM>
00208 void MeshBasedTissueWithGhostNodes<DIM>::Validate()
00209 {
00210     // Get a list of all the nodes that are ghosts
00211     std::vector<bool> validated_node = mIsGhostNode;
00212     assert(mIsGhostNode.size()==this->GetNumNodes());
00213 
00214     // Look through all of the cells and record what node they are associated with.
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         // If the node attached to this cell is labelled as a ghost node, then throw an error
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     // Copy mIsGhostNode to a temporary vector
00244     std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00245 
00246     // Reinitialise mIsGhostNode
00247     mIsGhostNode.clear();
00248     mIsGhostNode.resize(this->GetNumNodes());
00249 
00250     // Update mIsGhostNode using the node map
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     // First update ghost positions first because they do not affect the real cells
00265     UpdateGhostPositions(dt);
00266 
00267     // Then call the base class method
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 // Explicit instantiation
00294 
00295 
00296 template class MeshBasedTissueWithGhostNodes<1>;
00297 template class MeshBasedTissueWithGhostNodes<2>;
00298 template class MeshBasedTissueWithGhostNodes<3>;

Generated on Tue Aug 4 16:10:21 2009 for Chaste by  doxygen 1.5.5