VertexElement.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2011
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 #include "VertexElement.hpp"
00029 #include "RandomNumberGenerator.hpp"
00030 #include <cassert>
00031 
00032 
00033 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00034 VertexElement<ELEMENT_DIM, SPACE_DIM>::VertexElement(unsigned index,
00035                                                      const std::vector<VertexElement<ELEMENT_DIM-1,SPACE_DIM>*>& rFaces,
00036                                                      const std::vector<bool>& rOrientations,
00037                                                      const std::vector<Node<SPACE_DIM>*>& rNodes)
00038     : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes),
00039       mFaces(rFaces),
00040       mOrientations(rOrientations)
00041 {
00042     // This constructor should only be used in 3D
00043     assert(SPACE_DIM == 3);
00044 
00045     // Each face must have an associated orientation
00046     assert(mFaces.size() == mOrientations.size());
00047 
00048     if (SPACE_DIM == ELEMENT_DIM)
00049     {
00050         // Register element with nodes
00051         RegisterWithNodes();
00052     }
00053 }
00054 
00055 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00056 VertexElement<ELEMENT_DIM, SPACE_DIM>::VertexElement(unsigned index,
00057                                                      const std::vector<VertexElement<ELEMENT_DIM-1,SPACE_DIM>*>& rFaces,
00058                                                      const std::vector<bool>& rOrientations)
00059     : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index),
00060       mFaces(rFaces),
00061       mOrientations(rOrientations)
00062 {
00063     // Each face must have an associated orientation
00064     assert(mFaces.size() == mOrientations.size());
00065 
00066     // Make a set of nodes with mFaces
00067     std::set<Node<SPACE_DIM>* > nodes_set;
00068     for (unsigned face_index=0; face_index<mFaces.size(); face_index++)
00069     {
00070         for (unsigned node_index=0; node_index<mFaces[face_index]->GetNumNodes(); node_index++)
00071         {
00072             nodes_set.insert(mFaces[face_index]->GetNode(node_index));
00073         }
00074     }
00075 
00076     // Populate mNodes
00077     for (typename std::set< Node<SPACE_DIM>* >::iterator node_iter = nodes_set.begin();
00078          node_iter != nodes_set.end();
00079          ++node_iter)
00080     {
00081          this->mNodes.push_back(*node_iter);
00082     }
00083 
00084     // Register element with nodes
00085     RegisterWithNodes();
00086 }
00087 
00088 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00089 VertexElement<ELEMENT_DIM, SPACE_DIM>::VertexElement(unsigned index)
00090     : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index)
00091 {
00092 }
00093 
00094 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00095 VertexElement<ELEMENT_DIM, SPACE_DIM>::VertexElement(unsigned index,
00096                                                      const std::vector<Node<SPACE_DIM>*>& rNodes)
00097     : AbstractElement<ELEMENT_DIM, SPACE_DIM>(index, rNodes)
00098 {
00099     if (SPACE_DIM == ELEMENT_DIM)
00100     {
00101         RegisterWithNodes();
00102     }
00103 }
00104 
00105 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00106 VertexElement<ELEMENT_DIM, SPACE_DIM>::~VertexElement()
00107 {
00108 }
00109 
00110 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00111 unsigned VertexElement<ELEMENT_DIM, SPACE_DIM>::GetNumFaces() const
00112 {
00113     return mFaces.size();
00114 }
00115 
00116 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00117 void VertexElement<ELEMENT_DIM, SPACE_DIM>::RegisterWithNodes()
00118 {
00119     for (unsigned i=0; i<this->mNodes.size(); i++)
00120     {
00121         this->mNodes[i]->AddElement(this->mIndex);
00122     }
00123 }
00124 
00125 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00126 void VertexElement<ELEMENT_DIM, SPACE_DIM>::MarkAsDeleted()
00127 {
00128     // Mark element as deleted
00129     this->mIsDeleted = true;
00130 
00131     // Update nodes in the element so they know they are not contained by it
00132     for (unsigned i=0; i<this->GetNumNodes(); i++)
00133     {
00134         this->mNodes[i]->RemoveElement(this->mIndex);
00135     }
00136 }
00137 
00138 template <unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00139 void VertexElement<ELEMENT_DIM, SPACE_DIM>::ResetIndex(unsigned index)
00140 {
00141     for (unsigned i=0; i<this->GetNumNodes(); i++)
00142     {
00143        this->mNodes[i]->RemoveElement(this->mIndex);
00144     }
00145     this->mIndex = index;
00146     RegisterWithNodes();
00147 }
00148 
00149 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00150 void VertexElement<ELEMENT_DIM, SPACE_DIM>::UpdateNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00151 {
00152     assert(rIndex < this->mNodes.size());
00153 
00154     // Remove it from the node at this location
00155     this->mNodes[rIndex]->RemoveElement(this->mIndex);
00156 
00157     // Update the node at this location
00158     this->mNodes[rIndex] = pNode;
00159 
00160     // Add element to this node
00161     this->mNodes[rIndex]->AddElement(this->mIndex);
00162 }
00163 
00164 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00165 void VertexElement<ELEMENT_DIM, SPACE_DIM>::DeleteNode(const unsigned& rIndex)
00166 {
00167     assert(rIndex < this->mNodes.size());
00168 
00169     // Remove element from the node at this location
00170     this->mNodes[rIndex]->RemoveElement(this->mIndex);
00171 
00172     // Remove the node at rIndex (removes node from element)
00173     this->mNodes.erase(this->mNodes.begin() + rIndex);
00174 }
00175 
00176 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00177 void VertexElement<ELEMENT_DIM, SPACE_DIM>::AddNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00178 {
00184     if (this->mNodes.empty())
00185     {
00186         // Populate mNodes with pNode
00187         this->mNodes.push_back(pNode);
00188 
00189         // Add element to this node
00190         this->mNodes[0]->AddElement(this->mIndex);
00191     }
00192     else
00193     {
00194         assert(rIndex < this->mNodes.size());
00195 
00196         // Add pNode to rIndex+1 element of mNodes pushing the others up
00197         this->mNodes.insert(this->mNodes.begin() + rIndex+1,  pNode);
00198 
00199         // Add element to this node
00200         this->mNodes[rIndex+1]->AddElement(this->mIndex);
00201     }
00202 }
00203 
00204 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00205 void VertexElement<ELEMENT_DIM, SPACE_DIM>::AddFace(VertexElement<ELEMENT_DIM-1,SPACE_DIM>* pFace)
00206 {
00207     // Add pFace to the end of mFaces
00208     this->mFaces.push_back(pFace);
00209 
00210     // Create a set of indices of nodes currently owned by this element
00211     std::set<unsigned> node_indices;
00212     for (unsigned local_index=0; local_index<this->GetNumNodes(); local_index++)
00213     {
00214         node_indices.insert(this->GetNodeGlobalIndex(local_index));
00215     }
00216 
00217     // Loop over nodes owned by pFace
00218     unsigned end_index = this->GetNumNodes()-1;
00219     for (unsigned local_index=0; local_index<pFace->GetNumNodes(); local_index++)
00220     {
00221         // If this node is not already owned by this element...
00222         unsigned global_index = pFace->GetNodeGlobalIndex(local_index);
00223         if (node_indices.find(global_index) == node_indices.end())
00224         {
00225             // ... then add it to the element (and vice versa)
00226             this->AddNode(end_index, pFace->GetNode(local_index));
00227             end_index++;
00228         }
00229     }
00230 }
00231 
00232 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00233 unsigned VertexElement<ELEMENT_DIM, SPACE_DIM>::GetNodeLocalIndex(unsigned globalIndex) const
00234 {
00235     unsigned local_index = UINT_MAX;
00236     for (unsigned i=0; i<this->mNodes.size(); i++)
00237     {
00238         if (this->GetNodeGlobalIndex(i) == globalIndex)
00239         {
00240             local_index = i;
00241         }
00242     }
00243     return local_index;
00244 }
00245 
00246 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00247 VertexElement<ELEMENT_DIM-1,  SPACE_DIM>* VertexElement<ELEMENT_DIM, SPACE_DIM>::GetFace(unsigned index) const
00248 {
00249     assert(index < mFaces.size());
00250     return mFaces[index];
00251 }
00252 
00253 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00254 bool VertexElement<ELEMENT_DIM, SPACE_DIM>::FaceIsOrientatedClockwise(unsigned index) const
00255 {
00256     assert(index < mOrientations.size());
00257     return mOrientations[index];
00258 }
00259 
00260 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM>
00261 bool VertexElement<ELEMENT_DIM, SPACE_DIM>::IsElementOnBoundary() const
00262 {
00263     bool is_element_on_boundary = false;
00264     for (unsigned i=0; i<this->mNodes.size(); i++)
00265     {
00266         if (this->GetNode(i)->IsBoundaryNode())
00267         {
00268             is_element_on_boundary = true;
00269             break;
00270         }
00271     }
00272     return is_element_on_boundary;
00273 }
00274 
00276 //                  Specialization for 1d elements                  //
00277 //                                                                  //
00278 //                 1d elements are just edges (lines)               //
00280 
00285 template<unsigned SPACE_DIM>
00286 VertexElement<1, SPACE_DIM>::VertexElement(unsigned index, const std::vector<Node<SPACE_DIM>*>& rNodes)
00287     : AbstractElement<1, SPACE_DIM>(index, rNodes)
00288 {
00289     // Sanity checking
00290     assert(this->mNodes.size() == 2);
00291     assert(SPACE_DIM > 0);
00292 }
00293 
00294 template<unsigned SPACE_DIM>
00295 VertexElement<1, SPACE_DIM>::~VertexElement()
00296 {
00297 }
00298 
00299 template<unsigned SPACE_DIM>
00300 unsigned VertexElement<1, SPACE_DIM>::GetNumFaces() const
00301 {
00302     return 0;
00303 }
00304 
00305 template<unsigned SPACE_DIM>
00306 void VertexElement<1, SPACE_DIM>::RegisterWithNodes()
00307 {
00308     for (unsigned i=0; i<this->mNodes.size(); i++)
00309     {
00310         this->mNodes[i]->AddElement(this->mIndex);
00311     }
00312 }
00313 
00314 template<unsigned SPACE_DIM>
00315 void VertexElement<1, SPACE_DIM>::MarkAsDeleted()
00316 {
00317     // Mark element as deleted
00318     this->mIsDeleted = true;
00319 
00320     // Update nodes in the element so they know they are not contained by it
00321     for (unsigned i=0; i<this->GetNumNodes(); i++)
00322     {
00323         this->mNodes[i]->RemoveElement(this->mIndex);
00324     }
00325 }
00326 
00327 template <unsigned SPACE_DIM>
00328 void VertexElement<1, SPACE_DIM>::ResetIndex(unsigned index)
00329 {
00330     for (unsigned i=0; i<this->GetNumNodes(); i++)
00331     {
00332        this->mNodes[i]->RemoveElement(this->mIndex);
00333     }
00334     this->mIndex = index;
00335     RegisterWithNodes();
00336 }
00337 
00338 template<unsigned SPACE_DIM>
00339 void VertexElement<1, SPACE_DIM>::UpdateNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00340 {
00341     assert(rIndex < this->mNodes.size());
00342 
00343     // Remove it from the node at this location
00344     this->mNodes[rIndex]->RemoveElement(this->mIndex);
00345 
00346     // Update the node at this location
00347     this->mNodes[rIndex] = pNode;
00348 
00349     // Add element to this node
00350     this->mNodes[rIndex]->AddElement(this->mIndex);
00351 }
00352 
00353 template<unsigned SPACE_DIM>
00354 void VertexElement<1, SPACE_DIM>::DeleteNode(const unsigned& rIndex)
00355 {
00356     assert(rIndex < this->mNodes.size());
00357 
00358     // Remove element from the node at this location
00359     this->mNodes[rIndex]->RemoveElement(this->mIndex);
00360 
00361     // Remove the node at rIndex (removes node from element)
00362     this->mNodes.erase(this->mNodes.begin() + rIndex);
00363 }
00364 
00365 template<unsigned SPACE_DIM>
00366 void VertexElement<1, SPACE_DIM>::AddNode(const unsigned& rIndex, Node<SPACE_DIM>* pNode)
00367 {
00368     assert(rIndex < this->mNodes.size());
00369 
00370     // Add pNode to rIndex+1 element of mNodes pushing the others up
00371     this->mNodes.insert(this->mNodes.begin() + rIndex+1,  pNode);
00372 
00373     // Add element to this node
00374     this->mNodes[rIndex+1]->AddElement(this->mIndex);
00375 }
00376 
00377 template<unsigned SPACE_DIM>
00378 unsigned VertexElement<1, SPACE_DIM>::GetNodeLocalIndex(unsigned globalIndex) const
00379 {
00380     unsigned local_index = UINT_MAX;
00381     for (unsigned i=0; i<this->mNodes.size(); i++)
00382     {
00383         if (this->GetNodeGlobalIndex(i) == globalIndex)
00384         {
00385             local_index = i;
00386         }
00387     }
00388     return local_index;
00389 }
00390 
00391 template<unsigned SPACE_DIM>
00392 VertexElement<0, SPACE_DIM>* VertexElement<1, SPACE_DIM>::GetFace(unsigned index) const
00393 {
00394     return NULL;
00395 }
00396 
00397 template<unsigned SPACE_DIM>
00398 bool VertexElement<1, SPACE_DIM>::FaceIsOrientatedClockwise(unsigned index) const
00399 {
00400     return false;
00401 }
00402 
00403 template<unsigned SPACE_DIM>
00404 bool VertexElement<1, SPACE_DIM>::IsElementOnBoundary() const
00405 {
00406     bool is_element_on_boundary = false;
00407     for (unsigned i=0; i<this->mNodes.size(); i++)
00408     {
00409         if (this->GetNode(i)->IsBoundaryNode())
00410         {
00411             is_element_on_boundary = true;
00412             break;
00413         }
00414     }
00415     return is_element_on_boundary;
00416 }
00417 
00418 
00419 
00420 
00422 // Explicit instantiation
00424 
00425 template class VertexElement<1,1>;
00426 template class VertexElement<1,2>;
00427 template class VertexElement<1,3>;
00428 template class VertexElement<2,2>;
00429 template class VertexElement<2,3>;
00430 template class VertexElement<3,3>;
Generated on Thu Dec 22 13:00:16 2011 for Chaste by  doxygen 1.6.3