42 #include <boost/config.hpp>
43 #include <boost/graph/adjacency_list.hpp>
44 #include <boost/graph/cuthill_mckee_ordering.hpp>
45 #include <boost/graph/properties.hpp>
46 #include <boost/graph/bandwidth.hpp>
52 namespace MultiRegions
72 const std::string variable):
85 const int numLocalCoeffs,
87 const Array<OneD, const ExpListSharedPtr> &bndCondExp,
88 const Array<OneD, const SpatialDomains::BoundaryConditionShPtr>
92 const bool checkIfSystemSingular,
93 const std::string variable) :
102 checkIfSystemSingular);
114 const int numLocalCoeffs,
116 const std::string variable):
143 const int numLocalCoeffs,
145 const Array<OneD, const ExpListSharedPtr> &bndCondExp,
146 const Array<OneD, const SpatialDomains::BoundaryConditionShPtr>
150 const bool checkIfSystemSingular)
153 int cnt = 0,offset=0;
157 int globalId, nGraphVerts;
159 int nEdgeInteriorCoeffs;
160 int firstNonDirGraphVertId;
161 int nLocBndCondDofs = 0;
162 int nLocDirBndCondDofs = 0;
163 int nExtraDirichlet = 0;
168 Array<OneD, unsigned int> edgeInteriorMap;
169 Array<OneD, int> edgeInteriorSign;
173 Array<OneD, map<int,int> > ReorderedGraphVertId(2);
174 Array<OneD, map<int,int> > Dofs(2);
176 set<int> extraDirVerts;
179 for(i = 0; i < locExpVector.size(); ++i)
182 for(j = 0; j < locExpVector[i]->GetNverts(); ++j)
185 Dofs[0][(exp2d->GetGeom2D())->GetVid(j)] = 1;
187 Dofs[1][(exp2d->GetGeom2D())->GetEid(j)] =
198 Array<OneD, Array<OneD, const SpatialDomains::BoundaryConditionShPtr> > bndConditionsVec(1,bndConditions);
200 bndCondExp,bndConditionsVec,
204 ReorderedGraphVertId,
205 firstNonDirGraphVertId,
209 checkIfSystemSingular);
215 for(i = 0; i < bndCondExp.num_elements(); i++)
217 for(j = 0; j < bndCondExp[i]->GetExpSize(); j++)
222 nLocDirBndCondDofs += bndSegExp->
GetNcoeffs();
224 if( bndCondExp[i]->GetExp(j)==bndCondExp[bndCondExp.num_elements()-1]->GetExp(bndCondExp[bndCondExp.num_elements()-1]->GetExpSize()-1)
225 && i==(bndCondExp.num_elements()-1)
226 && nLocDirBndCondDofs ==0
227 && checkIfSystemSingular==
true)
229 nLocDirBndCondDofs =1;
233 nLocBndCondDofs += bndSegExp->GetNcoeffs();
249 Array<OneD, int> graphVertOffset(ReorderedGraphVertId[0].size()+
250 ReorderedGraphVertId[1].size()+1);
251 graphVertOffset[0] = 0;
253 for(i = 0; i < locExpVector.size(); ++i)
256 for(j = 0; j < locExpansion->GetNedges(); ++j)
259 meshEdgeId = (locExpansion->GetGeom2D())->GetEid(j);
260 meshVertId = (locExpansion->GetGeom2D())->GetVid(j);
261 graphVertOffset[ReorderedGraphVertId[0][meshVertId]+1] = 1;
262 graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]+1] = nEdgeCoeffs-2;
264 bType = locExpansion->GetEdgeBasisType(j);
266 if( (nEdgeCoeffs >= 4)&&
276 for(i = 1; i < graphVertOffset.num_elements(); i++)
278 graphVertOffset[i] += graphVertOffset[i-1];
313 locExpVector[elmtid]->NumBndryCoeffs();
314 m_numLocalIntCoeffsPerPatch[i] = (
unsigned int)
315 locExpVector[elmtid]->GetNcoeffs() -
316 locExpVector[elmtid]->NumBndryCoeffs();
330 for(i = 0; i < locExpVector.size(); ++i)
337 for(j = 0; j < locExpansion->GetNedges(); ++j)
339 PeriodicMap::const_iterator it;
341 nEdgeInteriorCoeffs = locExpansion->GetEdgeNcoeffs(j)-2;
342 edgeOrient = (locExpansion->GetGeom2D())->GetEorient(j);
343 meshEdgeId = (locExpansion->GetGeom2D())->GetEid(j);
344 meshVertId = (locExpansion->GetGeom2D())->GetVid(j);
353 it = periodicEdgesId.find(meshEdgeId);
354 if (it != periodicEdgesId.end() &&
356 meshEdgeId == min(meshEdgeId, it->second[0].id))
363 locExpansion->GetEdgeInteriorMap(j,edgeOrient,edgeInteriorMap,edgeInteriorSign);
366 graphVertOffset[ReorderedGraphVertId[0][meshVertId]];
369 for(k = 0; k < nEdgeInteriorCoeffs; ++k)
372 graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]]+k;
378 for(k = 0; k < nEdgeInteriorCoeffs; ++k)
391 for(i = 0; i < bndCondExp.num_elements(); i++)
393 set<int> foundExtraVerts;
394 for(j = 0; j < bndCondExp[i]->GetExpSize(); j++)
398 cnt = offset + bndCondExp[i]->GetCoeff_Offset(j);
399 for(k = 0; k < 2; k++)
401 meshVertId = (bndSegExp->GetGeom1D())->GetVid(k);
402 m_bndCondCoeffsToGlobalCoeffsMap[cnt+bndSegExp->
GetVertexMap(k)] = graphVertOffset[ReorderedGraphVertId[0][meshVertId]];
405 if (iter != extraDirVerts.end() &&
406 foundExtraVerts.count(meshVertId) == 0)
408 int loc = bndCondExp[i]->GetCoeff_Offset(j) +
409 bndSegExp->GetVertexMap(k);
410 int gid = graphVertOffset[
411 ReorderedGraphVertId[0][meshVertId]];
414 foundExtraVerts.insert(meshVertId);
418 meshEdgeId = (bndSegExp->GetGeom1D())->GetEid();
420 for(k = 0; k < bndSegExp->GetNcoeffs(); k++)
422 if(m_bndCondCoeffsToGlobalCoeffsMap[cnt+k] == -1)
424 m_bndCondCoeffsToGlobalCoeffsMap[cnt+k] =
425 graphVertOffset[ReorderedGraphVertId[1][meshEdgeId]]+bndEdgeCnt;
430 offset += bndCondExp[i]->GetNcoeffs();
473 for (i = 0; i < Tit->second.size(); ++i)
475 valence[Tit->second[i].get<1>()] = 1.0;
484 for (i = 0; i < Tit->second.size(); ++i)
486 boost::get<2>(Tit->second.at(i)) = 1.0/valence[Tit->second.at(i).get<1>()];
499 Array<OneD, int> vwgts_perm(
500 Dofs[0].size()+Dofs[1].size()-firstNonDirGraphVertId);
501 for(i = 0; i < locExpVector.size(); ++i)
505 for(j = 0; j < locExpansion->GetNverts(); ++j)
507 meshEdgeId = (locExpansion->GetGeom2D())->GetEid(j);
508 meshVertId = (locExpansion->GetGeom2D())->GetVid(j);
510 if(ReorderedGraphVertId[0][meshVertId] >=
511 firstNonDirGraphVertId)
513 vwgts_perm[ReorderedGraphVertId[0][meshVertId]-
514 firstNonDirGraphVertId] =
518 if(ReorderedGraphVertId[1][meshEdgeId] >=
519 firstNonDirGraphVertId)
521 vwgts_perm[ReorderedGraphVertId[1][meshEdgeId]-
522 firstNonDirGraphVertId] =
528 bottomUpGraph->ExpandGraphWithVertexWeights(vwgts_perm);
535 m_hash = boost::hash_range(
540 m_comm->GetRowComm()->AllReduce(hash,
579 const Array<OneD, const ExpListSharedPtr> &bndCondExp,
580 const Array<
OneD, Array<OneD, const SpatialDomains::BoundaryConditionShPtr> > &bndConditions,
583 Array<
OneD, map<int,int> > &Dofs,
584 Array<
OneD, map<int,int> > &ReorderedGraphVertId,
585 int &firstNonDirGraphVertId,
586 int &nExtraDirichlet,
588 set<int> &extraDirVerts,
589 const bool checkIfSystemSingular,
595 int meshVertId, meshVertId2;
603 map<int,int>::const_iterator mapConstIt;
604 bool systemSingular =
true;
606 PeriodicMap::const_iterator pIt;
611 for(i = 0; i < bndCondExp.num_elements(); i++)
615 for(k = 0; k < bndConditions.num_elements(); ++k)
617 if (bndConditions[k][i]->GetBoundaryConditionType() ==
622 if (bndConditions[k][i]->GetBoundaryConditionType() !=
625 systemSingular =
false;
630 if(cnt == bndConditions.num_elements())
632 for(j = 0; j < bndCondExp[i]->GetNumElmts(); j++)
635 meshEdgeId = (bndSegExp->GetGeom1D())->GetEid();
636 ReorderedGraphVertId[1][meshEdgeId] = graphVertId++;
637 for(k = 0; k < 2; k++)
639 meshVertId = (bndSegExp->GetGeom1D())->GetVid(k);
640 if(ReorderedGraphVertId[0].count(meshVertId) == 0)
642 ReorderedGraphVertId[0][meshVertId] =
655 int n =
m_comm->GetSize();
656 int p =
m_comm->GetRank();
657 int s = systemSingular ? 1 : 0;
659 systemSingular = (s == 1 ?
true :
false);
662 Array<OneD, int> bccounts(n, 0);
663 bccounts[p] = bndCondExp.num_elements();
675 if(systemSingular ==
true && checkIfSystemSingular && maxBCIdx == p)
677 if (
m_session->DefinesParameter(
"SingularElement"))
680 m_session->LoadParameter(
"SingularElement", s_eid);
682 ASSERTL1(s_eid < locExpVector.size(),
683 "SingularElement Parameter is too large");
685 meshVertId = locExpVector[s_eid]
687 ->GetGeom2D()->GetVid(0);
689 else if (
m_session->DefinesParameter(
"SingularVertex"))
691 m_session->LoadParameter(
"SingularVertex", meshVertId);
693 else if (bndCondExp.num_elements() == 0)
696 meshVertId = locExpVector[0]
698 ->GetGeom2D()->GetVid(0);
702 bndSegExp = bndCondExp[bndCondExp.num_elements()-1]
704 meshVertId = bndSegExp->
GetGeom1D()->GetVid(0);
707 if (ReorderedGraphVertId[0].count(meshVertId) == 0)
709 ReorderedGraphVertId[0][meshVertId] = graphVertId++;
718 if(systemSingular ==
true && checkIfSystemSingular)
725 if (Dofs[0].count(meshVertId) > 0)
727 if (ReorderedGraphVertId[0].count(meshVertId) == 0)
729 ReorderedGraphVertId[0][meshVertId] = graphVertId++;
743 if (ReorderedGraphVertId[0].count(meshVertId) == 0)
749 gId = ReorderedGraphVertId[0][meshVertId];
752 for (pIt = periodicVerts.begin();
753 pIt != periodicVerts.end(); ++pIt)
760 if (pIt->first == meshVertId)
762 ReorderedGraphVertId[0][meshVertId] =
763 gId < 0 ? graphVertId++ : gId;
765 for (i = 0; i < pIt->second.size(); ++i)
767 if (pIt->second[i].isLocal)
769 ReorderedGraphVertId[0][pIt->second[i].id] =
777 for (i = 0; i < pIt->second.size(); ++i)
779 if (pIt->second[i].id == meshVertId)
788 ReorderedGraphVertId[0][pIt->first] =
789 gId < 0 ? graphVertId++ : gId;
791 for (i = 0; i < pIt->second.size(); ++i)
793 if (pIt->second[i].isLocal)
795 ReorderedGraphVertId[0][
796 pIt->second[i].id] = gId;
809 Array<OneD, int> counts (n, 0);
810 Array<OneD, int> offsets(n, 0);
811 counts[p] = ReorderedGraphVertId[0].size();
814 for (i = 1; i < n; ++i)
816 offsets[i] = offsets[i-1] + counts[i-1];
820 Array<OneD, int> vertexlist(nTot, 0);
822 for (it = ReorderedGraphVertId[0].begin(), i = 0;
823 it != ReorderedGraphVertId[0].end();
826 vertexlist[offsets[p] + i] = it->first;
830 map<int, int> extraDirVertIds;
835 for (i = 0; i < n; ++i)
842 for(j = 0; j < locExpVector.size(); j++)
844 locExpansion = boost::dynamic_pointer_cast<
848 for(k = 0; k < locExpansion->GetNverts(); k++)
850 meshVertId = locExpansion
852 ->GetGeom2D()->GetVid(k);
853 if (ReorderedGraphVertId[0].count(meshVertId) != 0)
858 for (l = 0; l < counts[i]; ++l)
860 if (vertexlist[offsets[i]+l] == meshVertId)
862 extraDirVertIds[meshVertId] = i;
863 ReorderedGraphVertId[0][meshVertId] =
872 for (i = 0; i < n; ++i)
878 counts[p] = extraDirVertIds.size();
884 for (i = 1; i < n; ++i)
886 offsets[i] = offsets[i-1] + counts[i-1];
889 Array<OneD, int> vertids (nTot, 0);
890 Array<OneD, int> vertprocs(nTot, 0);
892 for (it = extraDirVertIds.begin(), i = 0;
893 it != extraDirVertIds.end(); ++it, ++i)
895 vertids [offsets[p]+i] = it->first;
896 vertprocs[offsets[p]+i] = it->second;
902 for (i = 0; i < nTot; ++i)
904 if (
m_comm->GetRank() != vertprocs[i])
909 extraDirVerts.insert(vertids[i]);
912 firstNonDirGraphVertId = graphVertId;
919 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS> BoostGraph;
920 BoostGraph boostGraphObj;
922 int tempGraphVertId = 0;
928 map<int, int> vertTempGraphVertId;
929 map<int, int> edgeTempGraphVertId;
930 map<int, int> intTempGraphVertId;
931 Array<OneD, int> localVerts;
932 Array<OneD, int> localEdges;
933 Array<OneD, int> localinterior;
938 for (pIt = periodicVerts.begin(); pIt != periodicVerts.end(); ++pIt)
940 meshVertId = pIt->first;
943 if (ReorderedGraphVertId[0].count(pIt->first) != 0)
945 for (i = 0; i < pIt->second.size(); ++i)
947 meshVertId2 = pIt->second[i].id;
948 if (ReorderedGraphVertId[0].count(meshVertId2) == 0 &&
949 pIt->second[i].isLocal)
951 ReorderedGraphVertId[0][meshVertId2] =
952 ReorderedGraphVertId[0][meshVertId];
959 bool isDirichlet =
false;
960 for (i = 0; i < pIt->second.size(); ++i)
962 if (!pIt->second[i].isLocal)
967 meshVertId2 = pIt->second[i].id;
968 if (ReorderedGraphVertId[0].count(meshVertId2) > 0)
977 ReorderedGraphVertId[0][meshVertId] =
978 ReorderedGraphVertId[0][pIt->second[i].id];
980 for (j = 0; j < pIt->second.size(); ++j)
982 meshVertId2 = pIt->second[i].id;
983 if (j == i || !pIt->second[j].isLocal ||
984 ReorderedGraphVertId[0].count(meshVertId2) > 0)
989 ReorderedGraphVertId[0][meshVertId2] =
990 ReorderedGraphVertId[0][pIt->second[i].id];
997 for (i = 0; i < pIt->second.size(); ++i)
999 if (!pIt->second[i].isLocal)
1004 if (vertTempGraphVertId.count(pIt->second[i].id) > 0)
1010 if (i == pIt->second.size())
1012 vertTempGraphVertId[meshVertId] = tempGraphVertId++;
1016 vertTempGraphVertId[meshVertId] = vertTempGraphVertId[pIt->second[i].id];
1022 for (pIt = periodicEdges.begin(); pIt != periodicEdges.end(); ++pIt)
1024 if (!pIt->second[0].isLocal)
1027 meshEdgeId = pIt->first;
1028 ASSERTL0(ReorderedGraphVertId[1].count(meshEdgeId) == 0,
1029 "This periodic boundary edge has been specified before");
1030 edgeTempGraphVertId[meshEdgeId] = tempGraphVertId++;
1032 else if (pIt->first < pIt->second[0].id)
1034 ASSERTL0(ReorderedGraphVertId[1].count(pIt->first) == 0,
1035 "This periodic boundary edge has been specified before");
1036 ASSERTL0(ReorderedGraphVertId[1].count(pIt->second[0].id) == 0,
1037 "This periodic boundary edge has been specified before");
1039 edgeTempGraphVertId[pIt->first] = tempGraphVertId;
1040 edgeTempGraphVertId[pIt->second[0].id] = tempGraphVertId++;
1046 for(i = 0; i < locExpVector.size(); ++i)
1049 if((locExpansion = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D>(
1050 locExpVector[elmtid])))
1054 nTotalVerts += locExpansion->GetNverts();
1061 localVerts = Array<OneD, int>(nTotalVerts,-1);
1062 localEdges = Array<OneD, int>(nTotalVerts,-1);
1064 for(i = 0; i < locExpVector.size(); ++i)
1067 if((locExpansion = locExpVector[elmtid]
1068 ->as<StdRegions::StdExpansion2D>()))
1071 nVerts = locExpansion->GetNverts();
1072 for(j = 0; j < nVerts; ++j)
1074 meshVertId = locExpansion
1076 ->GetGeom2D()->GetVid(j);
1077 if(ReorderedGraphVertId[0].count(meshVertId) == 0)
1080 if(vertTempGraphVertId.count(meshVertId) == 0)
1082 boost::add_vertex(boostGraphObj);
1083 vertTempGraphVertId[meshVertId] = tempGraphVertId++;
1085 localVerts[localOffset + vertCnt++] = vertTempGraphVertId[meshVertId];
1089 localOffset+=nVerts;
1095 for(i = 0; i < locExpVector.size(); ++i)
1098 if((locExpansion = locExpVector[elmtid]
1099 ->as<StdRegions::StdExpansion2D>()))
1102 nVerts = locExpansion->GetNverts();
1103 for(j = 0; j < nVerts; ++j)
1105 meshEdgeId = locExpansion
1107 ->GetGeom2D()->GetEid(j);
1108 if(ReorderedGraphVertId[1].count(meshEdgeId) == 0)
1111 if(edgeTempGraphVertId.count(meshEdgeId) == 0)
1113 boost::add_vertex(boostGraphObj);
1114 edgeTempGraphVertId[meshEdgeId] = tempGraphVertId++;
1116 localEdges[localOffset + edgeCnt++] = edgeTempGraphVertId[meshEdgeId];
1120 localOffset+=nVerts;
1128 for(i = 0; i < locExpVector.size(); ++i)
1131 if((locExpansion = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D>(
1132 locExpVector[elmtid])))
1135 boost::add_vertex(boostGraphObj);
1136 intTempGraphVertId[elmtid] = tempGraphVertId++;
1142 for(i = 0; i < locExpVector.size(); ++i)
1145 if((locExpansion = boost::dynamic_pointer_cast<StdRegions::StdExpansion2D>(
1146 locExpVector[elmtid])))
1148 nVerts = locExpansion->GetNverts();
1152 for(j = 0; j < nVerts; j++)
1154 if(localVerts[j+localOffset]==-1)
1159 for(k = 0; k < nVerts; k++)
1161 if(localVerts[k+localOffset]==-1)
1167 boost::add_edge( (
size_t) localVerts[j+localOffset],
1168 (
size_t) localVerts[k+localOffset],boostGraphObj);
1172 for(k = 0; k < nVerts; k++)
1174 if(localEdges[k+localOffset]==-1)
1178 boost::add_edge( (
size_t) localVerts[j+localOffset],
1179 (
size_t) localEdges[k+localOffset],boostGraphObj);
1184 boost::add_edge( (
size_t) localVerts[j+localOffset],
1185 (
size_t) intTempGraphVertId[elmtid],boostGraphObj);
1189 for(j = 0; j < nVerts; j++)
1191 if(localEdges[j+localOffset]==-1)
1195 for(k = 0; k < nVerts; k++)
1197 if(localEdges[k+localOffset]==-1)
1203 boost::add_edge( (
size_t) localEdges[j+localOffset],
1204 (
size_t) localEdges[k+localOffset],boostGraphObj);
1207 for(k = 0; k < nVerts; k++)
1209 if(localVerts[k+localOffset]==-1)
1213 boost::add_edge( (
size_t) localEdges[j+localOffset],
1214 (
size_t) localVerts[k+localOffset],boostGraphObj);
1219 boost::add_edge( (
size_t) localEdges[j+localOffset],
1220 (
size_t) intTempGraphVertId[elmtid], boostGraphObj);
1226 for(j = 0; j < nVerts; j++)
1228 if(localVerts[j+localOffset]==-1)
1232 boost::add_edge( (
size_t) intTempGraphVertId[elmtid],
1233 (
size_t) localVerts[j+localOffset], boostGraphObj);
1236 for(j = 0; j < nVerts; j++)
1238 if(localEdges[j+localOffset]==-1)
1243 boost::add_edge( (
size_t) intTempGraphVertId[elmtid],
1244 (
size_t) localEdges[j+localOffset], boostGraphObj);
1252 ASSERTL0(
false,
"dynamic cast to a local 2D expansion failed");
1254 localOffset+=nVerts;
1263 vector<long> procVerts, procEdges;
1264 set <int> foundVerts, foundEdges;
1269 for(i = cnt = 0; i < locExpVector.size(); ++i)
1272 if((locExpansion = boost::dynamic_pointer_cast<
1275 for (j = 0; j < locExpansion->GetNverts(); ++j, ++cnt)
1277 int vid = locExpansion
1279 ->GetGeom2D()->GetVid(j)+1;
1280 int eid = locExpansion
1282 ->GetGeom2D()->GetEid(j)+1;
1284 if (foundVerts.count(vid) == 0)
1286 procVerts.push_back(vid);
1287 foundVerts.insert(vid);
1290 if (foundEdges.count(eid) == 0)
1292 procEdges.push_back(eid);
1293 foundEdges.insert(eid);
1300 "dynamic cast to a local 2D expansion failed");
1304 int unique_verts = foundVerts.size();
1305 int unique_edges = foundEdges.size();
1311 Array<OneD, long> vertArray(unique_verts, &procVerts[0]);
1312 Array<OneD, long> edgeArray(unique_edges, &procEdges[0]);
1315 Array<OneD, NekDouble> tmp3(unique_verts, 1.0);
1316 Array<OneD, NekDouble> tmp4(unique_edges, 1.0);
1322 for (i = 0; i < unique_verts; ++i)
1326 if (ReorderedGraphVertId[0].count(procVerts[i]-1) == 0)
1328 partVerts.insert(vertTempGraphVertId[procVerts[i]-1]);
1333 for (i = 0; i < unique_edges; ++i)
1337 if (ReorderedGraphVertId[1].count(procEdges[i]-1) == 0)
1339 partVerts.insert(edgeTempGraphVertId[procEdges[i]-1]);
1348 int nGraphVerts = tempGraphVertId;
1349 Array<OneD, int> perm(nGraphVerts);
1350 Array<OneD, int> iperm(nGraphVerts);
1404 for(mapIt = vertTempGraphVertId.begin(); mapIt != vertTempGraphVertId.end(); mapIt++)
1406 ReorderedGraphVertId[0][mapIt->first] = iperm[mapIt->second] + graphVertId;
1408 for(mapIt = edgeTempGraphVertId.begin(); mapIt != edgeTempGraphVertId.end(); mapIt++)
1410 ReorderedGraphVertId[1][mapIt->first] = iperm[mapIt->second] + graphVertId;
1415 for(mapIt = intTempGraphVertId.begin(); mapIt != intTempGraphVertId.end(); mapIt++)
1417 ReorderedGraphVertId[2][mapIt->first] = iperm[mapIt->second] + graphVertId;