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
00513
00514 template<unsigned DIM>
00515 std::set<unsigned> PottsMesh<DIM>::GetNeighbouringElementIndices(unsigned elementIndex)
00516 {
00517
00518 PottsElement<DIM>* p_element = this->GetElement(elementIndex);
00519
00520
00521 std::set<unsigned> neighbouring_element_indices;
00522
00523
00524 for (unsigned local_index=0; local_index<p_element->GetNumNodes(); local_index++)
00525 {
00526
00527 Node<DIM>* p_node = p_element->GetNode(local_index);
00528
00529
00530
00531
00532 std::set<unsigned> neighbouring_node_indices = GetVonNeumannNeighbouringNodeIndices(p_node->GetIndex());
00533
00534
00535 for (std::set<unsigned>::iterator neighbour_iter = neighbouring_node_indices.begin();
00536 neighbour_iter != neighbouring_node_indices.end();
00537 ++neighbour_iter)
00538 {
00539 std::set<unsigned> neighbouring_node_containing_elem_indices = this->GetNode(*neighbour_iter)->rGetContainingElementIndices();
00540
00541 assert(neighbouring_node_containing_elem_indices.size()<2);
00542
00543 if (neighbouring_node_containing_elem_indices.size()==1)
00544 {
00545
00546 neighbouring_element_indices.insert(*(neighbouring_node_containing_elem_indices.begin()));
00547 }
00548 }
00549 }
00550
00551
00552 neighbouring_element_indices.erase(elementIndex);
00553
00554 return neighbouring_element_indices;
00555 }
00556
00557 template<unsigned DIM>
00558 void PottsMesh<DIM>::ConstructFromMeshReader(AbstractMeshReader<DIM, DIM>& rMeshReader)
00559 {
00560 assert(rMeshReader.HasNodePermutation() == false);
00561
00562
00563 unsigned num_nodes = rMeshReader.GetNumNodes();
00564 unsigned num_elements = rMeshReader.GetNumElements();
00565
00566
00567 this->mNodes.reserve(num_nodes);
00568
00569 rMeshReader.Reset();
00570
00571
00572 std::vector<double> node_data;
00573 for (unsigned i=0; i<num_nodes; i++)
00574 {
00575 node_data = rMeshReader.GetNextNode();
00576 unsigned is_boundary_node = (bool) node_data[DIM];
00577 node_data.pop_back();
00578 this->mNodes.push_back(new Node<DIM>(i, node_data, is_boundary_node));
00579 }
00580
00581 rMeshReader.Reset();
00582
00583
00584 mElements.reserve(rMeshReader.GetNumElements());
00585
00586
00587 for (unsigned elem_index=0; elem_index<num_elements; elem_index++)
00588 {
00589
00590 ElementData element_data = rMeshReader.GetNextElementData();
00591
00592
00593 std::vector<Node<DIM>*> nodes;
00594 unsigned num_nodes_in_element = element_data.NodeIndices.size();
00595 for (unsigned j=0; j<num_nodes_in_element; j++)
00596 {
00597 assert(element_data.NodeIndices[j] < this->mNodes.size());
00598 nodes.push_back(this->mNodes[element_data.NodeIndices[j]]);
00599 }
00600
00601
00602 PottsElement<DIM>* p_element = new PottsElement<DIM>(elem_index, nodes);
00603 mElements.push_back(p_element);
00604
00605 if (rMeshReader.GetNumElementAttributes() > 0)
00606 {
00607 assert(rMeshReader.GetNumElementAttributes() == 1);
00608 double attribute_value = element_data.AttributeValue;
00609 p_element->SetAttribute(attribute_value);
00610 }
00611 }
00612
00613
00614 if (mVonNeumannNeighbouringNodeIndices.size()==0)
00615 {
00616 mVonNeumannNeighbouringNodeIndices.resize(num_nodes);
00617 }
00618 if (mMooreNeighbouringNodeIndices.size()==0)
00619 {
00620 mMooreNeighbouringNodeIndices.resize(num_nodes);
00621 }
00622 }
00623
00625
00627
00628 template class PottsMesh<1>;
00629 template class PottsMesh<2>;
00630 template class PottsMesh<3>;
00631
00632
00633 #include "SerializationExportWrapperForCpp.hpp"
00634 EXPORT_TEMPLATE_CLASS_SAME_DIMS(PottsMesh)