initial commit for version 1.6.x patch release
[OpenFOAM-1.6.x.git] / src / OpenFOAM / fields / FieldFields / FieldField / FieldFieldFunctions.C
blobc0600bd97c4afc124d10ddc6eeaafc3f674c4c51
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM 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 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "PstreamReduceOps.H"
28 #include "FieldFieldReuseFunctions.H"
30 #define TEMPLATE template<template<class> class Field, class Type>
31 #include "FieldFieldFunctionsM.C"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 namespace Foam
38 /* * * * * * * * * * * * * * * * Global functions  * * * * * * * * * * * * * */
40 template<template<class> class Field, class Type>
41 void component
43     FieldField<Field, typename FieldField<Field, Type>::cmptType>& sf,
44     const FieldField<Field, Type>& f,
45     const direction d
48     forAll(sf, i)
49     {
50         component(sf[i], f[i], d);
51     }
55 template<template<class> class Field, class Type>
56 void T(FieldField<Field, Type>& f1, const FieldField<Field, Type>& f2)
58     forAll(f1, i)
59     {
60         T(f1[i], f2[i]);
61     }
65 template<template<class> class Field, class Type, int r>
66 void pow
68     FieldField<Field, typename powProduct<Type, r>::type>& f,
69     const FieldField<Field, Type>& vf
72     forAll(f, i)
73     {
74         pow(f[i], vf[i]);
75     }
78 template<template<class> class Field, class Type, int r>
79 tmp<FieldField<Field, typename powProduct<Type, r>::type> >
80 pow
82     const FieldField<Field, Type>& f, typename powProduct<Type, r>::type
85     typedef typename powProduct<Type, r>::type powProductType;
86     tmp<FieldField<Field, powProductType> > tRes
87     (
88         FieldField<Field, powProductType>::NewCalculatedType(f)
89     );
90     pow<Type, r>(tRes(), f);
91     return tRes;
94 template<template<class> class Field, class Type, int r>
95 tmp<FieldField<Field, typename powProduct<Type, r>::type> >
96 pow
98     const tmp<FieldField<Field, Type> >& tf, typename powProduct<Type, r>::type
101     typedef typename powProduct<Type, r>::type powProductType;
102     tmp<FieldField<Field, powProductType> > tRes
103     (
104         reuseTmpFieldField<Field, powProductType, Type>::New(tf)
105     );
106     pow<Type, r>(tRes(), tf());
107     reuseTmpFieldField<Field, powProductType, Type>::clear(tf);
108     return tRes;
112 template<template<class> class Field, class Type>
113 void sqr
115     FieldField<Field, typename outerProduct<Type, Type>::type>& f,
116     const FieldField<Field, Type>& vf
119     forAll(f, i)
120     {
121         sqr(f[i], vf[i]);
122     }
125 template<template<class> class Field, class Type>
126 tmp<FieldField<Field, typename outerProduct<Type, Type>::type> >
127 sqr(const FieldField<Field, Type>& f)
129     typedef typename outerProduct<Type, Type>::type outerProductType;
130     tmp<FieldField<Field, outerProductType> > tRes
131     (
132         FieldField<Field, outerProductType>::NewCalculatedType(f)
133     );
134     sqr(tRes(), f);
135     return tRes;
138 template<template<class> class Field, class Type>
139 tmp<FieldField<Field, typename outerProduct<Type, Type>::type> >
140 sqr(const tmp<FieldField<Field, Type> >& tf)
142     typedef typename outerProduct<Type, Type>::type outerProductType;
143     tmp<FieldField<Field, outerProductType> > tRes
144     (
145         reuseTmpFieldField<Field, outerProductType, Type>::New(tf)
146     );
147     sqr(tRes(), tf());
148     reuseTmpFieldField<Field, outerProductType, Type>::clear(tf);
149     return tRes;
153 template<template<class> class Field, class Type>
154 void magSqr(FieldField<Field, scalar>& sf, const FieldField<Field, Type>& f)
156     forAll(sf, i)
157     {
158         magSqr(sf[i], f[i]);
159     }
162 template<template<class> class Field, class Type>
163 tmp<FieldField<Field, scalar> > magSqr(const FieldField<Field, Type>& f)
165     tmp<FieldField<Field, scalar> > tRes
166     (
167         FieldField<Field, scalar>::NewCalculatedType(f)
168     );
170     magSqr(tRes(), f);
171     return tRes;
174 template<template<class> class Field, class Type>
175 tmp<FieldField<Field, scalar> > magSqr(const tmp<FieldField<Field, Type> >& tf)
177     tmp<FieldField<Field, scalar> > tRes
178     (
179         reuseTmpFieldField<Field, scalar, Type>::New(tf)
180     );
182     magSqr(tRes(), tf());
183     reuseTmpFieldField<Field, scalar, Type>::clear(tf);
184     return tRes;
188 template<template<class> class Field, class Type>
189 void mag(FieldField<Field, scalar>& sf, const FieldField<Field, Type>& f)
191     forAll(sf, i)
192     {
193         mag(sf[i], f[i]);
194     }
197 template<template<class> class Field, class Type>
198 tmp<FieldField<Field, scalar> > mag(const FieldField<Field, Type>& f)
200     tmp<FieldField<Field, scalar> > tRes
201     (
202         FieldField<Field, scalar>::NewCalculatedType(f)
203     );
205     mag(tRes(), f);
206     return tRes;
209 template<template<class> class Field, class Type>
210 tmp<FieldField<Field, scalar> > mag(const tmp<FieldField<Field, Type> >& tf)
212     tmp<FieldField<Field, scalar> > tRes
213     (
214         reuseTmpFieldField<Field, scalar, Type>::New(tf)
215     );
217     mag(tRes(), tf());
218     reuseTmpFieldField<Field, scalar, Type>::clear(tf);
219     return tRes;
223 template<template<class> class Field, class Type>
224 void cmptMax
226     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
227     const FieldField<Field, Type>& f
230     forAll(cf, i)
231     {
232         cmptMax(cf[i], f[i]);
233     }
236 template<template<class> class Field, class Type>
237 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMax
239     const FieldField<Field, Type>& f
242     typedef typename FieldField<Field, Type>::cmptType cmptType;
243     tmp<FieldField<Field, cmptType> > tRes
244     (
245         FieldField<Field, cmptType>::NewCalculatedType(f)
246     );
247     cmptMax(tRes(), f);
248     return tRes;
251 template<template<class> class Field, class Type>
252 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMax
254     const tmp<FieldField<Field, Type> >& tf
257     typedef typename FieldField<Field, Type>::cmptType cmptType;
258     tmp<FieldField<Field, cmptType> > tRes
259     (
260         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
261     );
262     cmptMax(tRes(), tf());
263     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
264     return tRes;
268 template<template<class> class Field, class Type>
269 void cmptMin
271     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
272     const FieldField<Field, Type>& f
275     forAll(cf, i)
276     {
277         cmptMin(cf[i], f[i]);
278     }
281 template<template<class> class Field, class Type>
282 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMin
284     const FieldField<Field, Type>& f
287     typedef typename FieldField<Field, Type>::cmptType cmptType;
288     tmp<FieldField<Field, cmptType> > tRes
289     (
290         FieldField<Field, cmptType>::NewCalculatedType(f)
291     );
292     cmptMin(tRes(), f);
293     return tRes;
296 template<template<class> class Field, class Type>
297 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptMin
299     const tmp<FieldField<Field, Type> >& tf
302     typedef typename FieldField<Field, Type>::cmptType cmptType;
303     tmp<FieldField<Field, cmptType> > tRes
304     (
305         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
306     );
307     cmptMin(tRes(), tf());
308     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
309     return tRes;
313 template<template<class> class Field, class Type>
314 void cmptAv
316     FieldField<Field, typename FieldField<Field, Type>::cmptType>& cf,
317     const FieldField<Field, Type>& f
320     forAll(cf, i)
321     {
322         cmptAv(cf[i], f[i]);
323     }
326 template<template<class> class Field, class Type>
327 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptAv
329     const FieldField<Field, Type>& f
332     typedef typename FieldField<Field, Type>::cmptType cmptType;
333     tmp<FieldField<Field, cmptType> > tRes
334     (
335         FieldField<Field, cmptType>::NewCalculatedType(f)
336     );
337     cmptAv(tRes(), f);
338     return tRes;
341 template<template<class> class Field, class Type>
342 tmp<FieldField<Field, typename FieldField<Field, Type>::cmptType> > cmptAv
344     const tmp<FieldField<Field, Type> >& tf
347     typedef typename FieldField<Field, Type>::cmptType cmptType;
348     tmp<FieldField<Field, cmptType> > tRes
349     (
350         reuseTmpFieldField<Field, cmptType, Type>::New(tf)
351     );
352     cmptAv(tRes(), tf());
353     reuseTmpFieldField<Field, cmptType, Type>::clear(tf);
354     return tRes;
358 template<template<class> class Field, class Type>
359 void cmptMag
361     FieldField<Field, Type>& cf,
362     const FieldField<Field, Type>& f
365     forAll(cf, i)
366     {
367         cmptMag(cf[i], f[i]);
368     }
371 template<template<class> class Field, class Type>
372 tmp<FieldField<Field, Type> > cmptMag
374     const FieldField<Field, Type>& f
377     tmp<FieldField<Field, Type> > tRes
378     (
379         FieldField<Field, Type>::NewCalculatedType(f)
380     );
381     cmptMag(tRes(), f);
382     return tRes;
385 template<template<class> class Field, class Type>
386 tmp<FieldField<Field, Type> > cmptMag
388     const tmp<FieldField<Field, Type> >& tf
391     tmp<FieldField<Field, Type> > tRes
392     (
393         reuseTmpFieldField<Field, Type, Type>::New(tf)
394     );
395     cmptMag(tRes(), tf());
396     reuseTmpFieldField<Field, Type, Type>::clear(tf);
397     return tRes;
401 #define TMP_UNARY_FUNCTION(returnType, func)                                  \
402                                                                               \
403 template<template<class> class Field, class Type>                             \
404 returnType func(const tmp<FieldField<Field, Type> >& tf1)                     \
405 {                                                                             \
406     returnType res = func(tf1());                                             \
407     tf1.clear();                                                              \
408     return res;                                                               \
411 template<template<class> class Field, class Type>
412 Type max(const FieldField<Field, Type>& f)
414     label i = 0;
415     while(i < f.size() && !f[i].size()) i++;
417     if (i < f.size())
418     {
419         Type Max(max(f[i]));
421         for (label j=i+1; j<f.size(); j++)
422         {
423             if (f[j].size())
424             {
425                 Max = max(max(f[j]), Max);
426             }
427         }
429         return Max;
430     }
431     else
432     {
433         return pTraits<Type>::min;
434     }
437 TMP_UNARY_FUNCTION(Type, max)
439 template<template<class> class Field, class Type>
440 Type min(const FieldField<Field, Type>& f)
442     label i = 0;
443     while(i < f.size() && !f[i].size()) i++;
445     if (i < f.size())
446     {
447         label i = 0;
448         while(!f[i].size()) i++;
450         Type Min(min(f[i]));
452         for (label j=i+1; j<f.size(); j++)
453         {
454             if (f[j].size())
455             {
456                 Min = min(min(f[j]), Min);
457             }
458         }
460         return Min;
461     }
462     else
463     {
464         return pTraits<Type>::max;
465     }
468 TMP_UNARY_FUNCTION(Type, min)
470 template<template<class> class Field, class Type>
471 Type sum(const FieldField<Field, Type>& f)
473     if (f.size())
474     {
475         Type Sum = pTraits<Type>::zero;
477         forAll(f, i)
478         {
479             Sum += sum(f[i]);
480         }
482         return Sum;
483     }
484     else
485     {
486         return pTraits<Type>::zero;
487     }
490 TMP_UNARY_FUNCTION(Type, sum)
492 template<template<class> class Field, class Type>
493 scalar sumMag(const FieldField<Field, Type>& f)
495     if (f.size())
496     {
497         scalar SumMag = 0.0;
499         forAll(f, i)
500         {
501             SumMag += sumMag(f[i]);
502         }
504         return SumMag;
505     }
506     else
507     {
508         return 0.0;
509     }
512 TMP_UNARY_FUNCTION(scalar, sumMag)
514 template<template<class> class Field, class Type>
515 Type average(const FieldField<Field, Type>& f)
517     if (f.size())
518     {
519         label n = 0;
521         forAll(f, i)
522         {
523             n += f[i].size();
524         }
526         if (n == 0)
527         {
528             WarningIn("average(const FieldField<Field, Type>&) const")
529                 << "empty fieldField, returning zero" << endl;
531             return pTraits<Type>::zero;
532         }
534         Type avrg = sum(f)/n;
536         return avrg;
537     }
538     else
539     {
540         WarningIn("average(const FieldField<Field, Type>&) const")
541             << "empty fieldField, returning zero" << endl;
543         return pTraits<Type>::zero;
544     }
547 TMP_UNARY_FUNCTION(Type, average)
550 #include "PstreamReduceOps.H"
552 #define G_UNARY_FUNCTION(returnType, gFunc, func, rFunc)                      \
553                                                                               \
554 template<template<class> class Field, class Type>                             \
555 returnType gFunc(const FieldField<Field, Type>& f)                            \
556 {                                                                             \
557     returnType res = func(f);                                                 \
558     reduce(res, rFunc##Op<Type>());                                           \
559     return res;                                                               \
560 }                                                                             \
561 TMP_UNARY_FUNCTION(returnType, gFunc)
563 G_UNARY_FUNCTION(Type, gMax, max, max)
564 G_UNARY_FUNCTION(Type, gMin, min, min)
565 G_UNARY_FUNCTION(Type, gSum, sum, sum)
566 G_UNARY_FUNCTION(scalar, gSumMag, sumMag, sum)
568 #undef G_UNARY_FUNCTION
571 template<template<class> class Field, class Type>
572 Type gAverage(const FieldField<Field, Type>& f)
574     label n = 0;
576     forAll(f, i)
577     {
578         n += f[i].size();
579     }
581     reduce(n, sumOp<label>());
583     if (n > 0)
584     {
585         Type avrg = gSum(f)/n;
587         return avrg;
588     }
589     else
590     {
591         WarningIn("gAverage(const FieldField<Field, Type>&) const")
592             << "empty fieldField, returning zero" << endl;
594         return pTraits<Type>::zero;
595     }
598 TMP_UNARY_FUNCTION(Type, gAverage)
600 #undef TMP_UNARY_FUNCTION
603 BINARY_FUNCTION(Type, Type, Type, max)
604 BINARY_FUNCTION(Type, Type, Type, min)
605 BINARY_FUNCTION(Type, Type, Type, cmptMultiply)
606 BINARY_FUNCTION(Type, Type, Type, cmptDivide)
608 BINARY_TYPE_FUNCTION(Type, Type, Type, max)
609 BINARY_TYPE_FUNCTION(Type, Type, Type, min)
610 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptMultiply)
611 BINARY_TYPE_FUNCTION(Type, Type, Type, cmptDivide)
614 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
616 UNARY_OPERATOR(Type, Type, -, negate)
618 #ifndef __INTEL_COMPILER
619 BINARY_OPERATOR(Type, Type, scalar, *, multiply)
620 BINARY_OPERATOR(Type, scalar, Type, *, multiply)
621 #endif
622 BINARY_OPERATOR(Type, Type, scalar, /, divide)
624 BINARY_TYPE_OPERATOR_SF(Type, scalar, Type, *, multiply)
625 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, *, multiply)
627 BINARY_TYPE_OPERATOR_FS(Type, Type, scalar, /, divide)
630 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
632 #define PRODUCT_OPERATOR(product, op, opFunc)                                 \
633                                                                               \
634 template<template<class> class Field, class Type1, class Type2>               \
635 void opFunc                                                                   \
636 (                                                                             \
637     FieldField<Field, typename product<Type1, Type2>::type>& f,               \
638     const FieldField<Field, Type1>& f1,                                       \
639     const FieldField<Field, Type2>& f2                                        \
640 )                                                                             \
641 {                                                                             \
642     forAll(f, i)                                                              \
643     {                                                                         \
644         opFunc(f[i], f1[i], f2[i]);                                           \
645     }                                                                         \
646 }                                                                             \
647                                                                               \
648 template<template<class> class Field, class Type1, class Type2>               \
649 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
650 operator op                                                                   \
651 (                                                                             \
652     const FieldField<Field, Type1>& f1,                                       \
653     const FieldField<Field, Type2>& f2                                        \
654 )                                                                             \
655 {                                                                             \
656     typedef typename product<Type1, Type2>::type productType;                 \
657     tmp<FieldField<Field, productType> > tRes                                 \
658     (                                                                         \
659         FieldField<Field, productType>::NewCalculatedType(f1)                 \
660     );                                                                        \
661     opFunc(tRes(), f1, f2);                                                   \
662     return tRes;                                                              \
663 }                                                                             \
664                                                                               \
665 template<template<class> class Field, class Type1, class Type2>               \
666 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
667 operator op                                                                   \
668 (                                                                             \
669     const FieldField<Field, Type1>& f1,                                       \
670     const tmp<FieldField<Field, Type2> >& tf2                                 \
671 )                                                                             \
672 {                                                                             \
673     typedef typename product<Type1, Type2>::type productType;                 \
674     tmp<FieldField<Field, productType> > tRes                                 \
675     (                                                                         \
676         reuseTmpFieldField<Field, productType, Type2>::New(tf2)               \
677     );                                                                        \
678     opFunc(tRes(), f1, tf2());                                                \
679     reuseTmpFieldField<Field, productType, Type2>::clear(tf2);                \
680     return tRes;                                                              \
681 }                                                                             \
682                                                                               \
683 template<template<class> class Field, class Type1, class Type2>               \
684 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
685 operator op                                                                   \
686 (                                                                             \
687     const tmp<FieldField<Field, Type1> >& tf1,                                \
688     const FieldField<Field, Type2>& f2                                        \
689 )                                                                             \
690 {                                                                             \
691     typedef typename product<Type1, Type2>::type productType;                 \
692     tmp<FieldField<Field, productType> > tRes                                 \
693     (                                                                         \
694         reuseTmpFieldField<Field, productType, Type1>::New(tf1)               \
695     );                                                                        \
696     opFunc(tRes(), tf1(), f2);                                                \
697     reuseTmpFieldField<Field, productType, Type1>::clear(tf1);                \
698     return tRes;                                                              \
699 }                                                                             \
700                                                                               \
701 template<template<class> class Field, class Type1, class Type2>               \
702 tmp<FieldField<Field, typename product<Type1, Type2>::type> >                 \
703 operator op                                                                   \
704 (                                                                             \
705     const tmp<FieldField<Field, Type1> >& tf1,                                \
706     const tmp<FieldField<Field, Type2> >& tf2                                 \
707 )                                                                             \
708 {                                                                             \
709     typedef typename product<Type1, Type2>::type productType;                 \
710     tmp<FieldField<Field, productType> > tRes                                 \
711     (                                                                         \
712         reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::New   \
713             (tf1, tf2)                                                        \
714     );                                                                        \
715     opFunc(tRes(), tf1(), tf2());                                             \
716     reuseTmpTmpFieldField<Field, productType, Type1, Type1, Type2>::clear     \
717         (tf1, tf2);                                                           \
718     return tRes;                                                              \
719 }                                                                             \
720                                                                               \
721 template                                                                      \
722 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
723 void opFunc                                                                   \
724 (                                                                             \
725     FieldField<Field, typename product<Type, Form>::type>& f,                 \
726     const FieldField<Field, Type>& f1,                                        \
727     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
728 )                                                                             \
729 {                                                                             \
730     forAll(f, i)                                                              \
731     {                                                                         \
732         opFunc(f[i], f1[i], vs);                                              \
733     }                                                                         \
734 }                                                                             \
735                                                                               \
736 template                                                                      \
737 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
738 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
739 operator op                                                                   \
740 (                                                                             \
741     const FieldField<Field, Type>& f1,                                        \
742     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
743 )                                                                             \
744 {                                                                             \
745     typedef typename product<Type, Form>::type productType;                   \
746     tmp<FieldField<Field, productType> > tRes                                 \
747     (                                                                         \
748         FieldField<Field, productType>::NewCalculatedType(f1)                 \
749     );                                                                        \
750     opFunc(tRes(), f1, static_cast<const Form&>(vs));                         \
751     return tRes;                                                              \
752 }                                                                             \
753                                                                               \
754 template                                                                      \
755 <template<class> class Field, class Type, class Form, class Cmpt, int nCmpt>  \
756 tmp<FieldField<Field, typename product<Type, Form>::type> >                   \
757 operator op                                                                   \
758 (                                                                             \
759     const tmp<FieldField<Field, Type> >& tf1,                                 \
760     const VectorSpace<Form,Cmpt,nCmpt>& vs                                    \
761 )                                                                             \
762 {                                                                             \
763     typedef typename product<Type, Form>::type productType;                   \
764     tmp<FieldField<Field, productType> > tRes                                 \
765     (                                                                         \
766         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
767     );                                                                        \
768     opFunc(tRes(), tf1(), static_cast<const Form&>(vs));                      \
769     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
770     return tRes;                                                              \
771 }                                                                             \
772                                                                               \
773 template                                                                      \
774 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
775 void opFunc                                                                   \
776 (                                                                             \
777     FieldField<Field, typename product<Form, Type>::type>& f,                 \
778     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
779     const FieldField<Field, Type>& f1                                         \
780 )                                                                             \
781 {                                                                             \
782     forAll(f, i)                                                              \
783     {                                                                         \
784         opFunc(f[i], vs, f1[i]);                                              \
785     }                                                                         \
786 }                                                                             \
787                                                                               \
788 template                                                                      \
789 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
790 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
791 operator op                                                                   \
792 (                                                                             \
793     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
794     const FieldField<Field, Type>& f1                                         \
795 )                                                                             \
796 {                                                                             \
797     typedef typename product<Form, Type>::type productType;                   \
798     tmp<FieldField<Field, productType> > tRes                                 \
799     (                                                                         \
800         FieldField<Field, productType>::NewCalculatedType(f1)                 \
801     );                                                                        \
802     opFunc(tRes(), static_cast<const Form&>(vs), f1);                         \
803     return tRes;                                                              \
804 }                                                                             \
805                                                                               \
806 template                                                                      \
807 <template<class> class Field, class Form, class Cmpt, int nCmpt, class Type>  \
808 tmp<FieldField<Field, typename product<Form, Type>::type> >                   \
809 operator op                                                                   \
810 (                                                                             \
811     const VectorSpace<Form,Cmpt,nCmpt>& vs,                                   \
812     const tmp<FieldField<Field, Type> >& tf1                                  \
813 )                                                                             \
814 {                                                                             \
815     typedef typename product<Form, Type>::type productType;                   \
816     tmp<FieldField<Field, productType> > tRes                                 \
817     (                                                                         \
818         reuseTmpFieldField<Field, productType, Type>::New(tf1)                \
819     );                                                                        \
820     opFunc(tRes(), static_cast<const Form&>(vs), tf1());                      \
821     reuseTmpFieldField<Field, productType, Type>::clear(tf1);                 \
822     return tRes;                                                              \
825 PRODUCT_OPERATOR(typeOfSum, +, add)
826 PRODUCT_OPERATOR(typeOfSum, -, subtract)
828 PRODUCT_OPERATOR(outerProduct, *, outer)
829 PRODUCT_OPERATOR(crossProduct, ^, cross)
830 PRODUCT_OPERATOR(innerProduct, &, dot)
831 PRODUCT_OPERATOR(scalarProduct, &&, dotdot)
833 #undef PRODUCT_OPERATOR
836 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
838 } // End namespace Foam
840 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
842 #include "undefFieldFunctionsM.H"
844 // ************************************************************************* //