MeshBasedCellPopulationWithGhostNodes.cpp

00001 /*
00002 
00003 Copyright (c) 2005-2015, University of Oxford.
00004 All rights reserved.
00005 
00006 University of Oxford means the Chancellor, Masters and Scholars of the
00007 University of Oxford, having an administrative office at Wellington
00008 Square, Oxford OX1 2JD, UK.
00009 
00010 This file is part of Chaste.
00011 
00012 Redistribution and use in source and binary forms, with or without
00013 modification, are permitted provided that the following conditions are met:
00014  * Redistributions of source code must retain the above copyright notice,
00015    this list of conditions and the following disclaimer.
00016  * Redistributions in binary form must reproduce the above copyright notice,
00017    this list of conditions and the following disclaimer in the documentation
00018    and/or other materials provided with the distribution.
00019  * Neither the name of the University of Oxford nor the names of its
00020    contributors may be used to endorse or promote products derived from this
00021    software without specific prior written permission.
00022 
00023 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00027 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00029 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00032 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 
00034 */
00035 
00036 #include "MeshBasedCellPopulationWithGhostNodes.hpp"
00037 
00038 // Cell writers
00039 #include "CellAgesWriter.hpp"
00040 #include "CellAncestorWriter.hpp"
00041 #include "CellProliferativePhasesWriter.hpp"
00042 #include "CellProliferativeTypesWriter.hpp"
00043 #include "CellVolumesWriter.hpp"
00044 #include "CellLocationIndexWriter.hpp"
00045 
00046 // Cell population writers
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), // do not call the base class Validate()
00057                mGhostSpringStiffness(ghostSpringStiffness)
00058 {
00059     if (!locationIndices.empty())
00060     {
00061         // Create a set of node indices corresponding to ghost nodes
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         // This method finishes and then calls Validate()
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     // Reinitialise all entries of mIsGhostNode to false
00132     this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00133 
00134     // Update mIsGhostNode
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     // Initialise vector of forces on ghost nodes
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     // Calculate forces on ghost nodes
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     // There is reason not to subtract one position from the other (cylindrical meshes)
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     // Add new cell to cell population
00216     CellPtr p_created_cell = MeshBasedCellPopulation<DIM,DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00217     assert(p_created_cell == pNewCell);
00218 
00219     // Update size of mIsGhostNode if necessary
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     // Return pointer to new cell
00229     return p_created_cell;
00230 }
00231 
00232 template<unsigned DIM>
00233 void MeshBasedCellPopulationWithGhostNodes<DIM>::Validate()
00234 {
00235     // Get a list of all the nodes that are ghosts
00236     std::vector<bool> validated_node = mIsGhostNode;
00237     assert(mIsGhostNode.size()==this->GetNumNodes());
00238 
00239     // Look through all of the cells and record what node they are associated with.
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         // If the node attached to this cell is labelled as a ghost node, then throw an error
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     // Copy mIsGhostNode to a temporary vector
00265     std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00266 
00267     // Reinitialise mIsGhostNode
00268     mIsGhostNode.clear();
00269     mIsGhostNode.resize(this->GetNumNodes());
00270 
00271     // Update mIsGhostNode using the node map
00272     for (unsigned old_index=0; old_index<rMap.GetSize(); 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 std::set<unsigned> MeshBasedCellPopulationWithGhostNodes<DIM>::GetNeighbouringLocationIndices(CellPtr pCell)
00284 {
00285     unsigned node_index = this->GetLocationIndexUsingCell(pCell);
00286     std::set<unsigned> neighbour_indices = this->GetNeighbouringNodeIndices(node_index);
00287 
00288     // Remove ghost nodes from the neighbour indices
00289     for (std::set<unsigned>::iterator iter = neighbour_indices.begin();
00290          iter != neighbour_indices.end();)
00291     {
00292         if (this->IsGhostNode(*iter))
00293         {
00294             neighbour_indices.erase(iter++);
00295         }
00296         else
00297         {
00298             ++iter;
00299         }
00300     }
00301 
00302     return neighbour_indices;
00303 }
00304 
00305 template<unsigned DIM>
00306 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateNodeLocations(double dt)
00307 {
00308     // First update ghost positions first because they do not affect the real cells
00309     UpdateGhostPositions(dt);
00310 
00311     // Then call the base class method
00312     AbstractCentreBasedCellPopulation<DIM,DIM>::UpdateNodeLocations(dt);
00313 }
00314 
00315 
00316 template<unsigned DIM>
00317 void MeshBasedCellPopulationWithGhostNodes<DIM>::OpenWritersFiles(OutputFileHandler& rOutputFileHandler)
00318 {
00319     if (this->mOutputResultsForChasteVisualizer)
00320     {
00321         if (!this-> template HasWriter<CellLocationIndexWriter>())
00322         {
00323             this-> template AddCellWriter<CellLocationIndexWriter>();
00324         }
00325     }
00326 
00327     MeshBasedCellPopulation<DIM, DIM>::OpenWritersFiles(rOutputFileHandler);
00328 }
00329 
00330 template<unsigned DIM>
00331 void MeshBasedCellPopulationWithGhostNodes<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
00332 {
00333 #ifdef CHASTE_VTK
00334     if (this->mpVoronoiTessellation != NULL)
00335     {
00336         unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
00337         std::stringstream time;
00338         time << num_timesteps;
00339 
00340         // Create mesh writer for VTK output
00341         VertexMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results", false);
00342 
00343         // Iterate over any cell writers that are present
00344         unsigned num_vtk_cells = this->mpVoronoiTessellation->GetNumElements();
00345         for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
00346              cell_writer_iter != this->mCellWriters.end();
00347              ++cell_writer_iter)
00348         {
00349             // Create vector to store VTK cell data
00350             std::vector<double> vtk_cell_data(num_vtk_cells);
00351 
00352             // Loop over elements of mpVoronoiTessellation
00353             for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00354                  elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00355                  ++elem_iter)
00356             {
00357                 // Get the indices of this element and the corresponding node in mrMesh
00358                 unsigned elem_index = elem_iter->GetIndex();
00359                 unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00360 
00361                 // If this node corresponds to a ghost node, set any "cell" data to be -1.0
00362                 if (this->IsGhostNode(node_index))
00363                 {
00364                     // Populate the vector of VTK cell data
00365                     vtk_cell_data[elem_index] = -1.0;
00366                 }
00367                 else
00368                 {
00369                     // Get the cell corresponding to this node
00370                     CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00371 
00372                     // Populate the vector of VTK cell data
00373                     vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
00374                 }
00375             }
00376 
00377             mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
00378         }
00379 
00380         // Next, record which nodes are ghost nodes
00381         // Note that the cell writer hierarchy can not be used to do this as ghost nodes don't have corresponding cells.
00382         std::vector<double> ghosts(num_vtk_cells);
00383         for (typename VertexMesh<DIM, DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00384              elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00385              ++elem_iter)
00386         {
00387             unsigned elem_index = elem_iter->GetIndex();
00388             unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00389             ghosts[elem_index]  = (double) (this->IsGhostNode(node_index));
00390         }
00391         mesh_writer.AddCellData("Non-ghosts", ghosts);
00392 
00394 
00395         mesh_writer.WriteVtkUsingMesh(*(this->mpVoronoiTessellation), time.str());
00396         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00397         *(this->mpVtkMetaFile) << num_timesteps;
00398         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00399         *(this->mpVtkMetaFile) << num_timesteps;
00400         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00401     }
00402 #endif //CHASTE_VTK
00403 }
00404 
00405 template<unsigned DIM>
00406 void MeshBasedCellPopulationWithGhostNodes<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00407 {
00408     *rParamsFile << "\t\t<GhostSpringStiffness>" << mGhostSpringStiffness << "</GhostSpringStiffness>\n";
00409 
00410     // Call method on direct parent class
00411     MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00412 }
00413 
00414 // Explicit instantiation
00415 template class MeshBasedCellPopulationWithGhostNodes<1>;
00416 template class MeshBasedCellPopulationWithGhostNodes<2>;
00417 template class MeshBasedCellPopulationWithGhostNodes<3>;
00418 
00419 // Serialization for Boost >= 1.36
00420 #include "SerializationExportWrapperForCpp.hpp"
00421 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulationWithGhostNodes)

Generated by  doxygen 1.6.2