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

Generated by  doxygen 1.6.2