CryptSimulationBoundaryCondition.cpp

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)

Generated by  doxygen 1.6.2