Forward compatibility: flex
[foam-extend-3.2.git] / src / foam / fields / FieldFields / FieldField / FieldFieldFunctions.C
blobae2ed236809d8714c64014a173fdd015335c5689
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "PstreamReduceOps.H"
27 #include "FieldFieldReuseFunctions.H"
29 #define TEMPLATE template<template<class> class Field, class Type>
30 #include "FieldFieldFunctionsM.C"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
34 namespace Foam
37 /* * * * * * * * * * * * * * * * Global functions  * * * * * * * * * * * * * */
39 template<template<class> class Field, class Type>
40 void component
42     FieldField<Field, typename FieldField<Field, Type>::cmptType>& sf,
43     const FieldField<Field, Type>& f,
44     const direction d
47     forAll(sf, i)
48     {
49         component(sf[i], f[i], d);
50     }
54 template<template<class> class Field, class Type>
55 void T(FieldField<Field, Type>& f1, const FieldField<Field, Type>& f2)
57     forAll(f1, i)
58     {
59         T(f1[i], f2[i]);
60     }
64 template<template<class> class Field, class Type, int r>
65 void pow
67     FieldField<Field, typename powProduct<Type, r>::type>& f,
68     const FieldField<Field, Type>& vf
71     forAll(f, i)
72     {
73         pow(f[i], vf[i]);
74     }
77 template<template<class> class Field, class Type, int r>
78 tmp<FieldField<Field, typename powProduct<Type, r>::type> >
79 pow
81     const FieldField<Field, Type>& f, typename powProduct<Type, r>::type
84     typedef typename powProduct<Type, r>::type powProductType;
85     tmp<FieldField<Field, powProductType> > tRes
86     (
87         FieldField<Field, powProductType>::NewCalculatedType(f)
88     );
89     pow<Type, r>(tRes(), f);
90     return tRes;
93 template<template<class> class Field, class Type, int r>
94 tmp<FieldField<Field, typename powProduct<Type, r>::type> >
95 pow
97     const tmp<FieldField<Field, Type> >& tf, typename powProduct<Type, r>::type
100     typedef typename powProduct<Type, r>::type powProductType;
101     tmp<FieldField<Field, powProductType> > tRes
102     (
103         reuseTmpFieldField<Field, powProductType, Type>::New(tf)
104     );
105     pow<Type, r>(tRes(), tf());
106     reuseTmpFieldField<Field, powProductType, Type>::clear(tf);
107     return tRes;
111 template<template<class> class Field, class Type>
112 void sqr
114     FieldField<Field, typename outerProduct<Type, Type>::type>& f,
115     const FieldField<Field, Type>& vf
118     forAll(f, i)
119     {
120         sqr(f[i], vf[i]);
121     }
124 template<template<class> class Field, class Type>
125 tmp<FieldField<Field, typename outerProduct<Type, Type>::type> >
126 sqr(const FieldField<Field, Type>& f)
128     typedef typename outerProduct<Type, Type>::type outerProductType;
129     tmp<FieldField<Field, outerProductType> > tRes
130     (
131         FieldField<Field, outerProductType>::NewCalculatedType(f)
132     );
133     sqr(tRes(), f);
134     return tRes;
137 template<template<class> class Field, class Type>
138 tmp<FieldField<Field, typename outerProduct<Type, Type>::type> >
139 sqr(const tmp<FieldField<Field, Type> >& tf)
141     typedef typename outerProduct<Type, Type>::type outerProductType;
142     tmp<FieldField<Field, outerProductType> > tRes
143     (
144         reuseTmpFieldField<Field, outerProductType, Type>::New(tf)
145     );
146     sqr(tRes(), tf());
147     reuseTmpFieldField<Field, outerProductType, Type>::clear(tf);
148     return tRes;
152 template<template<class> class Field, class Type>
153 void magSqr(FieldField<Field, scalar>& sf, const FieldField<Field, Type>& f)
155     forAll(sf, i)
156     {
157         magSqr(sf[i], f[i]);
158     }
161 template<template<class> class Field, class Type>
162 tmp<FieldField<Field, scalar> > magSqr(const FieldField<Field, Type>& f)
164     tmp<FieldField<Field, scalar> > tRes
165     (
166         FieldField<Field, scalar>::NewCalculatedType(f)
167     );
169     magSqr(tRes(), f);
170     return tRes;
173 template<template<class> class Field, class Type>
174 tmp<FieldField<Field, scalar> > magSqr(const tmp<FieldField<Field, Type> >& tf)
176     tmp<FieldField<Field, scalar> > tRes
177     (
178         reuseTmpFieldField<Field, scalar, Type>::New(tf)
179     );
181     magSqr(tRes(), tf());
182     reuseTmpFieldField<Field, scalar, Type>::clear(tf);
183     return tRes;
187 template<template<class> class Field, class Type>
188 void mag(FieldField<Field, scalar>& sf, const FieldField<Field, Type>& f)
190     forAll(sf, i)
191     {
192         mag(sf[i], f[i]);
193     }
196 template<template<class> class Field, class Type>
197 tmp<FieldField<Field, scalar> > mag(const FieldField<Field, Type>& f)
199     tmp<FieldField<Field, scalar> > tRes
200     (
201         FieldField<Field, scalar>::NewCalculatedType(f)
202     );
204     mag(tRes(), f);
205     return tRes;
208 template<template<class> class Field, class Type>
209 tmp<FieldField<Field, scalar> > mag(const tmp<FieldField<Field, Type> >& tf)
211     tmp<FieldField<Field, scalar> > tRes
212     (
213         reuseTmpFieldField<Field, scalar, Type>::New(tf)
214     );
216     mag(tRes(), tf());
217     reuseTmpFieldField<Field, scalar, Type>::clear(tf);
218     return tRes;
222 template<template<class> class Field, class Type>
223 void cmptMax
225     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
226     const FieldField<Field, Type>& f
229     forAll(cf, i)
230     {
231         cmptMax(cf[i], f[i]);
232     }
235 template<template<class> class Field, class Type>
236 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMax
238     const FieldField<Field, Type>& f
241     typedef typename FieldField<Field, Type>::cmptType cmptType;
242     tmp<FieldField<Field, cmptType> > tRes
243     (
244         FieldField<Field, cmptType>::NewCalculatedType(f)
245     );
246     cmptMax(tRes(), f);
247     return tRes;
250 template<template<class> class Field, class Type>
251 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMax
253     const tmp<FieldField<Field, Type> >& tf
256     typedef typename FieldField<Field, Type>::cmptType cmptType;
257     tmp<FieldField<Field, cmptType> > tRes
258     (
259         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
260     );
261     cmptMax(tRes(), tf());
262     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
263     return tRes;
267 template<template<class> class Field, class Type>
268 void cmptMin
270     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
271     const FieldField<Field, Type>& f
274     forAll(cf, i)
275     {
276         cmptMin(cf[i], f[i]);
277     }
280 template<template<class> class Field, class Type>
281 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMin
283     const FieldField<Field, Type>& f
286     typedef typename FieldField<Field, Type>::cmptType cmptType;
287     tmp<FieldField<Field, cmptType> > tRes
288     (
289         FieldField<Field, cmptType>::NewCalculatedType(f)
290     );
291     cmptMin(tRes(), f);
292     return tRes;
295 template<template<class> class Field, class Type>
296 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMin
298     const tmp<FieldField<Field, Type> >& tf
301     typedef typename FieldField<Field, Type>::cmptType cmptType;
302     tmp<FieldField<Field, cmptType> > tRes
303     (
304         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
305     );
306     cmptMin(tRes(), tf());
307     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
308     return tRes;
312 template<template<class> class Field, class Type>
313 void cmptAv
315     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
316     const FieldField<Field, Type>& f
319     forAll(cf, i)
320     {
321         cmptAv(cf[i], f[i]);
322     }
325 template<template<class> class Field, class Type>
326 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptAv
328     const FieldField<Field, Type>& f
331     typedef typename FieldField<Field, Type>::cmptType cmptType;
332     tmp<FieldField<Field, cmptType> > tRes
333     (
334         FieldField<Field, cmptType>::NewCalculatedType(f)
335     );
336     cmptAv(tRes(), f);
337     return tRes;
340 template<template<class> class Field, class Type>
341 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptAv
343     const tmp<FieldField<Field, Type> >& tf
346     typedef typename FieldField<Field, Type>::cmptType cmptType;
347     tmp<FieldField<Field, cmptType> > tRes
348     (
349         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
350     );
351     cmptAv(tRes(), tf());
352     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
353     return tRes;
357 template<template<class> class Field, class Type>
358 void cmptMag
360     FieldField<Field, Type>& cf,
361     const FieldField<Field, Type>& f
364     forAll(cf, i)
365     {
366         cmptMag(cf[i], f[i]);
367     }
370 template<template<class> class Field, class Type>
371 tmp<FieldField<Field, Type> > cmptMag
373     const FieldField<Field, Type>& f
376     tmp<FieldField<Field, Type> > tRes
377     (
378         FieldField<Field, Type>::NewCalculatedType(f)
379     );
380     cmptMag(tRes(), f);
381     return tRes;
384 template<template<class> class Field, class Type>
385 tmp<FieldField<Field, Type> > cmptMag
387     const tmp<FieldField<Field, Type> >& tf
390     tmp<FieldField<Field, Type> > tRes
391     (
392         reuseTmpFieldField<Field, Type, Type>::New(tf)
393     );
394     cmptMag(tRes(), tf());
395     reuseTmpFieldField<Field, Type, Type>::clear(tf);
396     return tRes;
400 #define TMP_UNARY_FUNCTION(returnType, func)                                  \
401                                                                               \
402 template<template<class> class Field, class Type>                             \
403 returnType func(const tmp<FieldField<Field, Type> >& tf1)                     \
404 {                                                                             \
405     returnType res = func(tf1());                                             \
406     tf1.clear();                                                              \
407     return res;                                                               \
410 template<template<class> class Field, class Type>
411 Type max(const FieldField<Field, Type>& f)
413     label i = 0;
414     while(i < f.size() && !f[i].size()) i++;
416     if (i < f.size())
417     {
418         Type Max(max(f[i]));
420         for (label j=i+1; j<f.size(); j++)
421         {
422             if (f[j].size())
423             {
424                 Max = max(max(f[j]), Max);
425             }
426         }
428         return Max;
429     }
430     else
431     {
432         WarningIn("max(const FieldField<Field, Type>&) const")
433             << "empty fieldField, returning zero" << endl;
435         return pTraits<Type>::zero;
436     }
439 TMP_UNARY_FUNCTION(Type, max)
441 template<template<class> class Field, class Type>
442 Type min(const FieldField<Field, Type>& f)
444     label i = 0;
445     while(i < f.size() && !f[i].size()) i++;
447     if (i < f.size())
448     {
449         label i = 0;
450         while(!f[i].size()) i++;
452         Type Min(min(f[i]));
454         for (label j=i+1; j<f.size(); j++)
455         {
456             if (f[j].size())
457             {
458                 Min = min(min(f[j]), Min);
459             }
460         }
462         return Min;
463     }
464     else
465     {
466         WarningIn("min(const FieldField<Field, Type>&) const")
467             << "empty fieldField, returning zero" << endl;
469         return pTraits<Type>::zero;
470     }
473 TMP_UNARY_FUNCTION(Type, min)
475 template<template<class> class Field, class Type>
476 Type sum(const FieldField<Field, Type>& f)
478     if (f.size())
479     {
480         Type Sum = pTraits<Type>::zero;
482         forAll(f, i)
483         {
484             Sum += sum(f[i]);
485         }
487         return Sum;
488     }
489     else
490     {
491         return pTraits<Type>::zero;
492     }
495 TMP_UNARY_FUNCTION(Type, sum)
497 template<template<class> class Field, class Type>
498 scalar sumMag(const FieldField<Field, Type>& f)
500     if (f.size())
501     {
502         scalar SumMag = 0.0;
504         forAll(f, i)
505         {
506             SumMag += sumMag(f[i]);
507         }
509         return SumMag;
510     }
511     else
512     {
513         return 0.0;
514     }
517 TMP_UNARY_FUNCTION(scalar, sumMag)
519 template<template<class> class Field, class Type>
520 Type average(const FieldField<Field, Type>& f)
522     if (f.size())
523     {
524         label n = 0;
526         forAll(f, i)
527         {
528             n += f[i].size();
529         }
531         if (n == 0)
532         {
533             WarningIn("average(const FieldField<Field, Type>&) const")
534                 << "empty fieldField, returning zero" << endl;
536             return pTraits<Type>::zero;
537         }
539         Type avrg = sum(f)/n;
541         return avrg;
542     }
543     else
544     {
545         WarningIn("average(const FieldField<Field, Type>&) const")
546             << "empty fieldField, returning zero" << endl;
548         return pTraits<Type>::zero;
549     }
552 TMP_UNARY_FUNCTION(Type, average)
555 #include "PstreamReduceOps.H"
557 #define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc)                      \
558                                                                               \
559 template<template<class> class Field, class Type>                             \
560 returnType gFunc(const FieldField<Field, Type>& f)                            \
561 {                                                                             \
562     returnType res = func(f);                                                 \
563     reduce(res, rFunc##Op<Type>());                                           \
564     return res;                                                               \
565 }                                                                             \
566 TMP_UNARY_FUNCTION(returnType, gFunc)
568 G_UNARY_FUNCTION(Type, gMax, max, max)
569 G_UNARY_FUNCTION(Type, gMin, min, min)
570 G_UNARY_FUNCTION(Type, gSum, sum, sum)
571 G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
573 #undef G_UNARY_FUNCTION
576 template<class Type>
577 scalar gSumProd
579     const FieldField<Field, Type>& f1,
580     const FieldField<Field, Type>& f2
583     scalar SumProd = 0;
585     if (f1.size() && (f1.size() == f2.size()))
586     {
587         forAll (f1, i)
588         {
589             SumProd += sumProd(f1[i], f2[i]);
590         }
591         reduce(SumProd, sumOp<scalar>());
592     }
594     return SumProd;
598 template<template<class> class Field, class Type>
599 Type gAverage(const FieldField<Field, Type>& f)
601     label n = 0;
603     forAll(f, i)
604     {
605         n += f[i].size();
606     }
608     reduce(n, sumOp<label>());
610     if (n > 0)
611     {
612         Type avrg = gSum(f)/n;
614         return avrg;
615     }
616     else
617     {
618         WarningIn("gAverage(const FieldField<Field, Type>&) const")
619             << "empty fieldField, returning zero" << endl;
621         return pTraits<Type>::zero;
622     }
625 TMP_UNARY_FUNCTION(Type, gAverage)
627 #undef TMP_UNARY_FUNCTION
630 BINARY_FUNCTION(Type, Type, Type, max)
631 BINARY_FUNCTION(Type, Type, Type, min)
632 BINARY_FUNCTION(Type, Type, Type, cmptMultiply)
633 BINARY_FUNCTION(Type, Type, Type, cmptDivide)
635 BINARY_TYPE_FUNCTION(Type, Type, Type, max)
636 BINARY_TYPE_FUNCTION(Type, Type, Type, min)
637 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
638 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)
641 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
643 UNARY_OPERATOR(Type, Type, -, negate)
645 #ifndef __INTEL_COMPILER
646 BINARY_OPERATOR(Type, Type, scalar, *, multiply)
647 BINARY_OPERATOR(Type, scalar, Type, *, multiply)
648 #endif
649 BINARY_OPERATOR(Type, Type, scalar, /, divide)
651 BINARY_TYPE_OPERATOR_SF(Type, scalar, Type, *, multiply)
652 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, *, multiply)
654 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, /, divide)
657 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
659 #define PRODUCT_OPERATOR(product, op, opFunc)                                 \
660                                                                               \
661 template<template<class> class Field, class Type1, class Type2>               \
662 void opFunc                                                                   \
663 (                                                                             \
664     FieldField<Field, typename product<Type1, Type2>::type>& f,               \
665     const FieldField<Field, Type1>& f1,                                       \
666     const FieldField<Field, Type2>& f2                                        \
667 )                                                                             \
668 {                                                                             \
669     forAll(f, i)                                                              \
670     {                                                                         \
671         opFunc(f[i], f1[i], f2[i]);                                           \
672     }                                                                         \
673 }                                                                             \
674                                                                               \
675 template<template<class> class Field, class Type1, class Type2>               \
676 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
677 operator op                                                                   \
678 (                                                                             \
679     const FieldField<Field, Type1>& f1,                                       \
680     const FieldField<Field, Type2>& f2                                        \
681 )                                                                             \
682 {                                                                             \
683     typedef typename product<Type1, Type2>::type productType;                 \
684     tmp<FieldField<Field, productType> > tRes                                 \
685     (                                                                         \
686         FieldField<Field, productType>::NewCalculatedType(f1)                 \
687     );                                                                        \
688     opFunc(tRes(), f1, f2);                                                   \
689     return tRes;                                                              \
690 }                                                                             \
691                                                                               \
692 template<template<class> class Field, class Type1, class Type2>               \
693 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
694 operator op                                                                   \
695 (                                                                             \
696     const FieldField<Field, Type1>& f1,                                       \
697     const tmp<FieldField<Field, Type2> >& tf2                                 \
698 )                                                                             \
699 {                                                                             \
700     typedef typename product<Type1, Type2>::type productType;                 \
701     tmp<FieldField<Field, productType> > tRes                                 \
702     (                                                                         \
703         reuseTmpFieldField<Field, productType, Type2>::New(tf2)               \
704     );                                                                        \
705     opFunc(tRes(), f1, tf2());                                                \
706     reuseTmpFieldField<Field, productType, Type2>::clear(tf2);                \
707     return tRes;                                                              \
708 }                                                                             \
709                                                                               \
710 template<template<class> class Field, class Type1, class Type2>               \
711 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
712 operator op                                                                   \
713 (                                                                             \
714     const tmp<FieldField<Field, Type1> >& tf1,                                \
715     const FieldField<Field, Type2>& f2                                        \
716 )                                                                             \
717 {                                                                             \
718     typedef typename product<Type1, Type2>::type productType;                 \
719     tmp<FieldField<Field, productType> > tRes                                 \
720     (                                                                         \
721         reuseTmpFieldField<Field, productType, Type1>::New(tf1)               \
722     );                                                                        \
723     opFunc(tRes(), tf1(), f2);                                                \
724     reuseTmpFieldField<Field, productType, Type1>::clear(tf1);                \
725     return tRes;                                                              \
726 }                                                                             \
727                                                                               \
728 template<template<class> class Field, class Type1, class Type2>               \
729 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
730 operator op                                                                   \
731 (                                                                             \
732     const tmp<FieldField<Field, Type1> >& tf1,                                \
733     const tmp<FieldField<Field, Type2> >& tf2                                 \
734 )                                                                             \
735 {                                                                             \
736     typedef typename product<Type1, Type2>::type productType;                 \
737     tmp<FieldField<Field, productType> > tRes                                 \
738     (                                                                         \
739         reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::New   \
740             (tf1, tf2)                                                        \
741     );                                                                        \
742     opFunc(tRes(), tf1(), tf2());                                             \
743     reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::clear     \
744         (tf1, tf2);                                                           \
745     return tRes;                                                              \
746 }                                                                             \
747                                                                               \
748 template                                                                      \
749 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
750 void opFunc                                                                   \
751 (                                                                             \
752     FieldField<Field, typename product<Type, Form>::type>& f,                 \
753     const FieldField<Field, Type>& f1,                                        \
754     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
755 )                                                                             \
756 {                                                                             \
757     forAll(f, i)                                                              \
758     {                                                                         \
759         opFunc(f[i], f1[i], vs);                                              \
760     }                                                                         \
761 }                                                                             \
762                                                                               \
763 template                                                                      \
764 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
765 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
766 operator op                                                                   \
767 (                                                                             \
768     const FieldField<Field, Type>& f1,                                        \
769     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
770 )                                                                             \
771 {                                                                             \
772     typedef typename product<Type, Form>::type productType;                   \
773     tmp<FieldField<Field, productType> > tRes                                 \
774     (                                                                         \
775         FieldField<Field, productType>::NewCalculatedType(f1)                 \
776     );                                                                        \
777     opFunc(tRes(), f1, static_cast<const Form&>(vs));                         \
778     return tRes;                                                              \
779 }                                                                             \
780                                                                               \
781 template                                                                      \
782 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
783 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
784 operator op                                                                   \
785 (                                                                             \
786     const tmp<FieldField<Field, Type> >& tf1,                                 \
787     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
788 )                                                                             \
789 {                                                                             \
790     typedef typename product<Type, Form>::type productType;                   \
791     tmp<FieldField<Field, productType> > tRes                                 \
792     (                                                                         \
793         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
794     );                                                                        \
795     opFunc(tRes(), tf1(), static_cast<const Form&>(vs));                      \
796     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
797     return tRes;                                                              \
798 }                                                                             \
799                                                                               \
800 template                                                                      \
801 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
802 void opFunc                                                                   \
803 (                                                                             \
804     FieldField<Field, typename product<Form, Type>::type>& f,                 \
805     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
806     const FieldField<Field, Type>& f1                                         \
807 )                                                                             \
808 {                                                                             \
809     forAll(f, i)                                                              \
810     {                                                                         \
811         opFunc(f[i], vs, f1[i]);                                              \
812     }                                                                         \
813 }                                                                             \
814                                                                               \
815 template                                                                      \
816 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
817 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
818 operator op                                                                   \
819 (                                                                             \
820     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
821     const FieldField<Field, Type>& f1                                         \
822 )                                                                             \
823 {                                                                             \
824     typedef typename product<Form, Type>::type productType;                   \
825     tmp<FieldField<Field, productType> > tRes                                 \
826     (                                                                         \
827         FieldField<Field, productType>::NewCalculatedType(f1)                 \
828     );                                                                        \
829     opFunc(tRes(), static_cast<const Form&>(vs), f1);                         \
830     return tRes;                                                              \
831 }                                                                             \
832                                                                               \
833 template                                                                      \
834 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
835 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
836 operator op                                                                   \
837 (                                                                             \
838     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
839     const tmp<FieldField<Field, Type> >& tf1                                  \
840 )                                                                             \
841 {                                                                             \
842     typedef typename product<Form, Type>::type productType;                   \
843     tmp<FieldField<Field, productType> > tRes                                 \
844     (                                                                         \
845         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
846     );                                                                        \
847     opFunc(tRes(), static_cast<const Form&>(vs), tf1());                      \
848     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
849     return tRes;                                                              \
852 PRODUCT_OPERATOR(typeOfSum, +, add)
853 PRODUCT_OPERATOR(typeOfSum, -, subtract)
855 PRODUCT_OPERATOR(outerProduct, *, outer)
856 PRODUCT_OPERATOR(crossProduct, ^, cross)
857 PRODUCT_OPERATOR(innerProduct, &, dot)
858 PRODUCT_OPERATOR(scalarProduct, &&, dotdot)
860 #undef PRODUCT_OPERATOR
863 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
865 } // End namespace Foam
867 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
869 #include "undefFieldFunctionsM.H"
871 // ************************************************************************* //