NagaiHondaForce.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "NagaiHondaForce.hpp"
00037
00038 template<unsigned DIM>
00039 NagaiHondaForce<DIM>::NagaiHondaForce()
00040 : AbstractForce<DIM>(),
00041 mNagaiHondaDeformationEnergyParameter(100.0),
00042 mNagaiHondaMembraneSurfaceEnergyParameter(10.0),
00043 mNagaiHondaCellCellAdhesionEnergyParameter(1.0),
00044 mNagaiHondaCellBoundaryAdhesionEnergyParameter(1.0)
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
00057 if (dynamic_cast<VertexBasedCellPopulation<DIM>*>(&rCellPopulation) == NULL)
00058 {
00059 EXCEPTION("NagaiHondaForce is to be used with a VertexBasedCellPopulation only");
00060 }
00061
00062
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
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
00081
00082
00083
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
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
00099
00100
00101
00102
00103
00104
00105
00106
00107
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
00114 std::set<unsigned> containing_elem_indices = p_cell_population->GetNode(node_index)->rGetContainingElementIndices();
00115
00116
00117 for (std::set<unsigned>::iterator iter = containing_elem_indices.begin();
00118 iter != containing_elem_indices.end();
00119 ++iter)
00120 {
00121
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
00127 unsigned local_index = p_element->GetNodeLocalIndex(node_index);
00128
00129
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
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
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
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
00149 adhesion_contribution -= previous_edge_adhesion_parameter*previous_edge_gradient + next_edge_adhesion_parameter*next_edge_gradient;
00150
00151
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
00166 std::set<unsigned> elements_containing_nodeA = pNodeA->rGetContainingElementIndices();
00167 std::set<unsigned> elements_containing_nodeB = pNodeB->rGetContainingElementIndices();
00168
00169
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
00178 assert(!shared_elements.empty());
00179
00180 double adhesion_parameter = GetNagaiHondaCellCellAdhesionEnergyParameter();
00181
00182
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
00249 AbstractForce<DIM>::OutputForceParameters(rParamsFile);
00250 }
00251
00253
00255
00256 template class NagaiHondaForce<1>;
00257 template class NagaiHondaForce<2>;
00258 template class NagaiHondaForce<3>;
00259
00260
00261 #include "SerializationExportWrapperForCpp.hpp"
00262 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NagaiHondaForce)