CryptProjectionForce.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 "CryptProjectionForce.hpp"
00030 #include "MeshBasedCellPopulation.hpp"
00031 #include "WntConcentration.hpp"
00032 
00033 CryptProjectionForce::CryptProjectionForce()
00034     : GeneralisedLinearSpringForce<2>(),
00035       mIncludeWntChemotaxis(false),
00036       mWntChemotaxisStrength(100.0)
00037 {
00038     mA = WntConcentration<2>::Instance()->GetCryptProjectionParameterA();
00039     mB = WntConcentration<2>::Instance()->GetCryptProjectionParameterB();
00040 }
00041 
00042 CryptProjectionForce::~CryptProjectionForce()
00043 {
00044 }
00045 
00046 void CryptProjectionForce::UpdateNode3dLocationMap(AbstractCellPopulation<2>& rCellPopulation)
00047 {
00048     mNode3dLocationMap.clear();
00049 
00050     c_vector<double, 2> node_location_2d;
00051     c_vector<double, 3> node_location_3d;
00052 
00053     // Only consider nodes corresponding to real cells
00054     for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
00055          cell_iter != rCellPopulation.End();
00056          ++cell_iter)
00057     {
00058         // Get node index
00059         unsigned node_index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00060 
00061         // Get 3D location
00062         node_location_2d = rCellPopulation.GetLocationOfCellCentre(*cell_iter);
00063 
00064         node_location_3d[0] = node_location_2d[0];
00065         node_location_3d[1] = node_location_2d[1];
00066         node_location_3d[2] = CalculateCryptSurfaceHeightAtPoint(node_location_2d);
00067 
00068         // Add to map
00069         mNode3dLocationMap[node_index] = node_location_3d;
00070     }
00071 }
00072 
00073 double CryptProjectionForce::GetA() const
00074 {
00075     return mA;
00076 }
00077 
00078 double CryptProjectionForce::GetB() const
00079 {
00080     return mB;
00081 }
00082 
00083 void CryptProjectionForce::SetWntChemotaxisStrength(double wntChemotaxisStrength)
00084 {
00085     assert(wntChemotaxisStrength >= 0.0);
00086     mWntChemotaxisStrength = wntChemotaxisStrength;
00087 }
00088 double CryptProjectionForce::GetWntChemotaxisStrength()
00089 {
00090     return mWntChemotaxisStrength;
00091 }
00092 
00093 void CryptProjectionForce::SetWntChemotaxis(bool includeWntChemotaxis)
00094 {
00095     mIncludeWntChemotaxis = includeWntChemotaxis;
00096 }
00097 
00098 double CryptProjectionForce::CalculateCryptSurfaceHeightAtPoint(const c_vector<double,2>& rNodeLocation)
00099 {
00100     return mA*pow(norm_2(rNodeLocation), mB); // =z_coord;
00101 }
00102 
00103 double CryptProjectionForce::CalculateCryptSurfaceDerivativeAtPoint(const c_vector<double,2>& rNodeLocation)
00104 {
00105     return mA*mB*pow(norm_2(rNodeLocation), (mB - 1.0));
00106 }
00107 
00108 c_vector<double,2> CryptProjectionForce::CalculateForceBetweenNodes(unsigned nodeAGlobalIndex, unsigned nodeBGlobalIndex, AbstractCellPopulation<2>& rCellPopulation)
00109 {
00110     assert(rCellPopulation.IsMeshBasedCellPopulation());
00111     MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
00112 
00113     // We should only ever calculate the force between two distinct nodes
00114     assert(nodeAGlobalIndex != nodeBGlobalIndex);
00115 
00116     // Get the node locations in 2D
00117     c_vector<double,2> node_a_location_2d = rCellPopulation.GetNode(nodeAGlobalIndex)->rGetLocation();
00118     c_vector<double,2> node_b_location_2d = rCellPopulation.GetNode(nodeBGlobalIndex)->rGetLocation();
00119 
00120     // "Get the unit vector parallel to the line joining the two nodes" [GeneralisedLinearSpringForce]
00121 
00122     // Create a unit vector in the direction of the 3D spring
00123     c_vector<double,3> unit_difference = mNode3dLocationMap[nodeBGlobalIndex] - mNode3dLocationMap[nodeAGlobalIndex];
00124 
00125     // Calculate the distance between the two nodes
00126     double distance_between_nodes = norm_2(unit_difference);
00127     assert(distance_between_nodes > 0);
00128     assert(!std::isnan(distance_between_nodes));
00129 
00130     unit_difference /= distance_between_nodes;
00131 
00132     // If mUseCutOffLength has been set, then there is zero force between
00133     // two nodes located a distance apart greater than mUseCutOffLength
00134     if (this->mUseCutOffLength)
00135     {
00136         if (distance_between_nodes >= mMechanicsCutOffLength)
00137         {
00138             // Return zero (2D projected) force
00139             return zero_vector<double>(2);
00140         }
00141     }
00142 
00143     // Calculate the rest length of the spring connecting the two nodes
00144 
00145     double rest_length = 1.0;
00146 
00147     CellPtr p_cell_A = rCellPopulation.GetCellUsingLocationIndex(nodeAGlobalIndex);
00148     CellPtr p_cell_B = rCellPopulation.GetCellUsingLocationIndex(nodeBGlobalIndex);
00149 
00150     double ageA = p_cell_A->GetAge();
00151     double ageB = p_cell_B->GetAge();
00152 
00153     assert(!std::isnan(ageA));
00154     assert(!std::isnan(ageB));
00155 
00156     /*
00157      * If the cells are both newly divided, then the rest length of the spring
00158      * connecting them grows linearly with time, until mMeinekeSpringGrowthDuration hour after division.
00159      */
00160     if (ageA < mMeinekeSpringGrowthDuration && ageB < mMeinekeSpringGrowthDuration)
00161     {
00162         /*
00163          * The spring rest length increases from a predefined small parameter
00164          * to a normal rest length of 1.0, over a period of one hour.
00165          */
00166         std::pair<CellPtr,CellPtr> cell_pair = p_static_cast_cell_population->CreateCellPair(p_cell_A, p_cell_B);
00167         if (p_static_cast_cell_population->IsMarkedSpring(cell_pair))
00168         {
00169             double lambda = mMeinekeDivisionRestingSpringLength;
00170             rest_length = lambda + (1.0 - lambda) * ageA/mMeinekeSpringGrowthDuration;
00171         }
00172         if (ageA+SimulationTime::Instance()->GetTimeStep() >= mMeinekeSpringGrowthDuration)
00173         {
00174             // This spring is about to go out of scope
00175             p_static_cast_cell_population->UnmarkSpring(cell_pair);
00176         }
00177     }
00178 
00179     double a_rest_length = rest_length*0.5;
00180     double b_rest_length = a_rest_length;
00181 
00182     /*
00183      * If either of the cells has begun apoptosis, then the length of the spring
00184      * connecting them decreases linearly with time.
00185      */
00186     if (p_cell_A->HasApoptosisBegun())
00187     {
00188         double time_until_death_a = p_cell_A->GetTimeUntilDeath();
00189         a_rest_length = a_rest_length * time_until_death_a / p_cell_A->GetApoptosisTime();
00190     }
00191     if (p_cell_B->HasApoptosisBegun())
00192     {
00193         double time_until_death_b = p_cell_B->GetTimeUntilDeath();
00194         b_rest_length = b_rest_length * time_until_death_b / p_cell_B->GetApoptosisTime();
00195     }
00196 
00197     rest_length = a_rest_length + b_rest_length;
00198 
00199     // Assert that the rest length does not exceed 1
00200     assert(rest_length <= 1.0+1e-12);
00201 
00202     bool is_closer_than_rest_length = true;
00203 
00204     if (distance_between_nodes - rest_length > 0)
00205     {
00206         is_closer_than_rest_length = false;
00207     }
00208 
00209     /*
00210      * Although in this class the 'spring constant' is a constant parameter, in
00211      * subclasses it can depend on properties of each of the cells.
00212      */
00213     double multiplication_factor = 1.0;
00214     multiplication_factor *= VariableSpringConstantMultiplicationFactor(nodeAGlobalIndex, nodeBGlobalIndex, rCellPopulation, is_closer_than_rest_length);
00215 
00216     // Calculate the 3D force between the two points
00217     c_vector<double,3> force_between_nodes = multiplication_factor * this->GetMeinekeSpringStiffness() * unit_difference * (distance_between_nodes - rest_length);
00218 
00219     // Calculate an outward normal unit vector to the tangent plane of the crypt surface at the 3D point corresponding to node B
00220     c_vector<double,3> outward_normal_unit_vector;
00221 
00222     double dfdr = CalculateCryptSurfaceDerivativeAtPoint(node_b_location_2d);
00223     double theta_B = atan2(node_b_location_2d[1], node_b_location_2d[0]); // use atan2 to determine the quadrant
00224     double normalization_factor = sqrt(1 + dfdr*dfdr);
00225 
00226     outward_normal_unit_vector[0] = dfdr*cos(theta_B)/normalization_factor;
00227     outward_normal_unit_vector[1] = dfdr*sin(theta_B)/normalization_factor;
00228     outward_normal_unit_vector[2] = -1.0/normalization_factor;
00229 
00230     // Calculate the projection of the force onto the plane z=0
00231     c_vector<double,2> projected_force_between_nodes_2d;
00232     double force_dot_normal = inner_prod(force_between_nodes, outward_normal_unit_vector);
00233 
00234     for (unsigned i=0; i<2; i++)
00235     {
00236         projected_force_between_nodes_2d[i] = force_between_nodes[i]
00237                                               - force_dot_normal*outward_normal_unit_vector[i]
00238                                               + force_dot_normal*outward_normal_unit_vector[2];
00239     }
00240 
00241     return projected_force_between_nodes_2d;
00242 }
00243 
00244 void CryptProjectionForce::AddForceContribution(std::vector<c_vector<double,2> >& rForces,
00245                                                 AbstractCellPopulation<2>& rCellPopulation)
00246 {
00247     // First work out the 3D location of each cell
00248     UpdateNode3dLocationMap(rCellPopulation);
00249 
00250     assert(rCellPopulation.IsMeshBasedCellPopulation());
00251     MeshBasedCellPopulation<2>* p_static_cast_cell_population = static_cast<MeshBasedCellPopulation<2>*>(&rCellPopulation);
00252 
00253     for (MeshBasedCellPopulation<2>::SpringIterator spring_iterator = p_static_cast_cell_population->SpringsBegin();
00254          spring_iterator != p_static_cast_cell_population->SpringsEnd();
00255          ++spring_iterator)
00256     {
00257         unsigned nodeA_global_index = spring_iterator.GetNodeA()->GetIndex();
00258         unsigned nodeB_global_index = spring_iterator.GetNodeB()->GetIndex();
00259 
00260         c_vector<double, 2> force = CalculateForceBetweenNodes(nodeA_global_index, nodeB_global_index, rCellPopulation);
00261 
00262         rForces[nodeB_global_index] -= force;
00263         rForces[nodeA_global_index] += force;
00264     }
00265 
00266     if (mIncludeWntChemotaxis)
00267     {
00268         assert(WntConcentration<2>::Instance()->IsWntSetUp());
00269 
00270         for (AbstractCellPopulation<2>::Iterator cell_iter = rCellPopulation.Begin();
00271              cell_iter != rCellPopulation.End();
00272              ++cell_iter)
00273         {
00274             if (cell_iter->GetCellCycleModel()->GetCellProliferativeType()==STEM)
00275             {
00276                 c_vector<double, 2> wnt_chemotactic_force = mWntChemotaxisStrength*WntConcentration<2>::Instance()->GetWntGradient(*cell_iter);
00277                 unsigned index = rCellPopulation.GetLocationIndexUsingCell(*cell_iter);
00278 
00279                 rForces[index] += wnt_chemotactic_force;
00280             }
00281         }
00282     }
00283 }
00284 
00285 void CryptProjectionForce::OutputForceParameters(out_stream& rParamsFile)
00286 {
00287     *rParamsFile <<  "\t\t\t<A>"<<  mA << "</A> \n" ;
00288     *rParamsFile <<  "\t\t\t<B>"<<  mB << "</B> \n" ;
00289     *rParamsFile <<  "\t\t\t<IncludeWntChemotaxis>"<<  mIncludeWntChemotaxis << "</IncludeWntChemotaxis> \n" ;
00290     *rParamsFile <<  "\t\t\t<WntChemotaxisStrength>"<<  mWntChemotaxisStrength << "</WntChemotaxisStrength> \n" ;
00291 
00292     // Call direct parent class
00293     GeneralisedLinearSpringForce<2>::OutputForceParameters(rParamsFile);
00294 }
00295 
00296 // Serialization for Boost >= 1.36
00297 #include "SerializationExportWrapperForCpp.hpp"
00298 CHASTE_CLASS_EXPORT(CryptProjectionForce)

Generated on Mon Nov 1 12:35:16 2010 for Chaste by  doxygen 1.5.5