Chaste Release::3.1
|
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)