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