Loading...
Searching...
No Matches
cyclicAMIGAMGInterfaceField.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-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::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
62(
63 const GAMGInterface& GAMGCp,
64 const lduInterfaceField& fineInterface
65)
66:
67 GAMGInterfaceField(GAMGCp, fineInterface),
68 cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
69 doTransform_(false),
70 rank_(0)
71{
74
75 doTransform_ = p.doTransform();
76 rank_ = p.rank();
77}
78
79
80Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
81(
82 const GAMGInterface& GAMGCp,
83 const bool doTransform,
84 const int rank
85)
86:
87 GAMGInterfaceField(GAMGCp, doTransform, rank),
88 cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
89 doTransform_(doTransform),
90 rank_(rank)
91{}
92
93
94Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
95(
96 const GAMGInterface& GAMGCp,
97 Istream& is
98)
99:
100 GAMGInterfaceField(GAMGCp, is),
101 cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(GAMGCp)),
102 doTransform_(readBool(is)),
103 rank_(readLabel(is))
104{}
105
106
107Foam::cyclicAMIGAMGInterfaceField::cyclicAMIGAMGInterfaceField
108(
109 const GAMGInterface& GAMGCp,
111 const UPtrList<lduInterfaceField>& other
112)
113:
114 GAMGInterfaceField(GAMGCp, local),
115 cyclicAMIInterface_(refCast<const cyclicAMIGAMGInterface>(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 cyclicAMIInterface_.owner()
187 ? cyclicAMIInterface_.AMI()
188 : cyclicAMIInterface_.neighbPatch().AMI()
189 );
190 if (AMI.distributed() && AMI.comm() != -1)
191 {
192 //DebugPout<< "cyclicAMIFvPatchField::initInterfaceMatrixUpdate() :"
193 // << " interface:" << cyclicAMIInterface_.index()
194 // << " size:" << cyclicAMIInterface_.size()
195 // << " owner:" << cyclicAMIInterface_.owner()
196 // << " AMI distributed:" << AMI.distributed()
197 // << " AMI low-weight:" << AMI.applyLowWeightCorrection()
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(cyclicAMIInterface_.neighbPatchID());
211
212 solveScalarField pnf(psiInternal, nbrFaceCells);
213
214 // Transform according to the transformation tensors
215 transformCoupleField(pnf, cmpt);
216
217 // Assert that all receives are known to have finished
218 if (!recvRequests_.empty() || !recvRequests1_.empty())
219 {
221 << "Outstanding recv request(s) on patch "
222 << cyclicAMIInterface_.index()
223 << abort(FatalError);
224 }
225
226 const auto& cache = AMI.cache();
227
228 if (cache.index0() == -1 && cache.index1() == -1)
229 {
230 const auto& map =
231 (
232 cyclicAMIInterface_.owner()
233 ? AMI.tgtMap()
234 : AMI.srcMap()
235 );
236
237 // Insert send/receive requests (non-blocking). See e.g.
238 // cyclicAMIPolyPatchTemplates.C
239 const label oldWarnComm = UPstream::commWarn(AMI.comm());
240 map.send
241 (
242 pnf,
243 sendRequests_,
244 scalarSendBufs_,
245 recvRequests_,
246 scalarRecvBufs_,
247 19462+cyclicAMIInterface_.index() // unique offset + patch index
248 );
249 UPstream::commWarn(oldWarnComm);
250 }
251 else
252 {
253 cache.setDirection(cyclicAMIInterface_.owner());
254
255 if (cache.index0() != -1)
256 {
257 const auto& map0 = cache.cTgtMapPtr0()();
258 map0.send
259 (
260 pnf,
261 sendRequests_,
262 scalarSendBufs_,
263 recvRequests_,
264 scalarRecvBufs_,
265 19462+cyclicAMIInterface_.index() // unique offset + patch index
266 );
267 }
268
269 if (cache.index1() != -1)
270 {
271 const auto& map1 = cache.cTgtMapPtr1()();
272 map1.send
273 (
274 pnf,
275 sendRequests1_,
276 scalarSendBufs1_,
277 recvRequests1_,
278 scalarRecvBufs1_,
279 19463+cyclicAMIInterface_.index() // unique offset + patch index
280 );
281 }
283 }
284
285 this->updatedMatrix(false);
286}
287
288
290(
291 solveScalarField& result,
292 const bool add,
293 const lduAddressing& lduAddr,
294 const label patchId,
295 const solveScalarField& psiInternal,
296 const scalarField& coeffs,
297 const direction cmpt,
298 const Pstream::commsTypes commsType
299) const
300{
302
303 const labelUList& faceCells = lduAddr.patchAddr(patchId);
304
305 const auto& AMI =
306 (
307 cyclicAMIInterface_.owner()
308 ? cyclicAMIInterface_.AMI()
309 : cyclicAMIInterface_.neighbPatch().AMI()
310 );
311
312 solveScalarField defaultValues;
313 if (AMI.applyLowWeightCorrection())
314 {
315 defaultValues = solveScalarField(psiInternal, faceCells);
316 }
317
318 //DebugPout<< "cyclicAMIFvPatchField::updateInterfaceMatrix() :"
319 // << " interface:" << cyclicAMIInterface_.index()
320 // << " size:" << cyclicAMIInterface_.size()
321 // << " owner:" << cyclicAMIInterface_.owner()
322 // << " AMI distributed:" << AMI.distributed()
323 // << " AMI low-weight:" << AMI.applyLowWeightCorrection()
324 // << endl;
325
326 const auto& cache = AMI.cache();
327
328 // Assume that sends are also OK
329 sendRequests_.clear();
330 sendRequests1_.clear();
331
332 if (AMI.distributed() && AMI.comm() != -1)
333 {
334 if (commsType != UPstream::commsTypes::nonBlocking)
335 {
337 << "Can only evaluate distributed AMI with nonBlocking"
338 << exit(FatalError);
339 }
340
341 if (cache.index0() == -1 && cache.index1() == -1)
342 {
343 const auto& map =
344 (
345 cyclicAMIInterface_.owner()
346 ? AMI.tgtMap()
347 : AMI.srcMap()
348 );
349
350 // Receive (= copy) data from buffers into work. TBD: receive directly
351 // into slices of work.
352 solveScalarField work;
353 map.receive
354 (
355 recvRequests_,
356 scalarRecvBufs_,
357 work,
358 19462+cyclicAMIInterface_.index() // unique offset + patch index
359 );
360
361 // Receive requests all handled by last function call
362 recvRequests_.clear();
363
364 solveScalarField pnf(faceCells.size(), Zero);
365 AMI.weightedSum
366 (
367 cyclicAMIInterface_.owner(),
368 work,
369 pnf, // result
370 defaultValues
371 );
372
373 // Add result using coefficients
374 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
375 }
376 else
377 {
378 cache.setDirection(cyclicAMIInterface_.owner());
379
380 solveScalarField pnf(faceCells.size());
381 solveScalarField work(faceCells.size());
382
383 if (cache.index0() != -1)
384 {
385 // Receive (= copy) data from buffers into work. TBD: receive directly
386 // into slices of work.
387 work = Zero;
388 cache.cTgtMapPtr0()().receive
389 (
390 recvRequests_,
391 scalarRecvBufs_,
392 work,
393 19462+cyclicAMIInterface_.index() // unique offset + patch index
394 );
395
396 // Receive requests all handled by last function call
397 recvRequests_.clear();
398
399 pnf = Zero;
401 (
402 AMI.lowWeightCorrection(),
403 cache.cSrcAddress0(),
404 cache.cSrcWeights0(),
405 cache.cSrcWeightsSum0(),
406 work,
407 opType(plusEqOp<solveScalar>()),
408 pnf,
409 defaultValues
410 );
411
412 pnf *= (1-cache.weight());
413
414 // Add result using coefficients
415 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
416 }
417
418 if (cache.index1() != -1)
419 {
420 // Receive (= copy) data from buffers into work. TBD: receive directly
421 // into slices of work.
422 work = Zero;
423 cache.cTgtMapPtr1()().receive
424 (
425 recvRequests1_,
426 scalarRecvBufs1_,
427 work,
428 19463+cyclicAMIInterface_.index() // unique offset + patch index
429 );
430
431 // Receive requests all handled by last function call
432 recvRequests1_.clear();
433
434 pnf = Zero;
436 (
437 AMI.lowWeightCorrection(),
438 cache.cSrcAddress1(),
439 cache.cSrcWeights1(),
440 cache.cSrcWeightsSum1(),
441 work,
442 opType(plusEqOp<solveScalar>()),
443 pnf,
444 defaultValues
445 );
446
447 pnf *= cache.weight();
448
449 // Add result using coefficients
450 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
451 }
452 }
453 }
454 else
455 {
456 // Get neighbouring field
457 const labelUList& nbrFaceCells =
458 lduAddr.patchAddr(cyclicAMIInterface_.neighbPatchID());
459
460 solveScalarField work(psiInternal, nbrFaceCells);
461
462 // Transform according to the transformation tensors
463 transformCoupleField(work, cmpt);
464
465 solveScalarField pnf(faceCells.size());
466
467 if (cache.index0() == -1 && cache.index1() == -1)
468 {
469 pnf = Zero;
470 AMI.weightedSum
471 (
472 cyclicAMIInterface_.owner(),
473 work,
474 pnf, // result
475 defaultValues
476 );
477
478 // Add result using coefficients
479 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
480 }
481 else
482 {
483 cache.setDirection(cyclicAMIInterface_.owner());
484
485 if (cache.index0() != -1)
486 {
487 pnf = Zero;
489 (
490 AMI.lowWeightCorrection(),
491 cache.cSrcAddress0(),
492 cache.cSrcWeights0(),
493 cache.cSrcWeightsSum0(),
494 work,
495 opType(plusEqOp<solveScalar>()),
496 pnf,
497 defaultValues
498 );
499
500 pnf *= (1 - cache.weight());
501
502 // Add result using coefficients
503 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
504 }
505
506 if (cache.index1() != -1)
507 {
508 pnf = Zero;
510 (
511 AMI.lowWeightCorrection(),
512 cache.cSrcAddress1(),
513 cache.cSrcWeights1(),
514 cache.cSrcWeightsSum1(),
515 work,
516 opType(plusEqOp<solveScalar>()),
517 pnf,
518 defaultValues
519 );
520
521 pnf *= cache.weight();
522
523 // Add result using coefficients
524 this->addToInternalField(result, !add, faceCells, coeffs, pnf);
525 }
527 }
528
529 this->updatedMatrix(true);
530}
531
532
534{
535 //GAMGInterfaceField::write(os);
536 os << token::SPACE << doTransform()
537 << token::SPACE << rank();
538}
539
540
541// ************************************************************************* //
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.
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 field.
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 AMI interface.
Abstract base class for cyclic AMI coupled interfaces.
void transformCoupleField(Field< Type > &f) const
Transform given patch field.
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)
::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.
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)