NagaiHondaForce.cpp

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