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 -------------------------------------------------------------------------------
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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
30 
31 template<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 
49 template<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  cs.reset(cylindricalCS());
67  }
68 
69  if (!cs)
70  {
71  return interpolateUntransformed(fld, defaultValues);
72  }
73 
74  if constexpr (transform_supported)
75  {
76  const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
77 
78  if (debug)
79  {
80  Pout<< "cyclicAMIPolyPatch::interpolate :"
81  << " patch:" << this->name()
82  << " size:" << this->size()
83  << " nbrPatch:" << nbrPp.name()
84  << " size:" << nbrPp.size()
85  << endl;
86  }
87 
88  if (fld.size() != nbrPp.size())
89  {
91  << "Patch:" << this->name()
92  << " size:" << this->size()
93  << " neighbour patch:" << nbrPp.name()
94  << " size:" << nbrPp.size()
95  << " fld size:" << fld.size()
96  << exit(FatalError);
97  }
98 
99 
100  Field<Type> localFld(fld.size());
101 
102  // Transform to cylindrical coords
103  {
104  const tensorField nbrT(cs().R(nbrPp.faceCentres()));
105  Foam::invTransform(localFld, nbrT, fld);
106  }
107 
108  if (debug&2)
109  {
110  const vectorField::subField nbrFc(nbrPp.faceCentres());
111 
112  Pout<< "On patch:" << this->name()
113  << " size:" << this->size()
114  << " fc:" << gAverage(this->faceCentres())
115  << " getting remote data from:" << nbrPp.name()
116  << " size:" << nbrPp.size()
117  << " fc:" << gAverage(nbrFc)
118  << endl;
119 
120  forAll(fld, i)
121  {
122  Pout<< "At:" << nbrFc[i] << nl
123  << " cart:" << fld[i] << nl
124  << " cyli:" << localFld[i] << nl
125  << endl;
126  }
127  }
128 
129 
130  const tensorField ownT(cs().R(this->faceCentres()));
131 
132  Field<Type> localDeflt(defaultValues.size());
133  if (defaultValues.size() == size())
134  {
135  // Transform default values into cylindrical coords (using
136  // *this faceCentres)
137  // We get in UList (why? Copied from cyclicAMI). Convert to
138  // Field so we can use transformField routines.
139  const SubField<Type> defaultSubFld(defaultValues);
140  const Field<Type>& defaultFld(defaultSubFld);
141  Foam::invTransform(localDeflt, ownT, defaultFld);
142  }
143 
144  // Do the actual interpolation and interpolate back to cartesian
145  return Foam::transform
146  (
147  ownT,
148  interpolateUntransformed(localFld, localDeflt)
149  );
150  }
151  else // (!transform_supported)
152  {
154  << "CODING ERROR??" << nl
155  << "calculated cylindrical coordinate system,"
156  " but does not appear to be a vector-space type" << endl
158  return nullptr;
159  }
160 }
161 
162 
163 template<class Type>
165 (
166  const tmp<Field<Type>>& tFld,
167  const UList<Type>& defaultValues
168 ) const
169 {
170  return interpolate(tFld(), defaultValues);
171 }
172 
173 
174 template<class Type>
176 (
177  const Field<Type>& fld,
178  labelRange& sendRequests,
179  PtrList<List<Type>>& sendBuffers,
180  labelRange& recvRequests,
181  PtrList<List<Type>>& recvBuffers
182 ) const
183 {
184  const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
185 
186  if (AMI.distributed() && AMI.comm() != -1)
187  {
188  const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
189 
190  // Insert send/receive requests (non-blocking)
191  map.send
192  (
193  fld,
194  sendRequests,
195  sendBuffers,
196  recvRequests,
197  recvBuffers,
198  3894+this->index() // unique offset + patch index
199  );
200  }
201 }
202 
203 
204 template<class Type>
206 (
207  const Field<Type>& fld,
208  labelRange& sendRequests,
209  PtrList<List<Type>>& sendBuffers,
210  labelRange& recvRequests,
211  PtrList<List<Type>>& recvBuffers
212 ) const
213 {
214  const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
215 
216  if (!AMI.distributed() || AMI.comm() == -1)
217  {
218  return;
219  }
220 
221  // Can rotate fields (vector and non-spherical tensors)
222  constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
223 
224  [[maybe_unused]]
225  autoPtr<coordSystem::cylindrical> cs;
226 
227  if constexpr (transform_supported)
228  {
229  cs.reset(cylindricalCS());
230  }
231 
232  if (!cs)
233  {
234  initInterpolateUntransformed
235  (
236  fld,
237  sendRequests,
238  sendBuffers,
239  recvRequests,
240  recvBuffers
241  );
242  }
243  else if constexpr (transform_supported)
244  {
245  const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
246 
247  Field<Type> localFld(fld.size());
248 
249  // Transform to cylindrical coords
250  {
251  const tensorField nbrT(cs().R(nbrPp.faceCentres()));
252  Foam::invTransform(localFld, nbrT, fld);
253  }
254 
255  initInterpolateUntransformed
256  (
257  localFld,
258  sendRequests,
259  sendBuffers,
260  recvRequests,
261  recvBuffers
262  );
263  }
264 }
265 
266 
267 template<class Type>
269 (
270  const Field<Type>& localFld,
271  const labelRange& requests,
272  const PtrList<List<Type>>& recvBuffers,
273  const UList<Type>& defaultValues
274 ) const
275 {
276  auto tresult = tmp<Field<Type>>::New(this->size(), Zero);
277 
278  const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
279 
280  Field<Type> work;
281  if (AMI.distributed())
282  {
283  if (AMI.comm() == -1)
284  {
285  return tresult;
286  }
287 
288  const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
289 
290  // Receive (= copy) data from buffers into work. TBD: receive directly
291  // into slices of work.
292  map.receive
293  (
294  requests,
295  recvBuffers,
296  work,
297  3894+this->index() // unique offset + patch index
298  );
299  }
300  const Field<Type>& fld = (AMI.distributed() ? work : localFld);
301 
302  // Rotate fields (vector and non-spherical tensors)
303  constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
304 
305  [[maybe_unused]]
306  autoPtr<coordSystem::cylindrical> cs;
307 
308  // Rotate fields (vector and non-spherical tensors)
309  if constexpr (transform_supported)
310  {
311  cs.reset(cylindricalCS());
312  }
313 
314  if (!cs)
315  {
316  AMI.weightedSum
317  (
318  owner(),
319  fld,
320  tresult.ref(),
321  defaultValues
322  );
323  }
324  else if constexpr (transform_supported)
325  {
326  const tensorField ownT(cs().R(this->faceCentres()));
327 
328  Field<Type> localDeflt(defaultValues.size());
329  if (defaultValues.size() == size())
330  {
331  // Transform default values into cylindrical coords (using
332  // *this faceCentres)
333  // We get in UList (why? Copied from cyclicAMI). Convert to
334  // Field so we can use transformField routines.
335  const SubField<Type> defaultSubFld(defaultValues);
336  const Field<Type>& defaultFld(defaultSubFld);
337  Foam::invTransform(localDeflt, ownT, defaultFld);
338  }
339 
340  AMI.weightedSum
341  (
342  owner(),
343  fld,
344  tresult.ref(),
345  localDeflt
346  );
347 
348  // Transform back
349  Foam::transform(tresult.ref(), ownT, tresult());
350  }
352  return tresult;
353 }
354 
355 
356 template<class Type, class CombineOp>
358 (
359  const UList<Type>& fld,
360  const CombineOp& cop,
361  List<Type>& result,
362  const UList<Type>& defaultValues
363 ) const
364 {
365  //- Commented out for now since called with non-primitives (e.g. wallPoint
366  // from FaceCellWave) - missing Foam::transform, Foam::invTransform
367  /*
368  *
369  // Rotate fields (vector and non-spherical tensors)
370  constexpr bool transform_supported = is_rotational_vectorspace_v<Type>;
371 
372  [[maybe_unused]]
373  autoPtr<coordSystem::cylindrical> cs;
374 
375  // Rotate fields (vector and non-spherical tensors)
376  if constexpr (transform_supported)
377  {
378  cs.reset(cylindricalCS());
379  }
380 
381  if (cs)
382  {
383  const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
384 
385  // Transform to cylindrical coords
386  {
387  const tensorField nbrT(cs().R(nbrPp.faceCentres()));
388  Foam::invTransform(result, nbrT, result);
389  }
390 
391  const tensorField ownT(cs().R(this->faceCentres()));
392 
393  Field<Type> localDeflt(defaultValues.size());
394  if (defaultValues.size() == size())
395  {
396  // Transform default values into cylindrical coords (using
397  // *this faceCentres)
398  // We get in UList (why? Copied from cyclicAMI). Convert to
399  // Field so we can use transformField routines.
400  const SubField<Type> defaultSubFld(defaultValues);
401  const Field<Type>& defaultFld(defaultSubFld);
402  Foam::invTransform(localDeflt, ownT, defaultFld);
403  }
404 
405  // Do actual AMI interpolation
406  if (owner())
407  {
408  AMI().interpolateToSource
409  (
410  fld,
411  cop,
412  result,
413  localDeflt
414  );
415  }
416  else
417  {
418  neighbPatch().AMI().interpolateToTarget
419  (
420  fld,
421  cop,
422  result,
423  localDeflt
424  );
425  }
426 
427  // Transform back. Result is now at *this
428  Foam::transform(result, ownT, result);
429  }
430  else
431  */
432  {
433  if (owner())
434  {
435  AMI().interpolateToSource
436  (
437  fld,
438  cop,
439  result,
440  defaultValues
441  );
442  }
443  else
444  {
445  neighbPatch().AMI().interpolateToTarget
446  (
447  fld,
448  cop,
449  result,
450  defaultValues
451  );
452  }
453  }
454 }
455 
456 
457 // ************************************************************************* //
const AMIPatchToPatchInterpolation & AMI() const
Return a reference to the AMI interpolator.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensionSet invTransform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:527
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:600
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
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.
tmp< Field< Type > > interpolate(const Field< Type > &fld, const UList< Type > &defaultValues=UList< Type >()) const
Interpolate field.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:286
void initInterpolate(const Field< Type > &fld, labelRange &sendRequests, PtrList< List< Type >> &sendBuffers, labelRange &recvRequests, PtrList< List< Type >> &recvBuffers) const
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
Generic templated field type.
Definition: Field.H:63
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...
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void initInterpolateUntransformed(const Field< Type > &fld, labelRange &sendRequests, PtrList< List< Type >> &sendBuffers, labelRange &recvRequests, PtrList< List< Type >> &recvBuffers) const
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
int debug
Static debugging option.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
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...
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
tmp< Field< Type > > interpolateUntransformed(const Field< Type > &fld, const UList< Type > &defaultValues) const
Interpolate without periodic.
#define R(A, B, C, D, E, F, K, M)
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:54
virtual const cyclicAMIPolyPatch & neighbPatch() const
Return a reference to the neighbour patch.
virtual bool owner() const
Does this side own the patch?
SubField< vector > subField
Declare type of subField.
Definition: Field.H:177
A class for managing temporary objects.
Definition: HashPtrTable.H:50
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
coordSystem::cylindrical cylindricalCS
Compatibility typedef 1806.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127