Chaste Release::3.1
Cylindrical2dVertexMesh.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 "Cylindrical2dVertexMesh.hpp"
00037 
00038 Cylindrical2dVertexMesh::Cylindrical2dVertexMesh(double width,
00039                                                  std::vector<Node<2>*> nodes,
00040                                                  std::vector<VertexElement<2, 2>*> vertexElements,
00041                                                  double cellRearrangementThreshold,
00042                                                  double t2Threshold)
00043     : MutableVertexMesh<2,2>(nodes, vertexElements, cellRearrangementThreshold, t2Threshold),
00044       mWidth(width)
00045 {
00046     // ReMesh to remove any deleted nodes and relabel
00047     ReMesh();
00048 }
00049 
00050 Cylindrical2dVertexMesh::Cylindrical2dVertexMesh()
00051 {
00052 }
00053 
00054 Cylindrical2dVertexMesh::~Cylindrical2dVertexMesh()
00055 {
00056 }
00057 
00058 c_vector<double, 2> Cylindrical2dVertexMesh::GetVectorFromAtoB(const c_vector<double, 2>& rLocation1, const c_vector<double, 2>& rLocation2)
00059 {
00060     assert(mWidth > 0.0);
00061 
00062     c_vector<double, 2> vector = rLocation2 - rLocation1;
00063     vector[0] = fmod(vector[0], mWidth);
00064 
00065     // If the points are more than halfway around the cylinder apart, measure the other way
00066     if (vector[0] > mWidth/2.0)
00067     {
00068         vector[0] -= mWidth;
00069     }
00070     else if (vector[0] < -mWidth/2.0)
00071     {
00072         vector[0] += mWidth;
00073     }
00074     return vector;
00075 }
00076 
00077 void Cylindrical2dVertexMesh::SetNode(unsigned nodeIndex, ChastePoint<2> point)
00078 {
00079     double x_coord = point.rGetLocation()[0];
00080 
00081     // Perform a periodic movement if necessary
00082     if (x_coord >= mWidth)
00083     {
00084         // Move point to the left
00085         point.SetCoordinate(0, x_coord - mWidth);
00086     }
00087     else if (x_coord < 0.0)
00088     {
00089         // Move point to the right
00090         point.SetCoordinate(0, x_coord + mWidth);
00091     }
00092 
00093     // Update the node's location
00094     MutableVertexMesh<2,2>::SetNode(nodeIndex, point);
00095 }
00096 
00097 double Cylindrical2dVertexMesh::GetWidth(const unsigned& rDimension) const
00098 {
00099     double width = 0.0;
00100     assert(rDimension==0 || rDimension==1);
00101     if (rDimension==0)
00102     {
00103         width = mWidth;
00104     }
00105     else
00106     {
00107         width = VertexMesh<2,2>::GetWidth(rDimension);
00108     }
00109     return width;
00110 }
00111 
00112 unsigned Cylindrical2dVertexMesh::AddNode(Node<2>* pNewNode)
00113 {
00114     unsigned node_index = MutableVertexMesh<2,2>::AddNode(pNewNode);
00115 
00116     // If necessary move it to be back on the cylinder
00117     ChastePoint<2> new_node_point = pNewNode->GetPoint();
00118     SetNode(node_index, new_node_point);
00119 
00120     return node_index;
00121 }
00122 
00123 double Cylindrical2dVertexMesh::GetVolumeOfElement(unsigned index)
00124 {
00125     VertexElement<2, 2>* p_element = GetElement(index);
00126 
00127     c_vector<double, 2> first_node = p_element->GetNodeLocation(0);
00128     c_vector<double, 2> current_node;
00129     c_vector<double, 2> anticlockwise_node;
00130     c_vector<double, 2> transformed_current_node;
00131     c_vector<double, 2> transformed_anticlockwise_node;
00132 
00133     unsigned num_nodes_in_element = p_element->GetNumNodes();
00134 
00135     double element_area = 0;
00136 
00137     for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00138     {
00139         // Find locations of current node and anticlockwise node
00140         current_node = p_element->GetNodeLocation(local_index);
00141         anticlockwise_node = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
00142 
00143         /*
00144          * In order to calculate the area we map the origin to (x[0],y[0])
00145          * then use GetVectorFromAtoB() to get node cooordiantes
00146          */
00147 
00148         transformed_current_node = GetVectorFromAtoB(first_node, current_node);
00149         transformed_anticlockwise_node = GetVectorFromAtoB(first_node, anticlockwise_node);
00150 
00151         element_area += 0.5*(transformed_current_node[0]*transformed_anticlockwise_node[1]
00152                            - transformed_anticlockwise_node[0]*transformed_current_node[1]);
00153     }
00154 
00155     return element_area;
00156 }
00157 
00158 c_vector<double, 2> Cylindrical2dVertexMesh::GetCentroidOfElement(unsigned index)
00159 {
00160     VertexElement<2, 2>* p_element = GetElement(index);
00161 
00162     c_vector<double, 2> centroid;
00163     c_vector<double, 2> transformed_centroid = zero_vector<double>(2);
00164     c_vector<double, 2> first_node = p_element->GetNodeLocation(0);
00165     c_vector<double, 2> current_node_location;
00166     c_vector<double, 2> next_node_location;
00167     c_vector<double, 2> transformed_current_node;
00168     c_vector<double, 2> transformed_anticlockwise_node;
00169 
00170     double temp_centroid_x = 0;
00171     double temp_centroid_y = 0;
00172 
00173     unsigned num_nodes_in_element = p_element->GetNumNodes();
00174 
00175     for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++)
00176     {
00177         // Find locations of current node and anticlockwise node
00178         current_node_location = p_element->GetNodeLocation(local_index);
00179         next_node_location = p_element->GetNodeLocation((local_index+1)%num_nodes_in_element);
00180 
00181         /*
00182          * In order to calculate the centroid we map the origin to (x[0],y[0])
00183          * then use  GetVectorFromAtoB() to get node cooordiantes
00184          */
00185 
00186         transformed_current_node = GetVectorFromAtoB(first_node, current_node_location);
00187         transformed_anticlockwise_node = GetVectorFromAtoB(first_node, next_node_location);
00188 
00189         temp_centroid_x += (transformed_current_node[0]+transformed_anticlockwise_node[0])*(transformed_current_node[0]*transformed_anticlockwise_node[1]-transformed_current_node[1]*transformed_anticlockwise_node[0]);
00190         temp_centroid_y += (transformed_current_node[1]+transformed_anticlockwise_node[1])*(transformed_current_node[0]*transformed_anticlockwise_node[1]-transformed_current_node[1]*transformed_anticlockwise_node[0]);
00191     }
00192 
00193     double vertex_area = GetVolumeOfElement(index);
00194     double centroid_coefficient = 1.0/(6.0*vertex_area);
00195 
00196     transformed_centroid(0) = centroid_coefficient*temp_centroid_x;
00197     transformed_centroid(1) = centroid_coefficient*temp_centroid_y;
00198 
00199     centroid = transformed_centroid + first_node;
00200 
00201     return centroid;
00202 }
00203 
00204 // Serialization for Boost >= 1.36
00205 #include "SerializationExportWrapperForCpp.hpp"
00206 CHASTE_CLASS_EXPORT(Cylindrical2dVertexMesh)