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
00030
00031
00032
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
00049 Clear();
00050
00051
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
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
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
00125 for (unsigned i=0; i<mElements.size(); i++)
00126 {
00127 delete mElements[i];
00128 }
00129 mElements.clear();
00130
00131
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
00141
00142
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
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 double PottsMesh<DIM>::GetVolumeOfElement(unsigned index)
00192 {
00193 PottsElement<DIM>* p_element = GetElement(index);
00194 double element_volume = (double) p_element->GetNumNodes();
00195
00196 return element_volume;
00197 }
00198
00199 template<unsigned DIM>
00200 double PottsMesh<DIM>::GetSurfaceAreaOfElement(unsigned index)
00201 {
00203 assert(DIM==2 || DIM==3);
00204
00205
00206 PottsElement<DIM>* p_element = GetElement(index);
00207
00208 double surface_area = 0.0;
00209 for (unsigned node_index=0; node_index< p_element->GetNumNodes(); node_index++)
00210 {
00211 std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_element->GetNode(node_index)->GetIndex());
00212 unsigned local_edges = 2*DIM;
00213 for (std::set<unsigned>::iterator iter = neighbouring_node_indices.begin();
00214 iter != neighbouring_node_indices.end();
00215 iter++)
00216 {
00217 std::set<unsigned> neighbouring_node_element_indices = this->mNodes[*iter]->rGetContainingElementIndices();
00218
00219 if (neighbouring_node_element_indices.size()>0 && local_edges>0)
00220 {
00221 unsigned neighbouring_node_element_index = *(neighbouring_node_element_indices.begin());
00222 if (neighbouring_node_element_index == index)
00223 {
00224 local_edges--;
00225 }
00226 }
00227 }
00228 surface_area += local_edges;
00229 }
00230 return surface_area;
00231 }
00232
00233 template<unsigned DIM>
00234 std::set<unsigned> PottsMesh<DIM>::GetMooreNeighbouringNodeIndices(unsigned nodeIndex)
00235 {
00236 return mMooreNeighbouringNodeIndices[nodeIndex];
00237 }
00238
00239 template<unsigned DIM>
00240 std::set<unsigned> PottsMesh<DIM>::GetVonNeumannNeighbouringNodeIndices(unsigned nodeIndex)
00241 {
00242 return mVonNeumannNeighbouringNodeIndices[nodeIndex];
00243 }
00244
00245 template<unsigned DIM>
00246 void PottsMesh<DIM>::DeleteElement(unsigned index)
00247 {
00248
00249 this->mElements[index]->MarkAsDeleted();
00250 mDeletedElementIndices.push_back(index);
00251 }
00252
00253 template<unsigned DIM>
00254 void PottsMesh<DIM>::DeleteNode(unsigned index)
00255 {
00256
00257 this->mNodes[index]->MarkAsDeleted();
00258
00259
00260 std::set<unsigned> containing_element_indices = this->mNodes[index]->rGetContainingElementIndices();
00261
00262 for (std::set<unsigned>::iterator iter = containing_element_indices.begin();
00263 iter != containing_element_indices.end();
00264 iter++)
00265 {
00266 assert(mElements[*iter]->GetNumNodes() > 0);
00267 if (mElements[*iter]->GetNumNodes() == 1)
00268 {
00269 DeleteElement(*iter);
00270 }
00271 else
00272 {
00273 this->mElements[*iter]->DeleteNode(this->mElements[*iter]->GetNodeLocalIndex(index));
00274 }
00275 }
00276
00277
00278 mVonNeumannNeighbouringNodeIndices[index].clear();
00279 mMooreNeighbouringNodeIndices[index].clear();
00280
00281 assert(mVonNeumannNeighbouringNodeIndices.size()==mMooreNeighbouringNodeIndices.size());
00282 for (unsigned node_index = 0;
00283 node_index < mVonNeumannNeighbouringNodeIndices.size();
00284 node_index++)
00285 {
00286
00287 mVonNeumannNeighbouringNodeIndices[node_index].erase(index);
00288 mMooreNeighbouringNodeIndices[node_index].erase(index);
00289
00290
00291 if (!this->mNodes[node_index]->IsDeleted())
00292 {
00293 assert(!mVonNeumannNeighbouringNodeIndices[node_index].empty());
00294 assert(!mMooreNeighbouringNodeIndices[node_index].empty());
00295 }
00296 }
00297
00298
00299
00300 delete this->mNodes[index];
00301 this->mNodes.erase(this->mNodes.begin()+index);
00302 unsigned num_nodes = GetNumNodes();
00303 mVonNeumannNeighbouringNodeIndices.erase(mVonNeumannNeighbouringNodeIndices.begin()+index);
00304 mMooreNeighbouringNodeIndices.erase(mMooreNeighbouringNodeIndices.begin()+index);
00305
00306 assert(mVonNeumannNeighbouringNodeIndices.size()==num_nodes);
00307 assert(mMooreNeighbouringNodeIndices.size()==num_nodes);
00308
00309 for (unsigned node_index = 0; node_index < num_nodes; node_index++)
00310 {
00311
00312 if (node_index >= index)
00313 {
00314 assert(this->mNodes[node_index]->GetIndex() == node_index+1);
00315 this->mNodes[node_index]->SetIndex(node_index);
00316 }
00317 assert(this->mNodes[node_index]->GetIndex() == node_index);
00318
00319
00320
00321 std::set<unsigned> von_neuman = mVonNeumannNeighbouringNodeIndices[node_index];
00322 mVonNeumannNeighbouringNodeIndices[node_index].clear();
00323 for (std::set<unsigned>::iterator iter = von_neuman.begin();
00324 iter != von_neuman.end();
00325 iter++)
00326 {
00327 if (*iter >= index)
00328 {
00329 mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter-1);
00330 }
00331 else
00332 {
00333 mVonNeumannNeighbouringNodeIndices[node_index].insert(*iter);
00334 }
00335 }
00336 std::set<unsigned> moore = mMooreNeighbouringNodeIndices[node_index];
00337 mMooreNeighbouringNodeIndices[node_index].clear();
00338 for (std::set<unsigned>::iterator iter = moore.begin();
00339 iter != moore.end();
00340 iter++)
00341 {
00342 if (*iter >= index)
00343 {
00344 mMooreNeighbouringNodeIndices[node_index].insert(*iter-1);
00345 }
00346 else
00347 {
00348 mMooreNeighbouringNodeIndices[node_index].insert(*iter);
00349 }
00350 }
00351 }
00352
00353 assert(mDeletedElementIndices.size() <= 1);
00354 if (mDeletedElementIndices.size() == 1)
00355 {
00356 unsigned deleted_elem_index = mDeletedElementIndices[0];
00357 delete mElements[deleted_elem_index];
00358 mElements.erase(mElements.begin()+deleted_elem_index);
00359 mDeletedElementIndices.clear();
00360
00361 for (unsigned elem_index=deleted_elem_index; elem_index<GetNumElements(); elem_index++)
00362 {
00363 mElements[elem_index]->ResetIndex(elem_index);
00364 }
00365 }
00366 }
00367
00368 template<unsigned DIM>
00369 unsigned PottsMesh<DIM>::DivideElement(PottsElement<DIM>* pElement,
00370 bool placeOriginalElementBelow)
00371 {
00373 assert(DIM==2 || DIM==3);
00374
00375
00376 unsigned num_nodes = pElement->GetNumNodes();
00377
00378 if (num_nodes < 2)
00379 {
00380 EXCEPTION("Tried to divide a Potts element with only one node. Cell dividing too often given dynamic parameters.");
00381 }
00382
00383
00384 std::vector<Node<DIM>*> nodes_elem;
00385 for (unsigned i=0; i<num_nodes; i++)
00386 {
00387 nodes_elem.push_back(pElement->GetNode(i));
00388 }
00389
00390
00391 unsigned new_element_index;
00392 if (mDeletedElementIndices.empty())
00393 {
00394 new_element_index = this->mElements.size();
00395 }
00396 else
00397 {
00398 new_element_index = mDeletedElementIndices.back();
00399 mDeletedElementIndices.pop_back();
00400 delete this->mElements[new_element_index];
00401 }
00402
00403
00404 AddElement(new PottsElement<DIM>(new_element_index, nodes_elem));
00405
00411 unsigned half_num_nodes = num_nodes/2;
00412 assert(half_num_nodes > 0);
00413 assert(half_num_nodes < num_nodes);
00414
00415
00417 double height_midpoint_1 = 0.0;
00418 double height_midpoint_2 = 0.0;
00419 unsigned counter_1 = 0;
00420 unsigned counter_2 = 0;
00421
00422 for (unsigned i=0; i<num_nodes; i++)
00423 {
00424 if (i<half_num_nodes)
00425 {
00426 height_midpoint_1 += pElement->GetNode(i)->rGetLocation()[DIM - 1];
00427 counter_1++;
00428 }
00429 else
00430 {
00431 height_midpoint_2 += pElement->GetNode(i)->rGetLocation()[DIM -1];
00432 counter_2++;
00433 }
00434 }
00435 height_midpoint_1 /= (double)counter_1;
00436 height_midpoint_2 /= (double)counter_2;
00437
00438 for (unsigned i=num_nodes; i>0; i--)
00439 {
00440 if (i-1 >= half_num_nodes)
00441 {
00442 if (height_midpoint_1 < height_midpoint_2)
00443 {
00444 if (placeOriginalElementBelow)
00445 {
00446 pElement->DeleteNode(i-1);
00447 }
00448 else
00449 {
00450 this->mElements[new_element_index]->DeleteNode(i-1);
00451 }
00452 }
00453 else
00454 {
00455 if (placeOriginalElementBelow)
00456 {
00457 this->mElements[new_element_index]->DeleteNode(i-1);
00458 }
00459 else
00460 {
00461 pElement->DeleteNode(i-1);
00462 }
00463 }
00464 }
00465 else
00466 {
00467 if (height_midpoint_1 < height_midpoint_2)
00468 {
00469 if (placeOriginalElementBelow)
00470 {
00471 this->mElements[new_element_index]->DeleteNode(i-1);
00472 }
00473 else
00474 {
00475 pElement->DeleteNode(i-1);
00476 }
00477 }
00478 else
00479 {
00480 if (placeOriginalElementBelow)
00481 {
00482 pElement->DeleteNode(i-1);
00483 }
00484 else
00485 {
00486 this->mElements[new_element_index]->DeleteNode(i-1);
00487 }
00488 }
00489 }
00490 }
00491
00492 return new_element_index;
00493 }
00494
00495 template<unsigned DIM>
00496 unsigned PottsMesh<DIM>::AddElement(PottsElement<DIM>* pNewElement)
00497 {
00498 unsigned new_element_index = pNewElement->GetIndex();
00499
00500 if (new_element_index == this->mElements.size())
00501 {
00502 this->mElements.push_back(pNewElement);
00503 }
00504 else
00505 {
00506 this->mElements[new_element_index] = pNewElement;
00507 }
00508 pNewElement->RegisterWithNodes();
00509 return pNewElement->GetIndex();
00510 }
00511
00512 template<unsigned DIM>
00513 std::set<unsigned> PottsMesh<DIM>::GetNeighbouringElementIndices(unsigned elementIndex)
00514 {
00515
00516 PottsElement<DIM>* p_element = this->GetElement(elementIndex);
00517
00518
00519 std::set<unsigned> neighbouring_element_indices;
00520
00521
00522 for (unsigned local_index=0; local_index<p_element->GetNumNodes(); local_index++)
00523 {
00524
00525 Node<DIM>* p_node = p_element->GetNode(local_index);
00526
00527
00528
00529
00530 std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_node->GetIndex());
00531
00532
00533 for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00534 neighbour_iter != neighbouring_node_indices.end();
00535 ++neighbour_iter)
00536 {
00537 std::set<unsigned> neighbouring_node_containing_elem_indices = this->GetNode(*neighbour_iter)->rGetContainingElementIndices();
00538
00539 assert(neighbouring_node_containing_elem_indices.size()<2);
00540
00541 if (neighbouring_node_containing_elem_indices.size()==1)
00542 {
00543
00544 neighbouring_element_indices.insert(*(neighbouring_node_containing_elem_indices.begin()));
00545 }
00546 }
00547 }
00548
00549
00550 neighbouring_element_indices.erase(elementIndex);
00551
00552 return neighbouring_element_indices;
00553 }
00554
00555 template<unsigned DIM>
00556 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00557 {
00558 assert(rMeshReader.HasNodePermutation() == false);
00559
00560
00561 unsigned num_nodes = rMeshReader.GetNumNodes();
00562 unsigned num_elements = rMeshReader.GetNumElements();
00563
00564
00565 this->mNodes.reserve(num_nodes);
00566
00567 rMeshReader.Reset();
00568
00569
00570 std::vector<double> node_data;
00571 for (unsigned i=0; i<num_nodes; i++)
00572 {
00573 node_data = rMeshReader.GetNextNode();
00574 unsigned is_boundary_node = (bool) node_data[DIM];
00575 node_data.pop_back();
00576 this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00577 }
00578
00579 rMeshReader.Reset();
00580
00581
00582 mElements.reserve(rMeshReader.GetNumElements());
00583
00584
00585 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00586 {
00587
00588 ElementData element_data = rMeshReader.GetNextElementData();
00589
00590
00591 std::vector<Node<DIM>*> nodes;
00592 unsigned num_nodes_in_element = element_data.NodeIndices.size();
00593 for (unsigned j=0; j<num_nodes_in_element; j++)
00594 {
00595 assert(element_data.NodeIndices[j] < this->mNodes.size());
00596 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00597 }
00598
00599
00600 PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00601 mElements.push_back(p_element);
00602
00603 if (rMeshReader.GetNumElementAttributes() > 0)
00604 {
00605 assert(rMeshReader.GetNumElementAttributes() == 1);
00606 double attribute_value = element_data.AttributeValue;
00607 p_element->SetAttribute(attribute_value);
00608 }
00609 }
00610
00611
00612 if (mVonNeumannNeighbouringNodeIndices.empty())
00613 {
00614 mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
00615 }
00616 if (mMooreNeighbouringNodeIndices.empty())
00617 {
00618 mMooreNeighbouringNodeIndices.resize(num_nodes);
00619 }
00620 }
00621
00622
00623 template class PottsMesh<1>;
00624 template class PottsMesh<2>;
00625 template class PottsMesh<3>;
00626
00627
00628 #include "SerializationExportWrapperForCpp.hpp"
00629 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)