Loading...
Searching...
No Matches
cyclicACMIGAMGInterfaceField.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) 2013 OpenFOAM Foundation
9 Copyright (C) 2019-2024 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
31#include "lduMatrix.H"
32
33// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34
35namespace Foam
36{
39 (
43 );
45 (
49 );
51 (
55 );
56}
57
58
59// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60
61Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
62(
63 const GAMGInterface& GAMGCp,
64 const lduInterfaceField& fineInterface
65)
66:
67 GAMGInterfaceField(GAMGCp, fineInterface),
68 cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
69 doTransform_(false),
70 rank_(0)
71{
74
75 doTransform_ = p.doTransform();
76 rank_ = p.rank();
77}
78
79
80Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
81(
82 const GAMGInterface& GAMGCp,
83 const bool doTransform,
84 const int rank
85)
86:
87 GAMGInterfaceField(GAMGCp, doTransform, rank),
88 cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
89 doTransform_(doTransform),
90 rank_(rank)
91{}
92
93
94Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
95(
96 const GAMGInterface& GAMGCp,
97 Istream& is
98)
99:
100 GAMGInterfaceField(GAMGCp, is),
101 cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
102 doTransform_(readBool(is)),
103 rank_(readLabel(is))
104{}
105
106
107Foam::cyclicACMIGAMGInterfaceField::cyclicACMIGAMGInterfaceField
108(
109 const GAMGInterface& GAMGCp,
111 const UPtrList<lduInterfaceField>& other
112)
113:
114 GAMGInterfaceField(GAMGCp, local),
115 cyclicACMIInterface_(refCast<const cyclicACMIGAMGInterface>(GAMGCp)),
116 doTransform_(false),
117 rank_(0)
118{
120
121 doTransform_ = p.doTransform();
122 rank_ = p.rank();
123}
124
125
126// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
127
129{
130 if
131 (
133 (
134 recvRequests_.start(),
135 recvRequests_.size()
136 )
138 (
139 recvRequests1_.start(),
140 recvRequests1_.size()
141 )
142 )
143 {
144 recvRequests_.clear();
145 recvRequests1_.clear();
146
147 if
148 (
150 (
151 sendRequests_.start(),
152 sendRequests_.size()
153 )
155 (
156 sendRequests1_.start(),
157 sendRequests1_.size()
158 )
159 )
160 {
161 sendRequests_.clear();
162 sendRequests1_.clear();
163 }
164
165 return true;
166 }
167
168 return false;
169}
170
171
173(
174 solveScalarField& result,
175 const bool add,
176 const lduAddressing& lduAddr,
177 const label patchId,
178 const solveScalarField& psiInternal,
179 const scalarField& coeffs,
180 const direction cmpt,
181 const Pstream::commsTypes commsType
182) const
183{
184 const auto& AMI =
185 (
186 cyclicACMIInterface_.owner()
187 ? cyclicACMIInterface_.AMI()
188 : cyclicACMIInterface_.neighbPatch().AMI()
189 );
190
191 if (AMI.distributed() && AMI.comm() != -1)
192 {
193 DebugPout<< "cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :"
194 << " interface:" << cyclicACMIInterface_.index()
195 << " size:" << cyclicACMIInterface_.size()
196 << " owner:" << cyclicACMIInterface_.owner()
197 << " AMI distributed:" << AMI.distributed()
198 << endl;
199
200 // Start sending
201 if (commsType != UPstream::commsTypes::nonBlocking)
202 {
204 << "Can only evaluate distributed AMI with nonBlocking"
205 << exit(FatalError);
206 }
207
208 // Get neighbouring field
209 const labelUList& nbrFaceCells =
210 lduAddr.patchAddr(cyclicACMIInterface_.neighbPatchID());
211
212 solveScalarField pnf(psiInternal, nbrFaceCells);
213
214 // Transform according to the transformation tensors
215 transformCoupleField(pnf, cmpt);
216
217
218 // Assert that all receives are known to have finished
219 if (!recvRequests_.empty() || !recvRequests1_.empty())
220 {
222 << "Outstanding recv request(s) on patch "
223 << cyclicACMIInterface_.index()
224 << abort(FatalError);
225 }
226
227 const auto& cache = AMI.cache();
228
229 if (cache.index0() == -1 && cache.index1() == -1)
230 {
231 const auto& map =
232 (
233 cyclicACMIInterface_.owner()
234 ? AMI.tgtMap()
235 : AMI.srcMap()
236 );
237
238 // Insert send/receive requests (non-blocking). See e.g.
239 // cyclicAMIPolyPatchTemplates.C
240 const label oldWarnComm = UPstream::commWarn(AMI.comm());
241 map.send
242 (
243 pnf,
244 sendRequests_,
245 scalarSendBufs_,
246 recvRequests_,
247 scalarRecvBufs_,
248 19462+cyclicACMIInterface_.index() // unique offset + patch index
249 );
250 UPstream::commWarn(oldWarnComm);
251 }
252 else
253 {
254 cache.setDirection(cyclicACMIInterface_.owner());
255
256 if (cache.index0() != -1)
257 {
258 const auto& map0 = cache.cTgtMapPtr0()();
259 map0.send
260 (
261 pnf,
262 sendRequests_,
263 scalarSendBufs_,
264 recvRequests_,
265 scalarRecvBufs_,
266 19462+cyclicACMIInterface_.index() // unique offset + patch index
267 );
268 }
269
270 if (cache.index1() != -1)
271 {
272 const auto& map1 = cache.cTgtMapPtr1()();
273 map1.send
274 (
275 pnf,
276 sendRequests1_,
277 scalarSendBufs1_,
278 recvRequests1_,
279 scalarRecvBufs1_,
280 19463+cyclicACMIInterface_.index() // unique offset + patch index
281 );
282 }
284 }
285
286 this->updatedMatrix(false);
287}
288
289
291(
292 solveScalarField& result,
293 const bool add,
294 const lduAddressing& lduAddr,
295 const label patchId,
296 const solveScalarField& psiInternal,
297 const scalarField& coeffs,
298 const direction cmpt,
300) const
301{
303
304 const labelUList& faceCells = lduAddr.patchAddr(patchId);
305
306 const auto& AMI =
307 (
308 cyclicACMIInterface_.owner()
309 ? cyclicACMIInterface_.AMI()
310 : cyclicACMIInterface_.neighbPatch().AMI()
311 );
312
313 const auto& cache = AMI.cache();
314
315 if (AMI.distributed() && AMI.comm() != -1)
316 {
317 if (cache.index0() == -1 && cache.index1() == -1)
318 {
319 const auto& map =
320 (
321 cyclicACMIInterface_.owner()
322 ? AMI.tgtMap()
323 : AMI.srcMap()
324 );
325
326 // Receive (= copy) data from buffers into work. TBD: receive directly
327 // into slices of work.
328 solveScalarField work;
329 map.receive
330 (
331 recvRequests_,
332 scalarRecvBufs_,
333 work,
334 19462+cyclicACMIInterface_.index() // unique offset + patch index
335 );
336
337 // Receive requests all handled by last function call
338 recvRequests_.clear();
339
340 solveScalarField pnf(faceCells.size(), Zero);
341 AMI.weightedSum
342 (
343 cyclicACMIInterface_.owner(),
344 work,
345 pnf, // result
347 );
348
349 // Add result using coefficients
350 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
351 }
352 else
353 {
354 cache.setDirection(cyclicACMIInterface_.owner());
355
356 solveScalarField pnf(faceCells.size());
357 solveScalarField work(faceCells.size());
358
359 if (cache.index0() != -1)
360 {
361 // Receive (= copy) data from buffers into work. TBD: receive directly
362 // into slices of work.
363 work = Zero;
364 cache.cTgtMapPtr0()().receive
365 (
366 recvRequests_,
367 scalarRecvBufs_,
368 work,
369 19462+cyclicACMIInterface_.index() // unique offset + patch index
370 );
371
372 // Receive requests all handled by last function call
373 recvRequests_.clear();
374
375 pnf = Zero;
377 (
378 AMI.lowWeightCorrection(),
379 cache.cSrcAddress0(),
380 cache.cSrcWeights0(),
381 cache.cSrcWeightsSum0(),
382 work,
383 opType(plusEqOp<solveScalar>()),
384 pnf,
386 );
387
388 pnf *= (1-cache.weight());
389
390 // Add result using coefficients
391 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
392 }
393
394 if (cache.index1() != -1)
395 {
396 // Receive (= copy) data from buffers into work. TBD: receive directly
397 // into slices of work.
398 work = Zero;
399 cache.cTgtMapPtr1()().receive
400 (
401 recvRequests1_,
402 scalarRecvBufs1_,
403 work,
404 19463+cyclicACMIInterface_.index() // unique offset + patch index
405 );
406
407 // Receive requests all handled by last function call
408 recvRequests1_.clear();
409
410 pnf = Zero;
412 (
413 AMI.lowWeightCorrection(),
414 cache.cSrcAddress1(),
415 cache.cSrcWeights1(),
416 cache.cSrcWeightsSum1(),
417 work,
418 opType(plusEqOp<solveScalar>()),
419 pnf,
421 );
422
423 pnf *= cache.weight();
424
425 // Add result using coefficients
426 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
427 }
428 }
429 }
430 else
431 {
432 // Get neighbouring field
433 const labelUList& nbrFaceCells =
434 lduAddr.patchAddr(cyclicACMIInterface_.neighbPatchID());
435
436 solveScalarField work(psiInternal, nbrFaceCells);
437
438 // Transform according to the transformation tensors
439 transformCoupleField(work, cmpt);
440
441 if (cache.index0() == -1 && cache.index1() == -1)
442 {
443 solveScalarField pnf(faceCells.size(), Zero);
444
445 AMI.weightedSum
446 (
447 cyclicACMIInterface_.owner(),
448 work,
449 pnf, // result
451 );
452
453 const labelUList& faceCells = lduAddr.patchAddr(patchId);
454
455 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
456 }
457 else
458 {
459 cache.setDirection(cyclicACMIInterface_.owner());
460
461 solveScalarField pnf(faceCells.size());
462
463 if (cache.index0() != -1)
464 {
465 pnf = Zero;
467 (
468 AMI.lowWeightCorrection(),
469 cache.cSrcAddress0(),
470 cache.cSrcWeights0(),
471 cache.cSrcWeightsSum0(),
472 work,
473 opType(plusEqOp<solveScalar>()),
474 pnf,
476 );
477
478 pnf *= (1 - cache.weight());
479
480 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
481 }
482
483 if (cache.index1() != -1)
484 {
485 pnf = Zero;
487 (
488 AMI.lowWeightCorrection(),
489 cache.cSrcAddress1(),
490 cache.cSrcWeights1(),
491 cache.cSrcWeightsSum1(),
492 work,
493 opType(plusEqOp<solveScalar>()),
494 pnf,
496 );
497
498 pnf *= cache.weight();
499
500 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
501 }
503 }
504
505 this->updatedMatrix(true);
506}
507
508
510{
511 //GAMGInterfaceField::write(os);
512 os << token::SPACE << doTransform()
513 << token::SPACE << rank();
514}
515
516
517// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
static void weightedSum(const scalar lowWeightCorrection, const labelListList &allSlots, const scalarListList &allWeights, const scalarField &weightsSum, const UList< Type > &fld, const CombineOp &cop, List< Type > &result, const UList< Type > &defaultValues)
Weighted sum of contributions. Note: cop operates on single Type only.
static const Field< solveScalar > & null() noexcept
Definition Field.H:192
Abstract base class for GAMG agglomerated interface fields.
Abstract base class for GAMG agglomerated interfaces.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
static bool finishedRequests(label pos, label len=-1)
Non-blocking comms: have all requests (from position onwards) finished? Corresponds to MPI_Testall().
commsTypes
Communications types.
Definition UPstream.H:81
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
static label commWarn(const label communicator) noexcept
Alter communicator debugging setting. Warns for use of any communicator differing from specified....
Definition UPstream.H:1122
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition UPtrList.H:101
GAMG agglomerated cyclic interface for Arbitrarily Coupled Mesh Interface (ACMI) fields.
virtual bool doTransform() const
Cyclic interface functions.
virtual void initInterfaceMatrixUpdate(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Initialise neighbour matrix update.
virtual int rank() const
Return rank of component for transform.
virtual void write(Ostream &) const
Write to stream.
virtual void updateInterfaceMatrix(solveScalarField &result, const bool add, const lduAddressing &lduAddr, const label patchId, const solveScalarField &psiInternal, const scalarField &coeffs, const direction cmpt, const Pstream::commsTypes commsType) const
Update result field based on interface functionality.
virtual bool ready() const
Are all (receive) data available?
GAMG agglomerated cyclic ACMI interface.
void transformCoupleField(Field< Type > &f) const
Transform given patch field.
Abstract base class for cyclic AMI coupled interfaces.
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
An abstract base class for implicitly-coupled interface fields e.g. processor and cyclic patch fields...
bool updatedMatrix() const noexcept
Whether matrix has been updated.
void addToInternalField(Field< Type > &result, const bool add, const labelUList &faceCells, const scalarField &coeffs, const Field< Type > &vals) const
Add/subtract weighted contributions to internal field.
An abstract base class for implicitly-coupled interfaces e.g. processor and cyclic patches.
@ SPACE
Space [isspace].
Definition token.H:144
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
volScalarField & p
bool local
Definition EEqn.H:20
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
label patchId(-1)
#define DebugPout
Report an information message using Foam::Pout.
::Foam::direction rank(const expressions::valueTypeCode) noexcept
The vector-space rank associated with given valueTypeCode.
Definition exprTraits.C:70
Namespace for OpenFOAM.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition typeInfo.H:172
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void add(DimensionedField< scalar, GeoMesh > &result, const dimensioned< scalar > &dt1, const DimensionedField< scalar, GeoMesh > &f2)
errorManip< error > abort(error &err)
Definition errorManip.H:139
Field< solveScalar > solveScalarField
uint8_t direction
Definition direction.H:49
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
bool readBool(Istream &is)
Read bool from stream using Foam::Switch(Istream&).
Definition bool.C:72
dict add("bounds", meshBb)