699 assert(ELEMENT_DIM == 1);
704 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
708 if (mPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
712 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
730 this->ConstructFromMeshReader(mesh_reader);
735 mPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
736 mTotalNumNodes=width+1;
737 mTotalNumBoundaryElements=2u;
738 mTotalNumElements=width;
741 assert(!this->mpDistributedVectorFactory);
743 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
754 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
756 unsigned lo_node=this->mpDistributedVectorFactory->GetLow();
757 unsigned hi_node=this->mpDistributedVectorFactory->GetHigh();
769 for (
unsigned node_index=lo_node; node_index<hi_node; node_index++)
773 if (node_index<this->mpDistributedVectorFactory->GetLow() ||
774 node_index==this->mpDistributedVectorFactory->GetHigh() )
777 RegisterHaloNode(node_index);
778 mHaloNodes.push_back(p_node);
782 RegisterNode(node_index);
783 this->mNodes.push_back(p_node);
789 this->mBoundaryNodes.push_back(p_node);
790 RegisterBoundaryElement(0);
793 if (node_index==width)
795 this->mBoundaryNodes.push_back(p_node);
796 RegisterBoundaryElement(1);
800 if (node_index>lo_node)
802 std::vector<Node<SPACE_DIM>*> nodes;
803 nodes.push_back(p_old_node);
804 nodes.push_back(p_node);
805 RegisterElement(node_index-1);
817 assert(SPACE_DIM == 2);
818 assert(ELEMENT_DIM == 2);
822 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
826 if (mPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
830 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
848 this->ConstructFromMeshReader(mesh_reader);
853 mPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
855 mTotalNumNodes=(width+1)*(height+1);
856 mTotalNumBoundaryElements=(width+height)*2;
857 mTotalNumElements=width*height*2;
861 unsigned lo_y = y_partition.
GetLow();
862 unsigned hi_y = y_partition.
GetHigh();
864 assert(!this->mpDistributedVectorFactory);
866 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
877 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
892 for (
unsigned j=lo_y; j<hi_y; j++)
894 for (
unsigned i=0; i<width+1; i++)
896 bool is_boundary=
false;
897 if (i==0 || j==0 || i==width || j==height)
901 unsigned global_node_index=((width+1)*(j) + i);
906 RegisterHaloNode(global_node_index);
907 mHaloNodes.push_back(p_node);
911 RegisterNode(global_node_index);
912 this->mNodes.push_back(p_node);
916 this->mBoundaryNodes.push_back(p_node);
922 unsigned belem_index;
926 for (
unsigned i=0; i<width; i++)
928 std::vector<Node<SPACE_DIM>*> nodes;
929 nodes.push_back(GetNodeOrHaloNode( height*(width+1)+i+1 ));
930 nodes.push_back(GetNodeOrHaloNode( height*(width+1)+i ));
932 RegisterBoundaryElement(belem_index);
938 for (
unsigned j=lo_y+1; j<hi_y; j++)
940 std::vector<Node<SPACE_DIM>*> nodes;
941 nodes.push_back(GetNodeOrHaloNode( (width+1)*j-1 ));
942 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j+1)-1 ));
943 belem_index=width+j-1;
944 RegisterBoundaryElement(belem_index);
951 for (
unsigned i=0; i<width; i++)
953 std::vector<Node<SPACE_DIM>*> nodes;
954 nodes.push_back(GetNodeOrHaloNode( i ));
955 nodes.push_back(GetNodeOrHaloNode( i+1 ));
956 belem_index=width+height+i;
957 RegisterBoundaryElement(belem_index);
963 for (
unsigned j=lo_y; j<hi_y-1; j++)
965 std::vector<Node<SPACE_DIM>*> nodes;
966 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j+1) ));
967 nodes.push_back(GetNodeOrHaloNode( (width+1)*(j) ));
968 belem_index=2*width+height+j;
969 RegisterBoundaryElement(belem_index);
976 for (
unsigned j=lo_y; j<hi_y-1; j++)
978 for (
unsigned i=0; i<width; i++)
980 unsigned parity=(i+(height-j))%2;
981 unsigned nw=(j+1)*(width+1)+i;
982 unsigned sw=(j)*(width+1)+i;
983 std::vector<Node<SPACE_DIM>*> upper_nodes;
984 upper_nodes.push_back(GetNodeOrHaloNode( nw ));
985 upper_nodes.push_back(GetNodeOrHaloNode( nw+1 ));
986 if (stagger==
false || parity == 1)
988 upper_nodes.push_back(GetNodeOrHaloNode( sw+1 ));
992 upper_nodes.push_back(GetNodeOrHaloNode( sw ));
994 elem_index=2*(j*width+i);
995 RegisterElement(elem_index);
997 std::vector<Node<SPACE_DIM>*> lower_nodes;
998 lower_nodes.push_back(GetNodeOrHaloNode( sw+1 ));
999 lower_nodes.push_back(GetNodeOrHaloNode( sw ));
1000 if (stagger==
false ||parity == 1)
1002 lower_nodes.push_back(GetNodeOrHaloNode( nw ));
1006 lower_nodes.push_back(GetNodeOrHaloNode( nw+1 ));
1009 RegisterElement(elem_index);
1022 assert(SPACE_DIM == 3);
1023 assert(ELEMENT_DIM == 3);
1027 EXCEPTION(
"There aren't enough nodes to make parallelisation worthwhile");
1031 if (mPartitioning == DistributedTetrahedralMeshPartitionType::GEOMETRIC)
1035 EXCEPTION(
"Space region not set for GEOMETRIC partition of DistributedTetrahedralMesh");
1053 this->ConstructFromMeshReader(mesh_reader);
1058 mPartitioning=DistributedTetrahedralMeshPartitionType::DUMB;
1060 mTotalNumNodes=(width+1)*(height+1)*(depth+1);
1061 mTotalNumBoundaryElements=((width*height)+(width*depth)+(height*depth))*4;
1062 mTotalNumElements=width*height*depth*6;
1066 unsigned lo_z = z_partition.
GetLow();
1067 unsigned hi_z = z_partition.
GetHigh();
1070 assert(!this->mpDistributedVectorFactory);
1072 if (this->mpDistributedVectorFactory->GetLocalOwnership() == 0)
1083 bool am_top_most = (this->mpDistributedVectorFactory->GetHigh() == mTotalNumNodes);
1097 unsigned global_node_index;
1098 for (
unsigned k=lo_z; k<hi_z; k++)
1100 for (
unsigned j=0; j<height+1; j++)
1102 for (
unsigned i=0; i<width+1; i++)
1104 bool is_boundary =
false;
1105 if (i==0 || j==0 || k==0 || i==width || j==height || k==depth)
1109 global_node_index = (k*(height+1)+j)*(width+1)+i;
1116 RegisterHaloNode(global_node_index);
1117 mHaloNodes.push_back(p_node);
1121 RegisterNode(global_node_index);
1122 this->mNodes.push_back(p_node);
1127 this->mBoundaryNodes.push_back(p_node);
1135 unsigned element_nodes[6][4] = {{0, 1, 5, 7}, {0, 1, 3, 7},
1136 {0, 2, 3, 7}, {0, 2, 6, 7},
1137 {0, 4, 6, 7}, {0, 4, 5, 7}};
1138 std::vector<Node<SPACE_DIM>*> tetrahedra_nodes;
1140 for (
unsigned k=lo_z; k<hi_z-1; k++)
1142 unsigned belem_index = 0;
1146 belem_index = 2*(height*width+k*2*(height+width));
1149 for (
unsigned j=0; j<height; j++)
1151 for (
unsigned i=0; i<width; i++)
1154 unsigned global_node_indices[8];
1155 unsigned local_node_index = 0;
1157 for (
unsigned z = 0; z < 2; z++)
1159 for (
unsigned y = 0; y < 2; y++)
1161 for (
unsigned x = 0; x < 2; x++)
1163 global_node_indices[local_node_index] = i+x+(width+1)*(j+y+(height+1)*(k+z));
1170 for (
unsigned m = 0; m < 6; m++)
1174 tetrahedra_nodes.clear();
1176 for (
unsigned n = 0; n < 4; n++)
1178 tetrahedra_nodes.push_back(GetNodeOrHaloNode( global_node_indices[element_nodes[m][n]] ));
1180 unsigned elem_index = 6 * ((k*height+j)*width+i)+m;
1181 RegisterElement(elem_index);
1186 std::vector<Node<SPACE_DIM>*> triangle_nodes;
1190 triangle_nodes.clear();
1191 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1192 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1193 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1194 RegisterBoundaryElement(belem_index);
1196 triangle_nodes.clear();
1197 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1198 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1199 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1200 RegisterBoundaryElement(belem_index);
1205 triangle_nodes.clear();
1206 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1207 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1208 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1209 RegisterBoundaryElement(belem_index);
1211 triangle_nodes.clear();
1212 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1213 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1214 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1215 RegisterBoundaryElement(belem_index);
1220 triangle_nodes.clear();
1221 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1222 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1223 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1224 RegisterBoundaryElement(belem_index);
1226 triangle_nodes.clear();
1227 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1228 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1229 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1230 RegisterBoundaryElement(belem_index);
1235 triangle_nodes.clear();
1236 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1237 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1238 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1239 RegisterBoundaryElement(belem_index);
1241 triangle_nodes.clear();
1242 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1243 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1244 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1245 RegisterBoundaryElement(belem_index);
1250 triangle_nodes.clear();
1251 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1252 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1253 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[2] ));
1254 RegisterBoundaryElement(belem_index);
1256 triangle_nodes.clear();
1257 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[0] ));
1258 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[1] ));
1259 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[3] ));
1260 RegisterBoundaryElement(belem_index);
1265 triangle_nodes.clear();
1266 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1267 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1268 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[5] ));
1269 RegisterBoundaryElement(belem_index);
1271 triangle_nodes.clear();
1272 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[4] ));
1273 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[6] ));
1274 triangle_nodes.push_back(GetNodeOrHaloNode( global_node_indices[7] ));
1275 RegisterBoundaryElement(belem_index);
1310 std::set<unsigned>& rElementsOwned,
1311 std::set<unsigned>& rNodesOwned,
1312 std::set<unsigned>& rHaloNodesOwned,
1313 std::vector<unsigned>& rProcessorsOffset)
1316 assert(ELEMENT_DIM==2 || ELEMENT_DIM==3);
1325 boost::scoped_array<idxtype> element_distribution(
new idxtype[num_procs+1]);
1326 boost::scoped_array<int> element_counts(
new int[num_procs]);
1328 element_distribution[0] = 0;
1330 for (
unsigned proc_index=1; proc_index<num_procs; proc_index++)
1332 element_distribution[proc_index] = element_distribution[proc_index-1] + num_elements/num_procs;
1333 element_counts[proc_index-1] = element_distribution[proc_index] - element_distribution[proc_index-1];
1336 element_distribution[num_procs] = num_elements;
1337 element_counts[num_procs-1] = element_distribution[num_procs] - element_distribution[num_procs-1];
1342 idxtype first_local_element = element_distribution[local_proc_index];
1343 idxtype last_plus_one_element = element_distribution[local_proc_index+1];
1344 idxtype num_local_elements = last_plus_one_element - first_local_element;
1346 boost::scoped_array<idxtype> eind(
new idxtype[num_local_elements*(ELEMENT_DIM+1)]);
1347 boost::scoped_array<idxtype> eptr(
new idxtype[num_local_elements+1]);
1357 for (idxtype element_index = 0; element_index < first_local_element; element_index++)
1363 unsigned counter = 0;
1364 for (idxtype element_index = 0; element_index < num_local_elements; element_index++)
1370 eptr[element_index] = counter;
1371 for (
unsigned i=0; i<ELEMENT_DIM+1; i++)
1376 eptr[num_local_elements] = counter;
1378 rMeshReader.
Reset();
1380 idxtype numflag = 0;
1388 idxtype ncommonnodes = 3;
1389 if (ELEMENT_DIM == 2)
1394 MPI_Comm communicator = PETSC_COMM_WORLD;
1400 ParMETIS_V3_Mesh2Dual(element_distribution.get(), eptr.get(), eind.get(),
1401 &numflag, &ncommonnodes, &xadj, &adjncy, &communicator);
1408 idxtype weight_flag = 0;
1409 idxtype n_constraints = 1;
1414 boost::scoped_array<real_t> tpwgts(
new real_t[n_subdomains]);
1415 real_t ubvec_value = (real_t)1.05;
1418 tpwgts[proc] = ((real_t)1.0)/n_subdomains;
1420 boost::scoped_array<idxtype> local_partition(
new idxtype[num_local_elements]);
1436 ParMETIS_V3_PartKway(element_distribution.get(), xadj, adjncy,
nullptr,
nullptr, &weight_flag, &numflag,
1437 &n_constraints, &n_subdomains, tpwgts.get(), &ubvec_value,
1438 options, &edgecut, local_partition.get(), &communicator);
1442 boost::scoped_array<idxtype> global_element_partition(
new idxtype[num_elements]);
1445 MPI_Datatype mpi_idxtype = MPI_LONG_LONG_INT;
1446 if (
sizeof(idxtype) ==
sizeof(
int))
1448 mpi_idxtype = MPI_INT;
1450 boost::scoped_array<int> int_element_distribution(
new int[num_procs+1]);
1451 for (
unsigned i=0; i<num_procs+1; ++i)
1453 int_element_distribution[i] = element_distribution[i];
1455 MPI_Allgatherv(local_partition.get(), num_local_elements, mpi_idxtype,
1456 global_element_partition.get(), element_counts.get(), int_element_distribution.get(), mpi_idxtype, PETSC_COMM_WORLD);
1458 local_partition.reset();
1460 for (
unsigned elem_index=0; elem_index<num_elements; elem_index++)
1462 if ((
unsigned) global_element_partition[elem_index] == local_proc_index)
1464 rElementsOwned.insert(elem_index);
1468 rMeshReader.
Reset();
1475 std::vector<unsigned> global_node_partition(num_nodes, UNASSIGNED_NODE);
1477 assert(rProcessorsOffset.size() == 0);
1503 for (
unsigned element_number = 0; element_number < mTotalNumElements; element_number++)
1505 unsigned element_owner = global_element_partition[element_number];
1511 for (std::vector<unsigned>::const_iterator node_it = element_data.
NodeIndices.begin();
1519 if (global_node_partition[*node_it] == UNASSIGNED_NODE)
1521 if (element_owner == local_proc_index)
1523 rNodesOwned.insert(*node_it);
1526 global_node_partition[*node_it] = element_owner;
1533 rProcessorsOffset[proc]++;
1538 if (element_owner == local_proc_index)
1541 if (global_node_partition[*node_it] != local_proc_index)
1543 rHaloNodesOwned.insert(*node_it);
1563 rElementsOwned.clear();
1564 rMeshReader.
Reset();
1565 for (
unsigned element_number = 0; element_number < mTotalNumElements; element_number++)
1569 bool element_owned =
false;
1570 std::set<unsigned> temp_halo_nodes;
1572 for (std::vector<unsigned>::const_iterator node_it = element_data.
NodeIndices.begin();
1576 if (rNodesOwned.find(*node_it) != rNodesOwned.end())
1578 element_owned =
true;
1579 rElementsOwned.insert(element_number);
1583 temp_halo_nodes.insert(*node_it);
1589 rHaloNodesOwned.insert(temp_halo_nodes.begin(), temp_halo_nodes.end());
1593 rMeshReader.
Reset();
1600 this->mNodePermutation.resize(this->GetNumNodes());
1602 for (
unsigned node_index=0; node_index<this->GetNumNodes(); node_index++)
1604 unsigned partition = global_node_partition[node_index];
1605 assert(partition != UNASSIGNED_NODE);
1607 this->mNodePermutation[node_index] = rProcessorsOffset[partition] + local_index[partition];
1609 local_index[partition]++;