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