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 "CryptSimulationBoundaryCondition.hpp" 00030 #include "WntConcentration.hpp" 00031 #include "AbstractCentreBasedCellPopulation.hpp" 00032 #include "RandomNumberGenerator.hpp" 00033 00034 template<unsigned DIM> 00035 CryptSimulationBoundaryCondition<DIM>::CryptSimulationBoundaryCondition(AbstractCellPopulation<DIM>* pCellPopulation) 00036 : AbstractCellPopulationBoundaryCondition<DIM>(pCellPopulation), 00037 mUseJiggledBottomCells(false) 00038 { 00039 } 00040 00041 template<unsigned DIM> 00042 void CryptSimulationBoundaryCondition<DIM>::ImposeBoundaryCondition(const std::vector< c_vector<double, DIM> >& rOldLocations) 00043 { 00044 // We only allow jiggling of bottom cells in 2D 00045 if (DIM == 1) 00046 { 00047 mUseJiggledBottomCells = false; 00048 } 00049 00050 // Check whether a WntConcentration singleton has been set up 00051 bool is_wnt_included = WntConcentration<DIM>::Instance()->IsWntSetUp(); 00052 if (!is_wnt_included) 00053 { 00054 WntConcentration<DIM>::Destroy(); 00055 } 00056 00057 // We iterate differently depending on whether we are using a centre- or vertex-based model 00058 if (dynamic_cast<AbstractCentreBasedCellPopulation<DIM>*>(this->mpCellPopulation)) 00059 { 00060 // Iterate over all nodes associated with real cells to update their positions 00061 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin(); 00062 cell_iter != this->mpCellPopulation->End(); 00063 ++cell_iter) 00064 { 00065 // Get index of node associated with cell 00066 unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter); 00067 00068 // Get pointer to this node 00069 Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index); 00070 00071 if (!is_wnt_included) 00072 { 00073 /* 00074 * If WntConcentration is not set up then stem cells must be pinned, 00075 * so we reset the location of each stem cell. 00076 */ 00077 if (cell_iter->GetCellCycleModel()->GetCellProliferativeType() == STEM) 00078 { 00079 // Get old node location 00080 c_vector<double, DIM> old_node_location = rOldLocations[node_index]; 00081 00082 // Return node to old location 00083 p_node->rGetModifiableLocation() = old_node_location; 00084 } 00085 } 00086 00087 // Any cell that has moved below the bottom of the crypt must be moved back up 00088 if (p_node->rGetLocation()[DIM-1] < 0.0) 00089 { 00090 p_node->rGetModifiableLocation()[DIM-1] = 0.0; 00091 00092 if (mUseJiggledBottomCells) 00093 { 00094 /* 00095 * Here we give the cell a push upwards so that it doesn't 00096 * get stuck on the bottom of the crypt (as per #422). 00097 * 00098 * Note that all stem cells may get moved to the same height, so 00099 * we use a random perturbation to help ensure we are not simply 00100 * faced with the same problem at a different height! 00101 */ 00102 p_node->rGetModifiableLocation()[DIM-1] = 0.05*RandomNumberGenerator::Instance()->ranf(); 00103 } 00104 } 00105 assert(p_node->rGetLocation()[DIM-1] >= 0.0); 00106 } 00107 } 00108 else 00109 { 00110 // Iterate over all nodes to update their positions 00111 for (unsigned node_index=0; node_index<this->mpCellPopulation->GetNumNodes(); node_index++) 00112 { 00113 // Get pointer to this node 00114 Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index); 00115 00116 if (!is_wnt_included) 00117 { 00118 /* 00119 * If WntConcentration is not set up then stem cells must be pinned, 00120 * so we reset the location of each node whose height was close to zero. 00121 */ 00122 double node_height = rOldLocations[node_index][DIM-1]; 00123 if (node_height < DBL_EPSILON) 00124 { 00125 // Return node to its old height, but allow it to slide left or right 00126 p_node->rGetModifiableLocation()[DIM-1] = node_height; 00127 } 00128 } 00129 00130 // Any node that has moved below the bottom of the crypt must be moved back up 00131 if (p_node->rGetLocation()[DIM-1] < 0.0) 00132 { 00133 p_node->rGetModifiableLocation()[DIM-1] = 0.0; 00134 00135 if (mUseJiggledBottomCells) 00136 { 00137 /* 00138 * Here we give the node a push upwards so that it doesn't 00139 * get stuck on the bottom of the crypt. 00140 */ 00141 p_node->rGetModifiableLocation()[DIM-1] = 0.05*RandomNumberGenerator::Instance()->ranf(); 00142 } 00143 } 00144 assert(p_node->rGetLocation()[DIM-1] >= 0.0); 00145 } 00146 } 00147 } 00148 00149 template<unsigned DIM> 00150 bool CryptSimulationBoundaryCondition<DIM>::VerifyBoundaryCondition() 00151 { 00152 bool boundary_condition_satisfied = true; 00153 00154 /* 00155 * Here we verify that the boundary condition is still satisfied by simply 00156 * checking that no cells lies below the y=0 boundary. 00157 */ 00158 for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin(); 00159 cell_iter != this->mpCellPopulation->End(); 00160 ++cell_iter) 00161 { 00162 // Get index of node associated with cell 00163 unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter); 00164 00165 // Get pointer to this node 00166 Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index); 00167 00168 // If this node lies below the y=0 boundary, break and return false 00169 if (p_node->rGetLocation()[DIM-1] < 0.0) 00170 { 00171 boundary_condition_satisfied = false; 00172 break; 00173 } 00174 } 00175 00176 return boundary_condition_satisfied; 00177 } 00178 00179 template<unsigned DIM> 00180 void CryptSimulationBoundaryCondition<DIM>::SetUseJiggledBottomCells(bool useJiggledBottomCells) 00181 { 00182 mUseJiggledBottomCells = useJiggledBottomCells; 00183 } 00184 00185 template<unsigned DIM> 00186 bool CryptSimulationBoundaryCondition<DIM>::GetUseJiggledBottomCells() 00187 { 00188 return mUseJiggledBottomCells; 00189 } 00190 00191 template<unsigned DIM> 00192 void CryptSimulationBoundaryCondition<DIM>::OutputCellPopulationBoundaryConditionParameters(out_stream& rParamsFile) 00193 { 00194 *rParamsFile << "\t\t<UseJiggledBottomCells>" << mUseJiggledBottomCells << "</UseJiggledBottomCells>\n"; 00196 // Call method on direct parent class 00197 AbstractCellPopulationBoundaryCondition<DIM>::OutputCellPopulationBoundaryConditionParameters(rParamsFile); 00198 } 00199 00201 // Explicit instantiation 00203 00204 template class CryptSimulationBoundaryCondition<1>; 00205 template class CryptSimulationBoundaryCondition<2>; 00206 template class CryptSimulationBoundaryCondition<3>; 00207 00208 // Serialization for Boost >= 1.36 00209 #include "SerializationExportWrapperForCpp.hpp" 00210 EXPORT_TEMPLATE_CLASS_SAME_DIMS(CryptSimulationBoundaryCondition)