36 #include "DistributedTetrahedralMesh.hpp"
43 #include <boost/scoped_array.hpp>
46 #include "Element.hpp"
47 #include "BoundaryElement.hpp"
50 #include "DistributedVectorFactory.hpp"
51 #include "OutputFileHandler.hpp"
52 #include "NodePartitioner.hpp"
54 #include "RandomNumberGenerator.hpp"
57 #include "TetrahedralMesh.hpp"
61 #if (PARMETIS_MAJOR_VERSION >= 4) //ParMETIS 4.x and above
73 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
76 mTotalNumElements(0u),
77 mTotalNumBoundaryElements(0u),
80 mMetisPartitioning(partitioningMethod)
82 if (ELEMENT_DIM == 1 && (partitioningMethod != DistributedTetrahedralMeshPartitionType::GEOMETRIC))
89 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
92 for (
unsigned i=0; i<this->mHaloNodes.size(); i++)
94 delete this->mHaloNodes[i];
98 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
102 mMetisPartitioning = DistributedTetrahedralMeshPartitionType::DUMB;
105 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
108 std::set<unsigned>& rNodesOwned,
109 std::set<unsigned>& rHaloNodesOwned,
110 std::set<unsigned>& rElementsOwned,
111 std::vector<unsigned>& rProcessorsOffset)
114 if (mMetisPartitioning==DistributedTetrahedralMeshPartitionType::PARMETIS_LIBRARY &&
PetscTools::IsParallel())
120 ParMetisLibraryNodeAndElementPartitioning(rMeshReader, rElementsOwned, rNodesOwned, rHaloNodesOwned, rProcessorsOffset);
127 if (mMetisPartitioning==DistributedTetrahedralMeshPartitionType::METIS_LIBRARY &&
PetscTools::IsParallel())
131 else if (mMetisPartitioning==DistributedTetrahedralMeshPartitionType::PETSC_MAT_PARTITION &&
PetscTools::IsParallel())
135 else if (mMetisPartitioning==DistributedTetrahedralMeshPartitionType::GEOMETRIC &&
PetscTools::IsParallel())
139 EXCEPTION(
"Using GEOMETRIC partition for DistributedTetrahedralMesh with local regions not set. Call SetProcessRegion(ChasteCuboid)");
152 for ( std::set<unsigned>::iterator iter=rNodesOwned.begin();
153 iter!=rNodesOwned.end();
157 rElementsOwned.insert( containing_elements.begin(), containing_elements.end() );
162 std::set<unsigned> node_index_set;
164 for ( std::set<unsigned>::iterator iter=rElementsOwned.begin();
165 iter!=rElementsOwned.end();
174 std::set_difference(node_index_set.begin(), node_index_set.end(),
175 rNodesOwned.begin(), rNodesOwned.end(),
176 std::inserter(rHaloNodesOwned, rHaloNodesOwned.begin()));
180 for (
unsigned element_number = 0; element_number < mTotalNumElements; element_number++)
184 bool element_owned =
false;
185 std::set<unsigned> temp_halo_nodes;
187 for (std::vector<unsigned>::const_iterator it = element_data.
NodeIndices.begin();
191 if (rNodesOwned.find(*it) != rNodesOwned.end())
193 element_owned =
true;
194 rElementsOwned.insert(element_number);
198 temp_halo_nodes.insert(*it);
204 rHaloNodesOwned.insert(temp_halo_nodes.begin(), temp_halo_nodes.end());
209 if (mMetisPartitioning==DistributedTetrahedralMeshPartitionType::PETSC_MAT_PARTITION &&
PetscTools::IsParallel())
221 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
225 std::set<unsigned> nodes_owned;
226 std::set<unsigned> halo_nodes_owned;
227 std::set<unsigned> elements_owned;
228 std::vector<unsigned> proc_offsets;
232 mTotalNumBoundaryElements = rMeshReader.
GetNumFaces();
238 ComputeMeshPartitioning(rMeshReader, nodes_owned, halo_nodes_owned, elements_owned, proc_offsets);
243 this->mElements.reserve(elements_owned.size());
244 this->mNodes.reserve(nodes_owned.size());
250 std::vector<double> coords;
257 unsigned global_node_index = node_it.GetIndex();
259 RegisterNode(global_node_index);
269 this->mNodes.push_back(p_node);
276 unsigned global_node_index = node_it.
GetIndex();
278 RegisterHaloNode(global_node_index);
279 mHaloNodes.push_back(
new Node<SPACE_DIM>(global_node_index, coords,
false));
286 for (
unsigned node_index=0; node_index < mTotalNumNodes; node_index++)
288 std::vector<double> coords;
293 if (nodes_owned.find(node_index) != nodes_owned.end())
295 RegisterNode(node_index);
304 this->mNodes.push_back(p_node);
308 if (halo_nodes_owned.find(node_index) != halo_nodes_owned.end())
310 RegisterHaloNode(node_index);
322 unsigned global_element_index = elem_it.GetIndex();
324 std::vector<Node<SPACE_DIM>*> nodes;
325 for (
unsigned j=0; j<ELEMENT_DIM+1; j++)
328 nodes.push_back(this->GetNodeOrHaloNode(element_data.
NodeIndices[j]));
331 RegisterElement(global_element_index);
333 this->mElements.push_back(p_element);
346 for (
unsigned face_index=0; face_index<mTotalNumBoundaryElements; face_index++)
349 std::vector<unsigned> node_indices = face_data.
NodeIndices;
353 for (
unsigned node_index=0; node_index<node_indices.size(); node_index++)
356 if (mNodesMapping.find(node_indices[node_index]) != mNodesMapping.end())
370 std::vector<Node<SPACE_DIM>*> nodes;
372 for (
unsigned node_index=0; node_index<node_indices.size(); node_index++)
378 nodes.push_back(this->GetNodeOrHaloNode(node_indices[node_index]));
382 EXCEPTION(
"Face does not appear in element file (Face " << face_index <<
" in "<<this->mMeshFileBaseName<<
")");
388 for (
unsigned j=0; j<nodes.size(); j++)
390 if (!nodes[j]->IsBoundaryNode())
392 nodes[j]->SetAsBoundaryNode();
393 this->mBoundaryNodes.push_back(nodes[j]);
396 nodes[j]->AddBoundaryElement(face_index);
399 RegisterBoundaryElement(face_index);
401 this->mBoundaryElements.push_back(p_boundary_element);
419 assert(this->mNodePermutation.size() != 0);
430 num_owned = proc_offsets[rank+1]-proc_offsets[rank];
434 num_owned = mTotalNumNodes - proc_offsets[rank];
437 assert(!this->mpDistributedVectorFactory);
443 assert(this->mpDistributedVectorFactory);
455 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
458 return this->mNodes.size();
461 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
464 return this->mHaloNodes.size();
467 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
470 return this->mElements.size();
473 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
476 return this->mBoundaryElements.size();
479 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
482 return mTotalNumNodes;
485 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
488 return mTotalNumNodes;
491 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
494 return mTotalNumElements;
497 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
500 return mMetisPartitioning;
503 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
506 return mTotalNumBoundaryElements;
509 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
513 rHaloIndices.clear();
514 for (
unsigned i=0; i<mHaloNodes.size(); i++)
516 rHaloIndices.push_back(mHaloNodes[i]->GetIndex());
520 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
523 if (mpSpaceRegion == NULL)
525 EXCEPTION(
"Trying to get unset mpSpaceRegion");
527 return mpSpaceRegion;
530 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
537 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
540 mpSpaceRegion = pRegion;
543 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
556 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
569 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
572 mNodesMapping[index] = this->mNodes.size();
575 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
578 mHaloNodesMapping[index] = mHaloNodes.size();
581 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
584 mElementsMapping[index] = this->mElements.size();
587 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
590 mBoundaryElementsMapping[index] = this->mBoundaryElements.size();
593 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
596 std::map<unsigned, unsigned>::const_iterator node_position = mNodesMapping.find(index);
598 if (node_position == mNodesMapping.end())
602 return node_position->second;
612 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
615 std::map<unsigned, unsigned>::const_iterator element_position = mElementsMapping.find(index);
617 if (element_position == mElementsMapping.end())
622 return element_position->second;
625 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
628 std::map<unsigned, unsigned>::const_iterator boundary_element_position = mBoundaryElementsMapping.find(index);
630 if (boundary_element_position == mBoundaryElementsMapping.end())
635 return boundary_element_position->second;
638 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
641 std::map<unsigned, unsigned>::const_iterator node_position;
643 if ((node_position=mHaloNodesMapping.find(index)) != mHaloNodesMapping.end())
645 return mHaloNodes[node_position->second];
648 if ((node_position=mNodesMapping.find(index)) != mNodesMapping.end())
651 return this->mNodes[node_position->second];
657 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
663 mNodesMapping.clear();
664 mHaloNodesMapping.clear();
667 for (
unsigned index=0; index<this->mNodes.size(); index++)
669 unsigned old_index = this->mNodes[index]->GetIndex();
670 unsigned new_index = this->mNodePermutation[old_index];
672 this->mNodes[index]->SetIndex(new_index);
673 mNodesMapping[new_index] = index;
676 for (
unsigned index=0; index<mHaloNodes.size(); index++)
678 unsigned old_index = mHaloNodes[index]->GetIndex();
679 unsigned new_index = this->mNodePermutation[old_index];
681 mHaloNodes[index]->SetIndex(new_index);
682 mHaloNodesMapping[new_index] = index;
686 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
689 assert(ELEMENT_DIM == 1);
694 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
698 if(mMetisPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
702 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
720 this->ConstructFromMeshReader(mesh_reader);
725 mMetisPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
726 mTotalNumNodes=width+1;
727 mTotalNumBoundaryElements=2u;
728 mTotalNumElements=width;
731 assert(!this->mpDistributedVectorFactory);
733 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
743 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
745 unsigned lo_node=this->mpDistributedVectorFactory->GetLow();
746 unsigned hi_node=this->mpDistributedVectorFactory->GetHigh();
758 for (
unsigned node_index=lo_node; node_index<hi_node; node_index++)
762 if (node_index<this->mpDistributedVectorFactory->GetLow() ||
763 node_index==this->mpDistributedVectorFactory->GetHigh() )
766 RegisterHaloNode(node_index);
767 mHaloNodes.push_back(p_node);
771 RegisterNode(node_index);
772 this->mNodes.push_back(p_node);
778 this->mBoundaryNodes.push_back(p_node);
779 RegisterBoundaryElement(0);
782 if (node_index==width)
784 this->mBoundaryNodes.push_back(p_node);
785 RegisterBoundaryElement(1);
789 if (node_index>lo_node)
791 std::vector<Node<SPACE_DIM>*> nodes;
792 nodes.push_back(p_old_node);
793 nodes.push_back(p_node);
794 RegisterElement(node_index-1);
803 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
806 assert(SPACE_DIM == 2);
807 assert(ELEMENT_DIM == 2);
811 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
815 if(mMetisPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
819 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
837 this->ConstructFromMeshReader(mesh_reader);
842 mMetisPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
844 mTotalNumNodes=(width+1)*(height+1);
845 mTotalNumBoundaryElements=(width+height)*2;
846 mTotalNumElements=width*height*2;
850 unsigned lo_y = y_partition.
GetLow();
851 unsigned hi_y = y_partition.
GetHigh();
853 assert(!this->mpDistributedVectorFactory);
855 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
864 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
879 for (
unsigned j=lo_y; j<hi_y; j++)
881 for (
unsigned i=0; i<width+1; i++)
883 bool is_boundary=
false;
884 if (i==0 || j==0 || i==width || j==height)
888 unsigned global_node_index=((width+1)*(j) + i);
893 RegisterHaloNode(global_node_index);
894 mHaloNodes.push_back(p_node);
898 RegisterNode(global_node_index);
899 this->mNodes.push_back(p_node);
903 this->mBoundaryNodes.push_back(p_node);
909 unsigned belem_index;
913 for (
unsigned i=0; i<width; i++)
915 std::vector<Node<SPACE_DIM>*> nodes;
916 nodes.push_back(GetNodeOrHaloNode( height*(width+1)+i+1 ));
917 nodes.push_back(GetNodeOrHaloNode( height*(width+1)+i ));
919 RegisterBoundaryElement(belem_index);
925 for (
unsigned j=lo_y+1; j<hi_y; j++)
927 std::vector<Node<SPACE_DIM>*> nodes;
928 nodes.push_back(GetNodeOrHaloNode( (width+1)*j-1 ));
929 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j+1)-1 ));
930 belem_index=width+j-1;
931 RegisterBoundaryElement(belem_index);
938 for (
unsigned i=0; i<width; i++)
940 std::vector<Node<SPACE_DIM>*> nodes;
941 nodes.push_back(GetNodeOrHaloNode( i ));
942 nodes.push_back(GetNodeOrHaloNode( i+1 ));
943 belem_index=width+height+i;
944 RegisterBoundaryElement(belem_index);
950 for (
unsigned j=lo_y; j<hi_y-1; j++)
952 std::vector<Node<SPACE_DIM>*> nodes;
953 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j+1) ));
954 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j) ));
955 belem_index=2*width+height+j;
956 RegisterBoundaryElement(belem_index);
963 for (
unsigned j=lo_y; j<hi_y-1; j++)
965 for (
unsigned i=0; i<width; i++)
967 unsigned parity=(i+(height-j))%2;
968 unsigned nw=(j+1)*(width+1)+i;
969 unsigned sw=(j)*(width+1)+i;
970 std::vector<Node<SPACE_DIM>*> upper_nodes;
971 upper_nodes.push_back(GetNodeOrHaloNode( nw ));
972 upper_nodes.push_back(GetNodeOrHaloNode( nw+1 ));
973 if (stagger==
false || parity == 1)
975 upper_nodes.push_back(GetNodeOrHaloNode( sw+1 ));
979 upper_nodes.push_back(GetNodeOrHaloNode( sw ));
981 elem_index=2*(j*width+i);
982 RegisterElement(elem_index);
984 std::vector<Node<SPACE_DIM>*> lower_nodes;
985 lower_nodes.push_back(GetNodeOrHaloNode( sw+1 ));
986 lower_nodes.push_back(GetNodeOrHaloNode( sw ));
987 if (stagger==
false ||parity == 1)
989 lower_nodes.push_back(GetNodeOrHaloNode( nw ));
993 lower_nodes.push_back(GetNodeOrHaloNode( nw+1 ));
996 RegisterElement(elem_index);
1004 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1009 assert(SPACE_DIM == 3);
1010 assert(ELEMENT_DIM == 3);
1014 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
1018 if(mMetisPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
1022 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
1040 this->ConstructFromMeshReader(mesh_reader);
1045 mMetisPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
1047 mTotalNumNodes=(width+1)*(height+1)*(depth+1);
1048 mTotalNumBoundaryElements=((width*height)+(width*depth)+(height*depth))*4;
1049 mTotalNumElements=width*height*depth*6;
1053 unsigned lo_z = z_partition.
GetLow();
1054 unsigned hi_z = z_partition.
GetHigh();
1057 assert(!this->mpDistributedVectorFactory);
1059 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
1067 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
1081 unsigned global_node_index;
1082 for (
unsigned k=lo_z; k<hi_z; k++)
1084 for (
unsigned j=0; j<height+1; j++)
1086 for (
unsigned i=0; i<width+1; i++)
1088 bool is_boundary =
false;
1089 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
1093 global_node_index = (k*(height+1)+j)*(width+1)+i;
1100 RegisterHaloNode(global_node_index);
1101 mHaloNodes.push_back(p_node);
1105 RegisterNode(global_node_index);
1106 this->mNodes.push_back(p_node);
1111 this->mBoundaryNodes.push_back(p_node);
1119 unsigned element_nodes[6][4] = {{0, 1, 5, 7}, {0, 1, 3, 7},
1120 {0, 2, 3, 7}, {0, 2, 6, 7},
1121 {0, 4, 6, 7}, {0, 4, 5, 7}};
1122 std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
1124 for (
unsigned k=lo_z; k<hi_z-1; k++)
1126 unsigned belem_index = 0;
1130 belem_index = 2*(height*width+k*2*(height+width));
1133 for (
unsigned j=0; j<height; j++)
1135 for (
unsigned i=0; i<width; i++)
1138 unsigned global_node_indices[8];
1139 unsigned local_node_index = 0;
1141 for (
unsigned z = 0; z < 2; z++)
1143 for (
unsigned y = 0; y < 2; y++)
1145 for (
unsigned x = 0; x < 2; x++)
1147 global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
1154 for (
unsigned m = 0; m < 6; m++)
1158 tetrahedra_nodes.clear();
1160 for (
unsigned n = 0; n < 4; n++)
1162 tetrahedra_nodes.push_back(GetNodeOrHaloNode( global_node_indices[element_nodes[m][n]] ));
1164 unsigned elem_index = 6 * ((k*height+j)*width+i)+m;
1165 RegisterElement(elem_index);
1170 std::vector<Node<SPACE_DIM>*> triangle_nodes;
1174 triangle_nodes.clear();
1175 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1176 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1177 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1178 RegisterBoundaryElement(belem_index);
1180 triangle_nodes.clear();
1181 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1182 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1183 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1184 RegisterBoundaryElement(belem_index);
1189 triangle_nodes.clear();
1190 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1191 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1192 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1193 RegisterBoundaryElement(belem_index);
1195 triangle_nodes.clear();
1196 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1197 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1198 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1199 RegisterBoundaryElement(belem_index);
1204 triangle_nodes.clear();
1205 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1206 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1207 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1208 RegisterBoundaryElement(belem_index);
1210 triangle_nodes.clear();
1211 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1212 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1213 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1214 RegisterBoundaryElement(belem_index);
1219 triangle_nodes.clear();
1220 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1221 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1222 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1223 RegisterBoundaryElement(belem_index);
1225 triangle_nodes.clear();
1226 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1227 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1228 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1229 RegisterBoundaryElement(belem_index);
1234 triangle_nodes.clear();
1235 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1236 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1237 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1238 RegisterBoundaryElement(belem_index);
1240 triangle_nodes.clear();
1241 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1242 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1243 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1244 RegisterBoundaryElement(belem_index);
1249 triangle_nodes.clear();
1250 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1251 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1252 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1253 RegisterBoundaryElement(belem_index);
1255 triangle_nodes.clear();
1256 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1257 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1258 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1259 RegisterBoundaryElement(belem_index);
1268 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1274 for (
unsigned i=0; i<mHaloNodes.size(); i++)
1276 c_vector<double, SPACE_DIM>& r_location = mHaloNodes[i]->rGetModifiableLocation();
1279 r_location[2] *= zFactor;
1283 r_location[1] *= yFactor;
1285 r_location[0] *= xFactor;
1291 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1294 std::set<unsigned>& rElementsOwned,
1295 std::set<unsigned>& rNodesOwned,
1296 std::set<unsigned>& rHaloNodesOwned,
1297 std::vector<unsigned>& rProcessorsOffset)
1300 assert(ELEMENT_DIM==2 || ELEMENT_DIM==3);
1309 boost::scoped_array<idxtype> element_distribution(
new idxtype[num_procs+1]);
1310 boost::scoped_array<int> element_counts(
new int[num_procs]);
1312 element_distribution[0] = 0;
1314 for (
unsigned proc_index=1; proc_index<num_procs; proc_index++)
1316 element_distribution[proc_index] = element_distribution[proc_index-1] + num_elements/num_procs;
1317 element_counts[proc_index-1] = element_distribution[proc_index] - element_distribution[proc_index-1];
1320 element_distribution[num_procs] = num_elements;
1321 element_counts[num_procs-1] = element_distribution[num_procs] - element_distribution[num_procs-1];
1326 idxtype first_local_element = element_distribution[local_proc_index];
1327 idxtype last_plus_one_element = element_distribution[local_proc_index+1];
1328 idxtype num_local_elements = last_plus_one_element - first_local_element;
1330 boost::scoped_array<idxtype> eind(
new idxtype[num_local_elements*(ELEMENT_DIM+1)]);
1331 boost::scoped_array<idxtype> eptr(
new idxtype[num_local_elements+1]);
1341 for (idxtype element_index = 0; element_index < first_local_element; element_index++)
1347 unsigned counter = 0;
1348 for (idxtype element_index = 0; element_index < num_local_elements; element_index++)
1354 eptr[element_index] = counter;
1355 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
1360 eptr[num_local_elements] = counter;
1362 rMeshReader.
Reset();
1364 idxtype numflag = 0;
1372 idxtype ncommonnodes = 3;
1373 if (ELEMENT_DIM == 2)
1378 MPI_Comm communicator = PETSC_COMM_WORLD;
1384 ParMETIS_V3_Mesh2Dual(element_distribution.get(), eptr.get(), eind.get(),
1385 &numflag, &ncommonnodes, &xadj, &adjncy, &communicator);
1392 idxtype weight_flag = 0;
1393 idxtype n_constraints = 1;
1398 boost::scoped_array<real_t> tpwgts(
new real_t[n_subdomains]);
1399 real_t ubvec_value = (real_t)1.05;
1402 tpwgts[proc] = ((real_t)1.0)/n_subdomains;
1404 boost::scoped_array<idxtype> local_partition(
new idxtype[num_local_elements]);
1420 ParMETIS_V3_PartKway(element_distribution.get(), xadj, adjncy, NULL, NULL, &weight_flag, &numflag,
1421 &n_constraints, &n_subdomains, tpwgts.get(), &ubvec_value,
1422 options, &edgecut, local_partition.get(), &communicator);
1426 boost::scoped_array<idxtype> global_element_partition(
new idxtype[num_elements]);
1429 MPI_Datatype mpi_idxtype = MPI_LONG_LONG_INT;
1430 if (
sizeof(idxtype) ==
sizeof(
int))
1432 mpi_idxtype = MPI_INT;
1434 boost::scoped_array<int> int_element_distribution(
new int[num_procs+1]);
1435 for (
unsigned i=0; i<num_procs+1; ++i)
1437 int_element_distribution[i] = element_distribution[i];
1439 MPI_Allgatherv(local_partition.get(), num_local_elements, mpi_idxtype,
1440 global_element_partition.get(), element_counts.get(), int_element_distribution.get(), mpi_idxtype, PETSC_COMM_WORLD);
1442 local_partition.reset();
1444 for (
unsigned elem_index=0; elem_index<num_elements; elem_index++)
1446 if ((
unsigned) global_element_partition[elem_index] == local_proc_index)
1448 rElementsOwned.insert(elem_index);
1452 rMeshReader.
Reset();
1459 std::vector<unsigned> global_node_partition(num_nodes, UNASSIGNED_NODE);
1461 assert(rProcessorsOffset.size() == 0);
1462 rProcessorsOffset.resize(PetscTools::GetNumProcs(), 0);
1487 for (
unsigned element_number = 0; element_number < mTotalNumElements; element_number++)
1489 unsigned element_owner = global_element_partition[element_number];
1495 for (std::vector<unsigned>::const_iterator node_it = element_data.
NodeIndices.begin();
1503 if ( global_node_partition[*node_it] == UNASSIGNED_NODE )
1505 if (element_owner == local_proc_index)
1507 rNodesOwned.insert(*node_it);
1510 global_node_partition[*node_it] = element_owner;
1517 rProcessorsOffset[proc]++;
1522 if (element_owner == local_proc_index)
1525 if (global_node_partition[*node_it] != local_proc_index)
1527 rHaloNodesOwned.insert(*node_it);
1547 rElementsOwned.clear();
1548 rMeshReader.
Reset();
1549 for (
unsigned element_number = 0; element_number < mTotalNumElements; element_number++)
1553 bool element_owned =
false;
1554 std::set<unsigned> temp_halo_nodes;
1556 for (std::vector<unsigned>::const_iterator node_it = element_data.
NodeIndices.begin();
1560 if (rNodesOwned.find(*node_it) != rNodesOwned.end())
1562 element_owned =
true;
1563 rElementsOwned.insert(element_number);
1567 temp_halo_nodes.insert(*node_it);
1573 rHaloNodesOwned.insert(temp_halo_nodes.begin(), temp_halo_nodes.end());
1577 rMeshReader.
Reset();
1582 std::vector<unsigned> local_index(PetscTools::GetNumProcs(), 0);
1584 this->mNodePermutation.resize(this->GetNumNodes());
1586 for (
unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
1588 unsigned partition = global_node_partition[node_index];
1589 assert(partition != UNASSIGNED_NODE);
1591 this->mNodePermutation[node_index] = rProcessorsOffset[partition] + local_index[partition];
1593 local_index[partition]++;
1597 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1611 #define COVERAGE_IGNORE
1614 #undef COVERAGE_IGNORE
1619 c_vector<double, SPACE_DIM> global_minimum_point;
1620 c_vector<double, SPACE_DIM> global_maximum_point;
1621 MPI_Allreduce(&my_minimum_point.
rGetLocation()[0], &global_minimum_point[0], SPACE_DIM, MPI_DOUBLE, MPI_MIN, PETSC_COMM_WORLD);
1622 MPI_Allreduce(&my_maximum_point.
rGetLocation()[0], &global_maximum_point[0], SPACE_DIM, MPI_DOUBLE, MPI_MAX, PETSC_COMM_WORLD);
1630 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1637 double best_node_point_distance = DBL_MAX;
1638 if (best_node_index != UINT_MAX)
1640 best_node_point_distance = norm_2(this->GetNode(best_node_index)->rGetLocation() - rTestPoint.
rGetLocation());
1652 value.node_index = best_node_index;
1653 value.distance = best_node_point_distance;
1655 MPI_Allreduce( &value, &minval, 1, MPI_DOUBLE_INT, MPI_MINLOC, MPI_COMM_WORLD );
1657 return minval.node_index;
1660 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1664 c_vector<double, 2> global_min_max;
1666 MPI_Allreduce(&local_min_max[0], &global_min_max[0], 1, MPI_DOUBLE, MPI_MIN, PETSC_COMM_WORLD);
1667 MPI_Allreduce(&local_min_max[1], &global_min_max[1], 1, MPI_DOUBLE, MPI_MAX, PETSC_COMM_WORLD);
1669 return global_min_max;
1672 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1675 return mHaloNodes.begin();
1678 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1682 for (
unsigned i=0; i<this->mHaloNodes.size(); i++)
1684 c_vector<double, SPACE_DIM>& r_location = this->mHaloNodes[i]->rGetModifiableLocation();
1685 r_location = prod(rotationMatrix, r_location);
1688 for (
unsigned i=0; i<this->mNodes.size(); i++)
1690 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
1691 r_location = prod(rotationMatrix, r_location);
1695 template<
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1699 for (
unsigned i=0; i<this->mHaloNodes.size(); i++)
1701 c_vector<double, SPACE_DIM>& r_location = this->mHaloNodes[i]->rGetModifiableLocation();
1702 r_location += rDisplacement;
1705 for (
unsigned i=0; i<this->mNodes.size(); i++)
1707 c_vector<double, SPACE_DIM>& r_location = this->mNodes[i]->rGetModifiableLocation();
1708 r_location += rDisplacement;
1712 template <
unsigned ELEMENT_DIM,
unsigned SPACE_DIM>
1715 return mHaloNodes.end();
ElementIterator GetElementIteratorBegin()
void SetAttribute(double attribute)
void ConstructLinearMesh(unsigned width)
unsigned GetNumLocalNodes() const
unsigned GetNumBoundaryElements() const
virtual unsigned GetNearestNodeIndex(const ChastePoint< SPACE_DIM > &rTestPoint)
virtual ElementData GetNextElementData()=0
virtual ElementData GetElementData(unsigned index)
c_vector< double, DIM > & rGetLocation()
void RegisterNode(unsigned index)
DistributedTetrahedralMeshPartitionType::type GetPartitionType() const
void Rotate(c_matrix< double, SPACE_DIM, SPACE_DIM > rotationMatrix)
void AddNodeAttribute(double attribute)
NodeIterator GetNodeIteratorEnd()
void SetProcessRegion(ChasteCuboid< SPACE_DIM > *pRegion)
NodeIterator GetNodeIteratorBegin()
#define EXCEPTION(message)
DistributedTetrahedralMeshPartitionType::type mMetisPartitioning
std::vector< Node< SPACE_DIM > * >::const_iterator HaloNodeIterator
virtual void ConstructFromMeshReader(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader)
DistributedTetrahedralMesh(DistributedTetrahedralMeshPartitionType::type partitioningMethod=DistributedTetrahedralMeshPartitionType::PARMETIS_LIBRARY)
unsigned GetNumNodes() const
void GetHaloNodeIndices(std::vector< unsigned > &rHaloIndices) const
static void DumbPartitioning(AbstractMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, std::set< unsigned > &rNodesOwned)
static void GeometricPartitioning(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader, std::vector< unsigned > &rNodePermutation, std::set< unsigned > &rNodesOwned, std::vector< unsigned > &rProcessorsOffset, ChasteCuboid< SPACE_DIM > *pRegion)
virtual ChasteCuboid< SPACE_DIM > CalculateBoundingBox() const
void SetDistributedVectorFactory(DistributedVectorFactory *pFactory)
bool CalculateDesignatedOwnershipOfBoundaryElement(unsigned faceIndex)
static void PrintAndReset(std::string message)
void ComputeMeshPartitioning(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader, std::set< unsigned > &rNodesOwned, std::set< unsigned > &rHaloNodesOwned, std::set< unsigned > &rElementsOwned, std::vector< unsigned > &rProcessorsOffset)
std::string GetOutputDirectoryFullPath() const
void RegisterElement(unsigned index)
HaloNodeIterator GetHaloNodeIteratorBegin() const
virtual ElementData GetNextFaceData()=0
std::vector< unsigned > NodeIndices
virtual bool HasNodePermutation()
HaloNodeIterator GetHaloNodeIteratorEnd() const
static void MetisLibraryPartitioning(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader, std::vector< unsigned > &rNodePermutation, std::set< unsigned > &rNodesOwned, std::vector< unsigned > &rProcessorsOffset)
void RegisterHaloNode(unsigned index)
unsigned GetNumElements() const
const ChastePoint< SPACE_DIM > & rGetUpperCorner() const
ElementIterator GetElementIteratorEnd()
static void PetscMatrixPartitioning(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader, std::vector< unsigned > &rNodePermutation, std::set< unsigned > &rNodesOwned, std::vector< unsigned > &rProcessorsOffset)
virtual unsigned GetNumElements() const =0
unsigned SolveBoundaryElementMapping(unsigned index) const
unsigned SolveNodeMapping(unsigned index) const
unsigned GetNumLocalElements() const
virtual bool HasNclFile()
void Translate(const c_vector< double, SPACE_DIM > &rDisplacement)
virtual void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true)
unsigned SolveElementMapping(unsigned index) const
#define EXPORT_TEMPLATE_CLASS_ALL_DIMS(CLASS)
virtual unsigned GetNumFaceAttributes() const
virtual unsigned GetNumElementAttributes() const
virtual c_vector< double, 2 > CalculateMinMaxEdgeLengths()
Node< SPACE_DIM > * GetNodeOrHaloNode(unsigned index) const
virtual ChasteCuboid< SPACE_DIM > CalculateBoundingBox() const
virtual void ConstructCuboid(unsigned width, unsigned height, unsigned depth)
virtual void Scale(const double xFactor=1.0, const double yFactor=1.0, const double zFactor=1.0)
unsigned GetLocalOwnership() const
virtual bool IsFileFormatBinary()
void ConstructCuboid(unsigned width, unsigned height, unsigned depth)
void RegisterBoundaryElement(unsigned index)
unsigned GetNumAllNodes() const
ChasteCuboid< SPACE_DIM > * GetProcessRegion()
virtual unsigned GetNearestNodeIndex(const ChastePoint< SPACE_DIM > &rTestPoint)
unsigned GetNumLocalBoundaryElements() const
virtual std::vector< unsigned > GetContainingElementIndices(unsigned index)
unsigned GetNumHaloNodes() const
virtual void Scale(const double xFactor=1.0, const double yFactor=1.0, const double zFactor=1.0)
void ParMetisLibraryNodeAndElementPartitioning(AbstractMeshReader< ELEMENT_DIM, SPACE_DIM > &rMeshReader, std::set< unsigned > &rElementsOwned, std::set< unsigned > &rNodesOwned, std::set< unsigned > &rHaloNodesOwned, std::vector< unsigned > &rProcessorsOffset)
virtual std::string GetMeshFileBaseName()
virtual void SetDistributedVectorFactory(DistributedVectorFactory *pFactory)
virtual void ConstructLinearMesh(unsigned width)
virtual std::vector< double > GetNextNode()=0
unsigned GetIndex() const
bool CalculateDesignatedOwnershipOfElement(unsigned elementIndex)
virtual void WriteFilesUsingMesh(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, bool keepOriginalElementIndexing=true)
void ConstructRectangularMesh(unsigned width, unsigned height, bool stagger=true)
virtual c_vector< double, 2 > CalculateMinMaxEdgeLengths()
void SetElementOwnerships()
virtual ~DistributedTetrahedralMesh()
virtual unsigned GetNumNodes() const =0
virtual std::vector< double > GetNodeAttributes()
virtual unsigned GetNumFaces() const =0
virtual const std::vector< unsigned > & rGetNodePermutation()
const ChastePoint< SPACE_DIM > & rGetLowerCorner() const