HeterotypicBoundaryLengthWriter.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 "HeterotypicBoundaryLengthWriter.hpp"
00037 #include "AbstractCellPopulation.hpp"
00038 #include "MeshBasedCellPopulation.hpp"
00039 #include "CaBasedCellPopulation.hpp"
00040 #include "NodeBasedCellPopulation.hpp"
00041 #include "PottsBasedCellPopulation.hpp"
00042 #include "VertexBasedCellPopulation.hpp"
00043 
00044 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00045 HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::HeterotypicBoundaryLengthWriter()
00046     : AbstractCellPopulationWriter<ELEMENT_DIM, SPACE_DIM>("heterotypicboundary.dat")
00047 {
00048 }
00049 
00050 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00051 void HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::Visit(MeshBasedCellPopulation<ELEMENT_DIM, SPACE_DIM>* pCellPopulation)
00052 {
00053     // Initialise helper variables
00054     double heterotypic_boundary_length = 0.0;
00055     double total_shared_edges_length = 0.0;
00056     double num_heterotypic_pairs = 0.0;
00057     double total_num_pairs = 0.0;
00058 
00059     // Make sure the Voronoi tessellation has been created
00061     pCellPopulation->CreateVoronoiTessellation();
00062 
00063     // Iterate over cells
00064     for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter = pCellPopulation->Begin();
00065          cell_iter != pCellPopulation->End();
00066          ++cell_iter)
00067     {
00068         // Get the location index corresponding to this cell
00069         unsigned index = pCellPopulation->GetLocationIndexUsingCell(*cell_iter);
00070 
00071         // Store whether this cell is labelled
00072         bool cell_is_labelled = cell_iter->template HasCellProperty<CellLabel>();
00073 
00074         // Get the set of neighbouring location indices
00075         std::set<unsigned> neighbour_indices = pCellPopulation->GetNeighbouringNodeIndices(index);
00076 
00077         // Iterate over these neighbours
00078         for (std::set<unsigned>::iterator neighbour_iter = neighbour_indices.begin();
00079              neighbour_iter != neighbour_indices.end();
00080              ++neighbour_iter)
00081         {
00082             // Get the length of the edge shared with this neighbour
00083             unsigned neighbour_index = *neighbour_iter;
00084             double edge_length = pCellPopulation->GetVoronoiEdgeLength(index,neighbour_index);
00085 
00086             // Ignore ghost nodes (in the case of a MeshBasedCellPopulationWithGhostNodes)
00088             if (!pCellPopulation->IsGhostNode(neighbour_index))
00089             {
00090                 total_shared_edges_length += edge_length;
00091                 total_num_pairs += 1.0;
00092 
00093                 // Store whether this neighbour is labelled
00094                 CellPtr p_neighbour_cell = pCellPopulation->GetCellUsingLocationIndex(neighbour_index);
00095                 bool neighbour_is_labelled = p_neighbour_cell->template HasCellProperty<CellLabel>();
00096 
00097                 // If this cell is labelled and its neighbour is not, or vice versa...
00098                 if (cell_is_labelled != neighbour_is_labelled)
00099                 {
00100                     // ... then increment the fractional boundary length
00101                     heterotypic_boundary_length += edge_length;
00102                     num_heterotypic_pairs += 1.0;
00103                 }
00104             }
00105         }
00106     }
00107 
00108     // We have counted each cell-cell edge twice
00109     heterotypic_boundary_length *= 0.5;
00110     total_shared_edges_length *= 0.5;
00111 
00112     // We have counted each pair of neighbouring cells twice
00113     num_heterotypic_pairs *= 0.5;
00114     total_num_pairs *= 0.5;
00115 
00116     *this->mpOutStream << heterotypic_boundary_length << "\t" << total_shared_edges_length << "\t" << num_heterotypic_pairs << "\t" << total_num_pairs;
00117 }
00118 
00119 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00120 void HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::Visit(CaBasedCellPopulation<SPACE_DIM>* pCellPopulation)
00121 {
00122 }
00123 
00124 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00125 void HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::Visit(NodeBasedCellPopulation<SPACE_DIM>* pCellPopulation)
00126 {
00127     // Make sure the cell population is updated so that mNodeNeighbours is set up
00129     pCellPopulation->Update();
00130 
00131     // Initialise helper variables
00132     double heterotypic_boundary_length = 0.0;
00133     double total_shared_edges_length = 0.0;
00134     double num_heterotypic_pairs = 0.0;
00135     double total_num_pairs = 0.0;
00136 
00137     // Loop over cells
00138     for (typename AbstractCellPopulation<SPACE_DIM>::Iterator cell_iter = pCellPopulation->Begin();
00139          cell_iter != pCellPopulation->End();
00140          ++cell_iter)
00141     {
00142         // Store whether this cell is labelled
00143         bool cell_is_labelled = cell_iter->template HasCellProperty<CellLabel>();
00144 
00145         // Store the radius of the node corresponding to this cell
00146         unsigned node_index = pCellPopulation->GetLocationIndexUsingCell(*cell_iter);
00147         double node_radius = pCellPopulation->GetNode(node_index)->GetRadius();
00148 
00149         // Get the set of neighbouring node indices
00150         std::set<unsigned> neighbour_indices = pCellPopulation->GetNeighbouringNodeIndices(node_index);
00151 
00152         if (!neighbour_indices.empty())
00153         {
00154             // Iterate over these neighbours
00155             for (std::set<unsigned>::iterator neighbour_iter = neighbour_indices.begin();
00156                  neighbour_iter != neighbour_indices.end();
00157                  ++neighbour_iter)
00158             {
00159                 // Store the radius of the node corresponding to this neighbour
00160                 double neighbour_radius = pCellPopulation->GetNode(*neighbour_iter)->GetRadius();
00161 
00162                 // Get the (approximate) length of the edge shared with this neighbour
00163                 double separation = pCellPopulation->rGetMesh().GetDistanceBetweenNodes(node_index, *neighbour_iter);
00164                 double sum_of_radii = node_radius + neighbour_radius;
00165 
00166                 // If the neighbours are close enough, then approximate their 'edge length'
00167                 if (separation < sum_of_radii)
00168                 {
00169                     // Use Heron's formula to compute the edge length
00170                     double a = node_radius;
00171                     double b = neighbour_radius;
00172                     double c = separation;
00173                     double s = 0.5*(a + b + c);
00174                     double A = sqrt(s*(s-a)*(s-b)*(s-c));
00175                     double edge_length = 4.0*A/c;
00176 
00177                     total_shared_edges_length += edge_length;
00178                     total_num_pairs += 1.0;
00179 
00180                     // Store whether this neighbour is labelled
00181                     CellPtr p_neighbour_cell = pCellPopulation->GetCellUsingLocationIndex(*neighbour_iter);
00182                     bool neighbour_is_labelled = p_neighbour_cell->template HasCellProperty<CellLabel>();
00183 
00184                     // If this cell is labelled and its neighbour is not, or vice versa...
00185                     if (cell_is_labelled != neighbour_is_labelled)
00186                     {
00187                         // ... then increment the fractional boundary length
00188                         heterotypic_boundary_length += edge_length;
00189                         num_heterotypic_pairs += 1.0;
00190                     }
00191                 }
00192             }
00193         }
00194     }
00195 
00196     // We have counted each cell-cell edge twice
00197     heterotypic_boundary_length *= 0.5;
00198     total_shared_edges_length *= 0.5;
00199 
00200     // We have counted each pair of neighbouring cells twice
00201     num_heterotypic_pairs *= 0.5;
00202     total_num_pairs *= 0.5;
00203 
00204     *this->mpOutStream << heterotypic_boundary_length << "\t" << total_shared_edges_length << "\t" << num_heterotypic_pairs << "\t" << total_num_pairs;
00205 }
00206 
00207 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00208 void HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::Visit(PottsBasedCellPopulation<SPACE_DIM>* pCellPopulation)
00209 {
00211 
00212     // Initialise helper variables
00213     double heterotypic_boundary_length = 0.0;
00214     double total_shared_edges_length = 0.0;
00215     double num_heterotypic_pairs = 0.0;
00216     double total_num_pairs = 0.0;
00217 
00218     // Iterate over cells
00219     for (typename AbstractCellPopulation<SPACE_DIM>::Iterator cell_iter = pCellPopulation->Begin();
00220          cell_iter != pCellPopulation->End();
00221          ++cell_iter)
00222     {
00223         // Store whether this cell is labelled
00224         bool cell_is_labelled = cell_iter->template HasCellProperty<CellLabel>();
00225 
00226         unsigned elem_index = pCellPopulation->GetLocationIndexUsingCell(*cell_iter);
00227         unsigned num_nodes_in_elem = pCellPopulation->rGetMesh().GetElement(elem_index)->GetNumNodes();
00228 
00229         // Iterate over nodes contained in the element corresponding to this cell
00230         for (unsigned local_index=0; local_index<num_nodes_in_elem; local_index++)
00231         {
00232             // Get this node's von Neumann neighbours (not Moore neighbours, since they must share an edge)
00233             unsigned global_index = pCellPopulation->rGetMesh().GetElement(elem_index)->GetNodeGlobalIndex(local_index);
00234             std::set<unsigned> neighbour_node_indices = pCellPopulation->rGetMesh().GetVonNeumannNeighbouringNodeIndices(global_index);
00235 
00236             // Iterate over these neighbours
00237             for (std::set<unsigned>::iterator neighbour_iter = neighbour_node_indices.begin();
00238                  neighbour_iter != neighbour_node_indices.end();
00239                  ++neighbour_iter)
00240             {
00241                 // Get the elements containing this neighbour
00242                 std::set<unsigned> neighbour_elem_indices = pCellPopulation->GetNode(*neighbour_iter)->rGetContainingElementIndices();
00243 
00244                 if (neighbour_elem_indices.size() == 1)
00245                 {
00246                     unsigned neigbour_elem_index = *(neighbour_elem_indices.begin());
00247 
00248                     if (neigbour_elem_index != elem_index)
00249                     {
00250                         // Edge is between two different elements
00251                         total_shared_edges_length += 1.0;
00252                         total_num_pairs += 1.0;
00253 
00254                         // Store whether the cell corresponding to this element index is labelled
00255                         CellPtr p_neighbour_cell = pCellPopulation->GetCellUsingLocationIndex(neigbour_elem_index);
00256                         bool neighbour_is_labelled = p_neighbour_cell->template HasCellProperty<CellLabel>();
00257 
00258                         // If this cell is labelled and its neighbour is not, or vice versa...
00259                         if (cell_is_labelled != neighbour_is_labelled)
00260                         {
00261                             // ... then increment the fractional boundary length
00262                             heterotypic_boundary_length += 1.0;
00263                             num_heterotypic_pairs += 1.0;
00264                         }
00265                     }
00266                 }
00267                 else
00268                 {
00269                     // Original node is on boundary of mesh so edge only counted once
00270                     total_shared_edges_length += 2.0;
00271                 }
00272             }
00273         }
00274     }
00275 
00276     // We have counted each cell-cell edge twice
00277     heterotypic_boundary_length *= 0.5;
00278     total_shared_edges_length *= 0.5;
00279 
00280     // We have counted each pair of neighbouring cells twice
00281     num_heterotypic_pairs *= 0.5;
00282     total_num_pairs *= 0.5;
00283 
00284     *this->mpOutStream << heterotypic_boundary_length << "\t" << total_shared_edges_length << "\t" << num_heterotypic_pairs << "\t" << total_num_pairs;
00285 }
00286 
00287 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00288 void HeterotypicBoundaryLengthWriter<ELEMENT_DIM, SPACE_DIM>::Visit(VertexBasedCellPopulation<SPACE_DIM>* pCellPopulation)
00289 {
00290     // Make sure the cell population is updated
00292     pCellPopulation->Update();
00293 
00294     // Initialise helper variables
00295     double heterotypic_boundary_length = 0.0;
00296     double total_shared_edges_length = 0.0;
00297     double num_heterotypic_pairs = 0.0;
00298     double total_num_pairs = 0.0;
00299 
00300     // Iterate over cells
00301     for (typename AbstractCellPopulation<SPACE_DIM>::Iterator cell_iter = pCellPopulation->Begin();
00302          cell_iter != pCellPopulation->End();
00303          ++cell_iter)
00304     {
00305         // Store whether this cell is labelled
00306         bool cell_is_labelled = cell_iter->template HasCellProperty<CellLabel>();
00307 
00308         // Get the set of neighbouring element indices
00309         unsigned elem_index = pCellPopulation->GetLocationIndexUsingCell(*cell_iter);
00310         std::set<unsigned> neighbour_elem_indices = pCellPopulation->rGetMesh().GetNeighbouringElementIndices(elem_index);
00311 
00312         // Iterate over these neighbours
00313         for (std::set<unsigned>::iterator neighbour_iter = neighbour_elem_indices.begin();
00314              neighbour_iter != neighbour_elem_indices.end();
00315              ++neighbour_iter)
00316         {
00317             // Get the length of the edge shared with this neighbour
00318             unsigned neighbour_index = *neighbour_iter;
00319             double edge_length = pCellPopulation->rGetMesh().GetEdgeLength(elem_index, neighbour_index);
00320 
00321             total_shared_edges_length += edge_length;
00322             total_num_pairs += 1.0;
00323 
00324             // Store whether this neighbour is labelled
00325             CellPtr p_neighbour_cell = pCellPopulation->GetCellUsingLocationIndex(*neighbour_iter);
00326             bool neighbour_is_labelled = p_neighbour_cell->template HasCellProperty<CellLabel>();
00327 
00328             // If this cell is labelled and its neighbour is not, or vice versa...
00329             if (cell_is_labelled != neighbour_is_labelled)
00330             {
00331                 // ... then increment the fractional boundary length
00332                 heterotypic_boundary_length += edge_length;
00333                 num_heterotypic_pairs += 1.0;
00334             }
00335         }
00336     }
00337 
00338     // We have counted each cell-cell edge twice
00339     heterotypic_boundary_length *= 0.5;
00340     total_shared_edges_length *= 0.5;
00341 
00342     // We have counted each pair of neighbouring cells twice
00343     num_heterotypic_pairs *= 0.5;
00344     total_num_pairs *= 0.5;
00345 
00346     *this->mpOutStream << heterotypic_boundary_length << "\t" << total_shared_edges_length << "\t" << num_heterotypic_pairs << "\t" << total_num_pairs;
00347 }
00348 
00349 // Explicit instantiation
00350 template class HeterotypicBoundaryLengthWriter<1,1>;
00351 template class HeterotypicBoundaryLengthWriter<1,2>;
00352 template class HeterotypicBoundaryLengthWriter<2,2>;
00353 template class HeterotypicBoundaryLengthWriter<1,3>;
00354 template class HeterotypicBoundaryLengthWriter<2,3>;
00355 template class HeterotypicBoundaryLengthWriter<3,3>;
00356 
00357 #include "SerializationExportWrapperForCpp.hpp"
00358 // Declare identifier for the serializer
00359 EXPORT_TEMPLATE_CLASS_ALL_DIMS(HeterotypicBoundaryLengthWriter)

Generated by  doxygen 1.6.2