NagaiHondaForce.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 "NagaiHondaForce.hpp"
00037 
00038 template<unsigned DIM>
00039 NagaiHondaForce<DIM>::NagaiHondaForce()
00040    : AbstractForce<DIM>(),
00041      mNagaiHondaDeformationEnergyParameter(100.0), // This is 1.0 in the Nagai & Honda paper
00042      mNagaiHondaMembraneSurfaceEnergyParameter(10.0), // This is 0.1 in the Nagai & Honda paper
00043      mNagaiHondaCellCellAdhesionEnergyParameter(1.0), // This is 0.01 in the Nagai & Honda paper
00044      mNagaiHondaCellBoundaryAdhesionEnergyParameter(1.0) // This is 0.01 in the Nagai & Honda paper
00045 {
00046 }
00047 
00048 template<unsigned DIM>
00049 NagaiHondaForce<DIM>::~NagaiHondaForce()
00050 {
00051 }
00052 
00053 template<unsigned DIM>
00054 void NagaiHondaForce<DIM>::AddForceContribution(AbstractCellPopulation<DIM>& rCellPopulation)
00055 {
00056     // Throw an exception message if not using a VertexBasedCellPopulation
00057     if (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation) == NULL)
00058     {
00059         EXCEPTION("NagaiHondaForce is to be used with a VertexBasedCellPopulation only");
00060     }
00061 
00062     // Define some helper variables
00063     VertexBasedCellPopulation<DIM>* p_cell_population = static_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation);
00064     unsigned num_nodes = p_cell_population->GetNumNodes();
00065     unsigned num_elements = p_cell_population->GetNumElements();
00066 
00067     // Begin by computing the area and perimeter of each element in the mesh, to avoid having to do this multiple times
00068     std::vector<double> element_areas(num_elements);
00069     std::vector<double> element_perimeters(num_elements);
00070     std::vector<double> target_areas(num_elements);
00071     for (typename VertexMesh<DIM,DIM>::VertexElementIterator elem_iter = p_cell_population->rGetMesh().GetElementIteratorBegin();
00072          elem_iter != p_cell_population->rGetMesh().GetElementIteratorEnd();
00073          ++elem_iter)
00074     {
00075         unsigned elem_index = elem_iter->GetIndex();
00076         element_areas[elem_index] = p_cell_population->rGetMesh().GetVolumeOfElement(elem_index);
00077         element_perimeters[elem_index] = p_cell_population->rGetMesh().GetSurfaceAreaOfElement(elem_index);
00078         try
00079         {
00080             // If we haven't specified a growth modifier, there won't be any target areas in the CellData array and CellData
00081             // will throw an exception that it doesn't have "target area" entries.  We add this piece of code to give a more
00082             // understandable message. There is a slight chance that the exception is thrown although the error is not about the
00083             // target areas.
00084             target_areas[elem_index] = p_cell_population->GetCellUsingLocationIndex(elem_index)->GetCellData()->GetItem("target area");
00085         }
00086         catch (Exception&)
00087         {
00088             EXCEPTION("You need to add an AbstractTargetAreaModifier to the simulation in order to use NagaiHondaForce");
00089         }
00090     }
00091 
00092     // Iterate over vertices in the cell population
00093     for (unsigned node_index=0; node_index<num_nodes; node_index++)
00094     {
00095         Node<DIM>* p_this_node = p_cell_population->GetNode(node_index);
00096 
00097         /*
00098          * The force on this Node is given by the gradient of the total free
00099          * energy of the CellPopulation, evaluated at the position of the vertex. This
00100          * free energy is the sum of the free energies of all CellPtrs in
00101          * the cell population. The free energy of each CellPtr is comprised of three
00102          * parts - a cell deformation energy, a membrane surface tension energy
00103          * and an adhesion energy.
00104          *
00105          * Note that since the movement of this Node only affects the free energy
00106          * of the CellPtrs containing it, we can just consider the contributions
00107          * to the free energy gradient from each of these CellPtrs.
00108          */
00109         c_vector<double, DIM> deformation_contribution = zero_vector<double>(DIM);
00110         c_vector<double, DIM> membrane_surface_tension_contribution = zero_vector<double>(DIM);
00111         c_vector<double, DIM> adhesion_contribution = zero_vector<double>(DIM);
00112 
00113         // Find the indices of the elements owned by this node
00114         std::set<unsigned> containing_elem_indices = p_cell_population->GetNode(node_index)->rGetContainingElementIndices();
00115 
00116         // Iterate over these elements
00117         for (std::set<unsigned>::iterator iter = containing_elem_indices.begin();
00118              iter != containing_elem_indices.end();
00119              ++iter)
00120         {
00121             // Get this element, its index and its number of nodes
00122             VertexElement<DIM, DIM>* p_element = p_cell_population->GetElement(*iter);
00123             unsigned elem_index = p_element->GetIndex();
00124             unsigned num_nodes_elem = p_element->GetNumNodes();
00125 
00126             // Find the local index of this node in this element
00127             unsigned local_index = p_element->GetNodeLocalIndex(node_index);
00128 
00129             // Add the force contribution from this cell's deformation energy (note the minus sign)
00130             c_vector<double, DIM> element_area_gradient = p_cell_population->rGetMesh().GetAreaGradientOfElementAtNode(p_element, local_index);
00131             deformation_contribution -= 2*GetNagaiHondaDeformationEnergyParameter()*(element_areas[elem_index] - target_areas[elem_index])*element_area_gradient;
00132 
00133             // Get the previous and next nodes in this element
00134             unsigned previous_node_local_index = (num_nodes_elem+local_index-1)%num_nodes_elem;
00135             Node<DIM>* p_previous_node = p_element->GetNode(previous_node_local_index);
00136 
00137             unsigned next_node_local_index = (local_index+1)%num_nodes_elem;
00138             Node<DIM>* p_next_node = p_element->GetNode(next_node_local_index);
00139 
00140             // Compute the adhesion parameter for each of these edges
00141             double previous_edge_adhesion_parameter = GetAdhesionParameter(p_previous_node, p_this_node, *p_cell_population);
00142             double next_edge_adhesion_parameter = GetAdhesionParameter(p_this_node, p_next_node, *p_cell_population);
00143 
00144             // Compute the gradient of each these edges, computed at the present node
00145             c_vector<double, DIM> previous_edge_gradient = -p_cell_population->rGetMesh().GetNextEdgeGradientOfElementAtNode(p_element, previous_node_local_index);
00146             c_vector<double, DIM> next_edge_gradient = p_cell_population->rGetMesh().GetNextEdgeGradientOfElementAtNode(p_element, local_index);
00147 
00148             // Add the force contribution from cell-cell and cell-boundary adhesion (note the minus sign)
00149             adhesion_contribution -= previous_edge_adhesion_parameter*previous_edge_gradient + next_edge_adhesion_parameter*next_edge_gradient;
00150 
00151             // Add the force contribution from this cell's membrane surface tension (note the minus sign)
00152             c_vector<double, DIM> element_perimeter_gradient = previous_edge_gradient + next_edge_gradient;
00153             double cell_target_perimeter = 2*sqrt(M_PI*target_areas[elem_index]);
00154             membrane_surface_tension_contribution -= 2*GetNagaiHondaMembraneSurfaceEnergyParameter()*(element_perimeters[elem_index] - cell_target_perimeter)*element_perimeter_gradient;
00155         }
00156 
00157         c_vector<double, DIM> force_on_node = deformation_contribution + membrane_surface_tension_contribution + adhesion_contribution;
00158         p_cell_population->GetNode(node_index)->AddAppliedForceContribution(force_on_node);
00159     }
00160 }
00161 
00162 template<unsigned DIM>
00163 double NagaiHondaForce<DIM>::GetAdhesionParameter(Node<DIM>* pNodeA, Node<DIM>* pNodeB, VertexBasedCellPopulation<DIM>& rVertexCellPopulation)
00164 {
00165     // Find the indices of the elements owned by each node
00166     std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
00167     std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
00168 
00169     // Find common elements
00170     std::set<unsigned> shared_elements;
00171     std::set_intersection(elements_containing_nodeA.begin(),
00172                           elements_containing_nodeA.end(),
00173                           elements_containing_nodeB.begin(),
00174                           elements_containing_nodeB.end(),
00175                           std::inserter(shared_elements, shared_elements.begin()));
00176 
00177     // Check that the nodes have a common edge
00178     assert(!shared_elements.empty());
00179 
00180     double adhesion_parameter = GetNagaiHondaCellCellAdhesionEnergyParameter();
00181 
00182     // If the edge corresponds to a single element, then the cell is on the boundary
00183     if (shared_elements.size() == 1)
00184     {
00185         adhesion_parameter = GetNagaiHondaCellBoundaryAdhesionEnergyParameter();
00186     }
00187 
00188     return adhesion_parameter;
00189 }
00190 
00191 template<unsigned DIM>
00192 double NagaiHondaForce<DIM>::GetNagaiHondaDeformationEnergyParameter()
00193 {
00194     return mNagaiHondaDeformationEnergyParameter;
00195 }
00196 
00197 template<unsigned DIM>
00198 double NagaiHondaForce<DIM>::GetNagaiHondaMembraneSurfaceEnergyParameter()
00199 {
00200     return mNagaiHondaMembraneSurfaceEnergyParameter;
00201 }
00202 
00203 template<unsigned DIM>
00204 double NagaiHondaForce<DIM>::GetNagaiHondaCellCellAdhesionEnergyParameter()
00205 {
00206     return mNagaiHondaCellCellAdhesionEnergyParameter;
00207 }
00208 
00209 template<unsigned DIM>
00210 double NagaiHondaForce<DIM>::GetNagaiHondaCellBoundaryAdhesionEnergyParameter()
00211 {
00212     return mNagaiHondaCellBoundaryAdhesionEnergyParameter;
00213 }
00214 
00215 template<unsigned DIM>
00216 void NagaiHondaForce<DIM>::SetNagaiHondaDeformationEnergyParameter(double deformationEnergyParameter)
00217 {
00218     mNagaiHondaDeformationEnergyParameter = deformationEnergyParameter;
00219 }
00220 
00221 template<unsigned DIM>
00222 void NagaiHondaForce<DIM>::SetNagaiHondaMembraneSurfaceEnergyParameter(double membraneSurfaceEnergyParameter)
00223 {
00224     mNagaiHondaMembraneSurfaceEnergyParameter = membraneSurfaceEnergyParameter;
00225 }
00226 
00227 template<unsigned DIM>
00228 void NagaiHondaForce<DIM>::SetNagaiHondaCellCellAdhesionEnergyParameter(double cellCellAdhesionEnergyParameter)
00229 {
00230     mNagaiHondaCellCellAdhesionEnergyParameter = cellCellAdhesionEnergyParameter;
00231 }
00232 
00233 template<unsigned DIM>
00234 void NagaiHondaForce<DIM>::SetNagaiHondaCellBoundaryAdhesionEnergyParameter(double cellBoundaryAdhesionEnergyParameter)
00235 {
00236     mNagaiHondaCellBoundaryAdhesionEnergyParameter = cellBoundaryAdhesionEnergyParameter;
00237 }
00238 
00239 
00240 template<unsigned DIM>
00241 void NagaiHondaForce<DIM>::OutputForceParameters(out_stream& rParamsFile)
00242 {
00243     *rParamsFile << "\t\t\t<NagaiHondaDeformationEnergyParameter>" << mNagaiHondaDeformationEnergyParameter << "</NagaiHondaDeformationEnergyParameter>\n";
00244     *rParamsFile << "\t\t\t<NagaiHondaMembraneSurfaceEnergyParameter>" << mNagaiHondaMembraneSurfaceEnergyParameter << "</NagaiHondaMembraneSurfaceEnergyParameter>\n";
00245     *rParamsFile << "\t\t\t<NagaiHondaCellCellAdhesionEnergyParameter>" << mNagaiHondaCellCellAdhesionEnergyParameter << "</NagaiHondaCellCellAdhesionEnergyParameter>\n";
00246     *rParamsFile << "\t\t\t<NagaiHondaCellBoundaryAdhesionEnergyParameter>" << mNagaiHondaCellBoundaryAdhesionEnergyParameter << "</NagaiHondaCellBoundaryAdhesionEnergyParameter>\n";
00247 
00248     // Call method on direct parent class
00249     AbstractForce<DIM>::OutputForceParameters(rParamsFile);
00250 }
00251 
00253 // Explicit instantiation
00255 
00256 template class NagaiHondaForce<1>;
00257 template class NagaiHondaForce<2>;
00258 template class NagaiHondaForce<3>;
00259 
00260 // Serialization for Boost >= 1.36
00261 #include "SerializationExportWrapperForCpp.hpp"
00262 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NagaiHondaForce)

Generated by  doxygen 1.6.2