Chaste Release::3.1
SemMesh.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 "SemMesh.hpp"
00037 #include "RandomNumberGenerator.hpp"
00038 #include "UblasCustomFunctions.hpp"
00039 #include <list>
00040 
00041 template<unsigned DIM>
00042 SemMesh<DIM>::SemMesh( std::vector<Node<DIM>*> nodes,
00043                         std::vector<PottsElement<DIM>*> pottsElements)
00044 {
00045     // SEM model only defined in 2 and 3D
00046     assert(DIM > 1);
00047 
00048     // Reset member variables and clear mNodes, mElements.
00049     Clear();
00050 
00051     // Populate mNodes and mElements
00052     for (unsigned node_index=0; node_index<nodes.size(); node_index++)
00053     {
00054         Node<DIM>* p_temp_node = nodes[node_index];
00055         this->mNodes.push_back(p_temp_node);
00056     }
00057     for (unsigned elem_index=0; elem_index<pottsElements.size(); elem_index++)
00058     {
00059         PottsElement<DIM>* p_temp_element = pottsElements[elem_index];
00060         mElements.push_back(p_temp_element);
00061     }
00062 
00063     // Register elements with nodes
00064     for (unsigned index=0; index<mElements.size(); index++)
00065     {
00066         PottsElement<DIM>* p_element = mElements[index];
00067 
00068         unsigned element_index = p_element->GetIndex();
00069         unsigned num_nodes_in_element = p_element->GetNumNodes();
00070 
00071         for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
00072         {
00073             p_element->GetNode(node_index)->AddElement(element_index);
00074         }
00075     }
00076 
00077     this->mMeshChangesDuringSimulation = true;
00078 }
00079 
00080 template<unsigned DIM>
00081 SemMesh<DIM>::SemMesh()
00082 {
00083     assert(DIM > 1);
00084     this->mMeshChangesDuringSimulation = true;
00085     Clear();
00086 }
00087 
00088 template<unsigned DIM>
00089 SemMesh<DIM>::~SemMesh()
00090 {
00091     Clear();
00092 }
00093 
00094 template<unsigned DIM>
00095 unsigned SemMesh<DIM>::SolveNodeMapping(unsigned index) const
00096 {
00097     assert(index < this->mNodes.size());
00098     return index;
00099 }
00100 
00101 template<unsigned DIM>
00102 unsigned SemMesh<DIM>::SolveElementMapping(unsigned index) const
00103 {
00104     assert(index < this->mElements.size());
00105     return index;
00106 }
00107 
00108 template<unsigned DIM>
00109 unsigned SemMesh<DIM>::SolveBoundaryElementMapping(unsigned index) const
00110 {
00111     return index;
00112 }
00113 
00114 template<unsigned DIM>
00115 void SemMesh<DIM>::Clear()
00116 {
00117     // Delete elements
00118     for (unsigned i=0; i<mElements.size(); i++)
00119     {
00120         delete mElements[i];
00121     }
00122     mElements.clear();
00123 
00124     // Delete nodes
00125     for (unsigned i=0; i<this->mNodes.size(); i++)
00126     {
00127         delete this->mNodes[i];
00128     }
00129     this->mNodes.clear();
00130 
00131     mDeletedElementIndices.clear();
00132     mDeletedNodeIndices.clear();
00133 }
00134 
00135 template<unsigned DIM>
00136 void SemMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00137 {
00138     // Store numbers of nodes and elements
00139     unsigned num_nodes = rMeshReader.GetNumNodes();
00140     unsigned num_elements = rMeshReader.GetNumElements();
00141 
00142     // Reserve memory for nodes
00143     this->mNodes.reserve(num_nodes);
00144 
00145     rMeshReader.Reset();
00146 
00147     // Add nodes
00148     std::vector<double> node_data;
00149     for (unsigned i=0; i<num_nodes; i++)
00150     {
00151         node_data = rMeshReader.GetNextNode();
00152         unsigned is_boundary_node = (unsigned) node_data[DIM];
00153         node_data.pop_back();
00154         this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00155     }
00156 
00157     rMeshReader.Reset();
00158 
00159     // Reserve memory for nodes
00160     mElements.reserve(rMeshReader.GetNumElements());
00161 
00162     // Add elements
00163     for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00164     {
00165      // Get the data for this element
00166      ElementData element_data = rMeshReader.GetNextElementData();
00167 
00168      // Get the nodes owned by this element
00169      std::vector<Node<DIM>*> nodes;
00170      unsigned num_nodes_in_element = element_data.NodeIndices.size();
00171      for (unsigned j=0; j<num_nodes_in_element; j++)
00172      {
00173          assert(element_data.NodeIndices[j] < this->mNodes.size());
00174          nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00175      }
00176 
00177      // Use nodes and index to construct this element
00178      PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00179      mElements.push_back(p_element);
00180 
00181      if (rMeshReader.GetNumElementAttributes() > 0)
00182      {
00183          assert(rMeshReader.GetNumElementAttributes() == 1);
00184          unsigned attribute_value = element_data.AttributeValue;
00185          p_element->SetAttribute(attribute_value);
00186      }
00187     }
00188 }
00189 
00190 template<unsigned DIM>
00191 unsigned SemMesh<DIM>::GetNumNodes() const
00192 {
00193     return this->mNodes.size() - mDeletedNodeIndices.size();
00194 }
00195 
00196 template<unsigned DIM>
00197 unsigned SemMesh<DIM>::GetNumAllNodes() const
00198 {
00199     return this->mNodes.size();
00200 }
00201 
00202 template<unsigned DIM>
00203 unsigned SemMesh<DIM>::GetNumElements() const
00204 {
00205     return mElements.size() - mDeletedElementIndices.size();
00206 }
00207 
00208 template<unsigned DIM>
00209 unsigned SemMesh<DIM>::GetNumAllElements() const
00210 {
00211     return mElements.size();
00212 }
00213 
00214 template<unsigned DIM>
00215 PottsElement<DIM>* SemMesh<DIM>::GetElement(unsigned index) const
00216 {
00217     assert(index < mElements.size());
00218     return mElements[index];
00219 }
00220 
00221 template<unsigned DIM>
00222 void SemMesh<DIM>::ReMesh()
00223 {
00224     std::vector<unsigned> old_element_indices;
00225     std::vector< std::vector<unsigned> > old_element_node_indices;
00226     std::vector< std::vector<c_vector<double, DIM> > > old_element_node_location;
00227 
00228     // For each element either note that it was deleted, or store the information needed to re-construct it, i.e. index and nodes.
00229     for (typename std::vector<PottsElement<DIM>* >::iterator element_iterator = this->mElements.begin();
00230          element_iterator != this->mElements.end();
00231          ++element_iterator)
00232     {
00233         if ((*element_iterator)->IsDeleted())
00234         {
00235             // Marked as deleted - don't store the nodes.
00236         }
00237         else
00238         {
00239             // Store the index and node location.
00240             old_element_indices.push_back( (*element_iterator)->GetIndex() );
00241 
00242             std::vector<unsigned> local_node_indices;
00243             std::vector< c_vector<double, DIM> > local_node_locations;
00244             for (unsigned local_index=0; local_index < (*element_iterator)->GetNumNodes(); local_index++)
00245             {
00246                 Node<DIM>* p_node = (*element_iterator)->GetNode(local_index);
00247                 local_node_indices.push_back(p_node->GetIndex());
00248                 local_node_locations.push_back(p_node->rGetLocation());
00249             }
00250             old_element_node_indices.push_back(local_node_indices);
00251             old_element_node_location.push_back(local_node_locations);
00252         }
00253     }
00254 
00255     // Clear all the local information.
00256     Clear();
00257 
00258     // Reconstruct the elements
00259     for (unsigned index=0; index < old_element_indices.size(); index++)
00260     {
00261         std::vector<Node<DIM>* > new_element_nodes;
00262         for (unsigned node=0; node < old_element_node_indices[index].size(); node++)
00263         {
00264             c_vector<double, DIM> new_location = old_element_node_location[index][node];
00265             unsigned new_index = old_element_node_indices[index][node];
00266             Node<DIM>* p_new_node = new Node<DIM>(new_index, new_location);
00267             new_element_nodes.push_back(p_new_node);
00268             this->mNodes.push_back(p_new_node);
00269         }
00270 
00271         this->mElements.push_back(new PottsElement<DIM>(old_element_indices[index], new_element_nodes));
00272     }
00273 
00274     // Register elements with nodes
00275     for (unsigned index=0; index < this->mElements.size(); index++)
00276     {
00277         PottsElement<DIM>* p_element = this->mElements[index];
00278 
00279         unsigned element_index = p_element->GetIndex();
00280         unsigned num_nodes_in_element = p_element->GetNumNodes();
00281 
00282         for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++)
00283         {
00284             p_element->GetNode(node_index)->AddElement(element_index);
00285         }
00286     }
00287 }
00288 
00289 template<unsigned DIM>
00290 void SemMesh<DIM>::DeleteElement(unsigned index)
00291 {
00292     // Delete the nodes
00293     for (unsigned node_index=0; node_index<this->mElements[index]->GetNumNodes(); node_index++)
00294     {
00295         Node<DIM>* p_node = this->mElements[index]->GetNode(node_index);
00296         p_node->MarkAsDeleted();
00297         mDeletedNodeIndices.push_back(node_index);
00298     }
00299 
00300     // Mark this element as deleted; this also updates the nodes containing element indices
00301     this->mElements[index]->MarkAsDeleted();
00302     mDeletedElementIndices.push_back(index);
00303 }
00304 
00305 template<unsigned DIM>
00306 unsigned SemMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement, std::vector<Node<DIM>* > newNodes)
00307 {
00308     unsigned new_element_index = pNewElement->GetIndex();
00309 
00310     if (new_element_index == this->mElements.size())
00311     {
00312         this->mElements.push_back(pNewElement);
00313     }
00314     else
00315     {
00316         delete this->mElements[new_element_index];
00317         this->mElements[new_element_index] = pNewElement;
00318     }
00319 
00320     // Add the nodes
00321     for (unsigned index=0; index<newNodes.size(); index++)
00322     {
00323         // Set index of the node correctly
00324         newNodes[index]->SetIndex(this->mNodes.size());
00325         this->mNodes.push_back(newNodes[index]);
00326     }
00327 
00328     pNewElement->RegisterWithNodes();
00329     return pNewElement->GetIndex();
00330 }
00331 
00333 // Explicit instantiation
00335 
00336 template class SemMesh<1>;
00337 template class SemMesh<2>;
00338 template class SemMesh<3>;
00339 
00340 // Serialization for Boost >= 1.36
00341 #include "SerializationExportWrapperForCpp.hpp"
00342 EXPORT_TEMPLATE_CLASS_SAME_DIMS(SemMesh)