Chaste Release::3.1
MeshBasedCellPopulationWithGhostNodes.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 template<unsigned DIM>
00039 MeshBasedCellPopulationWithGhostNodes<DIM>::MeshBasedCellPopulationWithGhostNodes(
00040      MutableMesh<DIM, DIM>& rMesh,
00041      std::vector<CellPtr>& rCells,
00042      const std::vector<unsigned> locationIndices,
00043      bool deleteMesh,
00044      double ghostSpringStiffness)
00045              : MeshBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false), // do not call the base class Validate()
00046                mGhostSpringStiffness(ghostSpringStiffness)
00047 {
00048     if (!locationIndices.empty())
00049     {
00050         // Create a set of node indices corresponding to ghost nodes
00051         std::set<unsigned> node_indices;
00052         std::set<unsigned> location_indices;
00053         std::set<unsigned> ghost_node_indices;
00054 
00055         for (unsigned i=0; i<this->GetNumNodes(); i++)
00056         {
00057             node_indices.insert(this->GetNode(i)->GetIndex());
00058         }
00059         for (unsigned i=0; i<locationIndices.size(); i++)
00060         {
00061             location_indices.insert(locationIndices[i]);
00062         }
00063 
00064         std::set_difference(node_indices.begin(), node_indices.end(),
00065                             location_indices.begin(), location_indices.end(),
00066                             std::inserter(ghost_node_indices, ghost_node_indices.begin()));
00067 
00068         // This method finishes and then calls Validate()
00069         SetGhostNodes(ghost_node_indices);
00070     }
00071     else
00072     {
00073         this->mIsGhostNode = std::vector<bool>(this->GetNumNodes(), false);
00074         Validate();
00075     }
00076 }
00077 
00078 template<unsigned DIM>
00079 MeshBasedCellPopulationWithGhostNodes<DIM>::MeshBasedCellPopulationWithGhostNodes(MutableMesh<DIM, DIM>& rMesh,
00080                                                                   double ghostSpringStiffness)
00081              : MeshBasedCellPopulation<DIM>(rMesh),
00082                mGhostSpringStiffness(ghostSpringStiffness)
00083 {
00084 }
00085 
00086 template<unsigned DIM>
00087 std::vector<bool>& MeshBasedCellPopulationWithGhostNodes<DIM>::rGetGhostNodes()
00088 {
00089     return this->mIsGhostNode;
00090 }
00091 
00092 template<unsigned DIM>
00093 bool MeshBasedCellPopulationWithGhostNodes<DIM>::IsGhostNode(unsigned index)
00094 {
00095     return this->mIsGhostNode[index];
00096 }
00097 
00098 template<unsigned DIM>
00099 std::set<unsigned> MeshBasedCellPopulationWithGhostNodes<DIM>::GetGhostNodeIndices()
00100 {
00101     std::set<unsigned> ghost_node_indices;
00102     for (unsigned i=0; i<this->mIsGhostNode.size(); i++)
00103     {
00104         if (this->mIsGhostNode[i])
00105         {
00106             ghost_node_indices.insert(i);
00107         }
00108     }
00109     return ghost_node_indices;
00110 }
00111 
00112 template<unsigned DIM>
00113 void MeshBasedCellPopulationWithGhostNodes<DIM>::SetGhostNodes(const std::set<unsigned>& rGhostNodeIndices)
00114 {
00115     // Reinitialise all entries of mIsGhostNode to false
00116     this->mIsGhostNode = std::vector<bool>(this->mrMesh.GetNumNodes(), false);
00117 
00118     // Update mIsGhostNode
00119     for (std::set<unsigned>::iterator iter=rGhostNodeIndices.begin(); iter!=rGhostNodeIndices.end(); ++iter)
00120     {
00121         this->mIsGhostNode[*iter] = true;
00122     }
00123 
00124     Validate();
00125 }
00126 
00127 template<unsigned DIM>
00128 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateGhostPositions(double dt)
00129 {
00130     // Initialise vector of forces on ghost nodes
00131     std::vector<c_vector<double, DIM> > drdt(this->GetNumNodes());
00132     for (unsigned i=0; i<drdt.size(); i++)
00133     {
00134         drdt[i] = zero_vector<double>(DIM);
00135     }
00136 
00137     // Calculate forces on ghost nodes
00138     for (typename MutableMesh<DIM, DIM>::EdgeIterator edge_iterator = static_cast<MutableMesh<DIM, DIM>&>((this->mrMesh)).EdgesBegin();
00139         edge_iterator != static_cast<MutableMesh<DIM, DIM>&>((this->mrMesh)).EdgesEnd();
00140         ++edge_iterator)
00141     {
00142         unsigned nodeA_global_index = edge_iterator.GetNodeA()->GetIndex();
00143         unsigned nodeB_global_index = edge_iterator.GetNodeB()->GetIndex();
00144 
00145         c_vector<double, DIM> force = CalculateForceBetweenGhostNodes(nodeA_global_index, nodeB_global_index);
00146 
00147         double damping_constant = this->GetDampingConstantNormal();
00148 
00149         if (!this->mIsGhostNode[nodeA_global_index])
00150         {
00151             drdt[nodeB_global_index] -= force / damping_constant;
00152         }
00153         else
00154         {
00155             drdt[nodeA_global_index] += force / damping_constant;
00156 
00157             if (this->mIsGhostNode[nodeB_global_index])
00158             {
00159                 drdt[nodeB_global_index] -= force / damping_constant;
00160             }
00161         }
00162     }
00163 
00164     for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
00165          node_iter != this->mrMesh.GetNodeIteratorEnd();
00166          ++node_iter)
00167     {
00168         unsigned node_index = node_iter->GetIndex();
00169         if (this->mIsGhostNode[node_index])
00170         {
00171             ChastePoint<DIM> new_point(node_iter->rGetLocation() + dt*drdt[node_index]);
00172             static_cast<MutableMesh<DIM, DIM>&>((this->mrMesh)).SetNode(node_index, new_point, false);
00173         }
00174     }
00175 }
00176 
00177 template<unsigned DIM>
00178 c_vector<double, DIM> MeshBasedCellPopulationWithGhostNodes<DIM>::CalculateForceBetweenGhostNodes(const unsigned& rNodeAGlobalIndex, const unsigned& rNodeBGlobalIndex)
00179 {
00180     assert(rNodeAGlobalIndex != rNodeBGlobalIndex);
00181     c_vector<double, DIM> unit_difference;
00182     c_vector<double, DIM> node_a_location = this->GetNode(rNodeAGlobalIndex)->rGetLocation();
00183     c_vector<double, DIM> node_b_location = this->GetNode(rNodeBGlobalIndex)->rGetLocation();
00184 
00185     // There is reason not to subtract one position from the other (cylindrical meshes)
00186     unit_difference = this->mrMesh.GetVectorFromAtoB(node_a_location, node_b_location);
00187 
00188     double distance_between_nodes = norm_2(unit_difference);
00189 
00190     unit_difference /= distance_between_nodes;
00191 
00192     double rest_length = 1.0;
00193 
00194     return mGhostSpringStiffness * unit_difference * (distance_between_nodes - rest_length);
00195 }
00196 
00197 template<unsigned DIM>
00198 CellPtr MeshBasedCellPopulationWithGhostNodes<DIM>::AddCell(CellPtr pNewCell, const c_vector<double,DIM>& rCellDivisionVector, CellPtr pParentCell)
00199 {
00200     // Add new cell to cell population
00201     CellPtr p_created_cell = MeshBasedCellPopulation<DIM>::AddCell(pNewCell, rCellDivisionVector, pParentCell);
00202     assert(p_created_cell == pNewCell);
00203 
00204     // Update size of mIsGhostNode if necessary
00205     unsigned new_node_index = this->GetLocationIndexUsingCell(p_created_cell);
00206 
00207     if (this->GetNumNodes() > this->mIsGhostNode.size())
00208     {
00209         this->mIsGhostNode.resize(this->GetNumNodes());
00210         this->mIsGhostNode[new_node_index] = false;
00211     }
00212 
00213     // Return pointer to new cell
00214     return p_created_cell;
00215 }
00216 
00217 template<unsigned DIM>
00218 void MeshBasedCellPopulationWithGhostNodes<DIM>::Validate()
00219 {
00220     // Get a list of all the nodes that are ghosts
00221     std::vector<bool> validated_node = mIsGhostNode;
00222     assert(mIsGhostNode.size()==this->GetNumNodes());
00223 
00224     // Look through all of the cells and record what node they are associated with.
00225     for (typename AbstractCellPopulation<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00226     {
00227         unsigned node_index = this->GetLocationIndexUsingCell((*cell_iter));
00228 
00229         // If the node attached to this cell is labelled as a ghost node, then throw an error
00230         if (mIsGhostNode[node_index])
00231         {
00232             EXCEPTION("Node " << node_index << " is labelled as a ghost node and has a cell attached");
00233         }
00234         validated_node[node_index] = true;
00235     }
00236 
00237     for (unsigned i=0; i<validated_node.size(); i++)
00238     {
00239         if (!validated_node[i])
00240         {
00241             EXCEPTION("Node " << i << " does not appear to be a ghost node or have a cell associated with it");
00242         }
00243     }
00244 }
00245 
00246 template<unsigned DIM>
00247 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap)
00248 {
00249     // Copy mIsGhostNode to a temporary vector
00250     std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode;
00251 
00252     // Reinitialise mIsGhostNode
00253     mIsGhostNode.clear();
00254     mIsGhostNode.resize(this->GetNumNodes());
00255 
00256     // Update mIsGhostNode using the node map
00257     for (unsigned old_index=0; old_index<rMap.Size(); old_index++)
00258     {
00259         if (!rMap.IsDeleted(old_index))
00260         {
00261             unsigned new_index = rMap.GetNewIndex(old_index);
00262             mIsGhostNode[new_index] = ghost_nodes_before_remesh[old_index];
00263         }
00264     }
00265 }
00266 
00267 template<unsigned DIM>
00268 void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateNodeLocations(const std::vector< c_vector<double, DIM> >& rNodeForces, double dt)
00269 {
00270     // First update ghost positions first because they do not affect the real cells
00271     UpdateGhostPositions(dt);
00272 
00273     // Then call the base class method
00274     AbstractCentreBasedCellPopulation<DIM>::UpdateNodeLocations(rNodeForces, dt);
00275 }
00276 
00277 template<unsigned DIM>
00278 void MeshBasedCellPopulationWithGhostNodes<DIM>::WriteVtkResultsToFile()
00279 {
00280 #ifdef CHASTE_VTK
00281     if (this->mpVoronoiTessellation != NULL)
00282     {
00283         VertexMeshWriter<DIM, DIM> mesh_writer(this->mDirPath, "results", false);
00284         std::stringstream time;
00285         time << SimulationTime::Instance()->GetTimeStepsElapsed();
00286 
00287         unsigned num_elements = this->mpVoronoiTessellation->GetNumElements();
00288         std::vector<double> ghosts(num_elements);
00289         std::vector<double> cell_types(num_elements);
00290         std::vector<double> cell_ancestors(num_elements);
00291         std::vector<double> cell_mutation_states(num_elements);
00292         std::vector<double> cell_ages(num_elements);
00293         std::vector<double> cell_cycle_phases(num_elements);
00294         std::vector<double> cell_volumes(num_elements);
00295         std::vector<std::vector<double> > cellwise_data;
00296 
00297         unsigned num_cell_data_items = 0;
00298         // This code is commented  because CellData can't deal with ghost nodes see #1975
00299 //        //We assume that the first cell is representative of all cells
00300 //            num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
00301 
00302         for (unsigned var=0; var<num_cell_data_items; var++)
00303         {
00304             // This code is commented code is because CellData can't deal with ghost nodes see #1975
00305             //std::vector<double> cellwise_data_var(num_elements);
00306             //cellwise_data.push_back(cellwise_data_var);
00307         }
00308 
00309         // Loop over Voronoi elements
00310         for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = this->mpVoronoiTessellation->GetElementIteratorBegin();
00311              elem_iter != this->mpVoronoiTessellation->GetElementIteratorEnd();
00312              ++elem_iter)
00313         {
00314             // Get index of this element in the Voronoi tessellation mesh
00315             unsigned elem_index = elem_iter->GetIndex();
00316 
00317             unsigned node_index = this->mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
00318 
00319             ghosts[elem_index] = (double)(this->IsGhostNode(node_index));
00320 
00321             if (!this->IsGhostNode(node_index))
00322             {
00323                 // Get the cell corresponding to this element
00324                 CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
00325 
00326                 if (this->mOutputCellAncestors)
00327                 {
00328                     double ancestor_index = (p_cell->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)p_cell->GetAncestor();
00329                     cell_ancestors[elem_index] = ancestor_index;
00330                 }
00331                 if (this->mOutputCellProliferativeTypes)
00332                 {
00333                     double cell_type = p_cell->GetCellProliferativeType();
00334                     cell_types[elem_index] = cell_type;
00335                 }
00336                 if (this->mOutputCellMutationStates)
00337                 {
00338                     double mutation_state = p_cell->GetMutationState()->GetColour();
00339                     cell_mutation_states[elem_index] = mutation_state;
00340                 }
00341                 if (this->mOutputCellAges)
00342                 {
00343                     double age = p_cell->GetAge();
00344                     cell_ages[elem_index] = age;
00345                 }
00346                 if (this->mOutputCellCyclePhases)
00347                 {
00348                     double cycle_phase = p_cell->GetCellCycleModel()->GetCurrentCellCyclePhase();
00349                     cell_cycle_phases[elem_index] = cycle_phase;
00350                 }
00351                 if (this->mOutputCellVolumes)
00352                 {
00353                     double cell_volume = this->mpVoronoiTessellation->GetVolumeOfElement(elem_index);
00354                     cell_volumes[elem_index] = cell_volume;
00355                 }
00356 
00357                 for (unsigned var=0; var<num_cell_data_items; var++)
00358                 {
00359                     // This code is commented  because CellData can't deal with ghost nodes see #1975
00360                     //cellwise_data[var][elem_index] =  cell_iter->GetCellData()->GetItem(var);
00361                 }
00362             }
00363             else
00364             {
00365                 if (this->mOutputCellAncestors)
00366                 {
00367                     cell_ancestors[elem_index] = -1.0;
00368                 }
00369                 if (this->mOutputCellProliferativeTypes)
00370                 {
00371                     cell_types[elem_index] = -1.0;
00372                 }
00373                 if (this->mOutputCellMutationStates)
00374                 {
00375                     cell_mutation_states[elem_index] = -1.0;
00376                 }
00377                 if (this->mOutputCellAges)
00378                 {
00379                     cell_ages[elem_index] = -1.0;
00380                 }
00381                 if (this->mOutputCellCyclePhases)
00382                 {
00383                     cell_cycle_phases[elem_index] = -1.0;
00384                 }
00385                 if (this->mOutputCellVolumes)
00386                 {
00387                     cell_volumes[elem_index] = -1.0;
00388                 }
00389             }
00390         }
00391 
00392         mesh_writer.AddCellData("Non-ghosts", ghosts);
00393         if (this->mOutputCellProliferativeTypes)
00394         {
00395             mesh_writer.AddCellData("Cell types", cell_types);
00396         }
00397         if (this->mOutputCellAncestors)
00398         {
00399             mesh_writer.AddCellData("Ancestors", cell_ancestors);
00400         }
00401         if (this->mOutputCellMutationStates)
00402         {
00403             mesh_writer.AddCellData("Mutation states", cell_mutation_states);
00404         }
00405         if (this->mOutputCellAges)
00406         {
00407             mesh_writer.AddCellData("Ages", cell_ages);
00408         }
00409         if (this->mOutputCellCyclePhases)
00410         {
00411             mesh_writer.AddCellData("Cycle phases", cell_cycle_phases);
00412         }
00413         if (this->mOutputCellVolumes)
00414         {
00415             mesh_writer.AddCellData("Cell volumes", cell_volumes);
00416         }
00418         // This code is commented code is because Cellwise Data can't deal with ghost nodes see #1975
00419         if (num_cell_data_items > 0)
00420         {
00421 //            for (unsigned var=0; var<cellwise_data.size(); var++)
00422 //            {
00423 //                // This code is commented  because Cellwise Data can't deal with ghost nodes see #1975
00424 //                std::stringstream data_name;
00425 //                data_name << "Cellwise data " << var;
00426 //                std::vector<double> cellwise_data_var = cellwise_data[var];
00427 //                mesh_writer.AddCellData(data_name.str(), cellwise_data_var);
00428 //            }
00429         }
00430         mesh_writer.WriteVtkUsingMesh(*(this->mpVoronoiTessellation), time.str());
00431         *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
00432         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00433         *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
00434         *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
00435         *(this->mpVtkMetaFile) << ".vtu\"/>\n";
00436     }
00437 #endif //CHASTE_VTK
00438 }
00439 
00440 template<unsigned DIM>
00441 void MeshBasedCellPopulationWithGhostNodes<DIM>::OutputCellPopulationParameters(out_stream& rParamsFile)
00442 {
00443     *rParamsFile << "\t\t<GhostSpringStiffness>" << mGhostSpringStiffness << "</GhostSpringStiffness>\n";
00444 
00445     // Call method on direct parent class
00446     MeshBasedCellPopulation<DIM>::OutputCellPopulationParameters(rParamsFile);
00447 }
00448 
00450 // Explicit instantiation
00452 
00453 template class MeshBasedCellPopulationWithGhostNodes<1>;
00454 template class MeshBasedCellPopulationWithGhostNodes<2>;
00455 template class MeshBasedCellPopulationWithGhostNodes<3>;
00456 
00457 // Serialization for Boost >= 1.36
00458 #include "SerializationExportWrapperForCpp.hpp"
00459 EXPORT_TEMPLATE_CLASS_SAME_DIMS(MeshBasedCellPopulationWithGhostNodes)