36 #include "VertexMesh.hpp"
37 #include "RandomNumberGenerator.hpp"
40 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
43 : mpDelaunayMesh(nullptr)
50 for (
unsigned node_index = 0; node_index < nodes.size(); node_index++)
53 this->
mNodes.push_back(p_temp_node);
55 for (
unsigned elem_index = 0; elem_index < vertexElements.size(); elem_index++)
58 mElements.push_back(p_temp_vertex_element);
65 std::set<unsigned> faces_counted;
68 for (
unsigned elem_index = 0; elem_index <
mElements.size(); elem_index++)
71 for (
unsigned face_index = 0; face_index <
mElements[elem_index]->GetNumFaces(); face_index++)
74 unsigned global_index = p_face->GetIndex();
77 if (faces_counted.find(global_index) == faces_counted.end())
80 faces_counted.insert(global_index);
87 for (
unsigned index = 0; index <
mElements.size(); index++)
91 unsigned element_index = p_element->
GetIndex();
92 unsigned num_nodes_in_element = p_element->
GetNumNodes();
94 for (
unsigned node_index = 0; node_index < num_nodes_in_element; node_index++)
96 p_element->
GetNode(node_index)->AddElement(element_index);
103 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
107 : mpDelaunayMesh(nullptr)
113 for (
unsigned node_index = 0; node_index < nodes.size(); node_index++)
116 this->
mNodes.push_back(p_temp_node);
119 for (
unsigned face_index = 0; face_index < faces.size(); face_index++)
121 VertexElement<ELEMENT_DIM - 1, SPACE_DIM>* p_temp_face = faces[face_index];
122 mFaces.push_back(p_temp_face);
125 for (
unsigned elem_index = 0; elem_index < vertexElements.size(); elem_index++)
128 mElements.push_back(p_temp_vertex_element);
132 for (
unsigned index = 0; index <
mElements.size(); index++)
135 for (
unsigned node_index = 0; node_index < p_temp_vertex_element->
GetNumNodes(); node_index++)
151 : mpDelaunayMesh(&rMesh)
162 this->
mNodes.reserve(num_nodes);
166 for (
unsigned elem_index = 0; elem_index < num_elements; elem_index++)
176 for (
unsigned i = 0; i < num_nodes; i++)
180 for (
unsigned local_index = 0; local_index < 3; local_index++)
182 unsigned elem_index =
mpDelaunayMesh->GetElement(i)->GetNodeGlobalIndex(local_index);
183 unsigned num_nodes_in_elem =
mElements[elem_index]->GetNumNodes();
184 unsigned end_index = num_nodes_in_elem > 0 ? num_nodes_in_elem - 1 : 0;
191 for (
unsigned elem_index = 0; elem_index <
mElements.size(); elem_index++)
198 std::vector<std::pair<double, unsigned> > index_angle_list;
199 for (
unsigned local_index = 0; local_index <
mElements[elem_index]->GetNumNodes(); local_index++)
201 c_vector<double, 2> vectorA =
mpDelaunayMesh->GetNode(elem_index)->rGetLocation();
202 c_vector<double, 2> vectorB =
mElements[elem_index]->GetNodeLocation(local_index);
203 c_vector<double, 2> centre_to_vertex =
mpDelaunayMesh->GetVectorFromAtoB(vectorA, vectorB);
205 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
206 unsigned global_index =
mElements[elem_index]->GetNodeGlobalIndex(local_index);
208 std::pair<double, unsigned> pair(angle, global_index);
209 index_angle_list.push_back(pair);
213 sort(index_angle_list.begin(), index_angle_list.end());
217 for (
unsigned count = 0; count < index_angle_list.size(); count++)
219 unsigned local_index = count > 1 ? count - 1 : 0;
220 p_new_element->
AddNode(
mNodes[index_angle_list[count].second], local_index);
241 : mpDelaunayMesh(&rMesh)
249 this->
mNodes.reserve(num_nodes);
254 std::map<unsigned, VertexElement<3, 3>*> index_element_map;
255 unsigned face_index = 0;
256 unsigned element_index = 0;
263 Node<3>* p_node_a = edge_iterator.GetNodeA();
264 Node<3>* p_node_b = edge_iterator.GetNodeB();
270 std::set<unsigned> edge_element_indices;
272 std::set_intersection(node_a_element_indices.begin(),
273 node_a_element_indices.end(),
274 node_b_element_indices.begin(),
275 node_b_element_indices.end(),
276 std::inserter(edge_element_indices, edge_element_indices.begin()));
278 c_vector<double, 3> edge_vector;
281 c_vector<double, 3> mid_edge;
282 mid_edge = edge_vector * 0.5 + p_node_a->
rGetLocation();
284 unsigned element0_index = *(edge_element_indices.begin());
286 c_vector<double, 3> basis_vector1;
287 basis_vector1 =
mNodes[element0_index]->rGetLocation() - mid_edge;
289 c_vector<double, 3> basis_vector2;
297 std::vector<std::pair<double, unsigned> > index_angle_list;
300 for (std::set<unsigned>::iterator index_iter = edge_element_indices.begin();
301 index_iter != edge_element_indices.end();
305 c_vector<double, 3> vertex_vector =
mNodes[*index_iter]->rGetLocation() - mid_edge;
307 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
308 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
310 double angle = atan2(local_vertex_dot_basis_vector2, local_vertex_dot_basis_vector1);
312 std::pair<double, unsigned> pair(angle, *index_iter);
313 index_angle_list.push_back(pair);
317 sort(index_angle_list.begin(), index_angle_list.end());
322 for (
unsigned count = 0; count < index_angle_list.size(); count++)
324 unsigned local_index = count > 1 ? count - 1 : 0;
325 p_face->AddNode(
mNodes[index_angle_list[count].second], local_index);
334 unsigned node_a_index = p_node_a->
GetIndex();
335 if (index_element_map[node_a_index])
338 index_element_map[node_a_index]->AddFace(p_face);
347 index_element_map[node_a_index] = p_element;
352 unsigned node_b_index = p_node_b->
GetIndex();
353 if (index_element_map[node_b_index])
356 index_element_map[node_b_index]->AddFace(p_face);
365 index_element_map[node_b_index] = p_element;
372 unsigned elem_count = 0;
373 for (std::map<
unsigned,
VertexElement<3, 3>*>::iterator element_iter = index_element_map.begin();
374 element_iter != index_element_map.end();
377 mElements.push_back(element_iter->second);
389 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
392 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
393 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
401 c_vector<double, SPACE_DIM + 1> circumsphere = rMesh.
GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
403 c_vector<double, SPACE_DIM> circumcentre;
404 for (
unsigned j = 0; j < SPACE_DIM; j++)
406 circumcentre(j) = circumsphere(j);
414 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
417 assert(SPACE_DIM == 2);
419 std::set<unsigned> node_indices_1;
420 for (
unsigned i = 0; i < mElements[elementIndex1]->GetNumNodes(); i++)
422 node_indices_1.insert(mElements[elementIndex1]->GetNodeGlobalIndex(i));
424 std::set<unsigned> node_indices_2;
425 for (
unsigned i = 0; i < mElements[elementIndex2]->GetNumNodes(); i++)
427 node_indices_2.insert(mElements[elementIndex2]->GetNodeGlobalIndex(i));
430 std::set<unsigned> shared_nodes;
431 std::set_intersection(node_indices_1.begin(), node_indices_1.end(),
432 node_indices_2.begin(), node_indices_2.end(),
433 std::inserter(shared_nodes, shared_nodes.begin()));
435 if (shared_nodes.size() == 1)
438 EXCEPTION(
"Elements " << elementIndex1 <<
" and " << elementIndex2 <<
" share only one node.");
440 assert(shared_nodes.size() == 2);
442 unsigned index1 = *(shared_nodes.begin());
443 unsigned index2 = *(++(shared_nodes.begin()));
445 double edge_length = this->GetDistanceBetweenNodes(index1, index2);
449 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
452 assert(SPACE_DIM == 2);
454 c_vector<double, 3> moments = CalculateMomentsOfElement(index);
456 double discriminant = sqrt((moments(0) - moments(1)) * (moments(0) - moments(1)) + 4.0 * moments(2) * moments(2));
459 double largest_eigenvalue = (moments(0) + moments(1) + discriminant) * 0.5;
460 double smallest_eigenvalue = (moments(0) + moments(1) - discriminant) * 0.5;
462 double elongation_shape_factor = sqrt(largest_eigenvalue / smallest_eigenvalue);
463 return elongation_shape_factor;
466 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
469 mpDelaunayMesh =
nullptr;
470 this->mMeshChangesDuringSimulation =
false;
474 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
480 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
483 assert(index < this->mNodes.size());
487 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
490 assert(index < this->mElements.size());
494 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
502 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
507 if (mVoronoiElementIndexMap.empty())
509 node_index = elementIndex;
513 for (std::map<unsigned, unsigned>::iterator iter = mVoronoiElementIndexMap.begin();
514 iter != mVoronoiElementIndexMap.end();
517 if (iter->second == elementIndex)
519 node_index = iter->first;
528 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
533 if (mVoronoiElementIndexMap.empty())
535 element_index = nodeIndex;
539 std::map<unsigned, unsigned>::iterator iter = mVoronoiElementIndexMap.find(nodeIndex);
541 if (iter == mVoronoiElementIndexMap.end())
543 EXCEPTION(
"This index does not correspond to a VertexElement");
547 element_index = iter->second;
551 return element_index;
554 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
557 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
563 unsigned rosette_rank = 0;
564 for (
unsigned node_idx = 0; node_idx < p_element->
GetNumNodes(); node_idx++)
566 unsigned num_elems_this_node = p_element->
GetNode(node_idx)->rGetContainingElementIndices().size();
568 if (num_elems_this_node > rosette_rank)
570 rosette_rank = num_elems_this_node;
578 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
582 for (
unsigned i = 0; i < mElements.size(); i++)
589 for (
unsigned i = 0; i < mFaces.size(); i++)
596 for (
unsigned i = 0; i < this->mNodes.size(); i++)
598 delete this->mNodes[i];
600 this->mNodes.clear();
603 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
606 return this->mNodes.size();
609 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
612 return mElements.size();
615 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
618 return mElements.size();
621 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
624 return mFaces.size();
627 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
630 assert(index < mElements.size());
631 return mElements[index];
634 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
637 assert(index < mFaces.size());
638 return mFaces[index];
641 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
647 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
658 double centroid_x = 0;
659 double centroid_y = 0;
662 double element_signed_area = 0.0;
665 c_vector<double, SPACE_DIM> first_node_location = p_element->
GetNodeLocation(0);
666 c_vector<double, SPACE_DIM> pos_1 = zero_vector<double>(SPACE_DIM);
669 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
671 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation((local_index + 1) % num_nodes);
672 c_vector<double, SPACE_DIM> pos_2 = GetVectorFromAtoB(first_node_location, next_node_location);
674 double this_x = pos_1[0];
675 double this_y = pos_1[1];
676 double next_x = pos_2[0];
677 double next_y = pos_2[1];
679 double signed_area_term = this_x * next_y - this_y * next_x;
681 centroid_x += (this_x + next_x) * signed_area_term;
682 centroid_y += (this_y + next_y) * signed_area_term;
683 element_signed_area += 0.5 * signed_area_term;
688 assert(element_signed_area != 0.0);
691 centroid = first_node_location;
692 centroid(0) += centroid_x / (6.0 * element_signed_area);
693 centroid(1) += centroid_y / (6.0 * element_signed_area);
699 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
703 centroid /= ((
double)num_nodes);
712 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
716 std::set<unsigned> neighbouring_node_indices;
719 std::set<unsigned> containing_elem_indices = this->GetNode(nodeIndex)->rGetContainingElementIndices();
722 for (std::set<unsigned>::iterator elem_iter = containing_elem_indices.begin();
723 elem_iter != containing_elem_indices.end();
727 unsigned local_index = GetElement(*elem_iter)->GetNodeLocalIndex(nodeIndex);
730 unsigned num_nodes = GetElement(*elem_iter)->GetNumNodes();
731 unsigned previous_local_index = (local_index + num_nodes - 1) % num_nodes;
732 unsigned next_local_index = (local_index + 1) % num_nodes;
735 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(previous_local_index));
736 neighbouring_node_indices.insert(GetElement(*elem_iter)->GetNodeGlobalIndex(next_local_index));
739 return neighbouring_node_indices;
742 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
749 std::set<unsigned> node_indices_in_this_element;
750 for (
unsigned local_index = 0; local_index < p_element->
GetNumNodes(); local_index++)
753 node_indices_in_this_element.insert(global_index);
757 if (node_indices_in_this_element.find(nodeIndex) == node_indices_in_this_element.end())
759 EXCEPTION(
"The given node is not contained in the given element.");
763 std::set<unsigned> neighbouring_node_indices_not_in_this_element;
766 std::set<unsigned> node_neighbours = GetNeighbouringNodeIndices(nodeIndex);
769 for (std::set<unsigned>::iterator iter = node_neighbours.begin();
770 iter != node_neighbours.end();
773 if (node_indices_in_this_element.find(*iter) == node_indices_in_this_element.end())
775 neighbouring_node_indices_not_in_this_element.insert(*iter);
779 return neighbouring_node_indices_not_in_this_element;
782 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
789 std::set<unsigned> neighbouring_element_indices;
792 for (
unsigned local_index = 0; local_index < p_element->
GetNumNodes(); local_index++)
801 std::set<unsigned> all_elements;
802 std::set_union(neighbouring_element_indices.begin(), neighbouring_element_indices.end(),
803 containing_elem_indices.begin(), containing_elem_indices.end(),
804 std::inserter(all_elements, all_elements.begin()));
807 neighbouring_element_indices = all_elements;
811 neighbouring_element_indices.erase(elementIndex);
813 return neighbouring_element_indices;
816 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
827 EXCEPTION(
"VertexMesh<1,1>::ConstructFromMeshReader() is not implemented");
835 EXCEPTION(
"VertexMesh<1,2>::ConstructFromMeshReader() is not implemented");
843 EXCEPTION(
"VertexMesh<1,3>::ConstructFromMeshReader() is not implemented");
851 EXCEPTION(
"VertexMesh<2,3>::ConstructFromMeshReader() is not implemented");
865 this->
mNodes.reserve(num_nodes);
870 std::vector<double> node_data;
871 for (
unsigned i = 0; i < num_nodes; i++)
874 unsigned is_boundary_node = (
bool)node_data[2];
875 node_data.pop_back();
876 this->
mNodes.push_back(
new Node<2>(i, node_data, is_boundary_node));
885 for (
unsigned elem_index = 0; elem_index < num_elements; elem_index++)
891 std::vector<Node<2>*> nodes;
892 unsigned num_nodes_in_element = element_data.
NodeIndices.size();
893 for (
unsigned j = 0; j < num_nodes_in_element; j++)
895 assert(element_data.
NodeIndices[j] < this->mNodes.size());
924 this->mNodes.reserve(num_nodes);
929 std::vector<double> node_data;
930 for (
unsigned i = 0; i < num_nodes; i++)
933 unsigned is_boundary_node = (
bool)node_data[3];
934 node_data.pop_back();
935 this->mNodes.push_back(
new Node<3>(i, node_data, is_boundary_node));
944 std::set<unsigned> faces_counted;
947 for (
unsigned elem_index = 0; elem_index < num_elements; elem_index++)
951 assert(dynamic_cast<VERTEX_MESH_READER*>(&rMeshReader) !=
nullptr);
954 VertexElementData element_data =
static_cast<VERTEX_MESH_READER*
>(&rMeshReader)->GetNextElementDataWithFaces();
957 std::vector<Node<3>*> nodes;
958 unsigned num_nodes_in_element = element_data.
NodeIndices.size();
959 for (
unsigned j = 0; j < num_nodes_in_element; j++)
961 assert(element_data.
NodeIndices[j] < this->mNodes.size());
962 nodes.push_back(this->mNodes[element_data.
NodeIndices[j]]);
966 std::vector<VertexElement<2, 3>*> faces;
967 unsigned num_faces_in_element = element_data.
Faces.size();
968 for (
unsigned i = 0; i < num_faces_in_element; i++)
977 std::vector<
Node<3>*> nodes_in_face;
978 unsigned num_nodes_in_face = face_data.
NodeIndices.size();
979 for (
unsigned j = 0; j < num_nodes_in_face; j++)
981 assert(face_data.
NodeIndices[j] < this->mNodes.size());
982 nodes_in_face.push_back(this->mNodes[face_data.
NodeIndices[j]]);
986 if (faces_counted.find(face_index) == faces_counted.end())
990 mFaces.push_back(p_face);
991 faces_counted.insert(face_index);
992 faces.push_back(p_face);
997 bool face_added =
false;
998 for (
unsigned k = 0; k < mFaces.size(); k++)
1000 if (mFaces[k]->GetIndex() == face_index)
1002 faces.push_back(mFaces[k]);
1008 assert(face_added ==
true);
1013 std::vector<bool> orientations = std::vector<bool>(num_faces_in_element,
true);
1017 mElements.push_back(p_element);
1023 p_element->SetAttribute(attribute_value);
1028 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1030 const c_vector<double, SPACE_DIM>& rLocationA,
const c_vector<double, SPACE_DIM>& rLocationB)
1032 c_vector<double, SPACE_DIM> vector;
1035 vector = mpDelaunayMesh->GetVectorFromAtoB(rLocationA, rLocationB);
1044 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1047 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
1052 double element_volume = 0.0;
1056 c_vector<double, SPACE_DIM> first_node_location = p_element->
GetNodeLocation(0);
1057 c_vector<double, SPACE_DIM> pos_1 = zero_vector<double>(SPACE_DIM);
1060 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
1062 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation((local_index + 1) % num_nodes);
1063 c_vector<double, SPACE_DIM> pos_2 = GetVectorFromAtoB(first_node_location, next_node_location);
1065 double this_x = pos_1[0];
1066 double this_y = pos_1[1];
1067 double next_x = pos_2[0];
1068 double next_y = pos_2[1];
1070 element_volume += 0.5 * (this_x * next_y - next_x * this_y);
1078 c_vector<double, SPACE_DIM> pyramid_apex = p_element->
GetNodeLocation(0);
1079 for (
unsigned face_index = 0; face_index < p_element->
GetNumFaces(); face_index++)
1085 c_vector<double, SPACE_DIM> unit_normal;
1086 double face_area = CalculateUnitNormalToFaceWithArea(p_face, unit_normal);
1089 c_vector<double, SPACE_DIM> base_to_apex = GetVectorFromAtoB(p_face->GetNodeLocation(0), pyramid_apex);
1090 double perpendicular_distance = fabs(inner_prod(base_to_apex, unit_normal));
1093 element_volume += face_area * perpendicular_distance / 3;
1098 return fabs(element_volume);
1101 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1104 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
1109 double surface_area = 0.0;
1114 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
1116 unsigned next_node_index = p_element->
GetNodeGlobalIndex((local_index + 1) % num_nodes);
1118 surface_area += this->GetDistanceBetweenNodes(this_node_index, next_node_index);
1119 this_node_index = next_node_index;
1125 for (
unsigned face_index = 0; face_index < p_element->
GetNumFaces(); face_index++)
1127 surface_area += CalculateAreaOfFace(p_element->
GetFace(face_index));
1130 return surface_area;
1136 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1139 assert(SPACE_DIM == 2);
1140 assert(ELEMENT_DIM == SPACE_DIM);
1147 bool element_includes_point =
false;
1207 c_vector<double, SPACE_DIM> first_vertex = p_element->
GetNodeLocation(0);
1208 c_vector<double, SPACE_DIM> test_point = GetVectorFromAtoB(first_vertex, rTestPoint);
1211 c_vector<double, SPACE_DIM> vertexA = zero_vector<double>(SPACE_DIM);
1212 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
1215 c_vector<double, SPACE_DIM> vector_a_to_point = GetVectorFromAtoB(vertexA, test_point);
1219 if (norm_2(vector_a_to_point) < DBL_EPSILON)
1224 c_vector<double, SPACE_DIM> vertexB = GetVectorFromAtoB(first_vertex, p_element->
GetNodeLocation((local_index + 1) % num_nodes));
1225 c_vector<double, SPACE_DIM> vector_b_to_point = GetVectorFromAtoB(vertexB, test_point);
1226 c_vector<double, SPACE_DIM> vector_a_to_b = GetVectorFromAtoB(vertexA, vertexB);
1229 if ((fabs(vector_a_to_b[1]) < DBL_EPSILON) && (fabs(vector_a_to_point[1]) < DBL_EPSILON) && (fabs(vector_b_to_point[1]) < DBL_EPSILON))
1231 if ((vector_a_to_point[0] > 0) != (vector_b_to_point[0] > 0))
1239 if ((vertexA[1] > test_point[1]) != (vertexB[1] > test_point[1]))
1242 if (test_point[0] < vertexA[0] + vector_a_to_b[0] * vector_a_to_point[1] / vector_a_to_b[1])
1244 element_includes_point = !element_includes_point;
1250 return element_includes_point;
1253 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1257 assert(SPACE_DIM == 2);
1258 assert(ELEMENT_DIM == SPACE_DIM);
1264 double min_squared_normal_distance = DBL_MAX;
1265 unsigned min_distance_edge_index = UINT_MAX;
1268 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
1271 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(local_index);
1272 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((local_index + 1) % num_nodes);
1274 c_vector<double, SPACE_DIM> vector_a_to_point = this->GetVectorFromAtoB(vertexA, rTestPoint);
1275 c_vector<double, SPACE_DIM> vector_a_to_b = this->GetVectorFromAtoB(vertexA, vertexB);
1276 double distance_a_to_b = norm_2(vector_a_to_b);
1278 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b / norm_2(vector_a_to_b);
1279 double distance_parallel_to_edge = inner_prod(vector_a_to_point, edge_ab_unit_vector);
1281 double squared_distance_normal_to_edge =
SmallPow(norm_2(vector_a_to_point), 2) -
SmallPow(distance_parallel_to_edge, 2);
1289 if (squared_distance_normal_to_edge < DBL_EPSILON)
1291 squared_distance_normal_to_edge = 0.0;
1294 if (fabs(distance_parallel_to_edge) < DBL_EPSILON)
1296 distance_parallel_to_edge = 0.0;
1298 else if (fabs(distance_parallel_to_edge - distance_a_to_b) < DBL_EPSILON)
1300 distance_parallel_to_edge = distance_a_to_b;
1304 if (squared_distance_normal_to_edge < min_squared_normal_distance && distance_parallel_to_edge >= 0 && distance_parallel_to_edge <= distance_a_to_b)
1306 min_squared_normal_distance = squared_distance_normal_to_edge;
1307 min_distance_edge_index = local_index;
1311 assert(min_distance_edge_index < num_nodes);
1312 return min_distance_edge_index;
1315 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1318 assert(SPACE_DIM == 2);
1323 c_vector<double, 3> moments = zero_vector<double>(3);
1326 c_vector<double, SPACE_DIM> centroid = GetCentroidOfElement(index);
1328 c_vector<double, SPACE_DIM> this_node_location = p_element->
GetNodeLocation(0);
1329 c_vector<double, SPACE_DIM> pos_1 = this->GetVectorFromAtoB(centroid, this_node_location);
1331 for (
unsigned local_index = 0; local_index < num_nodes; local_index++)
1333 unsigned next_index = (local_index + 1) % num_nodes;
1334 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation(next_index);
1335 c_vector<double, SPACE_DIM> pos_2 = this->GetVectorFromAtoB(centroid, next_node_location);
1337 double signed_area_term = pos_1(0) * pos_2(1) - pos_2(0) * pos_1(1);
1339 moments(0) += (pos_1(1) * pos_1(1) + pos_1(1) * pos_2(1) + pos_2(1) * pos_2(1)) * signed_area_term;
1342 moments(1) += (pos_1(0) * pos_1(0) + pos_1(0) * pos_2(0) + pos_2(0) * pos_2(0)) * signed_area_term;
1345 moments(2) += (pos_1(0) * pos_2(1) + 2 * pos_1(0) * pos_1(1) + 2 * pos_2(0) * pos_2(1) + pos_2(0) * pos_1(1)) * signed_area_term;
1360 if (moments(0) < 0.0)
1362 moments(0) = -moments(0);
1363 moments(1) = -moments(1);
1364 moments(2) = -moments(2);
1369 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1372 assert(SPACE_DIM == 2);
1374 c_vector<double, SPACE_DIM> short_axis = zero_vector<double>(SPACE_DIM);
1377 c_vector<double, 3> moments = CalculateMomentsOfElement(index);
1380 moments /= norm_2(moments);
1383 double discriminant = (moments(0) - moments(1)) * (moments(0) - moments(1)) + 4.0 * moments(2) * moments(2);
1384 if (fabs(discriminant) < DBL_EPSILON)
1388 short_axis(1) = sqrt(1.0 - short_axis(0) * short_axis(0));
1393 if (fabs(moments(2)) < DBL_EPSILON)
1395 if (moments(0) < moments(1))
1397 short_axis(0) = 0.0;
1398 short_axis(1) = 1.0;
1402 short_axis(0) = 1.0;
1403 short_axis(1) = 0.0;
1409 double lambda = 0.5 * (moments(0) + moments(1) + sqrt(discriminant));
1411 short_axis(0) = 1.0;
1412 short_axis(1) = (moments(0) - lambda) / moments(2);
1415 short_axis /= norm_2(short_axis);
1422 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1425 assert(SPACE_DIM == 2);
1427 unsigned num_nodes_in_element = pElement->
GetNumNodes();
1428 unsigned next_local_index = (localIndex + 1) % num_nodes_in_element;
1431 unsigned previous_local_index = (num_nodes_in_element + localIndex - 1) % num_nodes_in_element;
1433 c_vector<double, SPACE_DIM> previous_node_location = pElement->
GetNodeLocation(previous_local_index);
1434 c_vector<double, SPACE_DIM> next_node_location = pElement->
GetNodeLocation(next_local_index);
1435 c_vector<double, SPACE_DIM> difference_vector = this->GetVectorFromAtoB(previous_node_location, next_node_location);
1437 c_vector<double, SPACE_DIM> area_gradient;
1439 area_gradient[0] = 0.5 * difference_vector[1];
1440 area_gradient[1] = -0.5 * difference_vector[0];
1442 return area_gradient;
1445 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1448 assert(SPACE_DIM == 2);
1450 unsigned num_nodes_in_element = pElement->
GetNumNodes();
1453 unsigned previous_local_index = (num_nodes_in_element + localIndex - 1) % num_nodes_in_element;
1458 double previous_edge_length = this->GetDistanceBetweenNodes(this_global_index, previous_global_index);
1459 assert(previous_edge_length > DBL_EPSILON);
1461 c_vector<double, SPACE_DIM> previous_edge_gradient = this->GetVectorFromAtoB(pElement->
GetNodeLocation(previous_local_index), pElement->
GetNodeLocation(localIndex)) / previous_edge_length;
1463 return previous_edge_gradient;
1466 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1469 assert(SPACE_DIM == 2);
1471 unsigned next_local_index = (localIndex + 1) % (pElement->
GetNumNodes());
1476 double next_edge_length = this->GetDistanceBetweenNodes(this_global_index, next_global_index);
1477 assert(next_edge_length > DBL_EPSILON);
1479 c_vector<double, SPACE_DIM> next_edge_gradient = this->GetVectorFromAtoB(pElement->
GetNodeLocation(next_local_index), pElement->
GetNodeLocation(localIndex)) / next_edge_length;
1481 return next_edge_gradient;
1484 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1487 assert(SPACE_DIM == 2);
1489 c_vector<double, SPACE_DIM> previous_edge_gradient = GetPreviousEdgeGradientOfElementAtNode(pElement, localIndex);
1490 c_vector<double, SPACE_DIM> next_edge_gradient = GetNextEdgeGradientOfElementAtNode(pElement, localIndex);
1492 return previous_edge_gradient + next_edge_gradient;
1499 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1502 assert(SPACE_DIM == 3);
1508 rNormal = zero_vector<double>(SPACE_DIM);
1510 c_vector<double, SPACE_DIM> v_minus_v0 = this->GetVectorFromAtoB(pFace->
GetNode(0)->rGetLocation(), pFace->
GetNode(1)->rGetLocation());
1511 for (
unsigned local_index = 2; local_index < pFace->
GetNumNodes(); local_index++)
1513 c_vector<double, SPACE_DIM> vnext_minus_v0 = this->GetVectorFromAtoB(pFace->
GetNode(0)->rGetLocation(), pFace->
GetNode(local_index)->rGetLocation());
1515 v_minus_v0 = vnext_minus_v0;
1517 double magnitude = norm_2(rNormal);
1518 if (magnitude != 0.0)
1521 rNormal /= magnitude;
1525 return magnitude / 2.0;
1528 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1531 assert(SPACE_DIM == 3);
1534 c_vector<double, SPACE_DIM> unit_normal;
1535 return CalculateUnitNormalToFaceWithArea(pFace, unit_normal);
1539 #if defined(__xlC__)
virtual c_vector< double, 3 > CalculateMomentsOfElement(unsigned index)
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
void SetAttribute(double attribute)
VertexElement< ELEMENT_DIM-1, SPACE_DIM > * GetFace(unsigned index) const
unsigned GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(unsigned elementIndex)
virtual unsigned GetNumFaces() const
virtual c_vector< double, SPACE_DIM > GetVectorFromAtoB(const c_vector< double, SPACE_DIM > &rLocationA, const c_vector< double, SPACE_DIM > &rLocationB)
virtual ElementData GetNextElementData()=0
std::set< unsigned > GetNeighbouringNodeIndices(unsigned nodeIndex)
virtual unsigned GetNumElements() const
double SmallPow(double x, unsigned exponent)
unsigned GetNodeGlobalIndex(unsigned localIndex) const
unsigned GetNumAllElements() const
bool IsBoundaryNode() const
virtual unsigned GetNumElements() const
virtual void GetInverseJacobianForElement(unsigned elementIndex, c_matrix< double, SPACE_DIM, ELEMENT_DIM > &rJacobian, double &rJacobianDeterminant, c_matrix< double, ELEMENT_DIM, SPACE_DIM > &rInverseJacobian) const
std::vector< VertexElement< ELEMENT_DIM-1, SPACE_DIM > * > mFaces
#define EXCEPTION(message)
virtual unsigned GetNumNodes() const
Element< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
c_vector< T, 1 > VectorProduct(const c_vector< T, 1 > &rA, const c_vector< T, 1 > &rB)
void GenerateVerticesFromElementCircumcentres(TetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh)
std::set< unsigned > & rGetContainingElementIndices()
c_vector< double, SPACE_DIM > GetNextEdgeGradientOfElementAtNode(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned localIndex)
std::set< unsigned > GetNeighbouringNodeNotAlsoInElement(unsigned nodeIndex, unsigned elemIndex)
VertexElement< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
c_vector< double, SPACE_DIM > GetPreviousEdgeGradientOfElementAtNode(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned localIndex)
unsigned GetNumFaces() const
std::vector< ElementData > Faces
std::vector< unsigned > NodeIndices
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
virtual bool HasNodePermutation()
VertexElement< ELEMENT_DIM-1, SPACE_DIM > * GetFace(unsigned index) const
bool mMeshChangesDuringSimulation
void AddNode(Node< SPACE_DIM > *pNode, const unsigned &rIndex)
std::vector< Node< SPACE_DIM > * > mNodes
double CalculateUnitNormalToFaceWithArea(VertexElement< ELEMENT_DIM-1, SPACE_DIM > *pFace, c_vector< double, SPACE_DIM > &rNormal)
virtual unsigned GetNumElements() const =0
virtual double CalculateAreaOfFace(VertexElement< ELEMENT_DIM-1, SPACE_DIM > *pFace)
unsigned GetNumNodes() const
const unsigned UNSIGNED_UNSET
double GetElongationShapeFactorOfElement(unsigned elementIndex)
void AddFace(VertexElement< ELEMENT_DIM-1, SPACE_DIM > *pFace)
static RandomNumberGenerator * Instance()
virtual double GetVolumeOfElement(unsigned index)
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
virtual unsigned GetNumElementAttributes() const
std::vector< VertexElement< ELEMENT_DIM, SPACE_DIM > * > mElements
unsigned SolveNodeMapping(unsigned index) const
c_vector< double, SPACE_DIM > GetPerimeterGradientOfElementAtNode(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned localIndex)
const c_vector< double, SPACE_DIM > & rGetLocation() const
void AddElement(unsigned index)
unsigned GetIndex() const
unsigned SolveBoundaryElementMapping(unsigned index) const
virtual c_vector< double, SPACE_DIM > GetCentroidOfElement(unsigned index)
virtual c_vector< double, SPACE_DIM > GetVectorFromAtoB(const c_vector< double, SPACE_DIM > &rLocationA, const c_vector< double, SPACE_DIM > &rLocationB)
std::set< unsigned > GetNeighbouringElementIndices(unsigned elementIndex)
double GetNodeLocation(unsigned localIndex, unsigned dimension) const
virtual std::vector< double > GetNextNode()=0
c_vector< double, SPACE_DIM > GetAreaGradientOfElementAtNode(VertexElement< ELEMENT_DIM, SPACE_DIM > *pElement, unsigned localIndex)
unsigned GetIndex() const
virtual VertexMesh< ELEMENT_DIM, SPACE_DIM > * GetMeshForVtk()
double GetEdgeLength(unsigned elementIndex1, unsigned elementIndex2)
unsigned GetVoronoiElementIndexCorrespondingToDelaunayNodeIndex(unsigned nodeIndex)
virtual double GetSurfaceAreaOfElement(unsigned index)
std::vector< unsigned > NodeIndices
unsigned SolveElementMapping(unsigned index) const
virtual unsigned GetNumNodes() const =0
bool ElementIncludesPoint(const c_vector< double, SPACE_DIM > &rTestPoint, unsigned elementIndex)
unsigned GetLocalIndexForElementEdgeClosestToPoint(const c_vector< double, SPACE_DIM > &rTestPoint, unsigned elementIndex)
c_vector< double, SPACE_DIM > GetShortAxisOfElement(unsigned index)
TetrahedralMesh< ELEMENT_DIM, SPACE_DIM > * mpDelaunayMesh
std::map< unsigned, unsigned > mVoronoiElementIndexMap
unsigned GetRosetteRankOfElement(unsigned index)