00001 /* 00002 00003 Copyright (C) University of Oxford, 2005-2011 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 "AdvectionCaUpdateRule.hpp" 00030 #include "Exception.hpp" 00031 #include "RandomNumberGenerator.hpp" 00032 00033 template<unsigned DIM> 00034 AdvectionCaUpdateRule<DIM>::AdvectionCaUpdateRule(unsigned advectionDirection, double advectionSpeed) 00035 : AbstractCaUpdateRule<DIM>(), 00036 mAdvectionDirection(advectionDirection), 00037 mAdvectionSpeed(advectionSpeed) 00038 { 00039 } 00040 00041 template<unsigned DIM> 00042 AdvectionCaUpdateRule<DIM>::AdvectionCaUpdateRule() 00043 : AbstractCaUpdateRule<DIM>() 00044 { 00045 } 00046 00047 template<unsigned DIM> 00048 AdvectionCaUpdateRule<DIM>::~AdvectionCaUpdateRule() 00049 { 00050 } 00051 00057 template<unsigned DIM> 00058 unsigned AdvectionCaUpdateRule<DIM>::GetNewLocationOfCell(unsigned currentLocationIndex, 00059 CaBasedCellPopulation<DIM>& rCellPopulation, 00060 double dt) 00061 { 00062 // This method only works in 2D at present 00063 assert(DIM == 2); 00064 00065 // Make sure we have a cell at this node 00066 if (rCellPopulation.IsEmptySite(currentLocationIndex)) 00067 { 00068 EXCEPTION("There is no cell at the current location."); 00069 } 00070 00071 double probability_of_moving = dt*mAdvectionSpeed; 00072 00073 unsigned new_location_index = currentLocationIndex; 00074 00075 if (RandomNumberGenerator::Instance()->ranf() < probability_of_moving) 00076 { 00077 unsigned flow_induced_new_index = currentLocationIndex; 00078 double width = rCellPopulation.rGetMesh().GetWidth(0); 00079 unsigned nodes_across = (unsigned)width + 1; 00080 double height = rCellPopulation.rGetMesh().GetWidth(1); 00081 unsigned nodes_up = (unsigned)height + 1; 00082 00083 // Work out whether this node lies on any edge of the mesh 00084 bool on_south_edge = (currentLocationIndex < nodes_across); 00085 bool on_north_edge = (currentLocationIndex > nodes_up*(nodes_across - 1)-1); 00086 bool on_west_edge = (currentLocationIndex%nodes_across == 0); 00087 bool on_east_edge = (currentLocationIndex%nodes_across == nodes_across - 1); 00088 00089 switch (mAdvectionDirection) 00090 { 00091 case 0: 00092 { 00093 if (!on_north_edge) 00094 { 00095 flow_induced_new_index += nodes_across; 00096 } 00097 break; 00098 } 00099 case 1: 00100 { 00101 if (!on_north_edge && !on_west_edge) 00102 { 00103 flow_induced_new_index += nodes_across - 1; 00104 } 00105 break; 00106 } 00107 case 2: 00108 { 00109 if (!on_west_edge) 00110 { 00111 flow_induced_new_index -= 1; 00112 } 00113 break; 00114 } 00115 case 3: 00116 { 00117 if (!on_south_edge && !on_west_edge) 00118 { 00119 flow_induced_new_index -= nodes_across + 1; 00120 } 00121 break; 00122 } 00123 case 4: 00124 { 00125 if (!on_south_edge) 00126 { 00127 flow_induced_new_index -= nodes_across; 00128 } 00129 break; 00130 } 00131 case 5: 00132 { 00133 if (!on_south_edge && !on_east_edge) 00134 { 00135 flow_induced_new_index -= nodes_across - 1; 00136 } 00137 break; 00138 } 00139 case 6: 00140 { 00141 if (!on_east_edge) 00142 { 00143 flow_induced_new_index += 1; 00144 } 00145 break; 00146 } 00147 case 7: 00148 { 00149 if (!on_north_edge && !on_east_edge) 00150 { 00151 flow_induced_new_index += nodes_across + 1; 00152 } 00153 break; 00154 } 00155 default: 00156 NEVER_REACHED; 00157 } 00158 00159 if (rCellPopulation.IsEmptySite(flow_induced_new_index)) 00160 { 00161 new_location_index = flow_induced_new_index; 00162 } 00163 } 00164 return new_location_index; 00165 } 00166 00167 template<unsigned DIM> 00168 unsigned AdvectionCaUpdateRule<DIM>::GetAdvectionDirection() 00169 { 00170 return mAdvectionDirection; 00171 } 00172 00173 template<unsigned DIM> 00174 double AdvectionCaUpdateRule<DIM>::GetAdvectionSpeed() 00175 { 00176 return mAdvectionSpeed; 00177 } 00178 00179 template<unsigned DIM> 00180 void AdvectionCaUpdateRule<DIM>::OutputUpdateRuleParameters(out_stream& rParamsFile) 00181 { 00182 *rParamsFile << "\t\t\t<AdvectionDirection>" << mAdvectionDirection << "</AdvectionDirection>\n"; 00183 *rParamsFile << "\t\t\t<AdvectionSpeed>" << mAdvectionSpeed << "</AdvectionSpeed>\n"; 00184 00185 // Call method on direct parent class 00186 AbstractCaUpdateRule<DIM>::OutputUpdateRuleParameters(rParamsFile); 00187 } 00188 00190 // Explicit instantiation 00192 00193 template class AdvectionCaUpdateRule<1>; 00194 template class AdvectionCaUpdateRule<2>; 00195 template class AdvectionCaUpdateRule<3>; 00196 00197 // Serialization for Boost >= 1.36 00198 #include "SerializationExportWrapperForCpp.hpp" 00199 EXPORT_TEMPLATE_CLASS_SAME_DIMS(AdvectionCaUpdateRule)