36 #include "TetrahedralMesh.hpp"
44 #include "BoundaryElement.hpp"
45 #include "Element.hpp"
48 #include "OutputFileHandler.hpp"
50 #include "RandomNumberGenerator.hpp"
51 #include "Warnings.hpp"
61 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
67 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
81 this->mNodes.reserve(num_nodes);
89 std::vector<double> coords;
90 for (
unsigned node_index=0; node_index < num_nodes; node_index++)
101 this->mNodes.push_back(p_node);
114 std::vector<Node<SPACE_DIM>*> nodes;
122 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
124 assert(element_data.
NodeIndices[j] < this->mNodes.size());
125 nodes.push_back(this->mNodes[element_data.
NodeIndices[j]]);
130 this->mElements.push_back(p_element);
144 std::vector<unsigned> node_indices = face_data.
NodeIndices;
152 std::vector<Node<SPACE_DIM>*> nodes;
153 for (
unsigned node_index=0; node_index<node_indices.size(); node_index++)
155 assert(node_indices[node_index] < this->mNodes.size());
157 nodes.push_back(this->mNodes[node_indices[node_index]]);
161 for (
unsigned j=0; j<nodes.size(); j++)
163 if (!nodes[j]->IsBoundaryNode())
165 nodes[j]->SetAsBoundaryNode();
166 this->mBoundaryNodes.push_back(nodes[j]);
170 nodes[j]->AddBoundaryElement(face_index);
175 this->mBoundaryElements.push_back(p_boundary_element);
181 p_boundary_element->SetAttribute(attribute_value);
185 RefreshJacobianCachedData();
190 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
193 std::vector<unsigned> nodes_per_processor_vec;
195 std::ifstream file_stream(rNodesPerProcessorFile.c_str());
196 if (file_stream.is_open())
200 unsigned nodes_per_processor;
201 file_stream >> nodes_per_processor;
205 nodes_per_processor_vec.push_back(nodes_per_processor);
211 EXCEPTION(
"Unable to read nodes per processor file " + rNodesPerProcessorFile);
215 for (
unsigned i=0; i<nodes_per_processor_vec.size(); i++)
217 sum += nodes_per_processor_vec[i];
220 if (sum != this->GetNumNodes())
222 EXCEPTION(
"Sum of nodes per processor, " << sum
223 <<
", not equal to number of nodes in mesh, " << this->GetNumNodes());
230 EXCEPTION(
"Number of processes doesn't match the size of the nodes-per-processor file");
232 delete this->mpDistributedVectorFactory;
235 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
245 std::set< std::set<unsigned> > odd_parity_faces;
248 iter != this->GetElementIteratorEnd();
251 for (
unsigned face_index=0; face_index<=ELEMENT_DIM; face_index++)
253 std::set<unsigned> face_info;
254 for (
unsigned node_index=0; node_index<=ELEMENT_DIM; node_index++)
257 if (node_index != face_index)
259 face_info.insert(iter->GetNodeGlobalIndex(node_index));
263 std::set< std::set<unsigned> >::iterator find_face=odd_parity_faces.find(face_info);
264 if (find_face != odd_parity_faces.end())
268 odd_parity_faces.erase(find_face);
273 odd_parity_faces.insert(face_info);
284 return(odd_parity_faces.size() == this->GetNumBoundaryElements());
287 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
290 double mesh_volume = 0.0;
293 iter != this->GetElementIteratorEnd();
296 mesh_volume += iter->GetVolume(mElementJacobianDeterminants[iter->GetIndex()]);
302 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
306 assert(ELEMENT_DIM >= 1);
307 const unsigned bound_element_dim = ELEMENT_DIM-1;
308 assert(bound_element_dim < 3);
309 if ( bound_element_dim == 0)
314 double mesh_surface = 0.0;
317 while (it != this->GetBoundaryElementIteratorEnd())
319 mesh_surface += mBoundaryElementJacobianDeterminants[(*it)->GetIndex()];
323 if ( bound_element_dim == 2)
331 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
336 std::vector<unsigned> perm;
337 p_rng->
Shuffle(this->mNodes.size(), perm);
343 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
347 assert( this->GetNumAllNodes() == this->GetNumNodes());
349 assert(perm.size() == this->mNodes.size());
352 std::vector< Node<SPACE_DIM>* > copy_m_nodes;
353 copy_m_nodes.assign(this->mNodes.begin(), this->mNodes.end());
355 for (
unsigned original_index=0; original_index<this->mNodes.size(); original_index++)
357 assert(perm[original_index] < this->mNodes.size());
359 this->mNodes[ perm[original_index] ] = copy_m_nodes[original_index];
363 for (
unsigned index=0; index<this->mNodes.size(); index++)
365 this->mNodes[index]->SetIndex(index);
369 this->mNodePermutation = perm;
372 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
375 assert(startingElementGuess<this->GetNumElements());
381 unsigned i = startingElementGuess;
382 bool reached_end =
false;
386 if (this->mElements[i]->IncludesPoint(rTestPoint, strict))
388 assert(!this->mElements[i]->IsDeleted());
394 if (i==this->GetNumElements())
400 if (i==startingElementGuess)
407 std::stringstream ss;
409 for (
unsigned j=0; (int)j<(
int)SPACE_DIM-1; j++)
411 ss << rTestPoint[j] <<
",";
413 ss << rTestPoint[SPACE_DIM-1] <<
"] is not in mesh - all elements tested";
418 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
421 double max_min_weight = -std::numeric_limits<double>::infinity();
422 unsigned closest_index = 0;
423 for (
unsigned i=0; i<this->mElements.size(); i++)
425 c_vector<double, ELEMENT_DIM+1> weight=this->mElements[i]->CalculateInterpolationWeights(rTestPoint);
426 double neg_weight_sum=0.0;
427 for (
unsigned j=0; j<=ELEMENT_DIM; j++)
431 neg_weight_sum += weight[j];
434 if (neg_weight_sum > max_min_weight)
436 max_min_weight = neg_weight_sum;
440 assert(!this->mElements[closest_index]->IsDeleted());
441 return closest_index;
444 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
447 std::vector<unsigned> element_indices;
448 for (
unsigned i=0; i<this->mElements.size(); i++)
450 if (this->mElements[i]->IncludesPoint(rTestPoint))
452 assert(!this->mElements[i]->IsDeleted());
453 element_indices.push_back(i);
456 return element_indices;
459 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
463 for (
unsigned i=0; i<this->mBoundaryElements.size(); i++)
465 delete this->mBoundaryElements[i];
467 for (
unsigned i=0; i<this->mElements.size(); i++)
469 delete this->mElements[i];
471 for (
unsigned i=0; i<this->mNodes.size(); i++)
473 delete this->mNodes[i];
476 this->mNodes.clear();
477 this->mElements.clear();
478 this->mBoundaryElements.clear();
479 this->mBoundaryNodes.clear();
483 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
486 assert(SPACE_DIM == 2);
487 assert(SPACE_DIM == ELEMENT_DIM);
489 double x_difference = this->mNodes[indexB]->rGetLocation()[0] - this->mNodes[indexA]->rGetLocation()[0];
490 double y_difference = this->mNodes[indexB]->rGetLocation()[1] - this->mNodes[indexA]->rGetLocation()[1];
492 if (x_difference == 0)
494 if (y_difference > 0)
498 else if (y_difference < 0)
504 EXCEPTION(
"Tried to compute polar angle of (0,0)");
508 double angle = atan2(y_difference,x_difference);
516 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
524 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
527 assert((*
this) != mrMesh.EdgesEnd());
529 return p_element->
GetNode(mNodeBLocalIndex);
532 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
540 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
543 bool already_seen_this_edge;
545 unsigned num_elements = mrMesh.GetNumAllElements();
546 std::pair<unsigned, unsigned> current_node_pair;
553 mNodeBLocalIndex = (mNodeBLocalIndex + 1) % (ELEMENT_DIM+1);
554 if (mNodeBLocalIndex == mNodeALocalIndex)
556 mNodeALocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
557 mNodeBLocalIndex = (mNodeALocalIndex + 1) % (ELEMENT_DIM+1);
560 if (mNodeALocalIndex == 0 && mNodeBLocalIndex == 1)
567 while (mElemIndex!=num_elements && mrMesh.GetElement(mElemIndex)->IsDeleted());
570 if (mElemIndex != num_elements)
575 if (node_b_global_index < node_a_global_index)
578 unsigned temp = node_a_global_index;
579 node_a_global_index = node_b_global_index;
580 node_b_global_index = temp;
584 current_node_pair = std::pair<unsigned, unsigned>(node_a_global_index, node_b_global_index);
585 already_seen_this_edge = (mEdgesVisited.count(current_node_pair) != 0);
589 already_seen_this_edge =
false;
593 while (already_seen_this_edge);
594 mEdgesVisited.insert(current_node_pair);
599 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
602 mElemIndex(elemIndex),
616 if (node_b_global_index < node_a_global_index)
619 unsigned temp = node_a_global_index;
620 node_a_global_index = node_b_global_index;
621 node_b_global_index = temp;
625 std::pair<unsigned, unsigned> current_node_pair = std::pair<unsigned, unsigned>(node_a_global_index, node_b_global_index);
629 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
632 unsigned first_element_index = 0;
635 first_element_index++;
640 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
646 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
652 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
655 assert(index < this->
mNodes.size() );
659 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
666 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
673 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
683 if (ELEMENT_DIM < SPACE_DIM)
698 unsigned index = iter->GetIndex();
702 if (ELEMENT_DIM < SPACE_DIM)
708 unsigned index = iter->GetIndex();
717 unsigned index = (*itb)->GetIndex();
722 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
725 assert(ELEMENT_DIM <= SPACE_DIM);
731 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
734 assert(ELEMENT_DIM <= SPACE_DIM);
741 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
744 assert(ELEMENT_DIM < SPACE_DIM);
750 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
758 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
761 mesherIo.numberofpoints = 0;
762 mesherIo.pointlist = NULL;
763 mesherIo.numberofpointattributes = 0;
764 mesherIo.pointattributelist = (
double *) NULL;
765 mesherIo.pointmarkerlist = (
int *) NULL;
766 mesherIo.numberofsegments = 0;
767 mesherIo.numberofholes = 0;
768 mesherIo.numberofregions = 0;
769 mesherIo.trianglelist = (
int *) NULL;
770 mesherIo.triangleattributelist = (
double *) NULL;
771 mesherIo.numberoftriangleattributes = 0;
772 mesherIo.edgelist = (
int *) NULL;
773 mesherIo.edgemarkerlist = (
int *) NULL;
776 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
779 if (mesherIo.numberofpoints != 0)
781 mesherIo.numberofpoints=0;
782 free(mesherIo.pointlist);
786 free(mesherIo.pointattributelist);
787 free(mesherIo.pointmarkerlist);
788 free(mesherIo.trianglelist);
789 free(mesherIo.triangleattributelist);
790 free(mesherIo.edgelist);
791 free(mesherIo.edgemarkerlist);
794 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
795 template <
class MESHER_IO>
800 mesherInput.pointlist = (
double *) malloc(this->
GetNumNodes() * SPACE_DIM *
sizeof(
double));
804 mesherInput.pointlist =
new double[this->
GetNumNodes() * SPACE_DIM];
808 unsigned new_index = 0;
811 if (this->
mNodes[i]->IsDeleted())
818 for (
unsigned j=0; j<SPACE_DIM; j++)
820 mesherInput.pointlist[SPACE_DIM*new_index + j] = this->
mNodes[i]->rGetLocation()[j];
825 if (elementList != NULL)
827 unsigned element_index = 0;
830 mesherInput.numberofcorners=ELEMENT_DIM+1;
836 for (
unsigned j=0; j<=ELEMENT_DIM; j++)
838 elementList[element_index*(ELEMENT_DIM+1) + j] = (*elem_iter).GetNodeGlobalIndex(j);
845 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
846 template <
class MESHER_IO>
849 unsigned nodes_per_element = mesherOutput.numberofcorners;
851 assert( nodes_per_element == ELEMENT_DIM+1 || nodes_per_element == (ELEMENT_DIM+1)*(ELEMENT_DIM+2)/2 );
856 for (
unsigned node_index=0; node_index<(
unsigned)mesherOutput.numberofpoints; node_index++)
858 this->
mNodes.push_back(
new Node<SPACE_DIM>(node_index, &mesherOutput.pointlist[node_index * SPACE_DIM],
false));
862 this->
mElements.reserve(numberOfElements);
864 unsigned real_element_index=0;
865 for (
unsigned element_index=0; element_index<numberOfElements; element_index++)
867 std::vector<Node<SPACE_DIM>*> nodes;
868 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
870 unsigned global_node_index = elementList[element_index*(nodes_per_element) + j];
871 assert(global_node_index < this->
mNodes.size());
872 nodes.push_back(this->
mNodes[global_node_index]);
889 for (
unsigned j=ELEMENT_DIM+1; j<nodes_per_element; j++)
891 unsigned global_node_index = elementList[element_index*nodes_per_element + j];
892 assert(global_node_index < this->
mNodes.size());
893 this->
mElements[real_element_index]->AddNode( this->
mNodes[global_node_index] );
894 this->
mNodes[global_node_index]->AddElement(real_element_index);
895 this->
mNodes[global_node_index]->MarkAsInternal();
897 real_element_index++;
903 WARNING(
"Triangle has produced a zero area (collinear) element");
907 WARNING(
"Tetgen has produced a zero volume (coplanar) element");
913 unsigned next_boundary_element_index = 0;
914 for (
unsigned boundary_element_index=0; boundary_element_index<numberOfFaces; boundary_element_index++)
920 if (edgeMarkerList == NULL || edgeMarkerList[boundary_element_index] == 1)
922 std::vector<Node<SPACE_DIM>*> nodes;
923 for (
unsigned j=0; j<ELEMENT_DIM; j++)
925 unsigned global_node_index = faceList[boundary_element_index*ELEMENT_DIM + j];
926 assert(global_node_index < this->
mNodes.size());
927 nodes.push_back(this->
mNodes[global_node_index]);
928 if (!nodes[j]->IsBoundaryNode())
930 nodes[j]->SetAsBoundaryNode();
942 p_b_element =
new BoundaryElement<ELEMENT_DIM-1, SPACE_DIM>(next_boundary_element_index, nodes);
944 next_boundary_element_index++;
949 assert(SPACE_DIM == 3);
1027 #define CHASTE_SERIALIZATION_CPP
std::vector< c_matrix< double, SPACE_DIM, ELEMENT_DIM > > mElementJacobians
ElementIterator GetElementIteratorBegin(bool skipDeletedElements=true)
double GetAngleBetweenNodes(unsigned indexA, unsigned indexB)
std::vector< Element< ELEMENT_DIM, SPACE_DIM > * > mElements
void SetAttribute(double attribute)
std::vector< Node< SPACE_DIM > * > mBoundaryNodes
void ImportFromMesher(MESHER_IO &mesherOutput, unsigned numberOfElements, int *elementList, unsigned numberOfFaces, int *faceList, int *edgeMarkerList)
virtual ElementData GetNextElementData()=0
std::vector< unsigned > GetContainingElementIndices(const ChastePoint< SPACE_DIM > &rTestPoint)
BoundaryElementIterator GetBoundaryElementIteratorBegin() const
unsigned GetNodeGlobalIndex(unsigned localIndex) const
virtual void GetWeightedDirectionForBoundaryElement(unsigned elementIndex, c_vector< double, SPACE_DIM > &rWeightedDirection, double &rJacobianDeterminant) const
void AddNodeAttribute(double attribute)
unsigned GetContainingElementIndexWithInitialGuess(const ChastePoint< SPACE_DIM > &rTestPoint, unsigned startingElementGuess, bool strict=false)
ElementIterator GetElementIteratorEnd()
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 void RefreshJacobianCachedData()
std::vector< c_matrix< double, ELEMENT_DIM, SPACE_DIM > > mElementInverseJacobians
Element< ELEMENT_DIM, SPACE_DIM > * GetElement(unsigned index) const
void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
virtual unsigned GetNumNodes() const
virtual void GetJacobianForElement(unsigned elementIndex, c_matrix< double, SPACE_DIM, SPACE_DIM > &rJacobian, double &rJacobianDeterminant) const
virtual unsigned GetNumAllNodes() const
unsigned mNodeBLocalIndex
Node< SPACE_DIM > * GetNodeA()
unsigned mNodeALocalIndex
void Shuffle(std::vector< boost::shared_ptr< T > > &rValues)
virtual ElementData GetNextFaceData()=0
std::vector< unsigned > NodeIndices
void SetNewIndex(unsigned oldIndex, unsigned newIndex)
EdgeIterator(TetrahedralMesh &rMesh, unsigned elemIndex)
Node< SPACE_DIM > * GetNode(unsigned localIndex) const
virtual bool HasNodePermutation()
Node< SPACE_DIM > * GetNodeB()
void ReadNodesPerProcessorFile(const std::string &rNodesPerProcessorFile)
unsigned SolveBoundaryElementMapping(unsigned index) const
std::vector< Node< SPACE_DIM > * > mNodes
virtual unsigned GetNumElements() const =0
void InitialiseTriangulateIo(triangulateio &mesherIo)
std::vector< BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > * > mBoundaryElements
unsigned SolveElementMapping(unsigned index) const
void SetDeleted(unsigned index)
std::vector< double > mElementJacobianDeterminants
unsigned GetNearestElementIndex(const ChastePoint< SPACE_DIM > &rTestPoint)
std::vector< c_vector< double, SPACE_DIM > > mBoundaryElementWeightedDirections
static RandomNumberGenerator * Instance()
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
virtual unsigned GetNumFaceAttributes() const
bool operator!=(const typename TetrahedralMesh< ELEMENT_DIM, SPACE_DIM >::EdgeIterator &rOther)
virtual unsigned GetNumElementAttributes() const
unsigned GetNumAllElements() const
EdgeIterator EdgesBegin()
unsigned SolveNodeMapping(unsigned index) const
std::vector< double > mBoundaryElementJacobianDeterminants
unsigned GetNumAllBoundaryElements() const
virtual void GetWeightedDirectionForElement(unsigned elementIndex, c_vector< double, SPACE_DIM > &rWeightedDirection, double &rJacobianDeterminant) const
virtual std::string GetMeshFileBaseName()
EdgeIterator & operator++()
virtual std::vector< double > GetNextNode()=0
std::vector< BoundaryElement< ELEMENT_DIM-1, SPACE_DIM > * >::const_iterator BoundaryElementIterator
std::vector< c_vector< double, SPACE_DIM > > mElementWeightedDirections
void ExportToMesher(NodeMap &map, MESHER_IO &mesherInput, int *elementList=NULL)
std::set< std::pair< unsigned, unsigned > > mEdgesVisited
virtual unsigned GetNumNodes() const =0
void FreeTriangulateIo(triangulateio &mesherIo)
virtual std::vector< double > GetNodeAttributes()
virtual unsigned GetNumFaces() const =0
BoundaryElementIterator GetBoundaryElementIteratorEnd() const