Chaste Release::3.1
AdhesionPottsUpdateRule.cpp
00001 /*
00002 
00003 Copyright (c) 2005-2012, 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 "AdhesionPottsUpdateRule.hpp"
00037 
00038 template<unsigned DIM>
00039 AdhesionPottsUpdateRule<DIM>::AdhesionPottsUpdateRule()
00040     : AbstractPottsUpdateRule<DIM>(),
00041       mCellCellAdhesionEnergyParameter(0.1), // Educated guess
00042       mCellBoundaryAdhesionEnergyParameter(0.2) // Educated guess
00043 {
00044 }
00045 
00046 template<unsigned DIM>
00047 AdhesionPottsUpdateRule<DIM>::~AdhesionPottsUpdateRule()
00048 {
00049 }
00050 
00051 template<unsigned DIM>
00052 double AdhesionPottsUpdateRule<DIM>::EvaluateHamiltonianContribution(unsigned currentNodeIndex,
00053                                                                 unsigned targetNodeIndex,
00054                                                                 PottsBasedCellPopulation<DIM>& rCellPopulation)
00055 {
00056     std::set<unsigned> containing_elements = rCellPopulation.GetNode(currentNodeIndex)->rGetContainingElementIndices();
00057     std::set<unsigned> new_location_containing_elements = rCellPopulation.GetNode(targetNodeIndex)->rGetContainingElementIndices();
00058 
00059     bool current_node_contained = !containing_elements.empty();
00060     bool target_node_contained = !new_location_containing_elements.empty();
00061 
00062 
00063     // Every node must each be in at most one element
00064     assert(new_location_containing_elements.size() < 2);
00065 
00066     if (!current_node_contained && !target_node_contained)
00067     {
00068         EXCEPTION("At least one of the current node or target node must be in an element.");
00069     }
00070 
00071     if (current_node_contained && target_node_contained)
00072     {
00073         if (*(new_location_containing_elements.begin()) == *(containing_elements.begin()))
00074         {
00075             EXCEPTION("The current node and target node must not be in the same element.");
00076         }
00077     }
00078 
00079     // Iterate over nodes neighbouring the target node to work out the contact energy contribution
00080     double delta_H = 0.0;
00081     std::set<unsigned> target_neighbouring_node_indices = rCellPopulation.rGetMesh().GetVonNeumannNeighbouringNodeIndices(targetNodeIndex);
00082     for (std::set<unsigned>::iterator iter = target_neighbouring_node_indices.begin();
00083          iter != target_neighbouring_node_indices.end();
00084          ++iter)
00085     {
00086         std::set<unsigned> neighbouring_node_containing_elements = rCellPopulation.rGetMesh().GetNode(*iter)->rGetContainingElementIndices();
00087 
00088         // Every node must each be in at most one element
00089         assert(neighbouring_node_containing_elements.size() < 2);
00090 
00091         bool neighbouring_node_contained = !neighbouring_node_containing_elements.empty();
00092 
00099         if (neighbouring_node_contained && target_node_contained)
00100         {
00101             unsigned neighbour_element = (*neighbouring_node_containing_elements.begin());
00102             unsigned target_element = (*new_location_containing_elements.begin());
00103             if (target_element != neighbour_element)
00104             {
00105                 // The nodes are currently contained in different elements
00106                 delta_H -= GetCellCellAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(target_element), rCellPopulation.GetCellUsingLocationIndex(neighbour_element));
00107             }
00108         }
00109         else if (neighbouring_node_contained && !target_node_contained)
00110         {
00111             // The neighbouring node is contained in a Potts element, but the target node is not
00112             unsigned neighbour_element = (*neighbouring_node_containing_elements.begin());
00113             delta_H -= GetCellBoundaryAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(neighbour_element));
00114         }
00115         else if (!neighbouring_node_contained && target_node_contained)
00116         {
00117             // The target node is contained in a Potts element, but the neighbouring node is not
00118             unsigned target_element = (*new_location_containing_elements.begin());
00119             delta_H -= GetCellBoundaryAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(target_element));
00120         }
00121 
00128         if (neighbouring_node_contained && current_node_contained)
00129         {
00130             unsigned neighbour_element = (*neighbouring_node_containing_elements.begin());
00131             unsigned current_element = (*containing_elements.begin());
00132             if (current_element != neighbour_element)
00133             {
00134                 // The nodes are currently contained in different elements
00135                 delta_H += GetCellCellAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(current_element),rCellPopulation.GetCellUsingLocationIndex(neighbour_element));
00136             }
00137         }
00138         else if (neighbouring_node_contained && !current_node_contained)
00139         {
00140             // The neighbouring node is contained in a Potts element, but the current node is not
00141             unsigned neighbour_element = (*neighbouring_node_containing_elements.begin());
00142             delta_H += GetCellBoundaryAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(neighbour_element));
00143         }
00144         else if (!neighbouring_node_contained && current_node_contained)
00145         {
00146             // The current node is contained in a Potts element, but the neighbouring node is not
00147             unsigned current_element = (*containing_elements.begin());
00148             delta_H += GetCellBoundaryAdhesionEnergy(rCellPopulation.GetCellUsingLocationIndex(current_element));
00149         }
00150     }
00151 
00152     return delta_H;
00153 }
00154 
00155 template<unsigned DIM>
00156 double AdhesionPottsUpdateRule<DIM>::GetCellCellAdhesionEnergy(CellPtr pCellA, CellPtr pCellB)
00157 {
00158     return GetCellCellAdhesionEnergyParameter();
00159 }
00160 
00161 template<unsigned DIM>
00162 double AdhesionPottsUpdateRule<DIM>::GetCellBoundaryAdhesionEnergy(CellPtr pCell)
00163 {
00164     return GetCellBoundaryAdhesionEnergyParameter();
00165 }
00166 
00167 template<unsigned DIM>
00168 double AdhesionPottsUpdateRule<DIM>::GetCellCellAdhesionEnergyParameter()
00169 {
00170     return mCellCellAdhesionEnergyParameter;
00171 }
00172 
00173 template<unsigned DIM>
00174 double AdhesionPottsUpdateRule<DIM>::GetCellBoundaryAdhesionEnergyParameter()
00175 {
00176     return mCellBoundaryAdhesionEnergyParameter;
00177 }
00178 
00179 template<unsigned DIM>
00180 void AdhesionPottsUpdateRule<DIM>::SetCellCellAdhesionEnergyParameter(double cellCellAdhesionEnergyParameter)
00181 {
00182     mCellCellAdhesionEnergyParameter = cellCellAdhesionEnergyParameter;
00183 }
00184 
00185 template<unsigned DIM>
00186 void AdhesionPottsUpdateRule<DIM>::SetCellBoundaryAdhesionEnergyParameter(double cellBoundaryAdhesionEnergyParameter)
00187 {
00188     mCellBoundaryAdhesionEnergyParameter = cellBoundaryAdhesionEnergyParameter;
00189 }
00190 
00191 template<unsigned DIM>
00192 void AdhesionPottsUpdateRule<DIM>::OutputUpdateRuleParameters(out_stream& rParamsFile)
00193 {
00194     *rParamsFile << "\t\t\t<CellCellAdhesionEnergyParameter>" << mCellCellAdhesionEnergyParameter << "</CellCellAdhesionEnergyParameter>\n";
00195     *rParamsFile << "\t\t\t<CellBoundaryAdhesionEnergyParameter>" << mCellBoundaryAdhesionEnergyParameter << "</CellBoundaryAdhesionEnergyParameter>\n";
00196 
00197     // Call method on direct parent class
00198     AbstractPottsUpdateRule<DIM>::OutputUpdateRuleParameters(rParamsFile);
00199 }
00200 
00202 // Explicit instantiation
00204 
00205 template class AdhesionPottsUpdateRule<1>;
00206 template class AdhesionPottsUpdateRule<2>;
00207 template class AdhesionPottsUpdateRule<3>;
00208 
00209 // Serialization for Boost >= 1.36
00210 #include "SerializationExportWrapperForCpp.hpp"
00211 EXPORT_TEMPLATE_CLASS_SAME_DIMS(AdhesionPottsUpdateRule)