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>
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++)
164 this->
mNodes.reserve(num_nodes);
168 for (
unsigned elem_index=0; elem_index<num_elements; elem_index++)
178 for (
unsigned i=0; i<num_nodes; i++)
182 for (
unsigned local_index=0; local_index<3; local_index++)
184 unsigned elem_index =
mpDelaunayMesh->GetElement(i)->GetNodeGlobalIndex(local_index);
185 unsigned num_nodes_in_elem =
mElements[elem_index]->GetNumNodes();
186 unsigned end_index = num_nodes_in_elem>0 ? num_nodes_in_elem-1 : 0;
193 for (
unsigned elem_index=0; elem_index<
mElements.size(); elem_index++)
200 std::vector<std::pair<double, unsigned> > index_angle_list;
201 for (
unsigned local_index=0; local_index<
mElements[elem_index]->GetNumNodes(); local_index++)
203 c_vector<double, 2> vectorA =
mpDelaunayMesh->GetNode(elem_index)->rGetLocation();
204 c_vector<double, 2> vectorB =
mElements[elem_index]->GetNodeLocation(local_index);
205 c_vector<double, 2> centre_to_vertex =
mpDelaunayMesh->GetVectorFromAtoB(vectorA, vectorB);
207 double angle = atan2(centre_to_vertex(1), centre_to_vertex(0));
208 unsigned global_index =
mElements[elem_index]->GetNodeGlobalIndex(local_index);
210 std::pair<double, unsigned> pair(angle, global_index);
211 index_angle_list.push_back(pair);
215 sort(index_angle_list.begin(), index_angle_list.end());
219 for (
unsigned count = 0; count < index_angle_list.size(); count++)
221 unsigned local_index = count>1 ? count-1 : 0;
222 p_new_element->
AddNode(
mNodes[index_angle_list[count].second], local_index);
250 this->
mNodes.reserve(num_nodes);
255 std::map<unsigned, VertexElement<3,3>*> index_element_map;
256 unsigned face_index = 0;
257 unsigned element_index = 0;
264 Node<3>* p_node_a = edge_iterator.GetNodeA();
265 Node<3>* p_node_b = edge_iterator.GetNodeB();
271 std::set<unsigned> edge_element_indices;
273 std::set_intersection(node_a_element_indices.begin(),
274 node_a_element_indices.end(),
275 node_b_element_indices.begin(),
276 node_b_element_indices.end(),
277 std::inserter(edge_element_indices, edge_element_indices.begin()));
279 c_vector<double,3> edge_vector;
282 c_vector<double,3> mid_edge;
285 unsigned element0_index = *(edge_element_indices.begin());
287 c_vector<double,3> basis_vector1 =
mNodes[element0_index]->rGetLocation() - mid_edge;
288 c_vector<double,3> basis_vector2 =
VectorProduct(edge_vector, basis_vector1);
295 std::vector<std::pair<double, unsigned> > index_angle_list;
298 for (std::set<unsigned>::iterator index_iter = edge_element_indices.begin();
299 index_iter != edge_element_indices.end();
303 c_vector<double, 3> vertex_vector =
mNodes[*index_iter]->rGetLocation() - mid_edge;
305 double local_vertex_dot_basis_vector1 = inner_prod(vertex_vector, basis_vector1);
306 double local_vertex_dot_basis_vector2 = inner_prod(vertex_vector, basis_vector2);
308 double angle = atan2(local_vertex_dot_basis_vector2, local_vertex_dot_basis_vector1);
310 std::pair<double, unsigned> pair(angle, *index_iter);
311 index_angle_list.push_back(pair);
315 sort(index_angle_list.begin(), index_angle_list.end());
320 for (
unsigned count = 0; count < index_angle_list.size(); count++)
322 unsigned local_index = count>1 ? count-1 : 0;
323 p_face->AddNode(
mNodes[index_angle_list[count].second], local_index);
332 unsigned node_a_index = p_node_a->
GetIndex();
333 if (index_element_map[node_a_index])
336 index_element_map[node_a_index]->AddFace(p_face);
345 index_element_map[node_a_index] = p_element;
350 unsigned node_b_index = p_node_b->
GetIndex();
351 if (index_element_map[node_b_index])
354 index_element_map[node_b_index]->AddFace(p_face);
363 index_element_map[node_b_index] = p_element;
370 unsigned elem_count = 0;
371 for (std::map<
unsigned,
VertexElement<3,3>*>::iterator element_iter = index_element_map.begin();
372 element_iter != index_element_map.end();
375 mElements.push_back(element_iter->second);
383 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
386 c_matrix<double, SPACE_DIM, ELEMENT_DIM> jacobian;
387 c_matrix<double, ELEMENT_DIM, SPACE_DIM> inverse_jacobian;
395 c_vector<double, SPACE_DIM+1> circumsphere = rMesh.
GetElement(i)->CalculateCircumsphere(jacobian, inverse_jacobian);
397 c_vector<double, SPACE_DIM> circumcentre;
398 for (
unsigned j=0; j<SPACE_DIM; j++)
400 circumcentre(j) = circumsphere(j);
408 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
411 assert(SPACE_DIM == 2);
413 std::set<unsigned> node_indices_1;
414 for (
unsigned i=0; i<
mElements[elementIndex1]->GetNumNodes(); i++)
416 node_indices_1.insert(
mElements[elementIndex1]->GetNodeGlobalIndex(i));
418 std::set<unsigned> node_indices_2;
419 for (
unsigned i=0; i<
mElements[elementIndex2]->GetNumNodes(); i++)
421 node_indices_2.insert(
mElements[elementIndex2]->GetNodeGlobalIndex(i));
424 std::set<unsigned> shared_nodes;
425 std::set_intersection(node_indices_1.begin(), node_indices_1.end(),
426 node_indices_2.begin(), node_indices_2.end(),
427 std::inserter(shared_nodes, shared_nodes.begin()));
429 if (shared_nodes.size() == 1)
432 EXCEPTION(
"Elements "<< elementIndex1 <<
" and "<< elementIndex2<<
" share only one node.");
434 assert(shared_nodes.size() == 2);
436 unsigned index1 = *(shared_nodes.begin());
437 unsigned index2 = *(++(shared_nodes.begin()));
443 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
446 assert(SPACE_DIM == 2);
450 double discriminant = sqrt((moments(0) - moments(1))*(moments(0) - moments(1)) + 4.0*moments(2)*moments(2));
453 double largest_eigenvalue = (moments(0) + moments(1) + discriminant)*0.5;
454 double smallest_eigenvalue = (moments(0) + moments(1) - discriminant)*0.5;
456 double elongation_shape_factor = sqrt(largest_eigenvalue/smallest_eigenvalue);
457 return elongation_shape_factor;
460 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
468 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
474 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
477 assert(index < this->
mNodes.size());
481 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
488 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
496 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
503 node_index = elementIndex;
511 if (iter->second == elementIndex)
513 node_index = iter->first;
522 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
529 element_index = nodeIndex;
537 EXCEPTION(
"This index does not correspond to a VertexElement");
541 element_index = iter->second;
545 return element_index;
548 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
551 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
557 unsigned rosette_rank = 0;
558 for (
unsigned node_idx = 0 ; node_idx < p_element->
GetNumNodes() ; node_idx++)
560 unsigned num_elems_this_node = p_element->
GetNode(node_idx)->rGetContainingElementIndices().size();
562 if (num_elems_this_node > rosette_rank)
564 rosette_rank = num_elems_this_node;
572 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
576 for (
unsigned i=0; i<
mElements.size(); i++)
583 for (
unsigned i=0; i<
mFaces.size(); i++)
590 for (
unsigned i=0; i<this->
mNodes.size(); i++)
597 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
600 return this->
mNodes.size();
603 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
609 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
615 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
621 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
628 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
631 assert(index <
mFaces.size());
635 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
641 c_vector<double, SPACE_DIM> centroid = zero_vector<double>(SPACE_DIM);
652 double centroid_x = 0;
653 double centroid_y = 0;
656 double element_signed_area = 0.0;
659 c_vector<double, SPACE_DIM> first_node_location = p_element->
GetNodeLocation(0);
660 c_vector<double, SPACE_DIM> pos_1 = zero_vector<double>(SPACE_DIM);
663 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
665 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation((local_index+1)%num_nodes);
666 c_vector<double, SPACE_DIM> pos_2 =
GetVectorFromAtoB(first_node_location, next_node_location);
668 double this_x = pos_1[0];
669 double this_y = pos_1[1];
670 double next_x = pos_2[0];
671 double next_y = pos_2[1];
673 double signed_area_term = this_x*next_y - this_y*next_x;
675 centroid_x += (this_x + next_x)*signed_area_term;
676 centroid_y += (this_y + next_y)*signed_area_term;
677 element_signed_area += 0.5*signed_area_term;
682 assert(element_signed_area != 0.0);
685 centroid = first_node_location;
686 centroid(0) += centroid_x / (6.0*element_signed_area);
687 centroid(1) += centroid_y / (6.0*element_signed_area);
693 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
697 centroid /= ((
double) num_nodes);
706 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
710 std::set<unsigned> neighbouring_node_indices;
713 std::set<unsigned> containing_elem_indices = this->
GetNode(nodeIndex)->rGetContainingElementIndices();
716 for (std::set<unsigned>::iterator elem_iter = containing_elem_indices.begin();
717 elem_iter != containing_elem_indices.end();
721 unsigned local_index =
GetElement(*elem_iter)->GetNodeLocalIndex(nodeIndex);
724 unsigned num_nodes =
GetElement(*elem_iter)->GetNumNodes();
725 unsigned previous_local_index = (local_index + num_nodes - 1)%num_nodes;
726 unsigned next_local_index = (local_index + 1)%num_nodes;
729 neighbouring_node_indices.insert(
GetElement(*elem_iter)->GetNodeGlobalIndex(previous_local_index));
730 neighbouring_node_indices.insert(
GetElement(*elem_iter)->GetNodeGlobalIndex(next_local_index));
733 return neighbouring_node_indices;
736 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
743 std::set<unsigned> node_indices_in_this_element;
744 for (
unsigned local_index=0; local_index<p_element->
GetNumNodes(); local_index++)
747 node_indices_in_this_element.insert(global_index);
751 if (node_indices_in_this_element.find(nodeIndex) == node_indices_in_this_element.end())
753 EXCEPTION(
"The given node is not contained in the given element.");
757 std::set<unsigned> neighbouring_node_indices_not_in_this_element;
763 for (std::set<unsigned>::iterator iter = node_neighbours.begin();
764 iter != node_neighbours.end();
767 if (node_indices_in_this_element.find(*iter) == node_indices_in_this_element.end())
769 neighbouring_node_indices_not_in_this_element.insert(*iter);
773 return neighbouring_node_indices_not_in_this_element;
776 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
783 std::set<unsigned> neighbouring_element_indices;
786 for (
unsigned local_index=0; local_index<p_element->
GetNumNodes(); local_index++)
795 std::set<unsigned> all_elements;
796 std::set_union(neighbouring_element_indices.begin(), neighbouring_element_indices.end(),
797 containing_elem_indices.begin(), containing_elem_indices.end(),
798 std::inserter(all_elements, all_elements.begin()));
801 neighbouring_element_indices = all_elements;
805 neighbouring_element_indices.erase(elementIndex);
807 return neighbouring_element_indices;
815 EXCEPTION(
"VertexMesh<1,1>::ConstructFromMeshReader() is not implemented");
823 EXCEPTION(
"VertexMesh<1,2>::ConstructFromMeshReader() is not implemented");
831 EXCEPTION(
"VertexMesh<1,3>::ConstructFromMeshReader() is not implemented");
839 EXCEPTION(
"VertexMesh<2,3>::ConstructFromMeshReader() is not implemented");
853 this->
mNodes.reserve(num_nodes);
858 std::vector<double> node_data;
859 for (
unsigned i=0; i<num_nodes; i++)
862 unsigned is_boundary_node = (
bool) node_data[2];
863 node_data.pop_back();
864 this->
mNodes.push_back(
new Node<2>(i, node_data, is_boundary_node));
873 for (
unsigned elem_index=0; elem_index<num_elements; elem_index++)
879 std::vector<Node<2>*> nodes;
880 unsigned num_nodes_in_element = element_data.
NodeIndices.size();
881 for (
unsigned j=0; j<num_nodes_in_element; j++)
883 assert(element_data.
NodeIndices[j] < this->mNodes.size());
912 this->
mNodes.reserve(num_nodes);
917 std::vector<double> node_data;
918 for (
unsigned i=0; i<num_nodes; i++)
921 unsigned is_boundary_node = (
bool) node_data[3];
922 node_data.pop_back();
923 this->
mNodes.push_back(
new Node<3>(i, node_data, is_boundary_node));
932 std::set<unsigned> faces_counted;
935 for (
unsigned elem_index=0; elem_index<num_elements; elem_index++)
939 assert(dynamic_cast<VERTEX_MESH_READER*>(&rMeshReader) !=
nullptr);
942 VertexElementData element_data =
static_cast<VERTEX_MESH_READER*
>(&rMeshReader)->GetNextElementDataWithFaces();
945 std::vector<Node<3>*> nodes;
946 unsigned num_nodes_in_element = element_data.
NodeIndices.size();
947 for (
unsigned j=0; j<num_nodes_in_element; j++)
949 assert(element_data.
NodeIndices[j] < this->mNodes.size());
954 std::vector<VertexElement<2,3>*> faces;
955 unsigned num_faces_in_element = element_data.
Faces.size();
956 for (
unsigned i=0; i<num_faces_in_element; i++)
965 std::vector<
Node<3>*> nodes_in_face;
966 unsigned num_nodes_in_face = face_data.
NodeIndices.size();
967 for (
unsigned j=0; j<num_nodes_in_face; j++)
969 assert(face_data.
NodeIndices[j] < this->mNodes.size());
974 if (faces_counted.find(face_index) == faces_counted.end())
979 faces_counted.insert(face_index);
980 faces.push_back(p_face);
985 bool face_added =
false;
986 for (
unsigned k=0; k<
mFaces.size(); k++)
988 if (
mFaces[k]->GetIndex() == face_index)
990 faces.push_back(
mFaces[k]);
996 assert(face_added ==
true);
1001 std::vector<bool> orientations = std::vector<bool>(num_faces_in_element,
true);
1011 p_element->SetAttribute(attribute_value);
1017 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1019 const c_vector<double, SPACE_DIM>& rLocationA,
const c_vector<double, SPACE_DIM>& rLocationB)
1021 c_vector<double, SPACE_DIM> vector;
1024 vector =
mpDelaunayMesh->GetVectorFromAtoB(rLocationA, rLocationB);
1033 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1036 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
1041 double element_volume = 0.0;
1045 c_vector<double, SPACE_DIM> first_node_location = p_element->
GetNodeLocation(0);
1046 c_vector<double, SPACE_DIM> pos_1 = zero_vector<double>(SPACE_DIM);
1049 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
1051 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation((local_index+1)%num_nodes);
1052 c_vector<double, SPACE_DIM> pos_2 =
GetVectorFromAtoB(first_node_location, next_node_location);
1054 double this_x = pos_1[0];
1055 double this_y = pos_1[1];
1056 double next_x = pos_2[0];
1057 double next_y = pos_2[1];
1059 element_volume += 0.5*(this_x*next_y - next_x*this_y);
1067 c_vector<double, SPACE_DIM> pyramid_apex = p_element->
GetNodeLocation(0);
1068 for (
unsigned face_index=0; face_index<p_element->
GetNumFaces(); face_index++)
1074 c_vector<double, SPACE_DIM> unit_normal;
1078 c_vector<double, SPACE_DIM> base_to_apex =
GetVectorFromAtoB(p_face->GetNodeLocation(0), pyramid_apex);
1079 double perpendicular_distance = fabs(inner_prod(base_to_apex, unit_normal));
1083 element_volume += face_area * perpendicular_distance / 3;
1088 return fabs(element_volume);
1091 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1094 assert(SPACE_DIM == 2 || SPACE_DIM == 3);
1099 double surface_area = 0.0;
1104 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
1109 this_node_index = next_node_index;
1115 for (
unsigned face_index=0; face_index<p_element->
GetNumFaces(); face_index++)
1120 return surface_area;
1127 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1130 assert(SPACE_DIM == 2);
1131 assert(ELEMENT_DIM == SPACE_DIM);
1138 bool element_includes_point =
false;
1198 c_vector<double, SPACE_DIM> first_vertex = p_element->
GetNodeLocation(0);
1199 c_vector<double, SPACE_DIM> test_point =
GetVectorFromAtoB(first_vertex, rTestPoint);
1202 c_vector<double, SPACE_DIM> vertexA = zero_vector<double>(SPACE_DIM);
1203 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
1206 c_vector<double, SPACE_DIM> vector_a_to_point =
GetVectorFromAtoB(vertexA, test_point);
1210 if (norm_2(vector_a_to_point) < DBL_EPSILON)
1216 c_vector<double, SPACE_DIM> vector_b_to_point =
GetVectorFromAtoB(vertexB, test_point);
1217 c_vector<double, SPACE_DIM> vector_a_to_b =
GetVectorFromAtoB(vertexA, vertexB);
1220 if ((fabs(vector_a_to_b[1]) < DBL_EPSILON) &&
1221 (fabs(vector_a_to_point[1]) < DBL_EPSILON) &&
1222 (fabs(vector_b_to_point[1]) < DBL_EPSILON))
1224 if ((vector_a_to_point[0]>0) != (vector_b_to_point[0]>0))
1232 if ((vertexA[1] > test_point[1]) != (vertexB[1] > test_point[1]))
1235 if (test_point[0] < vertexA[0] + vector_a_to_b[0]*vector_a_to_point[1]/vector_a_to_b[1])
1237 element_includes_point = !element_includes_point;
1243 return element_includes_point;
1246 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1250 assert(SPACE_DIM == 2);
1251 assert(ELEMENT_DIM == SPACE_DIM);
1257 double min_squared_normal_distance = DBL_MAX;
1258 unsigned min_distance_edge_index = UINT_MAX;
1261 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
1264 c_vector<double, SPACE_DIM> vertexA = p_element->
GetNodeLocation(local_index);
1265 c_vector<double, SPACE_DIM> vertexB = p_element->
GetNodeLocation((local_index+1)%num_nodes);
1267 c_vector<double, SPACE_DIM> vector_a_to_point = this->
GetVectorFromAtoB(vertexA, rTestPoint);
1268 c_vector<double, SPACE_DIM> vector_a_to_b = this->
GetVectorFromAtoB(vertexA, vertexB);
1269 double distance_a_to_b = norm_2(vector_a_to_b);
1271 c_vector<double, SPACE_DIM> edge_ab_unit_vector = vector_a_to_b/norm_2(vector_a_to_b);
1272 double distance_parallel_to_edge = inner_prod(vector_a_to_point, edge_ab_unit_vector);
1274 double squared_distance_normal_to_edge =
SmallPow(norm_2(vector_a_to_point), 2) -
SmallPow(distance_parallel_to_edge, 2);
1282 if (squared_distance_normal_to_edge < DBL_EPSILON)
1284 squared_distance_normal_to_edge = 0.0;
1287 if (fabs(distance_parallel_to_edge) < DBL_EPSILON)
1289 distance_parallel_to_edge = 0.0;
1291 else if (fabs(distance_parallel_to_edge-distance_a_to_b) < DBL_EPSILON)
1293 distance_parallel_to_edge = distance_a_to_b;
1297 if (squared_distance_normal_to_edge < min_squared_normal_distance &&
1298 distance_parallel_to_edge >=0 &&
1299 distance_parallel_to_edge <= distance_a_to_b)
1301 min_squared_normal_distance = squared_distance_normal_to_edge;
1302 min_distance_edge_index = local_index;
1306 assert(min_distance_edge_index < num_nodes);
1307 return min_distance_edge_index;
1310 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1313 assert(SPACE_DIM == 2);
1318 c_vector<double, 3> moments = zero_vector<double>(3);
1323 c_vector<double, SPACE_DIM> this_node_location = p_element->
GetNodeLocation(0);
1324 c_vector<double, SPACE_DIM> pos_1 = this->
GetVectorFromAtoB(centroid, this_node_location);
1326 for (
unsigned local_index=0; local_index<num_nodes; local_index++)
1328 unsigned next_index = (local_index+1)%num_nodes;
1329 c_vector<double, SPACE_DIM> next_node_location = p_element->
GetNodeLocation(next_index);
1330 c_vector<double, SPACE_DIM> pos_2 = this->
GetVectorFromAtoB(centroid, next_node_location);
1332 double signed_area_term = pos_1(0)*pos_2(1) - pos_2(0)*pos_1(1);
1334 moments(0) += (pos_1(1)*pos_1(1) + pos_1(1)*pos_2(1) + pos_2(1)*pos_2(1) ) * signed_area_term;
1337 moments(1) += (pos_1(0)*pos_1(0) + pos_1(0)*pos_2(0) + pos_2(0)*pos_2(0)) * signed_area_term;
1340 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;
1355 if (moments(0) < 0.0)
1357 moments(0) = -moments(0);
1358 moments(1) = -moments(1);
1359 moments(2) = -moments(2);
1364 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1367 assert(SPACE_DIM == 2);
1369 c_vector<double, SPACE_DIM> short_axis = zero_vector<double>(SPACE_DIM);
1375 moments /= norm_2(moments);
1378 double discriminant = (moments(0) - moments(1)) * (moments(0) - moments(1)) + 4.0 * moments(2) * moments(2);
1379 if (fabs(discriminant) < DBL_EPSILON)
1383 short_axis(1) = sqrt(1.0 - short_axis(0) * short_axis(0));
1388 if (fabs(moments(2)) < DBL_EPSILON)
1390 if (moments(0) < moments(1))
1392 short_axis(0) = 0.0;
1393 short_axis(1) = 1.0;
1397 short_axis(0) = 1.0;
1398 short_axis(1) = 0.0;
1404 double lambda = 0.5 * (moments(0) + moments(1) + sqrt(discriminant));
1406 short_axis(0) = 1.0;
1407 short_axis(1) = (moments(0) - lambda) / moments(2);
1410 short_axis /= norm_2(short_axis);
1417 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1420 assert(SPACE_DIM == 2);
1422 unsigned num_nodes_in_element = pElement->
GetNumNodes();
1423 unsigned next_local_index = (localIndex+1)%num_nodes_in_element;
1426 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
1428 c_vector<double, SPACE_DIM> previous_node_location = pElement->
GetNodeLocation(previous_local_index);
1429 c_vector<double, SPACE_DIM> next_node_location = pElement->
GetNodeLocation(next_local_index);
1430 c_vector<double, SPACE_DIM> difference_vector = this->
GetVectorFromAtoB(previous_node_location, next_node_location);
1432 c_vector<double, SPACE_DIM> area_gradient;
1434 area_gradient[0] = 0.5*difference_vector[1];
1435 area_gradient[1] = -0.5*difference_vector[0];
1437 return area_gradient;
1440 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1443 assert(SPACE_DIM == 2);
1445 unsigned num_nodes_in_element = pElement->
GetNumNodes();
1448 unsigned previous_local_index = (num_nodes_in_element+localIndex-1)%num_nodes_in_element;
1454 assert(previous_edge_length > DBL_EPSILON);
1458 return previous_edge_gradient;
1461 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1464 assert(SPACE_DIM == 2);
1466 unsigned next_local_index = (localIndex+1)%(pElement->
GetNumNodes());
1472 assert(next_edge_length > DBL_EPSILON);
1476 return next_edge_gradient;
1479 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1482 assert(SPACE_DIM==2);
1487 return previous_edge_gradient + next_edge_gradient;
1494 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1497 assert(SPACE_DIM == 3);
1503 rNormal = zero_vector<double>(SPACE_DIM);
1506 for (
unsigned local_index=2; local_index<pFace->
GetNumNodes(); local_index++)
1510 v_minus_v0 = vnext_minus_v0;
1512 double magnitude = norm_2(rNormal);
1513 if (magnitude != 0.0)
1516 rNormal /= magnitude;
1520 return magnitude/2.0;
1523 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1526 assert(SPACE_DIM == 3);
1529 c_vector<double, SPACE_DIM> unit_normal;
1534 #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
Node< SPACE_DIM > * GetNode(unsigned index) 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
#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()
double GetDistanceBetweenNodes(unsigned indexA, unsigned indexB)
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
std::vector< VertexElement< ELEMENT_DIM-1, SPACE_DIM > * > mFaces
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)