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 "PottsMesh.hpp" 00037 #include "RandomNumberGenerator.hpp" 00038 #include "UblasCustomFunctions.hpp" 00039 #include <list> 00040 00041 00042 template<unsigned DIM> 00043 PottsMesh<DIM>::PottsMesh(std::vector<Node<DIM>*> nodes, 00044 std::vector<PottsElement<DIM>*> pottsElements, 00045 std::vector< std::set<unsigned> > vonNeumannNeighbouringNodeIndices, 00046 std::vector< std::set<unsigned> > mooreNeighbouringNodeIndices) 00047 { 00048 // Reset member variables and clear mNodes, mElements. 00049 Clear(); 00050 00051 // Verify the same size of nodes and neighbour information. 00052 if ( (vonNeumannNeighbouringNodeIndices.size() != nodes.size()) || (mooreNeighbouringNodeIndices.size() != nodes.size()) ) 00053 { 00054 EXCEPTION("Nodes and neighbour information for a potts mesh need to be the same length."); 00055 } 00056 mVonNeumannNeighbouringNodeIndices = vonNeumannNeighbouringNodeIndices; 00057 mMooreNeighbouringNodeIndices = mooreNeighbouringNodeIndices; 00058 00059 // Populate mNodes and mElements 00060 for (unsigned node_index=0; node_index<nodes.size(); node_index++) 00061 { 00062 Node<DIM>* p_temp_node = nodes[node_index]; 00063 this->mNodes.push_back(p_temp_node); 00064 } 00065 for (unsigned elem_index=0; elem_index<pottsElements.size(); elem_index++) 00066 { 00067 PottsElement<DIM>* p_temp_element = pottsElements[elem_index]; 00068 mElements.push_back(p_temp_element); 00069 } 00070 00071 // Register elements with nodes 00072 for (unsigned index=0; index<mElements.size(); index++) 00073 { 00074 PottsElement<DIM>* p_element = mElements[index]; 00075 00076 unsigned element_index = p_element->GetIndex(); 00077 unsigned num_nodes_in_element = p_element->GetNumNodes(); 00078 00079 for (unsigned node_index=0; node_index<num_nodes_in_element; node_index++) 00080 { 00081 p_element->GetNode(node_index)->AddElement(element_index); 00082 } 00083 } 00084 00085 this->mMeshChangesDuringSimulation = true; 00086 } 00087 00088 template<unsigned DIM> 00089 PottsMesh<DIM>::PottsMesh() 00090 { 00091 this->mMeshChangesDuringSimulation = true; 00092 Clear(); 00093 } 00094 00095 template<unsigned DIM> 00096 PottsMesh<DIM>::~PottsMesh() 00097 { 00098 Clear(); 00099 } 00100 00101 template<unsigned DIM> 00102 unsigned PottsMesh<DIM>::SolveNodeMapping(unsigned index) const 00103 { 00104 assert(index < this->mNodes.size()); 00105 return index; 00106 } 00107 00108 template<unsigned DIM> 00109 unsigned PottsMesh<DIM>::SolveElementMapping(unsigned index) const 00110 { 00111 assert(index < this->mElements.size()); 00112 return index; 00113 } 00114 00115 template<unsigned DIM> 00116 unsigned PottsMesh<DIM>::SolveBoundaryElementMapping(unsigned index) const 00117 { 00118 return index; 00119 } 00120 00121 template<unsigned DIM> 00122 void PottsMesh<DIM>::Clear() 00123 { 00124 // Delete elements 00125 for (unsigned i=0; i<mElements.size(); i++) 00126 { 00127 delete mElements[i]; 00128 } 00129 mElements.clear(); 00130 00131 // Delete nodes 00132 for (unsigned i=0; i<this->mNodes.size(); i++) 00133 { 00134 delete this->mNodes[i]; 00135 } 00136 this->mNodes.clear(); 00137 00138 mDeletedElementIndices.clear(); 00139 00140 // Delete neighbour info 00141 //mVonNeumannNeighbouringNodeIndices.clear(); 00142 //mMooreNeighbouringNodeIndices.clear(); 00143 } 00144 00145 template<unsigned DIM> 00146 unsigned PottsMesh<DIM>::GetNumNodes() const 00147 { 00148 return this->mNodes.size(); 00149 } 00150 00151 template<unsigned DIM> 00152 unsigned PottsMesh<DIM>::GetNumElements() const 00153 { 00154 return mElements.size() - mDeletedElementIndices.size(); 00155 } 00156 00157 template<unsigned DIM> 00158 unsigned PottsMesh<DIM>::GetNumAllElements() const 00159 { 00160 return mElements.size(); 00161 } 00162 00163 template<unsigned DIM> 00164 PottsElement<DIM>* PottsMesh<DIM>::GetElement(unsigned index) const 00165 { 00166 assert(index < mElements.size()); 00167 return mElements[index]; 00168 } 00169 00170 template<unsigned DIM> 00171 c_vector<double, DIM> PottsMesh<DIM>::GetCentroidOfElement(unsigned index) 00172 { 00173 PottsElement<DIM>* p_element = GetElement(index); 00174 unsigned num_nodes_in_element = p_element->GetNumNodes(); 00175 00177 c_vector<double, DIM> centroid = zero_vector<double>(DIM); 00178 00179 for (unsigned local_index=0; local_index<num_nodes_in_element; local_index++) 00180 { 00181 // Find location of current node and add it to the centroid 00182 centroid += p_element->GetNodeLocation(local_index); 00183 } 00184 00185 centroid /= num_nodes_in_element; 00186 00187 return centroid; 00188 } 00189 00190 template<unsigned DIM> 00191 c_vector<double, DIM> PottsMesh<DIM>::GetVectorFromAtoB(const c_vector<double, DIM>& rLocationA, const c_vector<double, DIM>& rLocationB) 00192 { 00193 c_vector<double, DIM> vector = AbstractMesh<DIM, DIM>::GetVectorFromAtoB(rLocationA, rLocationB); 00194 00195 return vector; 00196 } 00197 00198 template<unsigned DIM> 00199 double PottsMesh<DIM>::GetVolumeOfElement(unsigned index) 00200 { 00201 PottsElement<DIM>* p_element = GetElement(index); 00202 double element_volume = (double) p_element->GetNumNodes(); 00203 00204 return element_volume; 00205 } 00206 00207 template<unsigned DIM> 00208 double PottsMesh<DIM>::GetSurfaceAreaOfElement(unsigned index) 00209 { 00211 assert(DIM==2 || DIM==3); 00212 00213 // Get pointer to this element 00214 PottsElement<DIM>* p_element = GetElement(index); 00215 00216 double surface_area = 0.0; 00217 for (unsigned node_index=0; node_index< p_element->GetNumNodes(); node_index++) 00218 { 00219 std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex()); 00220 unsigned local_edges = 2*DIM; 00221 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin(); 00222 iter != neighbouring_node_indices.end(); 00223 iter++) 00224 { 00225 std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices(); 00226 00227 if (neighbouring_node_element_indices.size()>0 && local_edges>0) 00228 { 00229 unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin()); 00230 if (neighbouring_node_element_index == index) 00231 { 00232 local_edges--; 00233 } 00234 } 00235 } 00236 surface_area += local_edges; 00237 } 00238 return surface_area; 00239 } 00240 00241 template<unsigned DIM> 00242 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex) 00243 { 00244 return mMooreNeighbouringNodeIndices[nodeIndex]; 00245 } 00246 00247 template<unsigned DIM> 00248 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex) 00249 { 00250 return mVonNeumannNeighbouringNodeIndices[nodeIndex]; 00251 } 00252 00253 template<unsigned DIM> 00254 void PottsMesh<DIM>::DeleteElement(unsigned index) 00255 { 00256 // Mark this element as deleted; this also updates the nodes containing element indices 00257 this->mElements[index]->MarkAsDeleted(); 00258 mDeletedElementIndices.push_back(index); 00259 } 00260 00261 template<unsigned DIM> 00262 unsigned PottsMesh<DIM>::DivideElement(PottsElement<DIM>* pElement, 00263 bool placeOriginalElementBelow) 00264 { 00266 assert(DIM==2 || DIM==3); 00267 00268 // Store the number of nodes in the element (this changes when nodes are deleted from the element) 00269 unsigned num_nodes = pElement->GetNumNodes(); 00270 00271 if (num_nodes < 2) 00272 { 00273 EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters."); 00274 } 00275 00276 // Copy the nodes in this element 00277 std::vector<Node<DIM>*> nodes_elem; 00278 for (unsigned i=0; i<num_nodes; i++) 00279 { 00280 nodes_elem.push_back(pElement->GetNode(i)); 00281 } 00282 00283 // Get the index of the new element 00284 unsigned new_element_index; 00285 if (mDeletedElementIndices.empty()) 00286 { 00287 new_element_index = this->mElements.size(); 00288 } 00289 else 00290 { 00291 new_element_index = mDeletedElementIndices.back(); 00292 mDeletedElementIndices.pop_back(); 00293 delete this->mElements[new_element_index]; 00294 } 00295 00296 // Add the new element to the mesh 00297 AddElement(new PottsElement<DIM>(new_element_index, nodes_elem)); 00298 00304 unsigned half_num_nodes = num_nodes/2; // This will round down 00305 assert(half_num_nodes > 0); 00306 assert(half_num_nodes < num_nodes); 00307 00308 // Find lowest element 00310 double height_midpoint_1 = 0.0; 00311 double height_midpoint_2 = 0.0; 00312 unsigned counter_1 = 0; 00313 unsigned counter_2 = 0; 00314 00315 for (unsigned i=0; i<num_nodes; i++) 00316 { 00317 if (i<half_num_nodes) 00318 { 00319 height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[DIM - 1]; 00320 counter_1++; 00321 } 00322 else 00323 { 00324 height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[DIM -1]; 00325 counter_2++; 00326 } 00327 } 00328 height_midpoint_1 /= (double)counter_1; 00329 height_midpoint_2 /= (double)counter_2; 00330 00331 for (unsigned i=num_nodes; i>0; i--) 00332 { 00333 if (i-1 >= half_num_nodes) 00334 { 00335 if (height_midpoint_1 < height_midpoint_2) 00336 { 00337 if (placeOriginalElementBelow) 00338 { 00339 pElement->DeleteNode(i-1); 00340 } 00341 else 00342 { 00343 this->mElements[new_element_index]->DeleteNode(i-1); 00344 } 00345 } 00346 else 00347 { 00348 if (placeOriginalElementBelow) 00349 { 00350 this->mElements[new_element_index]->DeleteNode(i-1); 00351 } 00352 else 00353 { 00354 pElement->DeleteNode(i-1); 00355 } 00356 } 00357 } 00358 else // i-1 < half_num_nodes 00359 { 00360 if (height_midpoint_1 < height_midpoint_2) 00361 { 00362 if (placeOriginalElementBelow) 00363 { 00364 this->mElements[new_element_index]->DeleteNode(i-1); 00365 } 00366 else 00367 { 00368 pElement->DeleteNode(i-1); 00369 } 00370 } 00371 else 00372 { 00373 if (placeOriginalElementBelow) 00374 { 00375 pElement->DeleteNode(i-1); 00376 } 00377 else 00378 { 00379 this->mElements[new_element_index]->DeleteNode(i-1); 00380 } 00381 } 00382 } 00383 } 00384 00385 return new_element_index; 00386 } 00387 00388 template<unsigned DIM> 00389 unsigned PottsMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement) 00390 { 00391 unsigned new_element_index = pNewElement->GetIndex(); 00392 00393 if (new_element_index == this->mElements.size()) 00394 { 00395 this->mElements.push_back(pNewElement); 00396 } 00397 else 00398 { 00399 this->mElements[new_element_index] = pNewElement; 00400 } 00401 pNewElement->RegisterWithNodes(); 00402 return pNewElement->GetIndex(); 00403 } 00404 00405 template<unsigned DIM> 00406 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader) 00407 { 00408 // Store numbers of nodes and elements 00409 unsigned num_nodes = rMeshReader.GetNumNodes(); 00410 unsigned num_elements = rMeshReader.GetNumElements(); 00411 00412 // Reserve memory for nodes 00413 this->mNodes.reserve(num_nodes); 00414 00415 rMeshReader.Reset(); 00416 00417 // Add nodes 00418 std::vector<double> node_data; 00419 for (unsigned i=0; i<num_nodes; i++) 00420 { 00421 node_data = rMeshReader.GetNextNode(); 00422 unsigned is_boundary_node = (unsigned) node_data[DIM]; 00423 node_data.pop_back(); 00424 this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node)); 00425 } 00426 00427 rMeshReader.Reset(); 00428 00429 // Reserve memory for nodes 00430 mElements.reserve(rMeshReader.GetNumElements()); 00431 00432 // Add elements 00433 for (unsigned elem_index=0; elem_index<num_elements; elem_index++) 00434 { 00435 // Get the data for this element 00436 ElementData element_data = rMeshReader.GetNextElementData(); 00437 00438 // Get the nodes owned by this element 00439 std::vector<Node<DIM>*> nodes; 00440 unsigned num_nodes_in_element = element_data.NodeIndices.size(); 00441 for (unsigned j=0; j<num_nodes_in_element; j++) 00442 { 00443 assert(element_data.NodeIndices[j] < this->mNodes.size()); 00444 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]); 00445 } 00446 00447 // Use nodes and index to construct this element 00448 PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes); 00449 mElements.push_back(p_element); 00450 00451 if (rMeshReader.GetNumElementAttributes() > 0) 00452 { 00453 assert(rMeshReader.GetNumElementAttributes() == 1); 00454 unsigned attribute_value = element_data.AttributeValue; 00455 p_element->SetAttribute(attribute_value); 00456 } 00457 } 00458 00459 // If just using mesh reader then there is no neighbour information see #1932 00460 if (mVonNeumannNeighbouringNodeIndices.size()==0) 00461 { 00462 mVonNeumannNeighbouringNodeIndices.resize(num_nodes); 00463 } 00464 if (mMooreNeighbouringNodeIndices.size()==0) 00465 { 00466 mMooreNeighbouringNodeIndices.resize(num_nodes); 00467 } 00468 } 00469 00471 // Explicit instantiation 00473 00474 template class PottsMesh<1>; 00475 template class PottsMesh<2>; 00476 template class PottsMesh<3>; 00477 00478 // Serialization for Boost >= 1.36 00479 #include "SerializationExportWrapperForCpp.hpp" 00480 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)