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