1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 MixingPlane interpolation functions
28 Martin Beaudoin, Hydro-Quebec, 2009. All rights reserved
31 Hrvoje Jasak, Wikki Ltd.
33 \*---------------------------------------------------------------------------*/
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 template<class MasterPatch, class SlavePatch>
42 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::toProfile
44 const Field<Type>& srcF,
45 const labelListList& srcAddr,
46 const scalarListList& srcWeights,
47 Field<Type>& profileBandValues
50 // The src to profile transfer is done using weighted averaging
51 // evaluation of srcF.
52 // See: http://en.wikipedia.org/wiki/Weighted_mean
55 // average(phi) == -----------
58 // Note however that in our case, the weighting factors utilized
59 // for the computation of the weighted average are GGI weighting
60 // factors. So for every interpolation band, we have the following
61 // situation, thanks to the intrinsic conservativeness of the GGI
66 // which leads to the following simplification:
68 // average(phi) == sum(w*phi)
70 forAll (srcAddr, bandI)
72 forAll (srcAddr[bandI], faceI)
74 profileBandValues[bandI] +=
75 srcF[srcAddr[bandI][faceI]]*srcWeights[bandI][faceI];
81 template<class MasterPatch, class SlavePatch>
83 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::fromProfile
85 const Field<Type>& profileBandValues,
86 const labelListList& dstAddr,
87 const scalarListList& dstWeights,
88 Field<Type>& dstResultF
91 // The profile to dst transfer is done by distributing the
92 // average value accordingly to the dst weighting factors
93 forAll (dstAddr, faceI)
95 const labelList& curAddr = dstAddr[faceI];
96 const scalarList& curW = dstWeights[faceI];
98 dstResultF[faceI] = pTraits<Type>::zero;
100 forAll (curAddr, bandI)
102 dstResultF[faceI] += profileBandValues[curAddr[bandI]]*curW[bandI];
108 template<class MasterPatch, class SlavePatch>
110 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::maskedFromProfile
112 const Field<Type>& profileBandValues,
113 const labelListList& dstAddr,
114 const scalarListList& dstWeights,
115 Field<Type>& dstResultF,
116 const labelList& mask
119 // The profile to dst transfer is done by distributing the
120 // average value accordingly to the dst weighting factors
123 // Pick the masked face
124 const label faceI = mask[maskI];
126 const labelList& curAddr = dstAddr[faceI];
127 const scalarList& curW = dstWeights[faceI];
129 dstResultF[maskI] = pTraits<Type>::zero;
131 forAll (curAddr, bandI)
133 dstResultF[maskI] += profileBandValues[curAddr[bandI]]*curW[bandI];
139 template<class MasterPatch, class SlavePatch>
141 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::maskedTransform
143 Field<Type>& transField,
144 const tensorField& t,
145 const Field<Type>& inField,
146 const labelList& mask
149 // The profile to dst transfer is done by distributing the
150 // average value accordingly to the dst weighting factors
153 // Pick the masked face
154 const label faceI = mask[maskI];
156 transField[maskI] = transform(t[faceI], inField[maskI]);
161 template<class MasterPatch, class SlavePatch>
163 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::interpolate
165 const Field<Type>& srcF,
166 const labelListList& srcAddr,
167 const scalarListList& srcWeights,
168 const labelListList& dstAddr,
169 const scalarListList& dstWeights,
170 Field<Type>& dstResultF
173 Field<Type> profileBandValues(nProfileBands(), pTraits<Type>::zero);
175 // Interpolate from patch to profile
184 // profileBandValues are now the circumferentially averaged values
186 // Collect from profile to patch
197 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
199 template<class MasterPatch, class SlavePatch>
202 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToSlave
204 const Field<Type>& patchFF
207 if (patchFF.size() != masterPatch_.size())
211 "MixingPlaneInterpolation::masterToSlave("
212 "const Field<Type> ff) const"
213 ) << "given field does not correspond to patch. Patch size: "
214 << masterPatch_.size() << " field size: " << patchFF.size()
215 << abort(FatalError);
218 // Move master data from 'patch space' to 'profile space'
219 // MB: We need this back
220 Field<Type> profileFF = transform(masterPatchToProfileT(), patchFF);
223 tmp<Field<Type> > tresult
232 Field<Type>& result = tresult();
236 profileFF, // Master data in 'profile space'
237 masterPatchToProfileAddr(), // From master: compute the average
238 masterPatchToProfileWeights(),
239 slaveProfileToPatchAddr(), // To slave distribute average from
240 slaveProfileToPatchWeights(), // profile to patch
244 // Apply transform to bring the slave field back from 'profile space'
246 transform(result, slaveProfileToPatchT(), result);
252 template<class MasterPatch, class SlavePatch>
255 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToSlave
257 const tmp<Field<Type> >& tff
260 tmp<Field<Type> > tint = masterToSlave(tff());
266 template<class MasterPatch, class SlavePatch>
269 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToMaster
271 const Field<Type>& patchFF
274 if (patchFF.size() != slavePatch_.size())
278 "MixingPlaneInterpolation::slaveToMaster("
279 "const Field<Type> ff) const"
280 ) << "given field does not correspond to patch. Patch size: "
281 << slavePatch_.size() << " field size: " << patchFF.size()
282 << abort(FatalError);
285 // Move slave data from 'patch space' to 'profile space'
286 Field<Type> profileFF = transform(slavePatchToProfileT(), patchFF);
289 tmp<Field<Type> > tresult
298 Field<Type>& result = tresult();
302 profileFF, // Slave data in 'profile space'
303 slavePatchToProfileAddr(), // From slave: compute the average
304 slavePatchToProfileWeights(),
305 masterProfileToPatchAddr(), // To master: distribute the average
306 masterProfileToPatchWeights(),
310 // Apply transform to bring the master field back from 'profile space'
312 transform(result, masterProfileToPatchT(), result);
318 template<class MasterPatch, class SlavePatch>
321 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToMaster
323 const tmp<Field<Type> >& tff
326 tmp<Field<Type> > tint = slaveToMaster(tff());
332 template<class MasterPatch, class SlavePatch>
335 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToProfile
337 const Field<Type>& patchFF
340 if (patchFF.size() != masterPatch_.size())
344 "MixingPlaneInterpolation::masterToProfile("
345 "const Field<Type> ff) const"
346 ) << "given field does not correspond to patch. Patch size: "
347 << masterPatch_.size() << " field size: " << patchFF.size()
348 << abort(FatalError);
351 // Move master data from 'patch space' to 'profile space'
352 Field<Type> profileFF = transform(masterPatchToProfileT(), patchFF);
355 tmp<Field<Type> > tresult
364 Field<Type>& result = tresult();
368 profileFF, // Master data in 'profile space'
369 masterPatchToProfileAddr(), // From master: compute the average
370 masterPatchToProfileWeights(),
378 template<class MasterPatch, class SlavePatch>
381 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToProfile
383 const tmp<Field<Type> >& tff
386 tmp<Field<Type> > tint = masterToProfile(tff());
392 template<class MasterPatch, class SlavePatch>
395 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToProfile
397 const Field<Type>& patchFF
400 if (patchFF.size() != slavePatch_.size())
404 "MixingPlaneInterpolation::slaveToProfile("
405 "const Field<Type> ff) const"
406 ) << "given field does not correspond to patch. Patch size: "
407 << slavePatch_.size() << " field size: " << patchFF.size()
408 << abort(FatalError);
411 // Move slave data from 'patch space' to 'profile space'
412 Field<Type> profileFF = transform(slavePatchToProfileT(), patchFF);
415 tmp<Field<Type> > tresult
424 Field<Type>& result = tresult();
428 profileFF, // Slave data in 'profile space'
429 slavePatchToProfileAddr(), // From slave: compute the average
430 slavePatchToProfileWeights(),
438 template<class MasterPatch, class SlavePatch>
441 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToProfile
443 const tmp<Field<Type> >& tff
446 tmp<Field<Type> > tint = slaveToProfile(tff());
452 template<class MasterPatch, class SlavePatch>
455 MixingPlaneInterpolation<MasterPatch, SlavePatch>::profileToMaster
457 const Field<Type>& profileFF
460 if (profileFF.size() != nProfileBands())
464 "MixingPlaneInterpolation::profileToMaster("
465 "const Field<Type> ff) const"
466 ) << "given field does not correspond to profile. Profile size: "
467 << nProfileBands() << " field size: " << profileFF.size()
468 << abort(FatalError);
472 tmp<Field<Type> > tresult
481 Field<Type>& result = tresult();
485 profileFF, // Master data in 'profile space'
486 masterProfileToPatchAddr(), // To master: distribute the average
487 masterProfileToPatchWeights(),
491 // Apply transform to bring the master field back from 'profile space'
493 transform(result, masterProfileToPatchT(), result);
499 template<class MasterPatch, class SlavePatch>
502 MixingPlaneInterpolation<MasterPatch, SlavePatch>::profileToMaster
504 const tmp<Field<Type> >& tff
507 tmp<Field<Type> > tint = profileToMaster(tff());
513 template<class MasterPatch, class SlavePatch>
515 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::maskedProfileToMaster
517 const Field<Type>& profileFF,
519 const labelList& mask
522 if (profileFF.size() != nProfileBands() || result.size() != mask.size())
526 "bvoid MixingPlaneInterpolation<MasterPatch, SlavePatch>::"
527 "maskedProfileToMaster\n"
529 " const Field<Type>& profileFF,\n"
530 " Field<Type>& result,\n"
531 " const labelList& mask\n"
533 ) << "given field does not correspond to profile. Profile size: "
534 << nProfileBands() << " field size: " << profileFF.size()
535 << " result size: " << result.size()
536 << " mask size: " << mask.size()
537 << abort(FatalError);
543 profileFF, // Master data in 'profile space'
544 masterProfileToPatchAddr(), // To master: distribute the average
545 masterProfileToPatchWeights(),
550 // Apply transform to bring the master field back from 'profile space'
552 maskedTransform(result, masterProfileToPatchT(), result, mask);
556 template<class MasterPatch, class SlavePatch>
559 MixingPlaneInterpolation<MasterPatch, SlavePatch>::profileToSlave
561 const Field<Type>& profileFF
564 if (profileFF.size() != nProfileBands())
568 "MixingPlaneInterpolation::profileToSlave("
569 "const Field<Type> ff) const"
570 ) << "given field does not correspond to profile. Profile size: "
571 << nProfileBands() << " field size: " << profileFF.size()
572 << abort(FatalError);
576 tmp<Field<Type> > tresult
585 Field<Type>& result = tresult();
589 profileFF, // Slave data in 'profile space'
590 slaveProfileToPatchAddr(), // To slave distribute average from
591 slaveProfileToPatchWeights(), // profile to patch
595 // Apply transform to bring the slave field back from 'profile space'
597 transform(result, slaveProfileToPatchT(), result);
603 template<class MasterPatch, class SlavePatch>
606 MixingPlaneInterpolation<MasterPatch, SlavePatch>::profileToSlave
608 const tmp<Field<Type> >& tff
611 tmp<Field<Type> > tint = profileToSlave(tff());
617 template<class MasterPatch, class SlavePatch>
619 void MixingPlaneInterpolation<MasterPatch, SlavePatch>::maskedProfileToSlave
621 const Field<Type>& profileFF,
623 const labelList& mask
626 if (profileFF.size() != nProfileBands() || result.size() != mask.size())
630 "void MixingPlaneInterpolation<MasterPatch, SlavePatch>::"
631 "maskedProfileToSlave\n"
633 " const Field<Type>& profileFF,\n"
634 " Field<Type>& result,\n"
635 " const labelList& mask\n"
637 ) << "given field does not correspond to profile. Profile size: "
638 << nProfileBands() << " field size: " << profileFF.size()
639 << " result size: " << result.size()
640 << " mask size: " << mask.size()
641 << abort(FatalError);
646 profileFF, // Slave data in 'profile space'
647 slaveProfileToPatchAddr(), // To slave distribute average from
648 slaveProfileToPatchWeights(), // profile to patch
653 // Apply transform to bring the slave field back from 'profile space'
655 maskedTransform(result, slaveProfileToPatchT(), result, mask);
659 template<class MasterPatch, class SlavePatch>
662 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToMaster
664 const Field<Type>& patchFF
667 if (patchFF.size() != masterPatch_.size())
671 "MixingPlaneInterpolation::masterToMaster("
672 "const Field<Type> ff)"
673 ) << "given field does not correspond to patch. Patch size: "
674 << masterPatch_.size() << " field size: " << patchFF.size()
675 << abort(FatalError);
678 // Move master data from 'patch space' to 'profile space'
679 Field<Type> profileFF = transform(masterPatchToProfileT(), patchFF);
682 tmp<Field<Type> > tresult
691 Field<Type>& result = tresult();
695 profileFF, // Master data in 'profile space'
696 masterPatchToProfileAddr(), // From master: compute the average
697 masterPatchToProfileWeights(),
698 masterProfileToPatchAddr(), // To master: distribute the average
699 masterProfileToPatchWeights(),
703 // Apply transform to bring the master field back from 'profile space'
705 transform(result, masterProfileToPatchT(), result);
711 template<class MasterPatch, class SlavePatch>
714 MixingPlaneInterpolation<MasterPatch, SlavePatch>::masterToMaster
716 const tmp<Field<Type> >& tff
719 tmp<Field<Type> > tint = masterToMaster(tff());
725 template<class MasterPatch, class SlavePatch>
728 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToSlave
730 const Field<Type>& patchFF
733 if (patchFF.size() != slavePatch_.size())
737 "MixingPlaneInterpolation::slaveToSlave("
738 "const Field<Type> ff)"
739 ) << "given field does not correspond to patch. Patch size: "
740 << slavePatch_.size() << " field size: " << patchFF.size()
741 << abort(FatalError);
744 // Move slave data from 'patch space' to 'profile space'
745 Field<Type> profileFF = transform(slavePatchToProfileT(), patchFF);
748 tmp<Field<Type> > tresult
757 Field<Type>& result = tresult();
761 profileFF, // Slave data in 'profile space'
762 slavePatchToProfileAddr(), // From slave: compute the average
763 slavePatchToProfileWeights(),
764 slaveProfileToPatchAddr(), // To slave: distribute the average
765 slaveProfileToPatchWeights(),
769 // Apply transform to bring the slave field back from 'profile space'
771 transform(result, slaveProfileToPatchT(), result);
777 template<class MasterPatch, class SlavePatch>
780 MixingPlaneInterpolation<MasterPatch, SlavePatch>::slaveToSlave
782 const tmp<Field<Type> >& tff
785 tmp<Field<Type> > tint = slaveToSlave(tff());
791 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
793 } // End namespace Foam
795 // ************************************************************************* //