CryptSimulationBoundaryCondition.cpp

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)
Generated on Thu Dec 22 13:00:05 2011 for Chaste by  doxygen 1.6.3