Toroidal2dVertexMesh.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 "Toroidal2dVertexMesh.hpp"
00037 
00038 Toroidal2dVertexMesh::Toroidal2dVertexMesh(double width,
00039                                            double height,
00040                                            std::vector<Node<2>*> nodes,
00041                                            std::vector<VertexElement<2, 2>*> vertexElements,
00042                                            double cellRearrangementThreshold,
00043                                            double t2Threshold)
00044     : MutableVertexMesh<2,2>(nodes, vertexElements, cellRearrangementThreshold, t2Threshold),
00045       mWidth(width),
00046       mHeight(height)
00047 {
00048     // Call ReMesh() to remove any deleted nodes and relabel
00049     ReMesh();
00050 }
00051 
00052 Toroidal2dVertexMesh::Toroidal2dVertexMesh()
00053 {
00054 }
00055 
00056 Toroidal2dVertexMesh::~Toroidal2dVertexMesh()
00057 {
00058 }
00059 
00060 c_vector<double, 2> Toroidal2dVertexMesh::GetVectorFromAtoB(const c_vector<double, 2>& rLocation1, const c_vector<double, 2>& rLocation2)
00061 {
00062     assert(mWidth > 0.0);
00063     assert(mHeight > 0.0);
00064 
00065     c_vector<double, 2> vector = rLocation2 - rLocation1;
00066     vector[0] = fmod(vector[0], mWidth);
00067     vector[1] = fmod(vector[1], mHeight);
00068 
00069     // If the points are more than halfway across the domain, measure the other way
00070     if (vector[0] > 0.5*mWidth)
00071     {
00072         vector[0] -= mWidth;
00073     }
00074     else if (vector[0] < -0.5*mWidth)
00075     {
00076         vector[0] += mWidth;
00077     }
00078 
00079     // If the points are more than halfway up the domain, measure the other way
00080     if (vector[1] > 0.5*mHeight)
00081     {
00082         vector[1] -= mHeight;
00083     }
00084     else if (vector[1] < -0.5*mHeight)
00085     {
00086         vector[1] += mHeight;
00087     }
00088     return vector;
00089 }
00090 
00091 void Toroidal2dVertexMesh::SetNode(unsigned nodeIndex, ChastePoint<2> point)
00092 {
00093     double x_coord = point.rGetLocation()[0];
00094     double y_coord = point.rGetLocation()[1];
00095 
00096     // Perform a periodic movement if necessary
00097     if (x_coord >= mWidth)
00098     {
00099         // Move point left
00100         point.SetCoordinate(0, x_coord - mWidth);
00101     }
00102     else if (x_coord < 0.0)
00103     {
00104         // Move point right
00105         point.SetCoordinate(0, x_coord + mWidth);
00106     }
00107     if (y_coord >= mHeight)
00108     {
00109         // Move point down
00110         point.SetCoordinate(1, y_coord - mHeight);
00111     }
00112     else if (y_coord < 0.0)
00113     {
00114         // Move point up
00115         point.SetCoordinate(1, y_coord + mHeight);
00116     }
00117 
00118     // Update the node's location
00119     MutableVertexMesh<2,2>::SetNode(nodeIndex, point);
00120 }
00121 
00122 double Toroidal2dVertexMesh::GetWidth(const unsigned& rDimension) const
00123 {
00124     assert(rDimension==0 || rDimension==1);
00125 
00126     double width = mWidth;
00127     if (rDimension == 1)
00128     {
00129         width = mHeight;
00130     }
00131 
00132     return width;
00133 }
00134 
00135 unsigned Toroidal2dVertexMesh::AddNode(Node<2>* pNewNode)
00136 {
00137     unsigned node_index = MutableVertexMesh<2,2>::AddNode(pNewNode);
00138 
00139     // If necessary move it to be back onto the torus
00140     ChastePoint<2> new_node_point = pNewNode->GetPoint();
00141     SetNode(node_index, new_node_point);
00142 
00143     return node_index;
00144 }
00145 
00146 MutableVertexMesh<2, 2>* Toroidal2dVertexMesh::GetMeshForVtk()
00147 {
00148     unsigned num_nodes = GetNumNodes();
00149 
00150     std::vector<Node<2>*> temp_nodes(4*num_nodes);
00151     std::vector<VertexElement<2, 2>*> elements;
00152 
00153     // Create four copies of each node
00154     for (unsigned index=0; index<num_nodes; index++)
00155     {
00156         c_vector<double, 2> location = GetNode(index)->rGetLocation();
00157 
00158         // Node copy at original location
00159         Node<2>* p_node = new Node<2>(index, false, location[0], location[1]);
00160         temp_nodes[index] = p_node;
00161 
00162         // Node copy shifted right
00163         p_node = new Node<2>(num_nodes + index, false, location[0] + mWidth, location[1]);
00164         temp_nodes[num_nodes + index] = p_node;
00165 
00166         // Node copy shifted up
00167         p_node = new Node<2>(2*num_nodes + index, false, location[0], location[1] + mHeight);
00168         temp_nodes[2*num_nodes + index] = p_node;
00169 
00170         // Node copy shifted right and up
00171         p_node = new Node<2>(3*num_nodes + index, false, location[0] + mWidth, location[1] + mHeight);
00172         temp_nodes[3*num_nodes + index] = p_node;
00173     }
00174 
00175     // Iterate over elements
00176     for (VertexMesh<2,2>::VertexElementIterator elem_iter = GetElementIteratorBegin();
00177          elem_iter != GetElementIteratorEnd();
00178          ++elem_iter)
00179     {
00180         unsigned elem_index = elem_iter->GetIndex();
00181         unsigned num_nodes_in_elem = elem_iter->GetNumNodes();
00182 
00183         std::vector<Node<2>*> elem_nodes;
00184 
00185         // Compute whether the element straddles either periodic boundary
00186         bool element_straddles_left_right_boundary = false;
00187         bool element_straddles_top_bottom_boundary = false;
00188 
00189         c_vector<double, 2> this_node_location = elem_iter->GetNode(0)->rGetLocation();
00190         for (unsigned local_index=0; local_index<num_nodes_in_elem; local_index++)
00191         {
00192             c_vector<double, 2> next_node_location = elem_iter->GetNode((local_index+1)%num_nodes_in_elem)->rGetLocation();
00193             c_vector<double, 2> vector = next_node_location - this_node_location;
00194 
00195             if (fabs(vector[0]) > 0.5*mWidth)
00196             {
00197                 element_straddles_left_right_boundary = true;
00198             }
00199             if (fabs(vector[1]) > 0.5*mHeight)
00200             {
00201                 element_straddles_top_bottom_boundary = true;
00202             }
00203         }
00204 
00205         // Use the above information when duplicating the element
00206         for (unsigned local_index=0; local_index<num_nodes_in_elem; local_index++)
00207         {
00208             unsigned this_node_index = elem_iter->GetNodeGlobalIndex(local_index);
00209 
00210             // If the element straddles the left/right periodic boundary...
00211             if (element_straddles_left_right_boundary)
00212             {
00213                 // ...and this node is located to the left of the centre of the mesh...
00214                 bool node_is_right_of_centre = (elem_iter->GetNode(local_index)->rGetLocation()[0] - 0.5*mWidth > 0);
00215                 if (!node_is_right_of_centre)
00216                 {
00217                     // ...then choose the equivalent node to the right
00218                     this_node_index += num_nodes;
00219                 }
00220             }
00221 
00222             // If the element straddles the top/bottom periodic boundary...
00223             if (element_straddles_top_bottom_boundary)
00224             {
00225                 // ...and this node is located below the centre of the mesh...
00226                 bool node_is_above_centre = (elem_iter->GetNode(local_index)->rGetLocation()[1] - 0.5*mHeight > 0);
00227                 if (!node_is_above_centre)
00228                 {
00229                     // ...then choose the equivalent node above
00230                     this_node_index += 2*num_nodes;
00231                 }
00232             }
00233 
00234             elem_nodes.push_back(temp_nodes[this_node_index]);
00235         }
00236 
00237         VertexElement<2,2>* p_element = new VertexElement<2,2>(elem_index, elem_nodes);
00238         elements.push_back(p_element);
00239     }
00240 
00241     // Now delete any nodes from the mesh for VTK that are not contained in any elements
00242     std::vector<Node<2>*> nodes;
00243     unsigned count = 0;
00244     for (unsigned index=0; index<temp_nodes.size(); index++)
00245     {
00246         unsigned num_elems_containing_this_node = temp_nodes[index]->rGetContainingElementIndices().size();
00247 
00248         if (num_elems_containing_this_node == 0)
00249         {
00250             // Avoid memory leak
00251             delete temp_nodes[index];
00252         }
00253         else
00254         {
00255             temp_nodes[index]->SetIndex(count);
00256             nodes.push_back(temp_nodes[index]);
00257             count++;
00258         }
00259     }
00260 
00261     MutableVertexMesh<2, 2>* p_mesh = new MutableVertexMesh<2,2>(nodes, elements, mCellRearrangementThreshold, mT2Threshold);
00262     return p_mesh;
00263 }
00264 
00265 // Serialization for Boost >= 1.36
00266 #include "SerializationExportWrapperForCpp.hpp"
00267 CHASTE_CLASS_EXPORT(Toroidal2dVertexMesh)

Generated by  doxygen 1.6.2