9#ifdef NF_WITH_MPI_SUPPORT
18template<
typename BoundaryType>
19auto setProcessorBoundaryHelper(
20 UnstructuredMesh& mesh,
const std::vector<BoundaryType>& bcs, NeoN::mpi::Environment mpiEnviron
23 const auto rank = mpiEnviron.rank();
24 const auto ranks = mpiEnviron.sizeRank();
25 const bool isMiddle = (rank > 0 && rank < ranks - 1);
26 auto ret = std::vector<BoundaryType> {};
27 for (
int i = 0; i < static_cast<int>(bcs.size()); i++)
31 const bool isProc = (i == 1) || isMiddle;
32 std::string boundaryType = isProc ?
"processor" :
"calculated";
33 auto patchDict = Dictionary({{
"type", boundaryType}});
34 ret.emplace_back(mesh, patchDict, i);
45template<
typename ValueType>
46Vector<ValueType> partitionInternalVector(
47 const Vector<ValueType>& globalVector,
48 const UnstructuredMesh& localMesh,
49 NeoN::mpi::Environment mpiEnviron
52 const localIdx localSize =
static_cast<localIdx>(globalVector.size()) / mpiEnviron.sizeRank();
53 const localIdx firstIdx = mpiEnviron.rank() * localMesh.nCells();
54 return take(globalVector, {firstIdx, firstIdx + localSize});
58template<
typename FieldType>
60oneDPartitionField(FieldType field, UnstructuredMesh& mesh, NeoN::mpi::Environment mpiEnviron)
62 auto internalVector = partitionInternalVector(field.internalVector(), mesh, mpiEnviron);
63 auto bcsPart = setProcessorBoundaryHelper(mesh, field.boundaryConditions(), mpiEnviron);
64 FieldType ret(field.exec(), field.name +
"Part", mesh, bcsPart);
65 ret.internalVector() = internalVector;
67 const auto nProcBoundaryFaces = mesh.nProcBoundaryFaces();
68 if (nProcBoundaryFaces > 0)
71 static_cast<localIdx>(field.internalVector().size()) / mpiEnviron.sizeRank();
72 const localIdx firstIdx = mpiEnviron.rank() * mesh.nCells();
73 const auto nBoundaryFaces = mesh.nBoundaryFaces();
74 auto weightsH = mesh.boundaryMesh().weights().copyToHost();
75 auto globalInternalH = field.internalVector().copyToHost();
76 auto retBdH = ret.boundaryData().value().copyToHost();
77 const auto weightsHV = weightsH.view();
78 const auto globalInternalHV = globalInternalH.view();
79 auto retBdHV = retBdH.view();
80 for (
localIdx procFacei = 0; procFacei < nProcBoundaryFaces; procFacei++)
82 const auto bcfacei = nBoundaryFaces + procFacei;
85 const localIdx gIdx = weightsHV[bcfacei] > 0 ? firstIdx + localSize : firstIdx - 1;
86 retBdHV[bcfacei] = globalInternalHV[gIdx];
90 if (nBoundaryFaces > 0)
93 static_cast<localIdx>(field.boundaryData().value().size());
94 auto globalBdH = field.boundaryData().value().copyToHost();
95 const auto globalBdHV = globalBdH.view();
96 const bool isFirst = (mpiEnviron.rank() == 0);
97 for (
localIdx bfi = 0; bfi < nBoundaryFaces; bfi++)
99 const localIdx globalBfi = isFirst ? bfi : (nGlobalBdFaces - nBoundaryFaces + bfi);
100 retBdHV[bfi] = globalBdHV[globalBfi];
103 ret.boundaryData().value() = retBdH.copyToExecutor(field.exec());
111using detail::oneDPartitionField;
Integer types used throughout NeoN.
Vector< ValueType > take(const Vector< ValueType > &in, std::pair< localIdx, localIdx > range)
Given a Vector and an index range [first, first+length] a subvector is created.