Loading...
Searching...
No Matches
cyclicAMIPolyPatchTemplates.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-2016 OpenFOAM Foundation
9 Copyright (C) 2021-2025 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
29// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
30
31template<class Type>
33(
34 const Field<Type>& fld,
35 const UList<Type>& defaultValues
36) const
37{
38 if (owner())
39 {
40 return AMI().interpolateToSource(fld, defaultValues);
41 }
42 else
43 {
44 return neighbPatch().AMI().interpolateToTarget(fld, defaultValues);
45 }
46}
47
48
49template<class Type>
51(
52 const Field<Type>& fld,
53 const UList<Type>& defaultValues
54) const
55{
56 // Can rotate fields (vector and non-spherical tensors)
57 constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
58
59 [[maybe_unused]]
60 autoPtr<coordSystem::cylindrical> cs;
61
62 // Similar to doTransform.
63
64 if constexpr (transform_supported)
65 {
66 // Only creates the co-ord system if using periodic AMI
67 cs.reset(cylindricalCS());
68 }
69
70 if (!cs)
71 {
72 return interpolateUntransformed(fld, defaultValues);
73 }
74
75 if constexpr (transform_supported)
76 {
77 const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
78
79 if (debug)
80 {
81 Pout<< "cyclicAMIPolyPatch::interpolate :"
82 << " patch:" << this->name()
83 << " size:" << this->size()
84 << " nbrPatch:" << nbrPp.name()
85 << " size:" << nbrPp.size()
86 << endl;
87 }
88
89 if (fld.size() != nbrPp.size())
90 {
92 << "Patch:" << this->name()
93 << " size:" << this->size()
94 << " neighbour patch:" << nbrPp.name()
95 << " size:" << nbrPp.size()
96 << " fld size:" << fld.size()
97 << exit(FatalError);
98 }
99
100
101 Field<Type> localFld(fld.size());
102
103 // Transform to cylindrical coords
104 {
105 const tensorField nbrT(cs().R(nbrPp.faceCentres()));
106 Foam::invTransform(localFld, nbrT, fld);
107 }
108
109 if (debug&2)
110 {
111 const vectorField::subField nbrFc(nbrPp.faceCentres());
112
113 Pout<< "On patch:" << this->name()
114 << " size:" << this->size()
115 << " fc:" << gAverage(this->faceCentres())
116 << " getting remote data from:" << nbrPp.name()
117 << " size:" << nbrPp.size()
118 << " fc:" << gAverage(nbrFc)
119 << endl;
120
121 forAll(fld, i)
122 {
123 Pout<< "At:" << nbrFc[i] << nl
124 << " cart:" << fld[i] << nl
125 << " cyli:" << localFld[i] << nl
126 << endl;
127 }
128 }
129
130
131 const tensorField ownT(cs().R(this->faceCentres()));
132
133 Field<Type> localDeflt(defaultValues.size());
134 if (defaultValues.size() != 0 && defaultValues.size() == size())
135 {
136 // Transform default values into cylindrical coords (using
137 // *this faceCentres)
138 // We get in UList (why? Copied from cyclicAMI). Convert to
139 // Field so we can use transformField routines.
140 const SubField<Type> defaultSubFld(defaultValues);
141 const Field<Type>& defaultFld(defaultSubFld);
142 Foam::invTransform(localDeflt, ownT, defaultFld);
143 }
144
145 // Do the actual interpolation and interpolate back to cartesian
146 return Foam::transform
147 (
148 ownT,
149 interpolateUntransformed(localFld, localDeflt)
150 );
151 }
152 else // (!transform_supported)
153 {
155 << "CODING ERROR??" << nl
156 << "calculated cylindrical coordinate system,"
157 " but does not appear to be a vector-space type" << endl
159 return nullptr;
160 }
161}
162
163
164template<class Type>
166(
167 const tmp<Field<Type>>& tFld,
168 const UList<Type>& defaultValues
169) const
170{
171 return interpolate(tFld(), defaultValues);
172}
173
174
175template<class Type>
177(
178 const Field<Type>& fld,
179 labelRange& sendRequests,
180 labelRange& recvRequests,
181 PtrList<List<Type>>& sendBuffers,
182 PtrList<List<Type>>& recvBuffers,
183
184 labelRange& sendRequests1,
185 labelRange& recvRequests1,
186 PtrList<List<Type>>& sendBuffers1,
187 PtrList<List<Type>>& recvBuffers1
188) const
189{
190 const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
191
192 if (AMI.distributed() && AMI.comm() != -1)
193 {
194 const auto& cache = AMI.cache();
195
196 if (cache.index0() == -1 && cache.index1() == -1)
197 {
198 // No caching
199
200 const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
201
202 // Insert send/receive requests (non-blocking)
203 map.send
204 (
205 fld,
206 sendRequests,
207 sendBuffers,
208 recvRequests,
209 recvBuffers,
210 3894+this->index() // unique offset + patch index
211 );
212 }
213 else
214 {
215 // Caching is active
216
217 cache.setDirection(owner());
218
219 if (cache.index0() != -1)
220 {
221 const auto& map0 = cache.cTgtMapPtr0()();
222
223 // Insert send/receive requests (non-blocking)
224 map0.send
225 (
226 fld,
227 sendRequests,
228 sendBuffers,
229 recvRequests,
230 recvBuffers,
231 3894+this->index() // unique offset + patch index
232 );
233 }
234
235 if (cache.index1() != -1)
236 {
237 const auto& map1 = cache.cTgtMapPtr1()();
238
239 // Insert send/receive requests (non-blocking)
240 map1.send
241 (
242 fld,
243 sendRequests1,
244 sendBuffers1,
245 recvRequests1,
246 recvBuffers1,
247 3895+this->index() // unique offset + patch index
248 );
250 }
251 }
252}
253
254
255template<class Type>
257(
258 const Field<Type>& fld,
259 labelRange& sendRequests,
260 labelRange& recvRequests,
261 PtrList<List<Type>>& sendBuffers,
262 PtrList<List<Type>>& recvBuffers,
263
264 labelRange& sendRequests1,
265 labelRange& recvRequests1,
266 PtrList<List<Type>>& sendBuffers1,
267 PtrList<List<Type>>& recvBuffers1
268) const
269{
270 const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
271
272 if (!AMI.distributed() || AMI.comm() == -1)
273 {
274 return;
275 }
276
277 // Can rotate fields (vector and non-spherical tensors)
278 constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
279
280 if constexpr (transform_supported)
281 {
282 // Only creates the co-ord system if using periodic AMI
283 // - convert to cylindrical coordinate system
284 auto cs = cylindricalCS();
285
286 if (cs)
287 {
288 Field<Type> localFld(fld.size());
289 const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
290 const tensorField nbrT(cs().R(nbrPp.faceCentres()));
291 Foam::invTransform(localFld, nbrT, fld);
292
293 initInterpolateUntransformed
294 (
295 localFld,
296 sendRequests,
297 recvRequests,
298 sendBuffers,
299 recvBuffers,
300
301 sendRequests1,
302 recvRequests1,
303 sendBuffers1,
304 recvBuffers1
305 );
306
307 return;
308 }
309 }
310
311 initInterpolateUntransformed
312 (
313 fld,
314 sendRequests,
315 recvRequests,
316 sendBuffers,
317 recvBuffers,
318
319 sendRequests1,
320 recvRequests1,
321 sendBuffers1,
322 recvBuffers1
323 );
324}
325
326
327template<class Type>
329(
330 const Field<Type>& localFld,
331 const labelRange& requests,
332 const PtrList<List<Type>>& recvBuffers,
333 const labelRange& requests1,
334 const PtrList<List<Type>>& recvBuffers1,
335 const UList<Type>& defaultValues
336) const
337{
338 // Note: cannot be localFld.size() -> is set to null for distributed AMI
339 auto tresult = tmp<Field<Type>>::New(this->size(), Zero);
340
341 const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
342
343 const auto& cache = AMI.cache();
344 cache.setDirection(owner());
345
346 Field<Type> work;
347 Field<Type> work1;
348 if (AMI.distributed())
349 {
350 if (AMI.comm() == -1)
351 {
352 return tresult;
353 }
354
355 if (cache.index0() == -1 && cache.index1() == -1)
356 {
357 // No caching
358 const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
359
360 // Receive (= copy) data from buffers into work. TBD: receive
361 // directly into slices of work.
362 map.receive
363 (
364 requests,
365 recvBuffers,
366 work,
367 3894+this->index() // unique offset + patch index
368 );
369 }
370 else
371 {
372 // Using AMI cache
373
374 if (cache.index0() != -1)
375 {
376 cache.cTgtMapPtr0()().receive
377 (
378 requests,
379 recvBuffers,
380 work,
381 3894+this->index() // unique offset + patch index
382 );
383 }
384
385 if (cache.index1() != -1)
386 {
387 cache.cTgtMapPtr1()().receive
388 (
389 requests1,
390 recvBuffers1,
391 work1,
392 3895+this->index() // unique offset + patch index
393 );
394 }
395 }
396 }
397
398 const Field<Type>& fld = (AMI.distributed() ? work : localFld);
399 const Field<Type>& fld1 = (AMI.distributed() ? work1 : localFld);
400
401 // Rotate fields (vector and non-spherical tensors)
402 constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
403
404 // Rotate fields (vector and non-spherical tensors) for periodic AMI
405 tensorField ownTransform;
406 Field<Type> localDeflt;
407
408 if constexpr (transform_supported)
409 {
410 // Only creates the co-ord system if using periodic AMI
411 // - convert to cylindrical coordinate system
412 auto cs = cylindricalCS();
413
414 if (cs)
415 {
416 ownTransform = cs().R(this->faceCentres());
417 localDeflt = defaultValues;
418
419 if (defaultValues.size() == size())
420 {
421 // Transform default values into cylindrical coords (using
422 // *this faceCentres)
423 // We get in UList (why? Copied from cyclicAMI). Convert to
424 // Field so we can use transformField routines.
425 const SubField<Type> defaultSubFld(defaultValues);
426 const Field<Type>& defaultFld(defaultSubFld);
427 Foam::invTransform(localDeflt, ownTransform, defaultFld);
428 }
429 }
430 }
431
432 const auto& localDefaultValues =
433 localDeflt.size() ? localDeflt : defaultValues;
434
435 if (cache.index0() == -1 && cache.index1() == -1)
436 {
437 // No caching
438 AMI.weightedSum
439 (
440 owner(),
441 fld,
442 tresult.ref(),
443 localDefaultValues
444 );
445
446 // Transform back
447 if (ownTransform.size())
448 {
449 Foam::transform(tresult.ref(), ownTransform, tresult());
450 }
451
452 return tresult;
453 }
454 else
455 {
456 if (cache.index0() != -1)
457 {
459 (
460 AMI.lowWeightCorrection(),
461 cache.cSrcAddress0(),
462 cache.cSrcWeights0(),
463 cache.cSrcWeightsSum0(),
464 fld,
466 tresult.ref(),
467 localDefaultValues
468 );
469
470 if (ownTransform.size())
471 {
472 Foam::transform(tresult.ref(), ownTransform, tresult());
473 }
474
475 // Assuming cache weight is zero when index1 is inactive (==-1)
476 tresult.ref() *= (1 - cache.weight());
477 }
478
479 if (cache.index1() != -1)
480 {
481 auto tresult1 = tmp<Field<Type>>::New(this->size(), Zero);
482
484 (
485 AMI.lowWeightCorrection(),
486 cache.cSrcAddress1(),
487 cache.cSrcWeights1(),
488 cache.cSrcWeightsSum1(),
489 fld1,
491 tresult1.ref(),
492 localDefaultValues
493 );
494
495 if (ownTransform.size())
496 {
497 Foam::transform(tresult1.ref(), ownTransform, tresult1());
498 }
499
500 tresult1.ref() *= cache.weight();
501 tresult.ref() += tresult1();
502 }
504 return tresult;
505 }
506}
507
508
509template<class Type, class CombineOp>
511(
512 const UList<Type>& fld,
513 const CombineOp& cop,
514 List<Type>& result,
515 const UList<Type>& defaultValues
516) const
517{
518 //- Commented out for now since called with non-primitives (e.g. wallPoint
519 // from FaceCellWave) - missing Foam::transform, Foam::invTransform
520 /*
521 *
522 // Rotate fields (vector and non-spherical tensors)
523 constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
524
525 [[maybe_unused]]
526 autoPtr<coordSystem::cylindrical> cs;
527
528 // Rotate fields (vector and non-spherical tensors)
529 if constexpr (transform_supported)
530 {
531 cs.reset(cylindricalCS());
532 }
533
534 if (cs)
535 {
536 const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
537
538 // Transform to cylindrical coords
539 {
540 const tensorField nbrT(cs().R(nbrPp.faceCentres()));
541 Foam::invTransform(result, nbrT, result);
542 }
543
544 const tensorField ownT(cs().R(this->faceCentres()));
545
546 Field<Type> localDeflt(defaultValues.size());
547 if (defaultValues.size() == size())
548 {
549 // Transform default values into cylindrical coords (using
550 // *this faceCentres)
551 // We get in UList (why? Copied from cyclicAMI). Convert to
552 // Field so we can use transformField routines.
553 const SubField<Type> defaultSubFld(defaultValues);
554 const Field<Type>& defaultFld(defaultSubFld);
555 Foam::invTransform(localDeflt, ownT, defaultFld);
556 }
557
558 // Do actual AMI interpolation
559 if (owner())
560 {
561 AMI().interpolateToSource
562 (
563 fld,
564 cop,
565 result,
566 localDeflt
567 );
568 }
569 else
570 {
571 neighbPatch().AMI().interpolateToTarget
572 (
573 fld,
574 cop,
575 result,
576 localDeflt
577 );
578 }
579
580 // Transform back. Result is now at *this
581 Foam::transform(result, ownT, result);
582 }
583 else
584 */
585 {
586 if (owner())
587 {
588 AMI().interpolateToSource
589 (
590 fld,
591 cop,
592 result,
593 defaultValues
594 );
595 }
596 else
597 {
598 neighbPatch().AMI().interpolateToTarget
599 (
600 fld,
601 cop,
602 result,
603 defaultValues
604 );
605 }
606 }
607}
608
609
610// ************************************************************************* //
#define R(A, B, C, D, E, F, K, M)
if(patchID !=-1)
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
void interpolateToSource(const UList< Type > &fld, const CombineOp &cop, List< Type > &result, const UList< Type > &defaultValues=UList< Type >::null()) const
Interpolate from target to source with supplied op to combine existing value with remote value and we...
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.
void interpolateToTarget(const UList< Type > &fld, const CombineOp &cop, List< Type > &result, const UList< Type > &defaultValues=UList< Type >::null()) const
Interpolate from source to target with supplied op to combine existing value with remote value and we...
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
SubField< vector > subField
Definition Field.H:183
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
SubField is a Field obtained as a section of another Field, without its own allocation....
Definition SubField.H:58
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Definition UList.H:118
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
Cyclic patch for Arbitrary Mesh Interface (AMI).
virtual bool owner() const
Does this side own the patch?
tmp< Field< Type > > interpolateUntransformed(const Field< Type > &fld, const UList< Type > &defaultValues) const
Interpolate without periodic.
const AMIPatchToPatchInterpolation & AMI() const
Return a reference to the AMI interpolator.
virtual const cyclicAMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
tmp< Field< Type > > interpolate(const Field< Type > &fld, const UList< Type > &defaultValues=UList< Type >()) const
Interpolate field.
void initInterpolateUntransformed(const Field< Type > &fld, labelRange &sendRequests, labelRange &recvRequests, PtrList< List< Type > > &sendBuffers, PtrList< List< Type > > &recvBuffers, labelRange &sendRequests1, labelRange &recvRequests1, PtrList< List< Type > > &sendBuffers1, PtrList< List< Type > > &recvBuffers1) const
void initInterpolate(const Field< Type > &fld, labelRange &sendRequests, labelRange &recvRequests, PtrList< List< Type > > &sendBuffers, PtrList< List< Type > > &recvBuffers, labelRange &sendRequests1, labelRange &recvRequests1, PtrList< List< Type > > &sendBuffers1, PtrList< List< Type > > &recvBuffers1) const
cyclicAMIPolyPatch(const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm, const word &patchType, const transformType transform=UNKNOWN, const word &defaultAMIMethod=faceAreaWeightAMI::typeName)
Construct from (base coupled patch) components.
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
label index() const noexcept
The index of this patch in the boundaryMesh.
const word & name() const noexcept
The patch name.
const vectorField::subField faceCentres() const
Return face centres.
Definition polyPatch.C:320
A class for managing temporary objects.
Definition tmp.H:75
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
Namespace for handling debugging switches.
Definition debug.C:45
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
dimensionSet invTransform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
coordSystem::cylindrical cylindricalCS
Compatibility typedef 1806.
errorManip< error > abort(error &err)
Definition errorManip.H:139
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition curveTools.C:75
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
constexpr bool is_rotational_vectorspace_v
The is_rotational_vectorspace value of Type.
Definition pTraits.H:251
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299