lduMatrixUpdateMatrixInterfaces.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "lduMatrix.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
34 (
35  const bool add,
36  const FieldField<Field, scalar>& coupleCoeffs,
37  const lduInterfaceFieldPtrsList& interfaces,
38  const solveScalarField& psiif,
39  solveScalarField& result,
40  const direction cmpt
41 ) const
42 {
44 
45  if
46  (
48  || commsType == UPstream::commsTypes::nonBlocking
49  )
50  {
51  forAll(interfaces, interfacei)
52  {
53  if (interfaces.set(interfacei))
54  {
55  interfaces[interfacei].initInterfaceMatrixUpdate
56  (
57  result,
58  add,
59  mesh().lduAddr(),
60  interfacei,
61  psiif,
62  coupleCoeffs[interfacei],
63  cmpt,
64  commsType
65  );
66  }
67  }
68  }
69  else if (commsType == UPstream::commsTypes::scheduled)
70  {
71  const lduSchedule& patchSchedule = this->patchSchedule();
72 
73  // Loop over the "global" patches are on the list of interfaces but
74  // beyond the end of the schedule which only handles "normal" patches
75  for
76  (
77  label interfacei=patchSchedule.size()/2;
78  interfacei<interfaces.size();
79  interfacei++
80  )
81  {
82  if (interfaces.set(interfacei))
83  {
84  interfaces[interfacei].initInterfaceMatrixUpdate
85  (
86  result,
87  add,
88  mesh().lduAddr(),
89  interfacei,
90  psiif,
91  coupleCoeffs[interfacei],
92  cmpt,
94  );
95  }
96  }
97  }
98  else
99  {
101  << "Unsupported communications type "
103  << exit(FatalError);
104  }
105 }
106 
107 
109 (
110  const bool add,
111  const FieldField<Field, scalar>& coupleCoeffs,
112  const lduInterfaceFieldPtrsList& interfaces,
113  const solveScalarField& psiif,
114  solveScalarField& result,
115  const direction cmpt,
116  const label startRequest
117 ) const
118 {
120 
121  if
122  (
125  )
126  {
127  // Wait for some interface requests to become available and
128  // consume them. No guarantee that the finished requests actually
129  // correspond to any particular interface, but it is reasonably
130  // probable that some interfaces will be able to start consumption
131  // without waiting for all requests.
132 
133  DynamicList<int> indices; // (work array)
134 
135  // const label maxPolling =
136  // (
137  // (UPstream::nPollProcInterfaces < 0)
138  // ? (UPstream::nRequests() - startRequest)
139  // : UPstream::nPollProcInterfaces
140  // );
141 
142  for
143  (
144  bool pollingActive = (UPstream::nPollProcInterfaces < 0);
145  (
146  pollingActive
147  && UPstream::waitSomeRequests(startRequest, -1, &indices)
148  );
149  /*nil*/
150  )
151  {
152  pollingActive = false;
153 
154  forAll(interfaces, interfacei)
155  {
156  auto* intf = interfaces.get(interfacei);
157 
158  if (intf && !intf->updatedMatrix())
159  {
160  if (intf->ready())
161  {
162  intf->updateInterfaceMatrix
163  (
164  result,
165  add,
166  mesh().lduAddr(),
167  interfacei,
168  psiif,
169  coupleCoeffs[interfacei],
170  cmpt,
171  commsType
172  );
173  }
174  else
175  {
176  pollingActive = true;
177  }
178  }
179  }
180  }
181 
182  // [OLDER]
183  // Alternative for consuming interfaces as they become available.
184  // Within the loop, the ready() calls an MPI_Test
185  // that can trigger progression. However, a bit less reliably
186  // (and less efficient) since it is implies multiple calls to
187  // MPI_Test to progress the MPI transfer, but no guarantee that
188  // any of them will actually complete within nPollProcInterfaces
189  // calls.
190 
191  for (label i = 0; i < UPstream::nPollProcInterfaces; ++i)
192  {
193  bool allUpdated = true;
194 
195  forAll(interfaces, interfacei)
196  {
197  auto* intf = interfaces.get(interfacei);
198 
199  if (intf && !intf->updatedMatrix())
200  {
201  if (intf->ready())
202  {
203  intf->updateInterfaceMatrix
204  (
205  result,
206  add,
207  mesh().lduAddr(),
208  interfacei,
209  psiif,
210  coupleCoeffs[interfacei],
211  cmpt,
212  commsType
213  );
214  }
215  else
216  {
217  allUpdated = false;
218  }
219  }
220  }
221 
222  if (allUpdated)
223  {
224  break; // Early exit
225  }
226  }
227  }
228 
229 
230  if
231  (
232  commsType == UPstream::commsTypes::blocking
233  || commsType == UPstream::commsTypes::nonBlocking
234  )
235  {
236  // Wait until sends/receives have finished.
237  // - effectively a no-op (without waiting) if already completed.
238  if (commsType == UPstream::commsTypes::nonBlocking)
239  {
240  UPstream::waitRequests(startRequest);
241  }
242 
243  // Check/no-check for updatedMatrix() ?
244  const bool noCheck = (commsType == UPstream::commsTypes::blocking);
245 
246  // Consume anything still outstanding
247  forAll(interfaces, interfacei)
248  {
249  auto* intf = interfaces.get(interfacei);
250 
251  if (intf && (noCheck || !intf->updatedMatrix()))
252  {
253  intf->updateInterfaceMatrix
254  (
255  result,
256  add,
257  mesh().lduAddr(),
258  interfacei,
259  psiif,
260  coupleCoeffs[interfacei],
261  cmpt,
262  commsType
263  );
264  }
265  }
266  }
267  else if (commsType == UPstream::commsTypes::scheduled)
268  {
269  const lduSchedule& patchSchedule = this->patchSchedule();
270 
271  // Loop over all the "normal" interfaces relating to standard patches
272  for (const auto& sched : patchSchedule)
273  {
274  const label interfacei = sched.patch;
275 
276  if (interfaces.set(interfacei))
277  {
278  if (sched.init)
279  {
280  interfaces[interfacei].initInterfaceMatrixUpdate
281  (
282  result,
283  add,
284  mesh().lduAddr(),
285  interfacei,
286  psiif,
287  coupleCoeffs[interfacei],
288  cmpt,
289  commsType
290  );
291  }
292  else
293  {
294  interfaces[interfacei].updateInterfaceMatrix
295  (
296  result,
297  add,
298  mesh().lduAddr(),
299  interfacei,
300  psiif,
301  coupleCoeffs[interfacei],
302  cmpt,
303  commsType
304  );
305  }
306  }
307  }
308 
309  // Loop over the "global" patches are on the list of interfaces but
310  // beyond the end of the schedule which only handles "normal" patches
311  for
312  (
313  label interfacei=patchSchedule.size()/2;
314  interfacei<interfaces.size();
315  interfacei++
316  )
317  {
318  if (interfaces.set(interfacei))
319  {
320  interfaces[interfacei].updateInterfaceMatrix
321  (
322  result,
323  add,
324  mesh().lduAddr(),
325  interfacei,
326  psiif,
327  coupleCoeffs[interfacei],
328  cmpt,
330  );
331  }
332  }
333  }
334  else
335  {
337  << "Unsupported communications type "
338  << UPstream::commsTypeNames[commsType]
339  << exit(FatalError);
340  }
341 }
342 
343 
344 // ************************************************************************* //
UPtrList< const lduInterfaceField > lduInterfaceFieldPtrsList
List of coupled interface fields to be used in coupling.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
"blocking" : (MPI_Bsend, MPI_Recv)
uint8_t direction
Definition: direction.H:46
static const Enum< commsTypes > commsTypeNames
Enumerated names for the communication types.
Definition: UPstream.H:82
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Field< solveScalar > solveScalarField
commsTypes
Communications types.
Definition: UPstream.H:72
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Definition: lduSchedule.H:46
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1538
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:51
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
const lduSchedule & patchSchedule() const
Return the patch evaluation schedule.
Definition: lduMatrix.H:742
static int nPollProcInterfaces
Number of polling cycles in processor updates.
Definition: UPstream.H:380
dynamicFvMesh & mesh
"scheduled" : (MPI_Send, MPI_Recv)
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
void updateMatrixInterfaces(const bool add, const FieldField< Field, scalar > &interfaceCoeffs, const lduInterfaceFieldPtrsList &interfaces, const solveScalarField &psiif, solveScalarField &result, const direction cmpt, const label startRequest) const
Update interfaced interfaces for matrix operations.
void initMatrixInterfaces(const bool add, const FieldField< Field, scalar > &interfaceCoeffs, const lduInterfaceFieldPtrsList &interfaces, const solveScalarField &psiif, solveScalarField &result, const direction cmpt) const
Initialise the update of interfaced interfaces for matrix operations.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:385
const lduMesh & mesh() const noexcept
Return the LDU mesh from which the addressing is obtained.
Definition: lduMatrix.H:718
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:734
"nonBlocking" : (MPI_Isend, MPI_Irecv)
static bool waitSomeRequests(const label pos, label len=-1, DynamicList< int > *indices=nullptr)
Wait until some requests (from position onwards) have finished. Corresponds to MPI_Waitsome() ...
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrList.H:366