NeoN
A framework for CFD software
Loading...
Searching...
No Matches
partitioning.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025 - 2026 NeoN authors
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
8
9#ifdef NF_WITH_MPI_SUPPORT
10
11namespace NeoN
12{
13
14namespace detail
15{
16
18template<typename BoundaryType>
19auto setProcessorBoundaryHelper(
20 UnstructuredMesh& mesh, const std::vector<BoundaryType>& bcs, NeoN::mpi::Environment mpiEnviron
21)
22{
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++)
28 {
29 // boundary index 1 is always the proc boundary for first/last ranks;
30 // middle ranks have all boundaries as proc.
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);
35 }
36 return ret;
37}
38
45template<typename ValueType>
46Vector<ValueType> partitionInternalVector(
47 const Vector<ValueType>& globalVector,
48 const UnstructuredMesh& localMesh,
49 NeoN::mpi::Environment mpiEnviron
50)
51{
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});
55}
56
58template<typename FieldType>
59FieldType
60oneDPartitionField(FieldType field, UnstructuredMesh& mesh, NeoN::mpi::Environment mpiEnviron)
61{
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;
66
67 const auto nProcBoundaryFaces = mesh.nProcBoundaryFaces();
68 if (nProcBoundaryFaces > 0)
69 {
70 const localIdx localSize =
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++)
81 {
82 const auto bcfacei = nBoundaryFaces + procFacei;
83 // weight > 0: owner side (right-facing) — neighbour is at firstIdx + localSize
84 // weight < 0: non-owner side (left-facing) — neighbour is at firstIdx - 1
85 const localIdx gIdx = weightsHV[bcfacei] > 0 ? firstIdx + localSize : firstIdx - 1;
86 retBdHV[bcfacei] = globalInternalHV[gIdx];
87 }
88 // Copy physical boundary face values from the global field.
89 // First rank owns the leading global boundary faces; last rank owns the trailing ones.
90 if (nBoundaryFaces > 0)
91 {
92 const localIdx nGlobalBdFaces =
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++)
98 {
99 const localIdx globalBfi = isFirst ? bfi : (nGlobalBdFaces - nBoundaryFaces + bfi);
100 retBdHV[bfi] = globalBdHV[globalBfi];
101 }
102 }
103 ret.boundaryData().value() = retBdH.copyToExecutor(field.exec());
104 }
105
106 return ret;
107}
108
109} // namespace detail
110
111using detail::oneDPartitionField;
112
113} // namespace NeoN
114
115#endif
Integer types used throughout NeoN.
Definition array.hpp:18
int32_t localIdx
Definition label.hpp:50
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.