Cylindrical2dVertexMesh.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 "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] > 0.5*mWidth)
00067     {
00068         vector[0] -= mWidth;
00069     }
00070     else if (vector[0] < -0.5*mWidth)
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 void Cylindrical2dVertexMesh::Scale(const double xScale, const double yScale, const double zScale)
00124 
00125 {
00126 
00127     assert(zScale==1.0);
00128 
00129     AbstractMesh<2, 2>::Scale(xScale,yScale);
00130 
00131     // Also rescale the width of the mesh (this effectively scales the domain)
00132     mWidth *=xScale;
00133 
00134 }
00135 
00136 
00137 
00138 MutableVertexMesh<2, 2>* Cylindrical2dVertexMesh::GetMeshForVtk()
00139 {
00140     unsigned num_nodes = GetNumNodes();
00141 
00142     std::vector<Node<2>*> temp_nodes(2*num_nodes);
00143     std::vector<VertexElement<2, 2>*> elements;
00144 
00145     // Create four copies of each node
00146     for (unsigned index=0; index<num_nodes; index++)
00147     {
00148         c_vector<double, 2> location = GetNode(index)->rGetLocation();
00149 
00150         // Node copy at original location
00151         Node<2>* p_node = new Node<2>(index, false, location[0], location[1]);
00152         temp_nodes[index] = p_node;
00153 
00154         // Node copy shifted right
00155         p_node = new Node<2>(num_nodes + index, false, location[0] + mWidth, location[1]);
00156         temp_nodes[num_nodes + index] = p_node;
00157     }
00158 
00159     // Iterate over elements
00160     for (VertexMesh<2,2>::VertexElementIterator elem_iter = GetElementIteratorBegin();
00161          elem_iter != GetElementIteratorEnd();
00162          ++elem_iter)
00163     {
00164         unsigned elem_index = elem_iter->GetIndex();
00165         unsigned num_nodes_in_elem = elem_iter->GetNumNodes();
00166 
00167         std::vector<Node<2>*> elem_nodes;
00168 
00169         // Compute whether the element straddles either periodic boundary
00170         bool element_straddles_left_right_boundary = false;
00171 
00172         c_vector<double, 2> this_node_location = elem_iter->GetNode(0)->rGetLocation();
00173         for (unsigned local_index=0; local_index<num_nodes_in_elem; local_index++)
00174         {
00175             c_vector<double, 2> next_node_location = elem_iter->GetNode((local_index+1)%num_nodes_in_elem)->rGetLocation();
00176             c_vector<double, 2> vector = next_node_location - this_node_location;
00177 
00178             if (fabs(vector[0]) > 0.5*mWidth)
00179             {
00180                 element_straddles_left_right_boundary = true;
00181             }
00182         }
00183 
00184         // Use the above information when duplicating the element
00185         for (unsigned local_index=0; local_index<num_nodes_in_elem; local_index++)
00186         {
00187             unsigned this_node_index = elem_iter->GetNodeGlobalIndex(local_index);
00188 
00189             // If the element straddles the left/right periodic boundary...
00190             if (element_straddles_left_right_boundary)
00191             {
00192                 // ...and this node is located to the left of the centre of the mesh...
00193                 bool node_is_right_of_centre = (elem_iter->GetNode(local_index)->rGetLocation()[0] - 0.5*mWidth > 0);
00194                 if (!node_is_right_of_centre)
00195                 {
00196                     // ...then choose the equivalent node to the right
00197                     this_node_index += num_nodes;
00198                 }
00199             }
00200 
00201             elem_nodes.push_back(temp_nodes[this_node_index]);
00202         }
00203 
00204         VertexElement<2,2>* p_element = new VertexElement<2,2>(elem_index, elem_nodes);
00205         elements.push_back(p_element);
00206     }
00207 
00208     // Now delete any nodes from the mesh for VTK that are not contained in any elements
00209     std::vector<Node<2>*> nodes;
00210     unsigned count = 0;
00211     for (unsigned index=0; index<temp_nodes.size(); index++)
00212     {
00213         unsigned num_elems_containing_this_node = temp_nodes[index]->rGetContainingElementIndices().size();
00214 
00215         if (num_elems_containing_this_node == 0)
00216         {
00217             // Avoid memory leak
00218             delete temp_nodes[index];
00219         }
00220         else
00221         {
00222             temp_nodes[index]->SetIndex(count);
00223             nodes.push_back(temp_nodes[index]);
00224             count++;
00225         }
00226     }
00227 
00228     MutableVertexMesh<2, 2>* p_mesh = new MutableVertexMesh<2,2>(nodes, elements, mCellRearrangementThreshold, mT2Threshold);
00229     return p_mesh;
00230 }
00231 
00232 // Serialization for Boost >= 1.36
00233 #include "SerializationExportWrapperForCpp.hpp"
00234 CHASTE_CLASS_EXPORT(Cylindrical2dVertexMesh)

Generated by  doxygen 1.6.2