Chaste Release::3.1
NagaiHondaForce.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 "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 the Nagai & Honda paper
00043      mNagaiHondaCellCellAdhesionEnergyParameter(1.0), // This is 0.01 the Nagai & Honda paper
00044      mNagaiHondaCellBoundaryAdhesionEnergyParameter(1.0), // This is 0.01 the Nagai & Honda paper
00045      mMatureCellTargetArea(1.0)
00046 {
00047 }
00048 
00049 template<unsigned DIM>
00050 NagaiHondaForce<DIM>::~NagaiHondaForce()
00051 {
00052 }
00053 
00054 template<unsigned DIM>
00055 void NagaiHondaForce<DIM>::AddForceContribution(std::vector<c_vector<double, DIM> >& rForces,
00056                                                 AbstractCellPopulation<DIM>& rCellPopulation)
00057 {
00058     // Throw an exception message if not using a VertexBasedCellPopulation
00059     if (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation) == NULL)
00060     {
00061         EXCEPTION("NagaiHondaForce is to be used with a VertexBasedCellPopulation only");
00062     }
00063 
00064     // Helper variable that is a static cast of the cell population
00065     VertexBasedCellPopulation<DIM>* p_cell_population = static_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation);
00066 
00067     // Iterate over vertices in the cell population
00068     for (unsigned node_index=0; node_index<p_cell_population->GetNumNodes(); node_index++)
00069     {
00070         // Compute the force on this node
00071 
00072         /*
00073          * The force on this Node is given by the gradient of the total free
00074          * energy of the CellPopulation, evaluated at the position of the vertex. This
00075          * free energy is the sum of the free energies of all CellPtrs in
00076          * the cell population. The free energy of each CellPtr is comprised of three
00077          * parts - a cell deformation energy, a membrane surface tension energy
00078          * and an adhesion energy.
00079          *
00080          * Note that since the movement of this Node only affects the free energy
00081          * of the three CellPtrs containing it, we can just consider the
00082          * contributions to the free energy gradient from each of these three
00083          * CellPtrs.
00084          */
00085 
00086         c_vector<double, DIM> deformation_contribution = zero_vector<double>(DIM);
00087         c_vector<double, DIM> membrane_surface_tension_contribution = zero_vector<double>(DIM);
00088         c_vector<double, DIM> adhesion_contribution = zero_vector<double>(DIM);
00089 
00090         // Find the indices of the elements owned by this node
00091         std::set<unsigned> containing_elem_indices = p_cell_population->GetNode(node_index)->rGetContainingElementIndices();
00092 
00093         // Iterate over these elements
00094         for (std::set<unsigned>::iterator iter = containing_elem_indices.begin();
00095              iter != containing_elem_indices.end();
00096              ++iter)
00097         {
00098             // Get this element and its index
00099             VertexElement<DIM, DIM>* p_element = p_cell_population->GetElement(*iter);
00100             unsigned element_index = p_element->GetIndex();
00101 
00102             // Find the local index of this node in this element
00103             unsigned local_index = p_element->GetNodeLocalIndex(node_index);
00104 
00105             /******** Start of deformation force calculation ********/
00106 
00107             // Compute the area of this element and its gradient at this node
00108             double element_area = p_cell_population->rGetMesh().GetVolumeOfElement(*iter);
00109             c_vector<double, DIM> element_area_gradient = p_cell_population->rGetMesh().GetAreaGradientOfElementAtNode(p_element, local_index);
00110 
00111             // Get the target area of the cell
00112             double cell_target_area = GetTargetAreaOfCell(p_cell_population->GetCellUsingLocationIndex(element_index));
00113 
00114             // Add the force contribution from this cell's deformation energy (note the minus sign)
00115             deformation_contribution -= 2*GetNagaiHondaDeformationEnergyParameter()*(element_area - cell_target_area)*element_area_gradient;
00116 
00117             /******** End of deformation force calculation *************/
00118 
00119             /******** Start of membrane force calculation ***********/
00120 
00121             // Compute the perimeter of the element and its gradient at this node
00122             double element_perimeter = p_cell_population->rGetMesh().GetSurfaceAreaOfElement(*iter);
00123             c_vector<double, DIM> element_perimeter_gradient = p_cell_population->rGetMesh().GetPerimeterGradientOfElementAtNode(p_element, local_index);
00124 
00125             // Get the target perimeter of the cell
00126             double cell_target_perimeter = 2*sqrt(M_PI*cell_target_area);
00127 
00128             // Add the force contribution from this cell's membrane surface tension (note the minus sign)
00129             membrane_surface_tension_contribution -= 2*GetNagaiHondaMembraneSurfaceEnergyParameter()*(element_perimeter - cell_target_perimeter)*element_perimeter_gradient;
00130 
00131             /******** End of membrane force calculation **********/
00132 
00133             /******** Start of adhesion force calculation ***********/
00134 
00135             // Get the current, previous and next nodes in this element
00136             Node<DIM>* p_current_node = p_element->GetNode(local_index);
00137 
00138             unsigned previous_node_local_index = (p_element->GetNumNodes()+local_index-1)%(p_element->GetNumNodes());
00139             Node<DIM>* p_previous_node = p_element->GetNode(previous_node_local_index);
00140 
00141             unsigned next_node_local_index = (local_index+1)%(p_element->GetNumNodes());
00142             Node<DIM>* p_next_node = p_element->GetNode(next_node_local_index);
00143 
00144             // Compute the adhesion parameter for each of these edges
00145             double previous_edge_adhesion_parameter;
00146             double next_edge_adhesion_parameter;
00147 
00148             previous_edge_adhesion_parameter = GetAdhesionParameter(p_previous_node, p_current_node, *p_cell_population);
00149             next_edge_adhesion_parameter = GetAdhesionParameter(p_current_node, p_next_node, *p_cell_population);
00150 
00151             // Compute the gradient of the edge of the cell ending in this node
00152             c_vector<double, DIM> previous_edge_gradient = p_cell_population->rGetMesh().GetPreviousEdgeGradientOfElementAtNode(p_element, local_index);
00153 
00154             // Compute the gradient of the edge of the cell starting in this node
00155             c_vector<double, DIM> next_edge_gradient = p_cell_population->rGetMesh().GetNextEdgeGradientOfElementAtNode(p_element, local_index);
00156 
00157             // Add the force contribution from cell-cell and cell-boundary adhesion (note the minus sign)
00158             adhesion_contribution -= previous_edge_adhesion_parameter*previous_edge_gradient + next_edge_adhesion_parameter*next_edge_gradient;
00159 
00160             /******** End of adhesion force calculation *************/
00161         }
00162 
00163         c_vector<double, DIM> force_on_node = deformation_contribution +
00164                                               membrane_surface_tension_contribution +
00165                                               adhesion_contribution;
00166 
00167         rForces[node_index] += force_on_node;
00168     }
00169 }
00170 
00171 template<unsigned DIM>
00172 double NagaiHondaForce<DIM>::GetAdhesionParameter(Node<DIM>* pNodeA, Node<DIM>* pNodeB, VertexBasedCellPopulation<DIM>& rVertexCellPopulation)
00173 {
00174     // Find the indices of the elements owned by each node
00175     std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
00176     std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
00177 
00178     // Find common elements
00179     std::set<unsigned> shared_elements;
00180     std::set_intersection(elements_containing_nodeA.begin(),
00181                           elements_containing_nodeA.end(),
00182                           elements_containing_nodeB.begin(),
00183                           elements_containing_nodeB.end(),
00184                           std::inserter(shared_elements, shared_elements.begin()));
00185 
00186     // Check that the nodes have a common edge
00187     assert(!shared_elements.empty());
00188 
00189     double adhesion_parameter = GetNagaiHondaCellCellAdhesionEnergyParameter();
00190 
00191     // If the edge corresponds to a single element, then the cell is on the boundary
00192     if (shared_elements.size() == 1)
00193     {
00194         adhesion_parameter = GetNagaiHondaCellBoundaryAdhesionEnergyParameter();
00195     }
00196 
00197     return adhesion_parameter;
00198 }
00199 
00200 template<unsigned DIM>
00201 double NagaiHondaForce<DIM>::GetNagaiHondaDeformationEnergyParameter()
00202 {
00203     return mNagaiHondaDeformationEnergyParameter;
00204 }
00205 
00206 template<unsigned DIM>
00207 double NagaiHondaForce<DIM>::GetNagaiHondaMembraneSurfaceEnergyParameter()
00208 {
00209     return mNagaiHondaMembraneSurfaceEnergyParameter;
00210 }
00211 
00212 template<unsigned DIM>
00213 double NagaiHondaForce<DIM>::GetNagaiHondaCellCellAdhesionEnergyParameter()
00214 {
00215     return mNagaiHondaCellCellAdhesionEnergyParameter;
00216 }
00217 
00218 template<unsigned DIM>
00219 double NagaiHondaForce<DIM>::GetNagaiHondaCellBoundaryAdhesionEnergyParameter()
00220 {
00221     return mNagaiHondaCellBoundaryAdhesionEnergyParameter;
00222 }
00223 
00224 template<unsigned DIM>
00225 void NagaiHondaForce<DIM>::SetNagaiHondaDeformationEnergyParameter(double deformationEnergyParameter)
00226 {
00227     mNagaiHondaDeformationEnergyParameter = deformationEnergyParameter;
00228 }
00229 
00230 template<unsigned DIM>
00231 void NagaiHondaForce<DIM>::SetNagaiHondaMembraneSurfaceEnergyParameter(double membraneSurfaceEnergyParameter)
00232 {
00233     mNagaiHondaMembraneSurfaceEnergyParameter = membraneSurfaceEnergyParameter;
00234 }
00235 
00236 template<unsigned DIM>
00237 void NagaiHondaForce<DIM>::SetNagaiHondaCellCellAdhesionEnergyParameter(double cellCellAdhesionEnergyParameter)
00238 {
00239     mNagaiHondaCellCellAdhesionEnergyParameter = cellCellAdhesionEnergyParameter;
00240 }
00241 
00242 template<unsigned DIM>
00243 void NagaiHondaForce<DIM>::SetNagaiHondaCellBoundaryAdhesionEnergyParameter(double cellBoundaryAdhesionEnergyParameter)
00244 {
00245     mNagaiHondaCellBoundaryAdhesionEnergyParameter = cellBoundaryAdhesionEnergyParameter;
00246 }
00247 
00248 template<unsigned DIM>
00249 double NagaiHondaForce<DIM>::GetTargetAreaOfCell(const CellPtr pCell) const
00250 {
00251     // Get target area A of a healthy cell in S, G2 or M phase
00252     double cell_target_area = mMatureCellTargetArea;
00253 
00254     double cell_age = pCell->GetAge();
00255     double g1_duration = pCell->GetCellCycleModel()->GetG1Duration();
00256 
00257     // If the cell is differentiated then its G1 duration is infinite
00258     if (g1_duration == DBL_MAX) // don't use magic number, compare to DBL_MAX
00259     {
00260         // This is just for fixed cell-cycle models, need to work out how to find the g1 duration
00261         g1_duration = pCell->GetCellCycleModel()->GetTransitCellG1Duration();
00262     }
00263 
00264     if (pCell->HasCellProperty<ApoptoticCellProperty>())
00265     {
00266         // Age of cell when apoptosis begins
00267         if (pCell->GetStartOfApoptosisTime() - pCell->GetBirthTime() < g1_duration)
00268         {
00269             cell_target_area *= 0.5*(1 + (pCell->GetStartOfApoptosisTime() - pCell->GetBirthTime())/g1_duration);
00270         }
00271 
00272         // The target area of an apoptotic cell decreases linearly to zero (and past it negative)
00273         cell_target_area = cell_target_area - 0.5*cell_target_area/(pCell->GetApoptosisTime())*(SimulationTime::Instance()->GetTime()-pCell->GetStartOfApoptosisTime());
00274 
00275         // Don't allow a negative target area
00276         if (cell_target_area < 0)
00277         {
00278             cell_target_area = 0;
00279         }
00280     }
00281     else
00282     {
00283         // The target area of a proliferating cell increases linearly from A/2 to A over the course of the G1 phase
00284         if (cell_age < g1_duration)
00285         {
00286             cell_target_area *= 0.5*(1 + cell_age/g1_duration);
00287         }
00288     }
00289 
00290     return cell_target_area;
00291 }
00292 
00293 template<unsigned DIM>
00294 double NagaiHondaForce<DIM>::GetMatureCellTargetArea() const
00295 {
00296     return mMatureCellTargetArea;
00297 }
00298 
00299 template<unsigned DIM>
00300 void NagaiHondaForce<DIM>::SetMatureCellTargetArea(double matureCellTargetArea)
00301 {
00302     assert(matureCellTargetArea >= 0.0);
00303     mMatureCellTargetArea = matureCellTargetArea;
00304 }
00305 
00306 template<unsigned DIM>
00307 void NagaiHondaForce<DIM>::OutputForceParameters(out_stream& rParamsFile)
00308 {
00309     *rParamsFile << "\t\t\t<NagaiHondaDeformationEnergyParameter>" << mNagaiHondaDeformationEnergyParameter << "</NagaiHondaDeformationEnergyParameter>\n";
00310     *rParamsFile << "\t\t\t<NagaiHondaMembraneSurfaceEnergyParameter>" << mNagaiHondaMembraneSurfaceEnergyParameter << "</NagaiHondaMembraneSurfaceEnergyParameter>\n";
00311     *rParamsFile << "\t\t\t<NagaiHondaCellCellAdhesionEnergyParameter>" << mNagaiHondaCellCellAdhesionEnergyParameter << "</NagaiHondaCellCellAdhesionEnergyParameter>\n";
00312     *rParamsFile << "\t\t\t<NagaiHondaCellBoundaryAdhesionEnergyParameter>" << mNagaiHondaCellBoundaryAdhesionEnergyParameter << "</NagaiHondaCellBoundaryAdhesionEnergyParameter>\n";
00313     *rParamsFile << "\t\t\t<MatureCellTargetArea>" << mMatureCellTargetArea << "</MatureCellTargetArea>\n";
00314 
00315     // Call method on direct parent class
00316     AbstractForce<DIM>::OutputForceParameters(rParamsFile);
00317 }
00318 
00320 // Explicit instantiation
00322 
00323 template class NagaiHondaForce<1>;
00324 template class NagaiHondaForce<2>;
00325 template class NagaiHondaForce<3>;
00326 
00327 // Serialization for Boost >= 1.36
00328 #include "SerializationExportWrapperForCpp.hpp"
00329 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NagaiHondaForce)