Loading...
Searching...
No Matches
AMIInterpolationTemplates.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) 2015-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\*---------------------------------------------------------------------------*/
29#include "profiling.H"
30#include "mapDistribute.H"
31
32// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33
34template<class Type, class CombineOp>
36(
37 const scalar lowWeightCorrection,
38 const labelListList& allSlots,
39 const scalarListList& allWeights,
40 const scalarField& weightsSum,
41 const UList<Type>& fld,
42 const CombineOp& cop,
43 List<Type>& result,
44 const UList<Type>& defaultValues
45)
46{
47 if (lowWeightCorrection > 0)
48 {
49 forAll(result, facei)
50 {
51 if (weightsSum[facei] < lowWeightCorrection)
52 {
53 result[facei] = defaultValues[facei];
54 }
55 else
56 {
57 const labelList& slots = allSlots[facei];
58 const scalarList& weights = allWeights[facei];
59
60 forAll(slots, i)
61 {
62 cop(result[facei], facei, fld[slots[i]], weights[i]);
63 }
64 }
65 }
66 }
67 else
68 {
69 forAll(result, facei)
70 {
71 const labelList& slots = allSlots[facei];
72 const scalarList& weights = allWeights[facei];
73
74 forAll(slots, i)
75 {
76 cop(result[facei], facei, fld[slots[i]], weights[i]);
77 }
78 }
79 }
80}
81
82
83template<class Type>
85(
86 const bool toSource,
87 const UList<Type>& fld,
88 List<Type>& result,
89 const UList<Type>& defaultValues
90) const
91{
92 // Note: using non-caching AMI
94 (
95 lowWeightCorrection_,
96 (toSource ? srcAddress_ : tgtAddress_),
97 (toSource ? srcWeights_ : tgtWeights_),
98 (toSource ? srcWeightsSum_ : tgtWeightsSum_),
99 fld,
101 result,
102 defaultValues
103 );
104}
105
106
107template<class Type, class CombineOp, class InterpolateOp>
109(
110 const bool toSource,
111 const UList<Type>& fld,
112 const CombineOp& cop,
113 const InterpolateOp& iop,
114 List<Type>& result,
115 const UList<Type>& defaultValues
116) const
117{
118 // Note
119 // - behaves as old AMIInterpolation::interpolateToSource if toSource=true
120 // - `result` should be preallocated to correct size and initialized to
121 // an appropriate value (e.g. Zero)
122
123 // Get data locally and do a weighted sum
124
125 addProfiling(ami, "AMIInterpolation::interpolate");
126
127 cache_.setDirection(toSource);
128
129 auto checkSizes = [&](
130 const UList<Type>& fld,
131 const labelListList& srcAddr,
132 const labelListList& tgtAddr,
133 const UList<Type>& defVals,
134 const List<Type>& result
135 )
136 {
137 if (fld.size() != tgtAddr.size())
138 {
140 << "Supplied field size is not equal to "
141 << (toSource ? "target" : "source") << " patch size" << nl
142 << " source patch = " << srcAddr.size() << nl
143 << " target patch = " << tgtAddr.size() << nl
144 << " supplied field = " << fld.size()
145 << abort(FatalError);
146 }
147
148 if (result.size() != srcAddr.size())
149 {
151 << "Result field size is not equal to "
152 << (toSource ? "target" : "source") << " patch size" << nl
153 << " source patch = " << srcAddr.size() << nl
154 << " target patch = " << tgtAddr.size() << nl
155 << " result field = " << result.size()
156 << abort(FatalError);
157 }
158
159 if ((lowWeightCorrection_ > 0) && (defVals.size() != srcAddr.size()))
160 {
162 << "Employing default values when sum of weights falls below "
163 << lowWeightCorrection_
164 << " but number of default values is not equal to "
165 << (toSource ? "source" : "target") << " patch size" << nl
166 << " default values = " << defVals.size() << nl
167 << " source patch = " << srcAddr.size() << nl
168 << abort(FatalError);
169 }
170 };
171
172 // Work space for if distributed
173 List<Type> work;
174
175 List<Type> result0;
176 if (cache_.index0() != -1)
177 {
178 result0 = result;
179
180 const auto& srcAddress = cache_.cSrcAddress0();
181 const auto& srcWeights = cache_.cSrcWeights0();
182 const auto& srcWeightsSum = cache_.cSrcWeightsSum0();
183 const auto& tgtAddress = cache_.cTgtAddress0();
184
185 checkSizes(fld, srcAddress, tgtAddress, defaultValues, result0);
186
187 if (distributed() && cache_.cTgtMapPtr0())
188 {
189 const mapDistribute& map = cache_.cTgtMapPtr0()();
190
191 if (map.comm() == -1)
192 {
193 return;
194 }
195
196 work.resize_nocopy(map.constructSize());
197 SubList<Type>(work, fld.size()) = fld; // deep copy
198 map.distribute(work);
199 }
200
201 // if constexpr (is_contiguous_scalar<Type>::value)
202 // {
203 // result0 = Zero;
204 // }
205
207 (
208 lowWeightCorrection_,
209 srcAddress,
210 srcWeights,
211 srcWeightsSum,
212 (distributed() ? work : fld),
213 cop,
214 result0,
215 defaultValues
216 );
217 }
218
219 List<Type> result1;
220 if (cache_.index1() != -1)
221 {
222 result1 = result;
223
224 const auto& srcAddress = cache_.cSrcAddress1();
225 const auto& srcWeights = cache_.cSrcWeights1();
226 const auto& srcWeightsSum = cache_.cSrcWeightsSum1();
227 const auto& tgtAddress = cache_.cTgtAddress1();
228
229 checkSizes(fld, srcAddress, tgtAddress, defaultValues, result1);
230
231 if (distributed() && cache_.cTgtMapPtr1())
232 {
233 const mapDistribute& map = cache_.cTgtMapPtr1()();
234
235 if (map.comm() == -1)
236 {
237 return;
238 }
239
240 work.resize_nocopy(map.constructSize());
241 SubList<Type>(work, fld.size()) = fld; // deep copy
242 map.distribute(work);
243 }
244
245 // if constexpr (is_contiguous_scalar<Type>::value)
246 // {
247 // result1 = Zero;
248 // }
249
251 (
252 lowWeightCorrection_,
253 srcAddress,
254 srcWeights,
255 srcWeightsSum,
256 (distributed() ? work : fld),
257 cop,
258 result1,
259 defaultValues
260 );
261 }
262
263 if (cache_.applyLower())
264 {
265 result = result0;
266 }
267 else if (cache_.applyUpper())
268 {
269 result = result1;
270 }
271 else if (cache_.applyInterpolate())
272 {
273 forAll(result, i)
274 {
275 iop(result[i], i, i, result0[i], i, result1[i], cache_.weight());
276 }
277 }
278 else
279 {
280 // No cache - evaluate the AMI
281
282 const auto& srcAddress = (toSource ? srcAddress_ : tgtAddress_);
283 const auto& srcWeights = (toSource ? srcWeights_ : tgtWeights_);
284 const auto& srcWeightsSum =
285 (toSource ? srcWeightsSum_ : tgtWeightsSum_);
286 const auto& tgtAddress = (toSource ? tgtAddress_ : srcAddress_);
287
288 checkSizes(fld, srcAddress, tgtAddress, defaultValues, result);
289
290 if (distributed() && tgtMapPtr_)
291 {
292 const mapDistribute& map =
293 (
294 toSource
295 ? tgtMapPtr_()
296 : srcMapPtr_()
297 );
298
299 if (map.comm() == -1)
300 {
301 return;
302 }
303
304 work.resize_nocopy(map.constructSize());
305 SubList<Type>(work, fld.size()) = fld; // deep copy
306 map.distribute(work);
307 }
308
309 // result.resize_nocopy(srcAddress.size());
310
311 // if constexpr (is_contiguous_scalar<Type>::value)
312 // {
313 // result = Zero;
314 // }
315
317 (
318 lowWeightCorrection_,
319 srcAddress,
320 srcWeights,
321 srcWeightsSum,
322 (distributed() ? work : fld),
323 cop,
324 result,
325 defaultValues
326 );
327 }
328}
329
330
331// Leave API intact below!
332template<class Type, class CombineOp>
334(
335 const UList<Type>& fld,
336 const CombineOp& cop,
337 List<Type>& result,
338 const UList<Type>& defaultValues
339) const
340{
341 // In-place interpolation
342
343 addProfiling(ami, "AMIInterpolation::interpolateToTarget");
344
345 // Wrap lerp operator to operate inplace
346 auto iop = [&]
347 (
348 Type& res,
349 const label i,
350 const label ia,
351 const Type& a,
352 const label ib,
353 const Type& b,
354 const scalar w
355 )
356 {
357 // res = lerp(a, b, w);
358 res = (scalar{1}-w)*a + w*b;
359 };
360
362 (
363 false, // interpolate to target
364 fld,
365 cop,
366 iop,
367 result,
368 defaultValues
369 );
370}
371
372
373template<class Type, class CombineOp>
375(
376 const UList<Type>& fld,
377 const CombineOp& cop,
378 List<Type>& result,
379 const UList<Type>& defaultValues
380) const
381{
382 // In-place interpolation
383
384 addProfiling(ami, "AMIInterpolation::interpolateToSource");
385
386 // Wrap lerp operator to operate inplace
387 auto iop = [&]
388 (
389 Type& res,
390 const label i,
391 const label ia,
392 const Type& a,
393 const label ib,
394 const Type& b,
395 const scalar w
396 )
397 {
398 // res = lerp(a, b, w);
399 res = (scalar{1}-w)*a + w*b;
400 };
401
402
404 (
405 true, // toSource,
406 fld,
407 cop,
408 iop,
409 result,
410 defaultValues
411 );
412}
413
414
415template<class Type, class CombineOp>
417(
418 const Field<Type>& fld,
419 const CombineOp& cop,
420 const UList<Type>& defaultValues
421) const
422{
423 auto tresult = tmp<Field<Type>>::New(srcAddress_.size(), Zero);
424
425 interpolateToSource
426 (
427 fld,
429 tresult.ref(),
430 defaultValues
431 );
432
433 return tresult;
434}
435
436
437template<class Type, class CombineOp>
439(
440 const tmp<Field<Type>>& tFld,
441 const CombineOp& cop,
442 const UList<Type>& defaultValues
443) const
444{
445 return interpolateToSource(tFld(), cop, defaultValues);
446}
447
448
449template<class Type, class CombineOp>
451(
452 const Field<Type>& fld,
453 const CombineOp& cop,
454 const UList<Type>& defaultValues
455) const
456{
457 auto tresult = tmp<Field<Type>>::New(tgtAddress_.size(), Zero);
458
459 interpolateToTarget
460 (
461 fld,
463 tresult.ref(),
464 defaultValues
465 );
466
467 return tresult;
468}
469
470
471template<class Type, class CombineOp>
473(
474 const tmp<Field<Type>>& tFld,
475 const CombineOp& cop,
476 const UList<Type>& defaultValues
477) const
478{
479 return interpolateToTarget(tFld(), cop, defaultValues);
480}
481
482
483template<class Type>
485(
486 const Field<Type>& fld,
487 const UList<Type>& defaultValues
488) const
489{
490 return interpolateToSource(fld, plusEqOp<Type>(), defaultValues);
491}
492
493
494template<class Type>
496(
497 const tmp<Field<Type>>& tFld,
498 const UList<Type>& defaultValues
499) const
500{
501 return interpolateToSource(tFld(), plusEqOp<Type>(), defaultValues);
502}
503
504
505template<class Type>
507(
508 const Field<Type>& fld,
509 const UList<Type>& defaultValues
510) const
511{
512 return interpolateToTarget(fld, plusEqOp<Type>(), defaultValues);
513}
514
515
516template<class Type>
518(
519 const tmp<Field<Type>>& tFld,
520 const UList<Type>& defaultValues
521) const
522{
523 return interpolateToTarget(tFld(), plusEqOp<Type>(), defaultValues);
524}
525
526
527// ************************************************************************* //
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))
const scalarField & srcWeightsSum() const
Return const access to normalisation factor of source patch weights (i.e. the sum before normalisatio...
labelListList srcAddress_
Addresses of target faces per source face.
bool distributed() const noexcept
Distributed across processors (singlePatchProc == -1).
const labelListList & srcAddress() const
Return const access to source patch addressing.
autoPtr< mapDistribute > srcMapPtr_
Source map pointer - parallel running only.
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...
autoPtr< mapDistribute > tgtMapPtr_
Target map pointer - parallel running only.
const scalarListList & srcWeights() const
Return const access to source patch weights.
labelListList tgtAddress_
Addresses of source faces per target face.
const scalar lowWeightCorrection_
Threshold weight below which interpolation is deactivated.
scalar lowWeightCorrection() const
Threshold weight below which interpolation is deactivated.
scalarField srcWeightsSum_
Sum of weights of target faces per source face.
scalarListList tgtWeights_
Weights of source faces per target face.
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 interpolate(const bool toSource, const UList< Type > &fld, const CombineOp &cop, const InterpolateOp &iop, List< Type > &result, const UList< Type > &defaultValues) const
Weighted sum of (potentially distributed) contributions and apply caching+interpolation....
scalarListList srcWeights_
Weights of target faces per source face.
scalarField tgtWeightsSum_
Sum of weights of source faces per target face.
const labelListList & tgtAddress() const
Return const access to target patch addressing.
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
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
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition ListI.H:171
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
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)
Older name for setAddressableSize.
Definition UList.H:118
label comm() const noexcept
The communicator used.
label constructSize() const noexcept
Constructed data size.
Class containing processor-to-processor mapping information.
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Distribute List data using default commsType, default flip/negate operator.
A class for managing temporary objects.
Definition tmp.H:75
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
List< scalarList > scalarListList
List of scalarList.
Definition scalarList.H:35
Type weightedSum(const UList< scalar > &weights, const UList< Type > &fld)
The local weighted sum (integral) of a field, using the mag() of the weights.
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.
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
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
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
List< scalar > scalarList
List of scalar.
Definition scalarList.H:32
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#define addProfiling(Name,...)
Define profiling trigger with specified name and description string. The description is generated by ...
volScalarField & b
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299