GeneralisedLinearSpringForce.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
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 "GeneralisedLinearSpringForce.hpp"
00030 
00031 
00032 template<unsigned DIM>
00033 GeneralisedLinearSpringForce<DIM>::GeneralisedLinearSpringForce()
00034    : AbstractTwoBodyInteractionForce<DIM>()
00035 {
00036 }
00037 
00038 template<unsigned DIM>
00039 double GeneralisedLinearSpringForce<DIM>::VariableSpringConstantMultiplicationFactor(unsigned nodeAGlobalIndex,
00040                                                                                      unsigned nodeBGlobalIndex,
00041                                                                                      AbstractTissue<DIM>& rTissue,
00042                                                                                      bool isCloserThanRestLength)
00043 {
00044     return 1.0;
00045 }
00046 
00047 template<unsigned DIM>
00048 GeneralisedLinearSpringForce<DIM>::~GeneralisedLinearSpringForce()
00049 {
00050 }
00051 
00052 template<unsigned DIM>
00053 c_vector<double, DIM> GeneralisedLinearSpringForce<DIM>::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex,
00054                                                                                     unsigned nodeBGlobalIndex,
00055                                                                                     AbstractTissue<DIM>& rTissue)
00056 {
00057     // Helper pointer
00058     TissueConfig* p_config = TissueConfig::Instance();
00059 
00060     // We should only ever calculate the force between two distinct nodes
00061     assert(nodeAGlobalIndex != nodeBGlobalIndex);
00062 
00063     // Get the node locations
00064     c_vector<double, DIM> node_a_location = rTissue.GetNode(nodeAGlobalIndex)->rGetLocation();
00065     c_vector<double, DIM> node_b_location = rTissue.GetNode(nodeBGlobalIndex)->rGetLocation();
00066 
00067     // Get the unit vector parallel to the line joining the two nodes
00068     c_vector<double, DIM> unit_difference;
00069     if (rTissue.HasMesh())
00070     {
00071         /*
00072          * We use the mesh method GetVectorFromAtoB() to compute the direction of the
00073          * unit vector along the line joining the two nodes, rather than simply subtract
00074          * their positions, because this method can be overloaded (e.g. to enforce a
00075          * periodic boundary in Cylindrical2dMesh).
00076          */
00077         unit_difference = (static_cast<MeshBasedTissue<DIM>*>(&rTissue))->rGetMesh().GetVectorFromAtoB(node_a_location, node_b_location);
00078     }
00079     else
00080     {
00081         unit_difference = node_b_location - node_a_location;
00082     }
00083 
00084     // Calculate the distance between the two nodes
00085     double distance_between_nodes = norm_2(unit_difference);
00086     assert(distance_between_nodes > 0);
00087     assert(!std::isnan(distance_between_nodes));
00088 
00089     unit_difference /= distance_between_nodes;
00090 
00091     /*
00092      * If mUseCutoffPoint has been set, then there is zero force between
00093      * two nodes located a distance apart greater than mUseCutoffPoint.
00094      */
00095     if (this->mUseCutoffPoint)
00096     {
00097         if (distance_between_nodes >= p_config->GetMechanicsCutOffLength())
00098         {
00099             return zero_vector<double>(DIM); // c_vector<double,DIM>() is not guaranteed to be fresh memory
00100         }
00101     }
00102 
00103     // Calculate the rest length of the spring connecting the two nodes
00104 
00105     double rest_length = 1.0;
00106 
00107     TissueCell& r_cell_A = rTissue.rGetCellUsingLocationIndex(nodeAGlobalIndex);
00108     TissueCell& r_cell_B = rTissue.rGetCellUsingLocationIndex(nodeBGlobalIndex);
00109 
00110     double ageA = r_cell_A.GetAge();
00111     double ageB = r_cell_B.GetAge();
00112 
00113     assert(!std::isnan(ageA));
00114     assert(!std::isnan(ageB));
00115 
00116     double m_duration = p_config->GetMDuration();
00117 
00118     /*
00119      * If the cells are both newly divided, then the rest length of the spring
00120      * connecting them grows linearly with time, until 1 hour after division.
00121      */
00122     if ( ageA < m_duration && ageB < m_duration )
00123     {
00124         if (rTissue.HasMesh())
00125         {
00126             MeshBasedTissue<DIM>* p_static_cast_tissue = static_cast<MeshBasedTissue<DIM>*>(&rTissue);
00127 
00128             std::set<TissueCell*> cell_pair = p_static_cast_tissue->CreateCellPair(r_cell_A, r_cell_B);
00129 
00130             if (p_static_cast_tissue->IsMarkedSpring(cell_pair))
00131             {
00132                 // Spring rest length increases from a small value to the normal rest length over 1 hour
00133                 double lambda = p_config->GetDivisionRestingSpringLength();
00134                 rest_length = lambda + (1.0 - lambda) * ageA/m_duration;
00135             }
00136             if (ageA + SimulationTime::Instance()->GetTimeStep() >= m_duration)
00137             {
00138                 // This spring is about to go out of scope
00139                 p_static_cast_tissue->UnmarkSpring(cell_pair);
00140             }
00141         }
00142         else
00143         {
00144             // Spring rest length increases from mDivisionRestingSpringLength to normal rest length, 1.0, over 1 hour
00145             double lambda = p_config->GetDivisionRestingSpringLength();
00146             rest_length = lambda + (1.0 - lambda) * ageA/m_duration;
00147         }
00148     }
00149 
00150     double a_rest_length = rest_length*0.5;
00151     double b_rest_length = a_rest_length;
00152 
00153     /*
00154      * If either of the cells has begun apoptosis, then the length of the spring
00155      * connecting them decreases linearly with time.
00156      */
00157     if (r_cell_A.HasApoptosisBegun())
00158     {
00159         double time_until_death_a = r_cell_A.GetTimeUntilDeath();
00160         a_rest_length = a_rest_length * time_until_death_a / p_config->GetApoptosisTime();
00161     }
00162     if (r_cell_B.HasApoptosisBegun())
00163     {
00164         double time_until_death_b = r_cell_B.GetTimeUntilDeath();
00165         b_rest_length = b_rest_length * time_until_death_b / p_config->GetApoptosisTime();
00166     }
00167 
00168     rest_length = a_rest_length + b_rest_length;
00169     assert(rest_length <= 1.0+1e-12);
00170 
00171     bool is_closer_than_rest_length = (distance_between_nodes - rest_length <= 0);
00172 
00173     // Although in this class the 'spring constant' is a constant parameter, in
00174     // subclasses it can depend on properties of each of the cells
00175     double multiplication_factor = VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rTissue, is_closer_than_rest_length);
00176     double spring_stiffness = p_config->GetSpringStiffness();
00177     double overlap = distance_between_nodes - rest_length;
00178 
00179     if (rTissue.HasMesh())
00180     {
00181         return multiplication_factor * spring_stiffness * unit_difference * overlap;
00182     }
00183     else
00184     {
00185         // A reasonably stable simple force law
00186         if (distance_between_nodes > rest_length)
00187         {
00188             double alpha = 5;
00189             c_vector<double, DIM> temp = spring_stiffness * unit_difference * overlap * exp(-alpha * overlap);
00190             for (unsigned i=0; i<DIM; i++)
00191             {
00192                 assert(!std::isnan(temp[i]));
00193             }
00194             return temp;
00195         }
00196         else
00197         {
00198             c_vector<double, DIM> temp = spring_stiffness * unit_difference * log(1 + overlap);
00199             for (unsigned i=0; i<DIM; i++)
00200             {
00201                 assert(!std::isnan(temp[i]));
00202             }
00203             return temp;
00204         }
00205     }
00206 }
00207 
00208 
00210 // Explicit instantiation
00212 
00213 template class GeneralisedLinearSpringForce<1>;
00214 template class GeneralisedLinearSpringForce<2>;
00215 template class GeneralisedLinearSpringForce<3>;
00216 
00217 
00218 // Serialization for Boost >= 1.36
00219 #include "SerializationExportWrapperForCpp.hpp"
00220 EXPORT_TEMPLATE_CLASS_SAME_DIMS(GeneralisedLinearSpringForce)

Generated by  doxygen 1.6.2